plumvideo.c revision 1.14 1 1.14 uch /* $NetBSD: plumvideo.c,v 1.14 2000/10/04 13:53:55 uch Exp $ */
2 1.1 uch
3 1.7 uch /*-
4 1.14 uch * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
5 1.14 uch * All rights reserved.
6 1.14 uch *
7 1.14 uch * This code is derived from software contributed to The NetBSD Foundation
8 1.14 uch * by UCHIYAMA Yasushi.
9 1.1 uch *
10 1.1 uch * Redistribution and use in source and binary forms, with or without
11 1.1 uch * modification, are permitted provided that the following conditions
12 1.1 uch * are met:
13 1.1 uch * 1. Redistributions of source code must retain the above copyright
14 1.1 uch * notice, this list of conditions and the following disclaimer.
15 1.7 uch * 2. Redistributions in binary form must reproduce the above copyright
16 1.7 uch * notice, this list of conditions and the following disclaimer in the
17 1.7 uch * documentation and/or other materials provided with the distribution.
18 1.14 uch * 3. All advertising materials mentioning features or use of this software
19 1.14 uch * must display the following acknowledgement:
20 1.14 uch * This product includes software developed by the NetBSD
21 1.14 uch * Foundation, Inc. and its contributors.
22 1.14 uch * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.14 uch * contributors may be used to endorse or promote products derived
24 1.14 uch * from this software without specific prior written permission.
25 1.1 uch *
26 1.14 uch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.14 uch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.14 uch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.14 uch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.14 uch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.14 uch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.14 uch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.14 uch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.14 uch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.14 uch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.14 uch * POSSIBILITY OF SUCH DAMAGE.
37 1.1 uch */
38 1.14 uch
39 1.11 uch #define PLUMVIDEODEBUG
40 1.1 uch #include "opt_tx39_debug.h"
41 1.14 uch #include "plumohci.h" /* Plum2 OHCI shared memory allocated on V-RAM */
42 1.1 uch
43 1.1 uch #include <sys/param.h>
44 1.1 uch #include <sys/systm.h>
45 1.1 uch #include <sys/device.h>
46 1.1 uch
47 1.8 uch #include <sys/ioctl.h>
48 1.8 uch #include <sys/buf.h>
49 1.13 mrg #include <uvm/uvm_extern.h>
50 1.8 uch
51 1.2 uch #include <dev/cons.h> /* consdev */
52 1.2 uch
53 1.1 uch #include <machine/bus.h>
54 1.1 uch #include <machine/intr.h>
55 1.14 uch #include <machine/config_hook.h>
56 1.1 uch
57 1.1 uch #include <hpcmips/tx/tx39var.h>
58 1.1 uch #include <hpcmips/dev/plumvar.h>
59 1.1 uch #include <hpcmips/dev/plumicuvar.h>
60 1.1 uch #include <hpcmips/dev/plumpowervar.h>
61 1.1 uch #include <hpcmips/dev/plumvideoreg.h>
62 1.1 uch
63 1.2 uch #include <machine/bootinfo.h>
64 1.2 uch
65 1.8 uch #include <dev/wscons/wsdisplayvar.h>
66 1.8 uch #include <dev/rasops/rasops.h>
67 1.8 uch #include <arch/hpcmips/dev/video_subr.h>
68 1.8 uch
69 1.6 sato #include <dev/wscons/wsconsio.h>
70 1.4 uch #include <arch/hpcmips/dev/hpcfbvar.h>
71 1.4 uch #include <arch/hpcmips/dev/hpcfbio.h>
72 1.1 uch
73 1.3 uch #ifdef PLUMVIDEODEBUG
74 1.3 uch int plumvideo_debug = 1;
75 1.3 uch #define DPRINTF(arg) if (plumvideo_debug) printf arg;
76 1.3 uch #define DPRINTFN(n, arg) if (plumvideo_debug > (n)) printf arg;
77 1.3 uch #else
78 1.3 uch #define DPRINTF(arg)
79 1.3 uch #define DPRINTFN(n, arg)
80 1.3 uch #endif
81 1.3 uch
82 1.1 uch struct plumvideo_softc {
83 1.7 uch struct device sc_dev;
84 1.11 uch tx_chipset_tag_t sc_tc;
85 1.11 uch plum_chipset_tag_t sc_pc;
86 1.8 uch
87 1.14 uch void *sc_powerhook; /* power management hook */
88 1.14 uch
89 1.8 uch /* control register */
90 1.7 uch bus_space_tag_t sc_regt;
91 1.7 uch bus_space_handle_t sc_regh;
92 1.8 uch /* frame buffer */
93 1.8 uch bus_space_tag_t sc_fbiot;
94 1.8 uch bus_space_handle_t sc_fbioh;
95 1.8 uch /* clut buffer (8bpp only) */
96 1.8 uch bus_space_tag_t sc_clutiot;
97 1.8 uch bus_space_handle_t sc_clutioh;
98 1.8 uch /* bitblt */
99 1.8 uch bus_space_tag_t sc_bitbltt;
100 1.8 uch bus_space_handle_t sc_bitblth;
101 1.7 uch
102 1.11 uch struct video_chip sc_chip;
103 1.8 uch struct hpcfb_fbconf sc_fbconf;
104 1.8 uch struct hpcfb_dspconf sc_dspconf;
105 1.1 uch };
106 1.1 uch
107 1.14 uch int plumvideo_match(struct device*, struct cfdata*, void*);
108 1.14 uch void plumvideo_attach(struct device*, struct device*, void*);
109 1.8 uch
110 1.14 uch int plumvideo_ioctl(void *, u_long, caddr_t, int, struct proc *);
111 1.14 uch paddr_t plumvideo_mmap(void *, off_t, int);
112 1.7 uch
113 1.1 uch struct cfattach plumvideo_ca = {
114 1.1 uch sizeof(struct plumvideo_softc), plumvideo_match, plumvideo_attach
115 1.1 uch };
116 1.1 uch
117 1.7 uch struct hpcfb_accessops plumvideo_ha = {
118 1.7 uch plumvideo_ioctl, plumvideo_mmap
119 1.1 uch };
120 1.1 uch
121 1.14 uch int plumvideo_power(void *, int, long, void *);
122 1.14 uch
123 1.14 uch int plumvideo_init(struct plumvideo_softc *, int *);
124 1.14 uch void plumvideo_hpcfbinit(struct plumvideo_softc *, int);
125 1.8 uch
126 1.14 uch void plumvideo_clut_default(struct plumvideo_softc *);
127 1.14 uch void plumvideo_clut_set(struct plumvideo_softc *, u_int32_t *, int, int);
128 1.14 uch void plumvideo_clut_get(struct plumvideo_softc *, u_int32_t *, int, int);
129 1.14 uch void __plumvideo_clut_access(struct plumvideo_softc *,
130 1.14 uch void (*)(bus_space_tag_t, bus_space_handle_t));
131 1.14 uch static void _flush_cache(void) __attribute__((__unused__)); /* !!! */
132 1.8 uch
133 1.3 uch #ifdef PLUMVIDEODEBUG
134 1.14 uch void plumvideo_dump(struct plumvideo_softc*);
135 1.3 uch #endif
136 1.1 uch
137 1.14 uch #define ON 1
138 1.14 uch #define OFF 0
139 1.14 uch
140 1.1 uch int
141 1.14 uch plumvideo_match(struct device *parent, struct cfdata *cf, void *aux)
142 1.1 uch {
143 1.2 uch /*
144 1.2 uch * VRAM area also uses as UHOSTC shared RAM.
145 1.2 uch */
146 1.8 uch return (2); /* 1st attach group */
147 1.1 uch }
148 1.1 uch
149 1.1 uch void
150 1.14 uch plumvideo_attach(struct device *parent, struct device *self, void *aux)
151 1.1 uch {
152 1.1 uch struct plum_attach_args *pa = aux;
153 1.1 uch struct plumvideo_softc *sc = (void*)self;
154 1.7 uch struct hpcfb_attach_args ha;
155 1.14 uch int console, reverse_flag;
156 1.1 uch
157 1.1 uch sc->sc_pc = pa->pa_pc;
158 1.1 uch sc->sc_regt = pa->pa_regt;
159 1.8 uch sc->sc_fbiot = sc->sc_clutiot = sc->sc_bitbltt = pa->pa_iot;
160 1.1 uch
161 1.7 uch printf(": ");
162 1.14 uch
163 1.14 uch /* map register area */
164 1.1 uch if (bus_space_map(sc->sc_regt, PLUM_VIDEO_REGBASE,
165 1.1 uch PLUM_VIDEO_REGSIZE, 0, &sc->sc_regh)) {
166 1.14 uch printf("register map failed\n");
167 1.1 uch return;
168 1.1 uch }
169 1.2 uch
170 1.14 uch /* power control */
171 1.3 uch #ifndef PLUMVIDEODEBUG
172 1.14 uch if (bootinfo->bi_cnuse & BI_CNUSE_SERIAL)
173 1.14 uch plumvideo_power(sc, 0, 0, (void *)PWR_SUSPEND);
174 1.14 uch else
175 1.3 uch #endif
176 1.14 uch plumvideo_power(sc, 0, 0, (void *)PWR_RESUME);
177 1.14 uch /* Add a hard power hook to power saving */
178 1.14 uch sc->sc_powerhook = config_hook(CONFIG_HOOK_PMEVENT,
179 1.14 uch CONFIG_HOOK_PMEVENT_HARDPOWER,
180 1.14 uch CONFIG_HOOK_SHARE,
181 1.14 uch plumvideo_power, sc);
182 1.14 uch if (sc->sc_powerhook == 0)
183 1.14 uch printf("WARNING unable to establish hard power hook");
184 1.14 uch
185 1.2 uch /*
186 1.5 uch * Initialize LCD controller
187 1.5 uch * map V-RAM area.
188 1.5 uch * reinstall bootinfo structure.
189 1.5 uch * some OHCI shared-buffer hack. XXX
190 1.2 uch */
191 1.14 uch if (plumvideo_init(sc, &reverse_flag) != 0)
192 1.5 uch return;
193 1.5 uch
194 1.5 uch printf("\n");
195 1.2 uch
196 1.11 uch /* Attach frame buffer device */
197 1.14 uch plumvideo_hpcfbinit(sc, reverse_flag);
198 1.11 uch
199 1.3 uch #ifdef PLUMVIDEODEBUG
200 1.11 uch if (plumvideo_debug > 1)
201 1.3 uch plumvideo_dump(sc);
202 1.11 uch /* attach debug draw routine (debugging use) */
203 1.11 uch video_attach_drawfunc(&sc->sc_chip);
204 1.11 uch tx_conf_register_video(sc->sc_pc->pc_tc, &sc->sc_chip);
205 1.11 uch #endif /* PLUMVIDEODEBUG */
206 1.3 uch
207 1.7 uch console = cn_tab ? 0 : 1;
208 1.7 uch if(console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
209 1.2 uch panic("plumvideo_attach: can't init fb console");
210 1.2 uch }
211 1.7 uch
212 1.7 uch ha.ha_console = console;
213 1.7 uch ha.ha_accessops = &plumvideo_ha;
214 1.7 uch ha.ha_accessctx = sc;
215 1.7 uch ha.ha_curfbconf = 0;
216 1.7 uch ha.ha_nfbconf = 1;
217 1.7 uch ha.ha_fbconflist = &sc->sc_fbconf;
218 1.7 uch ha.ha_curdspconf = 0;
219 1.7 uch ha.ha_ndspconf = 1;
220 1.7 uch ha.ha_dspconflist = &sc->sc_dspconf;
221 1.7 uch
222 1.7 uch config_found(self, &ha, hpcfbprint);
223 1.1 uch }
224 1.1 uch
225 1.7 uch void
226 1.14 uch plumvideo_hpcfbinit(struct plumvideo_softc *sc, int reverse_flag)
227 1.7 uch {
228 1.7 uch struct hpcfb_fbconf *fb = &sc->sc_fbconf;
229 1.11 uch struct video_chip *chip = &sc->sc_chip;
230 1.8 uch vaddr_t fbvaddr = (vaddr_t)sc->sc_fbioh;
231 1.11 uch int height = chip->vc_fbheight;
232 1.11 uch int width = chip->vc_fbwidth;
233 1.11 uch int depth = chip->vc_fbdepth;
234 1.7 uch
235 1.7 uch memset(fb, 0, sizeof(struct hpcfb_fbconf));
236 1.7 uch
237 1.7 uch fb->hf_conf_index = 0; /* configuration index */
238 1.7 uch fb->hf_nconfs = 1; /* how many configurations */
239 1.8 uch strncpy(fb->hf_name, "PLUM built-in video", HPCFB_MAXNAMELEN);
240 1.8 uch /* frame buffer name */
241 1.8 uch strncpy(fb->hf_conf_name, "LCD", HPCFB_MAXNAMELEN);
242 1.8 uch /* configuration name */
243 1.11 uch fb->hf_height = height;
244 1.11 uch fb->hf_width = width;
245 1.7 uch fb->hf_baseaddr = mips_ptob(mips_btop(fbvaddr));
246 1.7 uch fb->hf_offset = (u_long)fbvaddr - fb->hf_baseaddr;
247 1.8 uch /* frame buffer start offset */
248 1.11 uch fb->hf_bytes_per_line = (width * depth) / NBBY;
249 1.7 uch fb->hf_nplanes = 1;
250 1.11 uch fb->hf_bytes_per_plane = height * fb->hf_bytes_per_line;
251 1.7 uch
252 1.7 uch fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
253 1.7 uch fb->hf_access_flags |= HPCFB_ACCESS_WORD;
254 1.7 uch fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
255 1.14 uch if (reverse_flag)
256 1.14 uch fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
257 1.7 uch
258 1.11 uch switch (depth) {
259 1.7 uch default:
260 1.7 uch panic("plumvideo_hpcfbinit: not supported color depth\n");
261 1.7 uch /* NOTREACHED */
262 1.7 uch case 16:
263 1.7 uch fb->hf_class = HPCFB_CLASS_RGBCOLOR;
264 1.7 uch fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
265 1.7 uch fb->hf_pack_width = 16;
266 1.7 uch fb->hf_pixels_per_pack = 1;
267 1.7 uch fb->hf_pixel_width = 16;
268 1.7 uch
269 1.7 uch fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
270 1.8 uch /* reserved for future use */
271 1.8 uch fb->hf_u.hf_rgb.hf_flags = 0;
272 1.7 uch
273 1.7 uch fb->hf_u.hf_rgb.hf_red_width = 5;
274 1.7 uch fb->hf_u.hf_rgb.hf_red_shift = 11;
275 1.7 uch fb->hf_u.hf_rgb.hf_green_width = 6;
276 1.7 uch fb->hf_u.hf_rgb.hf_green_shift = 5;
277 1.7 uch fb->hf_u.hf_rgb.hf_blue_width = 5;
278 1.7 uch fb->hf_u.hf_rgb.hf_blue_shift = 0;
279 1.7 uch fb->hf_u.hf_rgb.hf_alpha_width = 0;
280 1.7 uch fb->hf_u.hf_rgb.hf_alpha_shift = 0;
281 1.7 uch break;
282 1.7 uch
283 1.7 uch case 8:
284 1.7 uch fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
285 1.7 uch fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
286 1.7 uch fb->hf_pack_width = 8;
287 1.7 uch fb->hf_pixels_per_pack = 1;
288 1.7 uch fb->hf_pixel_width = 8;
289 1.7 uch fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
290 1.8 uch /* reserved for future use */
291 1.8 uch fb->hf_u.hf_indexed.hf_flags = 0;
292 1.7 uch break;
293 1.7 uch }
294 1.1 uch }
295 1.1 uch
296 1.5 uch int
297 1.14 uch plumvideo_init(struct plumvideo_softc *sc, int *reverse)
298 1.1 uch {
299 1.14 uch struct {
300 1.14 uch int reverse, normal;
301 1.14 uch } ctype[] = {
302 1.14 uch { BIFB_D2_M2L_3, BIFB_D2_M2L_0 },
303 1.14 uch { BIFB_D2_M2L_3x2, BIFB_D2_M2L_0x2 },
304 1.14 uch { BIFB_D8_FF, BIFB_D8_00 },
305 1.14 uch { BIFB_D16_FFFF, BIFB_D16_0000, },
306 1.14 uch { -1, -1 } /* terminator */
307 1.14 uch }, *ctypep;
308 1.14 uch struct video_chip *chip = &sc->sc_chip;
309 1.1 uch bus_space_tag_t regt = sc->sc_regt;
310 1.1 uch bus_space_handle_t regh = sc->sc_regh;
311 1.1 uch plumreg_t reg;
312 1.5 uch size_t vram_size;
313 1.11 uch int bpp, width, height, vram_pitch;
314 1.14 uch u_int16_t fbtype;
315 1.11 uch
316 1.11 uch chip->vc_v = sc->sc_pc->pc_tc;
317 1.8 uch #if notyet
318 1.8 uch /* map BitBlt area */
319 1.8 uch if (bus_space_map(sc->sc_bitbltt,
320 1.8 uch PLUM_VIDEO_BITBLT_IOBASE,
321 1.8 uch PLUM_VIDEO_BITBLT_IOSIZE, 0,
322 1.8 uch &sc->sc_bitblth)) {
323 1.8 uch printf(": BitBlt map failed\n");
324 1.8 uch return (1);
325 1.8 uch }
326 1.8 uch #endif
327 1.1 uch reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG);
328 1.14 uch
329 1.14 uch /* check reverse color */
330 1.14 uch fbtype = bootinfo->fb_type;
331 1.14 uch for (ctypep = ctype; ctypep->normal != -1 ; ctypep++) {
332 1.14 uch if (fbtype == ctypep->normal) {
333 1.14 uch *reverse = 0;
334 1.14 uch goto fbtype_found;
335 1.14 uch } else if (fbtype == ctypep->reverse) {
336 1.14 uch *reverse = 1;
337 1.14 uch goto fbtype_found;
338 1.14 uch }
339 1.14 uch }
340 1.14 uch printf(": unknown frame buffer type 0x%04x. attach failed.\n", fbtype);
341 1.14 uch return (1);
342 1.14 uch fbtype_found:
343 1.14 uch
344 1.8 uch switch (reg & PLUM_VIDEO_PLGMD_GMODE_MASK) {
345 1.5 uch case PLUM_VIDEO_PLGMD_16BPP:
346 1.14 uch #if NPLUMOHCI > 0 /* reserve V-RAM for USB OHCI */
347 1.5 uch /* FALLTHROUGH */
348 1.14 uch #else
349 1.5 uch bpp = 16;
350 1.5 uch break;
351 1.14 uch #endif
352 1.1 uch default:
353 1.14 uch bootinfo->fb_type = *reverse ? BIFB_D8_FF : BIFB_D8_00;
354 1.8 uch reg &= ~PLUM_VIDEO_PLGMD_GMODE_MASK;
355 1.8 uch plum_conf_write(regt, regh, PLUM_VIDEO_PLGMD_REG, reg);
356 1.5 uch reg |= PLUM_VIDEO_PLGMD_8BPP;
357 1.1 uch plum_conf_write(regt, regh, PLUM_VIDEO_PLGMD_REG, reg);
358 1.8 uch #if notyet
359 1.8 uch /* change BitBlt color depth */
360 1.8 uch plum_conf_write(sc->sc_bitbltt, sc->sc_bitblth, 0x8, 0);
361 1.8 uch #endif
362 1.1 uch /* FALLTHROUGH */
363 1.1 uch case PLUM_VIDEO_PLGMD_8BPP:
364 1.5 uch bpp = 8;
365 1.5 uch break;
366 1.5 uch }
367 1.11 uch chip->vc_fbdepth = bpp;
368 1.10 uch
369 1.10 uch /*
370 1.10 uch * Get display size from WindowsCE setted.
371 1.10 uch */
372 1.11 uch chip->vc_fbwidth = width = bootinfo->fb_width =
373 1.10 uch plum_conf_read(regt, regh, PLUM_VIDEO_PLHPX_REG) + 1;
374 1.11 uch chip->vc_fbheight = height = bootinfo->fb_height =
375 1.10 uch plum_conf_read(regt, regh, PLUM_VIDEO_PLVT_REG) -
376 1.10 uch plum_conf_read(regt, regh, PLUM_VIDEO_PLVDS_REG);
377 1.5 uch
378 1.5 uch /*
379 1.5 uch * set line byte length to bootinfo and LCD controller.
380 1.5 uch */
381 1.14 uch vram_pitch = bootinfo->fb_line_bytes = (width * bpp) / NBBY;
382 1.5 uch plum_conf_write(regt, regh, PLUM_VIDEO_PLPIT1_REG, vram_pitch);
383 1.5 uch plum_conf_write(regt, regh, PLUM_VIDEO_PLPIT2_REG,
384 1.5 uch vram_pitch & PLUM_VIDEO_PLPIT2_MASK);
385 1.5 uch plum_conf_write(regt, regh, PLUM_VIDEO_PLOFS_REG, vram_pitch);
386 1.14 uch
387 1.5 uch /*
388 1.8 uch * boot messages and map CLUT(if any).
389 1.5 uch */
390 1.5 uch printf("display mode: ");
391 1.8 uch switch (bpp) {
392 1.8 uch default:
393 1.5 uch printf("disabled ");
394 1.5 uch break;
395 1.8 uch case 8:
396 1.5 uch printf("8bpp ");
397 1.8 uch /* map CLUT area */
398 1.8 uch if (bus_space_map(sc->sc_clutiot,
399 1.8 uch PLUM_VIDEO_CLUT_LCD_IOBASE,
400 1.8 uch PLUM_VIDEO_CLUT_LCD_IOSIZE, 0,
401 1.8 uch &sc->sc_clutioh)) {
402 1.8 uch printf(": CLUT map failed\n");
403 1.8 uch return (1);
404 1.8 uch }
405 1.8 uch /* install default CLUT */
406 1.8 uch plumvideo_clut_default(sc);
407 1.1 uch break;
408 1.8 uch case 16:
409 1.5 uch printf("16bpp ");
410 1.1 uch break;
411 1.1 uch }
412 1.1 uch
413 1.5 uch /*
414 1.5 uch * calcurate frame buffer size.
415 1.5 uch */
416 1.5 uch reg = plum_conf_read(regt, regh, PLUM_VIDEO_PLGMD_REG);
417 1.11 uch vram_size = (width * height * bpp) / NBBY;
418 1.5 uch vram_size = mips_round_page(vram_size);
419 1.11 uch chip->vc_fbsize = vram_size;
420 1.5 uch
421 1.5 uch /*
422 1.5 uch * map V-RAM area.
423 1.5 uch */
424 1.8 uch if (bus_space_map(sc->sc_fbiot, PLUM_VIDEO_VRAM_IOBASE,
425 1.8 uch vram_size, 0, &sc->sc_fbioh)) {
426 1.5 uch printf(": V-RAM map failed\n");
427 1.5 uch return (1);
428 1.5 uch }
429 1.5 uch
430 1.8 uch bootinfo->fb_addr = (unsigned char *)sc->sc_fbioh;
431 1.11 uch chip->vc_fbvaddr = (vaddr_t)sc->sc_fbioh;
432 1.11 uch chip->vc_fbpaddr = PLUM_VIDEO_VRAM_IOBASE_PHYSICAL;
433 1.5 uch
434 1.5 uch return (0);
435 1.7 uch }
436 1.7 uch
437 1.7 uch int
438 1.14 uch plumvideo_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
439 1.7 uch {
440 1.7 uch struct plumvideo_softc *sc = (struct plumvideo_softc *)v;
441 1.7 uch struct hpcfb_fbconf *fbconf;
442 1.7 uch struct hpcfb_dspconf *dspconf;
443 1.8 uch struct wsdisplay_cmap *cmap;
444 1.8 uch u_int8_t *r, *g, *b;
445 1.8 uch u_int32_t *rgb;
446 1.8 uch int idx, cnt, error;
447 1.7 uch
448 1.7 uch switch (cmd) {
449 1.7 uch case WSDISPLAYIO_GETCMAP:
450 1.8 uch cmap = (struct wsdisplay_cmap*)data;
451 1.8 uch cnt = cmap->count;
452 1.8 uch idx = cmap->index;
453 1.8 uch
454 1.8 uch if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
455 1.8 uch sc->sc_fbconf.hf_pack_width != 8 ||
456 1.8 uch !LEGAL_CLUT_INDEX(idx) ||
457 1.8 uch !LEGAL_CLUT_INDEX(idx + cnt -1)) {
458 1.8 uch return (EINVAL);
459 1.8 uch }
460 1.8 uch
461 1.8 uch if (!uvm_useracc(cmap->red, cnt, B_WRITE) ||
462 1.8 uch !uvm_useracc(cmap->green, cnt, B_WRITE) ||
463 1.8 uch !uvm_useracc(cmap->blue, cnt, B_WRITE)) {
464 1.8 uch return (EFAULT);
465 1.8 uch }
466 1.8 uch
467 1.8 uch error = cmap_work_alloc(&r, &g, &b, &rgb, cnt);
468 1.8 uch if (error != 0) {
469 1.8 uch cmap_work_free(r, g, b, rgb);
470 1.8 uch return (ENOMEM);
471 1.8 uch }
472 1.8 uch plumvideo_clut_get(sc, rgb, idx, cnt);
473 1.8 uch rgb24_decompose(rgb, r, g, b, cnt);
474 1.8 uch
475 1.8 uch copyout(r, cmap->red, cnt);
476 1.8 uch copyout(g, cmap->green,cnt);
477 1.8 uch copyout(b, cmap->blue, cnt);
478 1.8 uch
479 1.8 uch cmap_work_free(r, g, b, rgb);
480 1.8 uch
481 1.8 uch return (0);
482 1.7 uch
483 1.7 uch case WSDISPLAYIO_PUTCMAP:
484 1.8 uch cmap = (struct wsdisplay_cmap*)data;
485 1.8 uch cnt = cmap->count;
486 1.8 uch idx = cmap->index;
487 1.8 uch
488 1.8 uch if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
489 1.8 uch sc->sc_fbconf.hf_pack_width != 8 ||
490 1.8 uch !LEGAL_CLUT_INDEX(idx) ||
491 1.8 uch !LEGAL_CLUT_INDEX(idx + cnt -1)) {
492 1.8 uch return (EINVAL);
493 1.8 uch }
494 1.8 uch
495 1.8 uch if (!uvm_useracc(cmap->red, cnt, B_WRITE) ||
496 1.8 uch !uvm_useracc(cmap->green, cnt, B_WRITE) ||
497 1.8 uch !uvm_useracc(cmap->blue, cnt, B_WRITE)) {
498 1.8 uch return (EFAULT);
499 1.8 uch }
500 1.8 uch
501 1.8 uch error = cmap_work_alloc(&r, &g, &b, &rgb, cnt);
502 1.8 uch if (error != 0) {
503 1.8 uch cmap_work_free(r, g, b, rgb);
504 1.8 uch return (ENOMEM);
505 1.8 uch }
506 1.8 uch rgb24_compose(rgb, r, g, b, cnt);
507 1.8 uch plumvideo_clut_set(sc, rgb, idx, cnt);
508 1.8 uch
509 1.8 uch cmap_work_free(r, g, b, rgb);
510 1.8 uch
511 1.9 uch return (0);
512 1.7 uch
513 1.7 uch case HPCFBIO_GCONF:
514 1.7 uch fbconf = (struct hpcfb_fbconf *)data;
515 1.7 uch if (fbconf->hf_conf_index != 0 &&
516 1.7 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
517 1.7 uch return (EINVAL);
518 1.7 uch }
519 1.7 uch *fbconf = sc->sc_fbconf; /* structure assignment */
520 1.7 uch return (0);
521 1.7 uch
522 1.7 uch case HPCFBIO_SCONF:
523 1.7 uch fbconf = (struct hpcfb_fbconf *)data;
524 1.7 uch if (fbconf->hf_conf_index != 0 &&
525 1.7 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
526 1.7 uch return (EINVAL);
527 1.7 uch }
528 1.7 uch /*
529 1.7 uch * nothing to do because we have only one configration
530 1.7 uch */
531 1.7 uch return (0);
532 1.7 uch
533 1.7 uch case HPCFBIO_GDSPCONF:
534 1.7 uch dspconf = (struct hpcfb_dspconf *)data;
535 1.7 uch if ((dspconf->hd_unit_index != 0 &&
536 1.7 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
537 1.7 uch (dspconf->hd_conf_index != 0 &&
538 1.7 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
539 1.7 uch return (EINVAL);
540 1.7 uch }
541 1.7 uch *dspconf = sc->sc_dspconf; /* structure assignment */
542 1.7 uch return (0);
543 1.7 uch
544 1.7 uch case HPCFBIO_SDSPCONF:
545 1.7 uch dspconf = (struct hpcfb_dspconf *)data;
546 1.7 uch if ((dspconf->hd_unit_index != 0 &&
547 1.7 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
548 1.7 uch (dspconf->hd_conf_index != 0 &&
549 1.7 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
550 1.7 uch return (EINVAL);
551 1.7 uch }
552 1.7 uch /*
553 1.7 uch * nothing to do
554 1.7 uch * because we have only one unit and one configration
555 1.7 uch */
556 1.7 uch return (0);
557 1.7 uch
558 1.7 uch case HPCFBIO_GOP:
559 1.7 uch case HPCFBIO_SOP:
560 1.7 uch /* XXX not implemented yet */
561 1.7 uch return (EINVAL);
562 1.7 uch }
563 1.7 uch
564 1.7 uch return (ENOTTY);
565 1.7 uch }
566 1.7 uch
567 1.12 simonb paddr_t
568 1.14 uch plumvideo_mmap(void *ctx, off_t offset, int prot)
569 1.7 uch {
570 1.7 uch struct plumvideo_softc *sc = (struct plumvideo_softc *)ctx;
571 1.7 uch
572 1.7 uch if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane +
573 1.7 uch sc->sc_fbconf.hf_offset) < offset) {
574 1.7 uch return (-1);
575 1.7 uch }
576 1.7 uch
577 1.7 uch return (mips_btop(PLUM_VIDEO_VRAM_IOBASE_PHYSICAL + offset));
578 1.8 uch }
579 1.8 uch
580 1.8 uch void
581 1.14 uch plumvideo_clut_get(struct plumvideo_softc *sc, u_int32_t *rgb, int beg,
582 1.14 uch int cnt)
583 1.8 uch {
584 1.14 uch static void __plumvideo_clut_get(bus_space_tag_t,
585 1.14 uch bus_space_handle_t);
586 1.8 uch static void __plumvideo_clut_get(iot, ioh)
587 1.8 uch bus_space_tag_t iot;
588 1.10 uch bus_space_handle_t ioh;
589 1.8 uch {
590 1.8 uch int i;
591 1.8 uch
592 1.8 uch for (i = 0, beg *= 4; i < cnt; i++, beg += 4) {
593 1.8 uch *rgb++ = bus_space_read_4(iot, ioh, beg) &
594 1.8 uch 0x00ffffff;
595 1.8 uch }
596 1.8 uch }
597 1.8 uch
598 1.8 uch KASSERT(rgb);
599 1.8 uch KASSERT(LEGAL_CLUT_INDEX(beg));
600 1.8 uch KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1));
601 1.8 uch __plumvideo_clut_access(sc, __plumvideo_clut_get);
602 1.8 uch }
603 1.8 uch
604 1.8 uch void
605 1.14 uch plumvideo_clut_set(struct plumvideo_softc *sc, u_int32_t *rgb, int beg,
606 1.14 uch int cnt)
607 1.8 uch {
608 1.14 uch static void __plumvideo_clut_set(bus_space_tag_t,
609 1.14 uch bus_space_handle_t);
610 1.8 uch static void __plumvideo_clut_set(iot, ioh)
611 1.8 uch bus_space_tag_t iot;
612 1.10 uch bus_space_handle_t ioh;
613 1.8 uch {
614 1.8 uch int i;
615 1.8 uch
616 1.8 uch for (i = 0, beg *= 4; i < cnt; i++, beg +=4) {
617 1.8 uch bus_space_write_4(iot, ioh, beg,
618 1.8 uch *rgb++ & 0x00ffffff);
619 1.8 uch }
620 1.8 uch }
621 1.8 uch
622 1.8 uch KASSERT(rgb);
623 1.8 uch KASSERT(LEGAL_CLUT_INDEX(beg));
624 1.8 uch KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1));
625 1.8 uch __plumvideo_clut_access(sc, __plumvideo_clut_set);
626 1.8 uch }
627 1.8 uch
628 1.8 uch void
629 1.14 uch plumvideo_clut_default(struct plumvideo_softc *sc)
630 1.8 uch {
631 1.14 uch static void __plumvideo_clut_default(bus_space_tag_t,
632 1.14 uch bus_space_handle_t);
633 1.8 uch static void __plumvideo_clut_default(iot, ioh)
634 1.8 uch bus_space_tag_t iot;
635 1.10 uch bus_space_handle_t ioh;
636 1.8 uch {
637 1.8 uch const u_int8_t compo6[6] = { 0, 51, 102, 153, 204, 255 };
638 1.8 uch const u_int32_t ansi_color[16] = {
639 1.8 uch 0x000000, 0xff0000, 0x00ff00, 0xffff00,
640 1.8 uch 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff,
641 1.8 uch 0x000000, 0x800000, 0x008000, 0x808000,
642 1.8 uch 0x000080, 0x800080, 0x008080, 0x808080,
643 1.8 uch };
644 1.8 uch int i, r, g, b;
645 1.8 uch
646 1.8 uch /* ANSI escape sequence */
647 1.8 uch for (i = 0; i < 16; i++) {
648 1.8 uch bus_space_write_4(iot, ioh, i << 2, ansi_color[i]);
649 1.8 uch }
650 1.8 uch /* 16 - 31, gray scale */
651 1.8 uch for ( ; i < 32; i++) {
652 1.8 uch int j = (i - 16) * 17;
653 1.8 uch bus_space_write_4(iot, ioh, i << 2, RGB24(j, j, j));
654 1.8 uch }
655 1.8 uch /* 32 - 247, RGB color */
656 1.8 uch for (r = 0; r < 6; r++) {
657 1.8 uch for (g = 0; g < 6; g++) {
658 1.8 uch for (b = 0; b < 6; b++) {
659 1.8 uch bus_space_write_4(iot, ioh, i << 2,
660 1.8 uch RGB24(compo6[r],
661 1.8 uch compo6[g],
662 1.8 uch compo6[b]));
663 1.8 uch i++;
664 1.8 uch }
665 1.8 uch }
666 1.8 uch }
667 1.8 uch /* 248 - 245, just white */
668 1.8 uch for ( ; i < 256; i++) {
669 1.8 uch bus_space_write_4(iot, ioh, i << 2, 0xffffff);
670 1.8 uch }
671 1.8 uch }
672 1.8 uch
673 1.8 uch __plumvideo_clut_access(sc, __plumvideo_clut_default);
674 1.8 uch }
675 1.8 uch
676 1.8 uch void
677 1.14 uch __plumvideo_clut_access(struct plumvideo_softc *sc, void (*palette_func)
678 1.14 uch (bus_space_tag_t, bus_space_handle_t))
679 1.8 uch {
680 1.8 uch bus_space_tag_t regt = sc->sc_regt;
681 1.8 uch bus_space_handle_t regh = sc->sc_regh;
682 1.8 uch plumreg_t val, gmode;
683 1.8 uch
684 1.8 uch /* display off */
685 1.8 uch val = bus_space_read_4(regt, regh, PLUM_VIDEO_PLGMD_REG);
686 1.8 uch gmode = val & PLUM_VIDEO_PLGMD_GMODE_MASK;
687 1.8 uch val &= ~PLUM_VIDEO_PLGMD_GMODE_MASK;
688 1.8 uch bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
689 1.8 uch
690 1.8 uch /* palette access disable */
691 1.8 uch val &= ~PLUM_VIDEO_PLGMD_PALETTE_ENABLE;
692 1.8 uch bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
693 1.8 uch
694 1.8 uch /* change palette mode to CPU */
695 1.8 uch val &= ~PLUM_VIDEO_PLGMD_MODE_DISPLAY;
696 1.8 uch bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
697 1.8 uch
698 1.8 uch /* palette access */
699 1.8 uch (*palette_func) (sc->sc_clutiot, sc->sc_clutioh);
700 1.8 uch
701 1.8 uch /* change palette mode to Display */
702 1.8 uch val |= PLUM_VIDEO_PLGMD_MODE_DISPLAY;
703 1.8 uch bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
704 1.9 uch
705 1.8 uch /* palette access enable */
706 1.8 uch val |= PLUM_VIDEO_PLGMD_PALETTE_ENABLE;
707 1.8 uch bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
708 1.8 uch
709 1.8 uch /* display on */
710 1.8 uch val |= gmode;
711 1.8 uch bus_space_write_4(regt, regh, PLUM_VIDEO_PLGMD_REG, val);
712 1.8 uch }
713 1.8 uch
714 1.8 uch /* !!! */
715 1.8 uch static void
716 1.8 uch _flush_cache()
717 1.8 uch {
718 1.8 uch MachFlushCache();
719 1.1 uch }
720 1.1 uch
721 1.14 uch int
722 1.14 uch plumvideo_power(void *ctx, int type, long id, void *msg)
723 1.14 uch {
724 1.14 uch struct plumvideo_softc *sc = ctx;
725 1.14 uch plum_chipset_tag_t pc = sc->sc_pc;
726 1.14 uch bus_space_tag_t regt = sc->sc_regt;
727 1.14 uch bus_space_handle_t regh = sc->sc_regh;
728 1.14 uch int why = (int)msg;
729 1.14 uch
730 1.14 uch switch (why) {
731 1.14 uch case PWR_RESUME:
732 1.14 uch DPRINTF(("%s: ON\n", sc->sc_dev.dv_xname));
733 1.14 uch /* power on */
734 1.14 uch /* LCD power on and display on */
735 1.14 uch plum_power_establish(pc, PLUM_PWR_LCD);
736 1.14 uch /* back-light on */
737 1.14 uch plum_power_establish(pc, PLUM_PWR_BKL);
738 1.14 uch plum_conf_write(regt, regh, PLUM_VIDEO_PLLUM_REG,
739 1.14 uch PLUM_VIDEO_PLLUM_MAX);
740 1.14 uch break;
741 1.14 uch case PWR_SUSPEND:
742 1.14 uch /* FALLTHROUGH */
743 1.14 uch case PWR_STANDBY:
744 1.14 uch DPRINTF(("%s: OFF\n", sc->sc_dev.dv_xname));
745 1.14 uch /* back-light off */
746 1.14 uch plum_conf_write(regt, regh, PLUM_VIDEO_PLLUM_REG,
747 1.14 uch PLUM_VIDEO_PLLUM_MIN);
748 1.14 uch plum_power_disestablish(pc, PLUM_PWR_BKL);
749 1.14 uch /* power down */
750 1.14 uch plum_power_disestablish(pc, PLUM_PWR_LCD);
751 1.14 uch break;
752 1.14 uch }
753 1.14 uch
754 1.14 uch return 0;
755 1.14 uch }
756 1.14 uch
757 1.3 uch #ifdef PLUMVIDEODEBUG
758 1.1 uch void
759 1.14 uch plumvideo_dump(struct plumvideo_softc *sc)
760 1.1 uch {
761 1.1 uch bus_space_tag_t regt = sc->sc_regt;
762 1.1 uch bus_space_handle_t regh = sc->sc_regh;
763 1.1 uch
764 1.1 uch plumreg_t reg;
765 1.3 uch int i;
766 1.1 uch
767 1.5 uch for (i = 0; i < 0x160; i += 4) {
768 1.1 uch reg = plum_conf_read(regt, regh, i);
769 1.3 uch printf("0x%03x %08x", i, reg);
770 1.1 uch bitdisp(reg);
771 1.1 uch }
772 1.1 uch }
773 1.3 uch #endif /* PLUMVIDEODEBUG */
774