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