pvr.c revision 1.1 1 /* $NetBSD: pvr.c,v 1.1 2001/01/16 00:33:20 marcus Exp $ */
2
3 /*
4 * Copyright (c) 2001 Marcus Comstedt
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Matt DeBergalis
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
41 #include <sys/conf.h>
42
43 #include <machine/cpu.h>
44 #include <machine/bus.h>
45
46 #include <dev/cons.h>
47
48 #include <dreamcast/dev/pvrvar.h>
49 #include <dreamcast/dev/maple/mkbdvar.h>
50 #include <dev/wscons/wsconsio.h>
51
52 #include <dev/rcons/raster.h>
53 #include <dev/wscons/wscons_raster.h>
54 #include <dev/wscons/wsdisplayvar.h>
55 #include <dev/wscons/wsconsio.h>
56 #include <dev/wscons/wscons_callbacks.h>
57
58 #include <sh3/shbvar.h>
59
60 #include "wsdisplay.h"
61 #include "mkbd.h"
62
63 #if NWSDISPLAY > 0
64 cdev_decl(wsdisplay);
65 #endif
66
67 int pvr_match __P((struct device *, struct cfdata *, void *));
68 void pvr_attach __P((struct device *, struct device *, void *));
69
70 struct cfattach pvr_ca = {
71 sizeof(struct pvr_softc),
72 pvr_match,
73 pvr_attach,
74 };
75
76
77 const struct wsdisplay_emulops pvr_emulops = {
78 rcons_cursor,
79 rcons_mapchar,
80 rcons_putchar,
81 rcons_copycols,
82 rcons_erasecols,
83 rcons_copyrows,
84 rcons_eraserows,
85 rcons_alloc_attr
86 };
87
88 const struct wsscreen_descr pvr_stdscreen = {
89 "52x20", 52, 20,
90 &pvr_emulops,
91 12, 24,
92 WSSCREEN_WSCOLORS,
93 };
94
95 const struct wsscreen_descr *_pvr_scrlist[] = {
96 &pvr_stdscreen,
97 };
98
99 const struct wsscreen_list pvr_screenlist = {
100 sizeof(_pvr_scrlist) / sizeof(struct wsscreen_descr *),
101 _pvr_scrlist
102 };
103
104 static int pvr_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
105 static paddr_t pvr_mmap __P((void *, off_t, int));
106 static int pvr_alloc_screen __P((void *, const struct wsscreen_descr *,
107 void **, int *, int *, long *));
108 static void pvr_free_screen __P((void *, void *));
109 static int pvr_show_screen __P((void *, void *, int,
110 void (*)(void *, int, int), void *));
111
112 static void pvr_check_cable __P((int *, int *));
113 static void pvr_init_dpy_hardware __P((void));
114
115
116 const struct wsdisplay_accessops pvr_accessops = {
117 pvr_ioctl,
118 pvr_mmap,
119 pvr_alloc_screen,
120 pvr_free_screen,
121 pvr_show_screen,
122 0 /* load_font */
123 };
124
125
126 static void
127 pvr_check_cable(vgamode_p, rgbmode_p)
128 int *vgamode_p;
129 int *rgbmode_p;
130 {
131 volatile u_int32_t *porta = (volatile u_int32_t *)0xff80002c;
132 u_int16_t v;
133
134 /* PORT8 and PORT9 is input */
135 *porta = (*porta & ~0xf0000) | 0xa0000;
136
137 /* Read PORT8 and PORT9 */
138 v = ((*(volatile u_int16_t *)(porta+1))>>8)&3;
139
140 if (! (v&2) )
141 *vgamode_p = *rgbmode_p = 1;
142 else {
143 *vgamode_p = 0;
144 *rgbmode_p = (v&1)? 0 : 1;
145 }
146 }
147
148 static void
149 pvr_init_dpy_hardware()
150 {
151 volatile u_int32_t *pvr = (volatile u_int32_t *)0xa05f8000;
152 int display_lines_per_field = 240;
153 int modulo = 1, voffset;
154 int vgamode, rgbmode;
155
156 pvr_check_cable(&vgamode, &rgbmode);
157
158 pvr[8/4] = 0; /* reset */
159 pvr[0x40/4] = 0; /* black border */
160
161 if(vgamode) {
162 pvr[0x44/4] = 0x800004; /* 31kHz, RGB565 */
163 pvr[0xd0/4] = 0x100; /* video output */
164 display_lines_per_field = 480;
165 voffset = 36;
166 } else {
167 pvr[0x44/4] = 0x000004; /* 15kHz, RGB565 */
168 pvr[0xd0/4] = 0x110; /* video output, NTSC, interlace */
169 modulo += 640*2/4; /* interlace -> skip every other line */
170 voffset = 18;
171 }
172
173 pvr[0x50/4]=0; /* video base address, long field */
174 pvr[0x54/4]=640*2; /* video base address, short field */
175
176 pvr[0x5c/4]=(modulo<<20)|((display_lines_per_field-1)<<10)|(640*2/4-1);
177
178 voffset = (voffset<<16) | voffset;
179
180 pvr[0xf0/4]=voffset; /* V start */
181 pvr[0xdc/4]=voffset+display_lines_per_field; /* V border */
182 pvr[0xec/4]=164; /* H start */
183 pvr[0xd8/4]=(524<<16)|857; /* HV counter */
184 pvr[0xd4/4]=(126<<16)|837; /* H border */
185 pvr[0xe8/4]=22<<16;
186
187 /* RGB / composite */
188 *(volatile u_int32_t *)0xa0702c00 = (rgbmode? 0 : 3) << 8;
189
190 pvr[0x44/4] |= 1; /* display on */
191 }
192
193
194
195
196 int
197 pvr_ioctl(v, cmd, data, flag, p)
198 void *v;
199 u_long cmd;
200 caddr_t data;
201 int flag;
202 struct proc *p;
203 {
204 switch (cmd) {
205 case WSDISPLAYIO_GTYPE:
206 case WSDISPLAYIO_GINFO:
207 case WSDISPLAYIO_GCURMAX:
208 case WSDISPLAYIO_GCURPOS:
209 case WSDISPLAYIO_GCURSOR:
210 case WSDISPLAYIO_GETCMAP:
211 case WSDISPLAYIO_GVIDEO:
212 case WSDISPLAYIO_PUTCMAP:
213 case WSDISPLAYIO_SCURPOS:
214 case WSDISPLAYIO_SCURSOR:
215 case WSDISPLAYIO_SVIDEO:
216 /* NONE of these operations are supported. */
217 return ENOTTY;
218 }
219
220 return -1;
221 }
222
223 static paddr_t
224 pvr_mmap(v, offset, prot)
225 void *v;
226 off_t offset;
227 int prot;
228 {
229 return (-1);
230 }
231
232 int
233 pvr_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
234 void *v;
235 const struct wsscreen_descr *type;
236 void **cookiep;
237 int *curxp, *curyp;
238 long *defattrp;
239 {
240 return (ENOMEM);
241 }
242
243 void
244 pvr_free_screen(v, cookie)
245 void *v;
246 void *cookie;
247 {
248 }
249
250 int
251 pvr_show_screen(v, cookie, waitok, cb, cbarg)
252 void *v;
253 void *cookie;
254 int waitok;
255 void (*cb) __P((void *, int, int));
256 void *cbarg;
257 {
258 return 0;
259 }
260
261
262 int
263 pvr_match(parent, match, aux)
264 struct device *parent;
265 struct cfdata *match;
266 void *aux;
267 {
268 struct shb_attach_args *sa = aux;
269
270 if(strcmp("pvr", match->cf_driver->cd_name))
271 return 0;
272
273 sa->ia_iosize = 0 /* 0x1400 */;
274 return (1);
275 }
276
277 void
278 pvr_attach(parent, self, aux)
279 struct device *parent;
280 struct device *self;
281 void *aux;
282 {
283 struct pvr_softc *sc;
284 struct wsemuldisplaydev_attach_args waa;
285 static int pvr_console_initted = 0;
286
287 sc = (struct pvr_softc *)self;
288
289 printf("\n");
290
291 /* initialize the raster */
292 waa.console = (++pvr_console_initted == 1);
293 waa.scrdata = &pvr_screenlist;
294 waa.accessops = &pvr_accessops;
295 waa.accesscookie = sc;
296
297 config_found(self, &waa, wsemuldisplaydevprint);
298 }
299
300
301 /* Console stuff */
302
303 void pvrcnprobe __P((struct consdev *));
304 void pvrcninit __P((struct consdev *));
305
306 void
307 pvrcninit(cndev)
308 struct consdev *cndev;
309 {
310 static struct rcons rcons;
311 static struct raster raster;
312 struct rcons *rcp;
313 struct raster *rap;
314
315 /* initialize the raster console blitter */
316 rap = &raster;
317 rap->width = 640;
318 rap->height = 480;
319 rap->depth = 16;
320 rap->linelongs = 640*2 / sizeof(u_int32_t);
321 rap->pixels = (void *)0xa5000000;
322
323 bzero(rap->pixels, 640*480*2);
324
325 pvr_init_dpy_hardware();
326
327 rcp = &rcons;
328 rcp->rc_sp = rap;
329 rcp->rc_crow = rcp->rc_ccol = -1;
330 rcp->rc_crowp = &rcp->rc_crow;
331 rcp->rc_ccolp = &rcp->rc_ccol;
332 rcons_init(rcp, 20, 52);
333
334 wsdisplay_cnattach(&pvr_stdscreen, rcp, 0, 0, 0);
335 cn_tab->cn_pri = CN_INTERNAL;
336
337 #if NMKBD > 0
338 mkbd_cnattach(); /* Connect keyboard and screen together */
339 #endif
340 }
341
342
343 void
344 pvrcnprobe(cndev)
345 struct consdev *cndev;
346 {
347 #if NWSDISPLAY > 0
348 int maj, unit;
349 #endif
350 cndev->cn_dev = NODEV;
351 cndev->cn_pri = CN_NORMAL;
352
353 #if NWSDISPLAY > 0
354 unit = 0;
355 for (maj = 0; maj < nchrdev; maj++) {
356 if (cdevsw[maj].d_open == wsdisplayopen) {
357 break;
358 }
359 }
360 if (maj != nchrdev) {
361 cndev->cn_pri = CN_INTERNAL;
362 cndev->cn_dev = makedev(maj, unit);
363 }
364 #endif
365 }
366