plumvideo.c revision 1.7 1 /* $NetBSD: plumvideo.c,v 1.7 2000/05/02 17:50:51 uch Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000 UCHIYAMA Yasushi. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
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, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "opt_tx39_debug.h"
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/device.h>
34
35 #include <dev/cons.h> /* consdev */
36
37 #include <machine/bus.h>
38 #include <machine/intr.h>
39
40 #include <hpcmips/tx/tx39var.h>
41 #include <hpcmips/dev/plumvar.h>
42 #include <hpcmips/dev/plumicuvar.h>
43 #include <hpcmips/dev/plumpowervar.h>
44 #include <hpcmips/dev/plumvideoreg.h>
45
46 #include <machine/bootinfo.h>
47
48 #include <dev/wscons/wsconsio.h>
49 #include <arch/hpcmips/dev/hpcfbvar.h>
50 #include <arch/hpcmips/dev/hpcfbio.h>
51
52 #ifdef PLUMVIDEODEBUG
53 int plumvideo_debug = 1;
54 #define DPRINTF(arg) if (plumvideo_debug) printf arg;
55 #define DPRINTFN(n, arg) if (plumvideo_debug > (n)) printf arg;
56 #else
57 #define DPRINTF(arg)
58 #define DPRINTFN(n, arg)
59 #endif
60
61 int plumvideo_match __P((struct device*, struct cfdata*, void*));
62 void plumvideo_attach __P((struct device*, struct device*, void*));
63
64 struct plumvideo_softc {
65 struct device sc_dev;
66 plum_chipset_tag_t sc_pc;
67 bus_space_tag_t sc_regt;
68 bus_space_handle_t sc_regh;
69 bus_space_tag_t sc_iot;
70 bus_space_handle_t sc_ioh;
71
72 int sc_width;
73 int sc_height;
74 int sc_depth;
75
76 struct hpcfb_fbconf sc_fbconf;
77 struct hpcfb_dspconf sc_dspconf;
78 };
79
80 void plumvideo_hpcfbinit __P((struct plumvideo_softc *));
81 int plumvideo_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
82 int plumvideo_mmap __P((void *, off_t, int));
83
84 struct cfattach plumvideo_ca = {
85 sizeof(struct plumvideo_softc), plumvideo_match, plumvideo_attach
86 };
87
88 struct hpcfb_accessops plumvideo_ha = {
89 plumvideo_ioctl, plumvideo_mmap
90 };
91
92 int plumvideo_init __P((struct plumvideo_softc*));
93 #ifdef PLUMVIDEODEBUG
94 void plumvideo_dump __P((struct plumvideo_softc*));
95 #endif
96
97 int
98 plumvideo_match(parent, cf, aux)
99 struct device *parent;
100 struct cfdata *cf;
101 void *aux;
102 {
103 /*
104 * VRAM area also uses as UHOSTC shared RAM.
105 */
106 return 2; /* 1st attach group */
107 }
108
109 void
110 plumvideo_attach(parent, self, aux)
111 struct device *parent;
112 struct device *self;
113 void *aux;
114 {
115 struct plum_attach_args *pa = aux;
116 struct plumvideo_softc *sc = (void*)self;
117 struct hpcfb_attach_args ha;
118 int console;
119
120 sc->sc_pc = pa->pa_pc;
121 sc->sc_regt = pa->pa_regt;
122 sc->sc_iot = pa->pa_iot;
123
124 printf(": ");
125 /*
126 * map register area
127 */
128 if (bus_space_map(sc->sc_regt, PLUM_VIDEO_REGBASE,
129 PLUM_VIDEO_REGSIZE, 0, &sc->sc_regh)) {
130 printf(": register map failed\n");
131 return;
132 }
133
134 /*
135 * Power control
136 */
137 #ifndef PLUMVIDEODEBUG
138 if (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) {
139 /* LCD power on and display off */
140 plum_power_disestablish(sc->sc_pc, PLUM_PWR_LCD);
141 /* power off V-RAM */
142 plum_power_disestablish(sc->sc_pc, PLUM_PWR_EXTPW2);
143 /* power off LCD */
144 plum_power_disestablish(sc->sc_pc, PLUM_PWR_EXTPW1);
145 /* power off RAMDAC */
146 plum_power_disestablish(sc->sc_pc, PLUM_PWR_EXTPW0);
147 /* back-light off */
148 plum_power_disestablish(sc->sc_pc, PLUM_PWR_BKL);
149 } else
150 #endif
151 {
152 /* LCD power on and display on */
153 plum_power_establish(sc->sc_pc, PLUM_PWR_LCD);
154 /* supply power to V-RAM */
155 plum_power_establish(sc->sc_pc, PLUM_PWR_EXTPW2);
156 /* supply power to LCD */
157 plum_power_establish(sc->sc_pc, PLUM_PWR_EXTPW1);
158 /* back-light on */
159 plum_power_establish(sc->sc_pc, PLUM_PWR_BKL);
160 }
161
162 /*
163 * Initialize LCD controller
164 * map V-RAM area.
165 * reinstall bootinfo structure.
166 * some OHCI shared-buffer hack. XXX
167 */
168 if (plumvideo_init(sc) != 0)
169 return;
170
171 printf("\n");
172
173 #ifdef PLUMVIDEODEBUG
174 if (plumvideo_debug)
175 plumvideo_dump(sc);
176 #endif
177 /* Attach frame buffer device */
178 plumvideo_hpcfbinit(sc);
179
180 console = cn_tab ? 0 : 1;
181 if(console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
182 panic("plumvideo_attach: can't init fb console");
183 }
184
185 ha.ha_console = console;
186 ha.ha_accessops = &plumvideo_ha;
187 ha.ha_accessctx = sc;
188 ha.ha_curfbconf = 0;
189 ha.ha_nfbconf = 1;
190 ha.ha_fbconflist = &sc->sc_fbconf;
191 ha.ha_curdspconf = 0;
192 ha.ha_ndspconf = 1;
193 ha.ha_dspconflist = &sc->sc_dspconf;
194
195 config_found(self, &ha, hpcfbprint);
196 }
197
198 void
199 plumvideo_hpcfbinit(sc)
200 struct plumvideo_softc *sc;
201 {
202 struct hpcfb_fbconf *fb = &sc->sc_fbconf;
203 vaddr_t fbvaddr = (vaddr_t)sc->sc_ioh;
204
205 memset(fb, 0, sizeof(struct hpcfb_fbconf));
206
207 fb->hf_conf_index = 0; /* configuration index */
208 fb->hf_nconfs = 1; /* how many configurations */
209 strcpy(fb->hf_name, "PLUM built-in video");
210 /* frame buffer name */
211 strcpy(fb->hf_conf_name, "LCD");
212 /* configuration name */
213 fb->hf_height = sc->sc_height;
214 fb->hf_width = sc->sc_width;
215 fb->hf_baseaddr = mips_ptob(mips_btop(fbvaddr));
216 fb->hf_offset = (u_long)fbvaddr - fb->hf_baseaddr;
217 /* frame buffer start offset */
218 fb->hf_bytes_per_line = (sc->sc_width * sc->sc_depth) / NBBY;
219 fb->hf_nplanes = 1;
220 fb->hf_bytes_per_plane = sc->sc_height * fb->hf_bytes_per_line;
221
222 fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
223 fb->hf_access_flags |= HPCFB_ACCESS_WORD;
224 fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
225
226 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
227 switch (sc->sc_depth) {
228 default:
229 panic("plumvideo_hpcfbinit: not supported color depth\n");
230 /* NOTREACHED */
231 case 16:
232 fb->hf_class = HPCFB_CLASS_RGBCOLOR;
233 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
234 fb->hf_pack_width = 16;
235 fb->hf_pixels_per_pack = 1;
236 fb->hf_pixel_width = 16;
237
238 fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
239 fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */
240
241 fb->hf_u.hf_rgb.hf_red_width = 5;
242 fb->hf_u.hf_rgb.hf_red_shift = 11;
243 fb->hf_u.hf_rgb.hf_green_width = 6;
244 fb->hf_u.hf_rgb.hf_green_shift = 5;
245 fb->hf_u.hf_rgb.hf_blue_width = 5;
246 fb->hf_u.hf_rgb.hf_blue_shift = 0;
247 fb->hf_u.hf_rgb.hf_alpha_width = 0;
248 fb->hf_u.hf_rgb.hf_alpha_shift = 0;
249 break;
250
251 case 8:
252 fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
253 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
254 fb->hf_pack_width = 8;
255 fb->hf_pixels_per_pack = 1;
256 fb->hf_pixel_width = 8;
257 fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
258 fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
259 break;
260 }
261 }
262
263 int
264 plumvideo_init(sc)
265 struct plumvideo_softc *sc;
266 {
267 bus_space_tag_t regt = sc->sc_regt;
268 bus_space_handle_t regh = sc->sc_regh;
269 plumreg_t reg;
270 size_t vram_size;
271 int bpp, vram_pitch;
272
273 reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG);
274 switch (reg & PLUM_VIDEO_PLGMD_MASK) {
275 case PLUM_VIDEO_PLGMD_16BPP:
276 #ifdef PLUM_BIG_OHCI_BUFFER
277 printf("(16bpp disabled) ");
278 /* FALLTHROUGH */
279 #else /* PLUM_BIG_OHCI_BUFFER */
280 bpp = 16;
281 break;
282 #endif /* PLUM_BIG_OHCI_BUFFER */
283 default:
284 bootinfo->fb_type = BIFB_D8_FF; /* over ride */
285 reg &= ~PLUM_VIDEO_PLGMD_MASK;
286 reg |= PLUM_VIDEO_PLGMD_8BPP;
287 plum_conf_write(regt, regh, PLUM_VIDEO_PLGMD_REG, reg);
288 /* FALLTHROUGH */
289 case PLUM_VIDEO_PLGMD_8BPP:
290 bpp = 8;
291 break;
292 }
293 sc->sc_depth = bpp;
294 sc->sc_width = bootinfo->fb_width;
295 sc->sc_height = bootinfo->fb_height;
296
297 /*
298 * set line byte length to bootinfo and LCD controller.
299 */
300 bootinfo->fb_line_bytes = (bootinfo->fb_width * bpp) / 8;
301
302 vram_pitch = bootinfo->fb_width / (8 / bpp);
303 plum_conf_write(regt, regh, PLUM_VIDEO_PLPIT1_REG, vram_pitch);
304 plum_conf_write(regt, regh, PLUM_VIDEO_PLPIT2_REG,
305 vram_pitch & PLUM_VIDEO_PLPIT2_MASK);
306 plum_conf_write(regt, regh, PLUM_VIDEO_PLOFS_REG, vram_pitch);
307
308 /*
309 * boot messages.
310 */
311 printf("display mode: ");
312 reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG);
313 switch (reg & PLUM_VIDEO_PLGMD_MASK) {
314 case PLUM_VIDEO_PLGMD_DISABLE:
315 printf("disabled ");
316 break;
317 case PLUM_VIDEO_PLGMD_8BPP:
318 printf("8bpp ");
319 break;
320 case PLUM_VIDEO_PLGMD_16BPP:
321 printf("16bpp ");
322 break;
323 }
324
325 /*
326 * calcurate frame buffer size.
327 */
328 reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG);
329 vram_size = (bootinfo->fb_width * bootinfo->fb_height *
330 (((reg & PLUM_VIDEO_PLGMD_MASK) == PLUM_VIDEO_PLGMD_16BPP)
331 ? 16 : 8)) / 8;
332 vram_size = mips_round_page(vram_size);
333
334 /*
335 * map V-RAM area.
336 */
337 if (bus_space_map(sc->sc_iot, PLUM_VIDEO_VRAM_IOBASE,
338 vram_size, 0, &sc->sc_ioh)) {
339 printf(": V-RAM map failed\n");
340 return (1);
341 }
342
343 bootinfo->fb_addr = (unsigned char *)sc->sc_ioh;
344
345 return (0);
346 }
347
348 int
349 plumvideo_ioctl(v, cmd, data, flag, p)
350 void *v;
351 u_long cmd;
352 caddr_t data;
353 int flag;
354 struct proc *p;
355 {
356 struct plumvideo_softc *sc = (struct plumvideo_softc *)v;
357 struct hpcfb_fbconf *fbconf;
358 struct hpcfb_dspconf *dspconf;
359
360 switch (cmd) {
361 case WSDISPLAYIO_GETCMAP:
362 /* XXX not implemented yet */
363 return (EINVAL);
364
365 case WSDISPLAYIO_PUTCMAP:
366 /* XXX not implemented yet */
367 return (EINVAL);
368
369 case HPCFBIO_GCONF:
370 fbconf = (struct hpcfb_fbconf *)data;
371 if (fbconf->hf_conf_index != 0 &&
372 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
373 return (EINVAL);
374 }
375 *fbconf = sc->sc_fbconf; /* structure assignment */
376 return (0);
377
378 case HPCFBIO_SCONF:
379 fbconf = (struct hpcfb_fbconf *)data;
380 if (fbconf->hf_conf_index != 0 &&
381 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
382 return (EINVAL);
383 }
384 /*
385 * nothing to do because we have only one configration
386 */
387 return (0);
388
389 case HPCFBIO_GDSPCONF:
390 dspconf = (struct hpcfb_dspconf *)data;
391 if ((dspconf->hd_unit_index != 0 &&
392 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
393 (dspconf->hd_conf_index != 0 &&
394 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
395 return (EINVAL);
396 }
397 *dspconf = sc->sc_dspconf; /* structure assignment */
398 return (0);
399
400 case HPCFBIO_SDSPCONF:
401 dspconf = (struct hpcfb_dspconf *)data;
402 if ((dspconf->hd_unit_index != 0 &&
403 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
404 (dspconf->hd_conf_index != 0 &&
405 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
406 return (EINVAL);
407 }
408 /*
409 * nothing to do
410 * because we have only one unit and one configration
411 */
412 return (0);
413
414 case HPCFBIO_GOP:
415 case HPCFBIO_SOP:
416 /* XXX not implemented yet */
417 return (EINVAL);
418 }
419
420 return (ENOTTY);
421 }
422
423 int
424 plumvideo_mmap(ctx, offset, prot)
425 void *ctx;
426 off_t offset;
427 int prot;
428 {
429 struct plumvideo_softc *sc = (struct plumvideo_softc *)ctx;
430
431 if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane +
432 sc->sc_fbconf.hf_offset) < offset) {
433 return (-1);
434 }
435
436 return (mips_btop(PLUM_VIDEO_VRAM_IOBASE_PHYSICAL + offset));
437 }
438
439 #ifdef PLUMVIDEODEBUG
440 void
441 plumvideo_dump(sc)
442 struct plumvideo_softc *sc;
443 {
444 bus_space_tag_t regt = sc->sc_regt;
445 bus_space_handle_t regh = sc->sc_regh;
446
447 plumreg_t reg;
448 int i;
449
450 for (i = 0; i < 0x160; i += 4) {
451 reg = plum_conf_read(regt, regh, i);
452 printf("0x%03x %08x", i, reg);
453 bitdisp(reg);
454 }
455 }
456 #endif /* PLUMVIDEODEBUG */
457