mq200.c revision 1.20 1 1.20 takemura /* $NetBSD: mq200.c,v 1.20 2002/04/14 06:07:41 takemura Exp $ */
2 1.1 takemura
3 1.1 takemura /*-
4 1.13 takemura * Copyright (c) 2000, 2001 TAKEMURA Shin
5 1.1 takemura * All rights reserved.
6 1.1 takemura *
7 1.1 takemura * Redistribution and use in source and binary forms, with or without
8 1.1 takemura * modification, are permitted provided that the following conditions
9 1.1 takemura * are met:
10 1.1 takemura * 1. Redistributions of source code must retain the above copyright
11 1.1 takemura * notice, this list of conditions and the following disclaimer.
12 1.1 takemura * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 takemura * notice, this list of conditions and the following disclaimer in the
14 1.1 takemura * documentation and/or other materials provided with the distribution.
15 1.1 takemura * 3. The name of the author may not be used to endorse or promote products
16 1.1 takemura * derived from this software without specific prior written permission.
17 1.1 takemura *
18 1.1 takemura * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 1.1 takemura * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 1.1 takemura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 1.1 takemura * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 1.1 takemura * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 1.1 takemura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 1.1 takemura * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 1.1 takemura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 1.1 takemura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 1.1 takemura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 1.1 takemura * SUCH DAMAGE.
29 1.1 takemura *
30 1.1 takemura */
31 1.1 takemura
32 1.1 takemura #include <sys/param.h>
33 1.1 takemura #include <sys/kernel.h>
34 1.1 takemura #include <sys/device.h>
35 1.1 takemura #include <sys/systm.h>
36 1.2 sato #include <sys/reboot.h>
37 1.1 takemura
38 1.1 takemura #include <uvm/uvm_extern.h>
39 1.1 takemura
40 1.1 takemura #include <dev/wscons/wsconsio.h>
41 1.1 takemura
42 1.1 takemura #include <machine/bootinfo.h>
43 1.1 takemura #include <machine/bus.h>
44 1.1 takemura #include <machine/autoconf.h>
45 1.1 takemura #include <machine/config_hook.h>
46 1.1 takemura #include <machine/platid.h>
47 1.1 takemura #include <machine/platid_mask.h>
48 1.1 takemura
49 1.13 takemura #include "opt_mq200.h"
50 1.1 takemura #include <hpcmips/dev/mq200reg.h>
51 1.1 takemura #include <hpcmips/dev/mq200var.h>
52 1.13 takemura #include <hpcmips/dev/mq200priv.h>
53 1.13 takemura
54 1.2 sato #include "bivideo.h"
55 1.2 sato #if NBIVIDEO > 0
56 1.9 uch #include <dev/hpc/bivideovar.h>
57 1.2 sato #endif
58 1.1 takemura
59 1.1 takemura /*
60 1.1 takemura * function prototypes
61 1.1 takemura */
62 1.18 uch static void mq200_power(int, void *);
63 1.18 uch static int mq200_hardpower(void *, int, long, void *);
64 1.18 uch static int mq200_fbinit(struct hpcfb_fbconf *);
65 1.18 uch static int mq200_ioctl(void *, u_long, caddr_t, int, struct proc *);
66 1.18 uch static paddr_t mq200_mmap(void *, off_t offset, int);
67 1.18 uch static void mq200_update_powerstate(struct mq200_softc *, int);
68 1.18 uch void mq200_init_backlight(struct mq200_softc *, int);
69 1.18 uch void mq200_init_brightness(struct mq200_softc *, int);
70 1.18 uch void mq200_init_contrast(struct mq200_softc *, int);
71 1.18 uch void mq200_set_brightness(struct mq200_softc *, int);
72 1.18 uch void mq200_set_contrast(struct mq200_softc *, int);
73 1.1 takemura
74 1.1 takemura /*
75 1.1 takemura * static variables
76 1.1 takemura */
77 1.1 takemura struct hpcfb_accessops mq200_ha = {
78 1.1 takemura mq200_ioctl, mq200_mmap
79 1.1 takemura };
80 1.1 takemura
81 1.13 takemura #ifdef MQ200_DEBUG
82 1.13 takemura int mq200_debug = MQ200DEBUG_CONF;
83 1.13 takemura #endif
84 1.13 takemura
85 1.1 takemura int
86 1.18 uch mq200_probe(bus_space_tag_t iot, bus_space_handle_t ioh)
87 1.1 takemura {
88 1.1 takemura unsigned long regval;
89 1.1 takemura
90 1.2 sato #if NBIVIDEO > 0
91 1.2 sato if (bivideo_dont_attach) /* some video driver already attached */
92 1.2 sato return (0);
93 1.2 sato #endif /* NBIVIDEO > 0 */
94 1.2 sato
95 1.1 takemura regval = bus_space_read_4(iot, ioh, MQ200_PC00R);
96 1.13 takemura VPRINTF("probe: vendor id=%04lx product id=%04lx\n",
97 1.18 uch regval & 0xffff, (regval >> 16) & 0xffff);
98 1.1 takemura if (regval != ((MQ200_PRODUCT_ID << 16) | MQ200_VENDOR_ID))
99 1.1 takemura return (0);
100 1.1 takemura
101 1.1 takemura return (1);
102 1.1 takemura }
103 1.1 takemura
104 1.1 takemura void
105 1.18 uch mq200_attach(struct mq200_softc *sc)
106 1.1 takemura {
107 1.1 takemura unsigned long regval;
108 1.1 takemura struct hpcfb_attach_args ha;
109 1.1 takemura int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
110 1.1 takemura
111 1.8 sato printf(": ");
112 1.8 sato if (mq200_fbinit(&sc->sc_fbconf) != 0) {
113 1.8 sato /* just return so that hpcfb will not be attached */
114 1.8 sato return;
115 1.8 sato }
116 1.8 sato
117 1.8 sato sc->sc_fbconf.hf_baseaddr = (u_long)bootinfo->fb_addr;
118 1.8 sato sc->sc_fbconf.hf_offset = (u_long)sc->sc_fbconf.hf_baseaddr -
119 1.8 sato MIPS_PHYS_TO_KSEG1(mips_ptob(mips_btop(sc->sc_baseaddr)));
120 1.13 takemura DPRINTF("hf_baseaddr=%lx\n", sc->sc_fbconf.hf_baseaddr);
121 1.13 takemura DPRINTF("hf_offset=%lx\n", sc->sc_fbconf.hf_offset);
122 1.8 sato
123 1.13 takemura regval = mq200_read(sc, MQ200_PC08R);
124 1.8 sato printf("MQ200 Rev.%02lx video controller", regval & 0xff);
125 1.8 sato if (console) {
126 1.8 sato printf(", console");
127 1.8 sato }
128 1.8 sato printf("\n");
129 1.8 sato printf("%s: framebuffer address: 0x%08lx\n",
130 1.18 uch sc->sc_dev.dv_xname, (u_long)bootinfo->fb_addr);
131 1.13 takemura
132 1.13 takemura /*
133 1.13 takemura * setup registers
134 1.13 takemura */
135 1.13 takemura sc->sc_flags = 0;
136 1.13 takemura sc->sc_baseclock = 12288; /* 12.288 MHz */
137 1.13 takemura #ifdef MQ200_DEBUG
138 1.13 takemura if (bootverbose) {
139 1.13 takemura /* dump current setting */
140 1.13 takemura mq200_dump_all(sc);
141 1.13 takemura mq200_dump_pll(sc);
142 1.13 takemura }
143 1.13 takemura #endif
144 1.13 takemura mq200_setup_regctx(sc);
145 1.13 takemura mq200_mdsetup(sc);
146 1.13 takemura if (sc->sc_md) {
147 1.20 takemura int mode;
148 1.20 takemura
149 1.20 takemura switch (sc->sc_fbconf.hf_pixel_width) {
150 1.20 takemura case 1: mode = MQ200_GCC_1BPP; break;
151 1.20 takemura case 2: mode = MQ200_GCC_2BPP; break;
152 1.20 takemura case 4: mode = MQ200_GCC_4BPP; break;
153 1.20 takemura case 8: mode = MQ200_GCC_8BPP; break;
154 1.20 takemura case 16: mode = MQ200_GCC_16BPP_DIRECT; break;
155 1.20 takemura default:
156 1.20 takemura printf("%s: %dbpp isn't supported\n",
157 1.20 takemura sc->sc_dev.dv_xname, sc->sc_fbconf.hf_pixel_width);
158 1.20 takemura return;
159 1.20 takemura }
160 1.20 takemura
161 1.13 takemura if (sc->sc_md->md_flags & MQ200_MD_HAVEFP) {
162 1.13 takemura sc->sc_flags |= MQ200_SC_GC2_ENABLE; /* FP */
163 1.13 takemura }
164 1.13 takemura #if MQ200_USECRT
165 1.13 takemura if (sc->sc_md->md_flags & MQ200_MD_HAVECRT) {
166 1.13 takemura int i;
167 1.13 takemura sc->sc_flags |= MQ200_SC_GC1_ENABLE; /* CRT */
168 1.13 takemura for (i = 0; i < mq200_crt_nparams; i++) {
169 1.13 takemura sc->sc_crt = &mq200_crt_params[i];
170 1.13 takemura if (sc->sc_md->md_fp_width <=
171 1.13 takemura mq200_crt_params[i].width &&
172 1.13 takemura sc->sc_md->md_fp_height <=
173 1.13 takemura mq200_crt_params[i].height)
174 1.13 takemura break;
175 1.13 takemura }
176 1.13 takemura }
177 1.13 takemura #endif
178 1.13 takemura mq200_setup(sc);
179 1.13 takemura
180 1.13 takemura if (sc->sc_flags & MQ200_SC_GC2_ENABLE) /* FP */
181 1.20 takemura mq200_win_enable(sc, MQ200_GC2, mode,
182 1.20 takemura sc->sc_fbconf.hf_baseaddr,
183 1.20 takemura sc->sc_fbconf.hf_width, sc->sc_fbconf.hf_height,
184 1.20 takemura sc->sc_fbconf.hf_bytes_per_plane);
185 1.13 takemura if (sc->sc_flags & MQ200_SC_GC1_ENABLE) /* CRT */
186 1.20 takemura mq200_win_enable(sc, MQ200_GC1, mode,
187 1.20 takemura sc->sc_fbconf.hf_baseaddr,
188 1.20 takemura sc->sc_fbconf.hf_width, sc->sc_fbconf.hf_height,
189 1.20 takemura sc->sc_fbconf.hf_bytes_per_plane);
190 1.13 takemura }
191 1.13 takemura #ifdef MQ200_DEBUG
192 1.13 takemura if (sc->sc_md == NULL || bootverbose) {
193 1.13 takemura mq200_dump_pll(sc);
194 1.13 takemura }
195 1.13 takemura #endif
196 1.8 sato
197 1.1 takemura /* Add a power hook to power saving */
198 1.10 sato sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
199 1.1 takemura sc->sc_powerhook = powerhook_establish(mq200_power, sc);
200 1.1 takemura if (sc->sc_powerhook == NULL)
201 1.1 takemura printf("%s: WARNING: unable to establish power hook\n",
202 1.18 uch sc->sc_dev.dv_xname);
203 1.1 takemura
204 1.1 takemura /* Add a hard power hook to power saving */
205 1.1 takemura sc->sc_hardpowerhook = config_hook(CONFIG_HOOK_PMEVENT,
206 1.18 uch CONFIG_HOOK_PMEVENT_HARDPOWER,
207 1.18 uch CONFIG_HOOK_SHARE,
208 1.18 uch mq200_hardpower, sc);
209 1.1 takemura if (sc->sc_hardpowerhook == NULL)
210 1.1 takemura printf("%s: WARNING: unable to establish hard power hook\n",
211 1.18 uch sc->sc_dev.dv_xname);
212 1.1 takemura
213 1.10 sato /* initialize backlight brightness and lcd contrast */
214 1.14 sato sc->sc_lcd_inited = 0;
215 1.14 sato mq200_init_brightness(sc, 1);
216 1.14 sato mq200_init_contrast(sc, 1);
217 1.14 sato mq200_init_backlight(sc, 1);
218 1.10 sato
219 1.1 takemura if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
220 1.1 takemura panic("mq200_attach: can't init fb console");
221 1.1 takemura }
222 1.1 takemura
223 1.1 takemura ha.ha_console = console;
224 1.1 takemura ha.ha_accessops = &mq200_ha;
225 1.1 takemura ha.ha_accessctx = sc;
226 1.1 takemura ha.ha_curfbconf = 0;
227 1.1 takemura ha.ha_nfbconf = 1;
228 1.1 takemura ha.ha_fbconflist = &sc->sc_fbconf;
229 1.1 takemura ha.ha_curdspconf = 0;
230 1.1 takemura ha.ha_ndspconf = 1;
231 1.1 takemura ha.ha_dspconflist = &sc->sc_dspconf;
232 1.1 takemura
233 1.1 takemura config_found(&sc->sc_dev, &ha, hpcfbprint);
234 1.1 takemura
235 1.2 sato #if NBIVIDEO > 0
236 1.1 takemura /*
237 1.1 takemura * bivideo is no longer need
238 1.1 takemura */
239 1.1 takemura bivideo_dont_attach = 1;
240 1.2 sato #endif /* NBIVIDEO > 0 */
241 1.1 takemura }
242 1.1 takemura
243 1.10 sato static void
244 1.18 uch mq200_update_powerstate(struct mq200_softc *sc, int updates)
245 1.10 sato {
246 1.12 sato
247 1.10 sato if (updates & PWRSTAT_LCD)
248 1.10 sato config_hook_call(CONFIG_HOOK_POWERCONTROL,
249 1.10 sato CONFIG_HOOK_POWERCONTROL_LCD,
250 1.11 sato (void*)!(sc->sc_powerstate &
251 1.18 uch (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)));
252 1.10 sato
253 1.10 sato if (updates & PWRSTAT_BACKLIGHT)
254 1.10 sato config_hook_call(CONFIG_HOOK_POWERCONTROL,
255 1.10 sato CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
256 1.11 sato (void*)(!(sc->sc_powerstate &
257 1.18 uch (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) &&
258 1.18 uch (sc->sc_powerstate & PWRSTAT_BACKLIGHT)));
259 1.10 sato }
260 1.10 sato
261 1.1 takemura static void
262 1.18 uch mq200_power(int why, void *arg)
263 1.1 takemura {
264 1.1 takemura struct mq200_softc *sc = arg;
265 1.1 takemura
266 1.1 takemura switch (why) {
267 1.1 takemura case PWR_SUSPEND:
268 1.10 sato sc->sc_powerstate |= PWRSTAT_SUSPEND;
269 1.10 sato mq200_update_powerstate(sc, PWRSTAT_ALL);
270 1.1 takemura break;
271 1.1 takemura case PWR_STANDBY:
272 1.10 sato sc->sc_powerstate |= PWRSTAT_SUSPEND;
273 1.10 sato mq200_update_powerstate(sc, PWRSTAT_ALL);
274 1.1 takemura break;
275 1.1 takemura case PWR_RESUME:
276 1.10 sato sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
277 1.10 sato mq200_update_powerstate(sc, PWRSTAT_ALL);
278 1.1 takemura break;
279 1.1 takemura }
280 1.1 takemura }
281 1.1 takemura
282 1.1 takemura static int
283 1.18 uch mq200_hardpower(void *ctx, int type, long id, void *msg)
284 1.1 takemura {
285 1.1 takemura struct mq200_softc *sc = ctx;
286 1.1 takemura int why = (int)msg;
287 1.1 takemura
288 1.1 takemura switch (why) {
289 1.1 takemura case PWR_SUSPEND:
290 1.10 sato sc->sc_mq200pwstate = MQ200_POWERSTATE_D2;
291 1.1 takemura break;
292 1.1 takemura case PWR_STANDBY:
293 1.10 sato sc->sc_mq200pwstate = MQ200_POWERSTATE_D3;
294 1.1 takemura break;
295 1.1 takemura case PWR_RESUME:
296 1.10 sato sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
297 1.1 takemura break;
298 1.1 takemura }
299 1.1 takemura
300 1.1 takemura bus_space_write_4(sc->sc_iot, sc->sc_ioh,
301 1.18 uch MQ200_PMCSR, sc->sc_mq200pwstate);
302 1.1 takemura
303 1.1 takemura /*
304 1.1 takemura * you should wait until the
305 1.1 takemura * power state transit sequence will end.
306 1.1 takemura */
307 1.1 takemura {
308 1.1 takemura unsigned long tmp;
309 1.1 takemura do {
310 1.1 takemura tmp = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
311 1.18 uch MQ200_PMCSR);
312 1.10 sato } while ((tmp & 0x3) != (sc->sc_mq200pwstate & 0x3));
313 1.1 takemura delay(100000); /* XXX */
314 1.1 takemura }
315 1.1 takemura
316 1.1 takemura return (0);
317 1.1 takemura }
318 1.1 takemura
319 1.1 takemura
320 1.1 takemura static int
321 1.18 uch mq200_fbinit(struct hpcfb_fbconf *fb)
322 1.1 takemura {
323 1.1 takemura
324 1.1 takemura /*
325 1.1 takemura * get fb settings from bootinfo
326 1.1 takemura */
327 1.1 takemura if (bootinfo == NULL ||
328 1.1 takemura bootinfo->fb_addr == 0 ||
329 1.1 takemura bootinfo->fb_line_bytes == 0 ||
330 1.1 takemura bootinfo->fb_width == 0 ||
331 1.1 takemura bootinfo->fb_height == 0) {
332 1.16 toshii printf("no frame buffer information.\n");
333 1.1 takemura return (-1);
334 1.1 takemura }
335 1.1 takemura
336 1.1 takemura /* zero fill */
337 1.1 takemura bzero(fb, sizeof(*fb));
338 1.1 takemura
339 1.1 takemura fb->hf_conf_index = 0; /* configuration index */
340 1.1 takemura fb->hf_nconfs = 1; /* how many configurations */
341 1.1 takemura strcpy(fb->hf_name, "built-in video");
342 1.1 takemura /* frame buffer name */
343 1.1 takemura strcpy(fb->hf_conf_name, "default");
344 1.1 takemura /* configuration name */
345 1.1 takemura fb->hf_height = bootinfo->fb_height;
346 1.1 takemura fb->hf_width = bootinfo->fb_width;
347 1.1 takemura fb->hf_baseaddr = mips_ptob(mips_btop(bootinfo->fb_addr));
348 1.1 takemura fb->hf_offset = (u_long)bootinfo->fb_addr - fb->hf_baseaddr;
349 1.1 takemura /* frame buffer start offset */
350 1.1 takemura fb->hf_bytes_per_line = bootinfo->fb_line_bytes;
351 1.1 takemura fb->hf_nplanes = 1;
352 1.1 takemura fb->hf_bytes_per_plane = bootinfo->fb_height *
353 1.18 uch bootinfo->fb_line_bytes;
354 1.1 takemura
355 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
356 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_WORD;
357 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
358 1.1 takemura
359 1.1 takemura switch (bootinfo->fb_type) {
360 1.20 takemura /*
361 1.20 takemura * monochrome
362 1.20 takemura */
363 1.20 takemura case BIFB_D1_M2L_1:
364 1.20 takemura fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
365 1.20 takemura /* fall through */
366 1.20 takemura case BIFB_D1_M2L_0:
367 1.20 takemura fb->hf_class = HPCFB_CLASS_GRAYSCALE;
368 1.20 takemura fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
369 1.20 takemura fb->hf_pack_width = 8;
370 1.20 takemura fb->hf_pixels_per_pack = 8;
371 1.20 takemura fb->hf_pixel_width = 1;
372 1.20 takemura fb->hf_class_data_length = sizeof(struct hf_gray_tag);
373 1.20 takemura fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
374 1.20 takemura break;
375 1.20 takemura
376 1.1 takemura /*
377 1.1 takemura * gray scale
378 1.1 takemura */
379 1.1 takemura case BIFB_D2_M2L_3:
380 1.1 takemura case BIFB_D2_M2L_3x2:
381 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
382 1.1 takemura /* fall through */
383 1.1 takemura case BIFB_D2_M2L_0:
384 1.1 takemura case BIFB_D2_M2L_0x2:
385 1.1 takemura fb->hf_class = HPCFB_CLASS_GRAYSCALE;
386 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
387 1.1 takemura fb->hf_pack_width = 8;
388 1.1 takemura fb->hf_pixels_per_pack = 4;
389 1.1 takemura fb->hf_pixel_width = 2;
390 1.7 takemura fb->hf_class_data_length = sizeof(struct hf_gray_tag);
391 1.7 takemura fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
392 1.7 takemura break;
393 1.7 takemura
394 1.7 takemura case BIFB_D4_M2L_F:
395 1.7 takemura case BIFB_D4_M2L_Fx2:
396 1.7 takemura fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
397 1.7 takemura /* fall through */
398 1.7 takemura case BIFB_D4_M2L_0:
399 1.7 takemura case BIFB_D4_M2L_0x2:
400 1.7 takemura fb->hf_class = HPCFB_CLASS_GRAYSCALE;
401 1.7 takemura fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
402 1.7 takemura fb->hf_pack_width = 8;
403 1.7 takemura fb->hf_pixels_per_pack = 2;
404 1.7 takemura fb->hf_pixel_width = 4;
405 1.1 takemura fb->hf_class_data_length = sizeof(struct hf_gray_tag);
406 1.1 takemura fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
407 1.1 takemura break;
408 1.1 takemura
409 1.1 takemura /*
410 1.1 takemura * indexed color
411 1.1 takemura */
412 1.1 takemura case BIFB_D8_FF:
413 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
414 1.1 takemura /* fall through */
415 1.1 takemura case BIFB_D8_00:
416 1.1 takemura fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
417 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
418 1.1 takemura fb->hf_pack_width = 8;
419 1.1 takemura fb->hf_pixels_per_pack = 1;
420 1.1 takemura fb->hf_pixel_width = 8;
421 1.1 takemura fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
422 1.1 takemura fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
423 1.1 takemura break;
424 1.1 takemura
425 1.1 takemura /*
426 1.1 takemura * RGB color
427 1.1 takemura */
428 1.1 takemura case BIFB_D16_FFFF:
429 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
430 1.1 takemura /* fall through */
431 1.1 takemura case BIFB_D16_0000:
432 1.1 takemura fb->hf_class = HPCFB_CLASS_RGBCOLOR;
433 1.1 takemura fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
434 1.17 takemura fb->hf_order_flags = HPCFB_REVORDER_BYTE;
435 1.1 takemura fb->hf_pack_width = 16;
436 1.1 takemura fb->hf_pixels_per_pack = 1;
437 1.1 takemura fb->hf_pixel_width = 16;
438 1.1 takemura
439 1.1 takemura fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
440 1.1 takemura fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */
441 1.1 takemura
442 1.1 takemura fb->hf_u.hf_rgb.hf_red_width = 5;
443 1.1 takemura fb->hf_u.hf_rgb.hf_red_shift = 11;
444 1.1 takemura fb->hf_u.hf_rgb.hf_green_width = 6;
445 1.1 takemura fb->hf_u.hf_rgb.hf_green_shift = 5;
446 1.1 takemura fb->hf_u.hf_rgb.hf_blue_width = 5;
447 1.1 takemura fb->hf_u.hf_rgb.hf_blue_shift = 0;
448 1.1 takemura fb->hf_u.hf_rgb.hf_alpha_width = 0;
449 1.1 takemura fb->hf_u.hf_rgb.hf_alpha_shift = 0;
450 1.1 takemura break;
451 1.1 takemura
452 1.1 takemura default:
453 1.1 takemura printf("unknown type (=%d).\n", bootinfo->fb_type);
454 1.1 takemura return (-1);
455 1.1 takemura break;
456 1.1 takemura }
457 1.1 takemura
458 1.1 takemura return (0); /* no error */
459 1.1 takemura }
460 1.1 takemura
461 1.1 takemura int
462 1.1 takemura mq200_ioctl(v, cmd, data, flag, p)
463 1.1 takemura void *v;
464 1.1 takemura u_long cmd;
465 1.1 takemura caddr_t data;
466 1.1 takemura int flag;
467 1.1 takemura struct proc *p;
468 1.1 takemura {
469 1.1 takemura struct mq200_softc *sc = (struct mq200_softc *)v;
470 1.1 takemura struct hpcfb_fbconf *fbconf;
471 1.1 takemura struct hpcfb_dspconf *dspconf;
472 1.1 takemura struct wsdisplay_cmap *cmap;
473 1.6 sato struct wsdisplay_param *dispparam;
474 1.1 takemura
475 1.1 takemura switch (cmd) {
476 1.1 takemura case WSDISPLAYIO_GETCMAP:
477 1.1 takemura cmap = (struct wsdisplay_cmap*)data;
478 1.1 takemura
479 1.1 takemura if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
480 1.1 takemura sc->sc_fbconf.hf_pack_width != 8 ||
481 1.1 takemura 256 <= cmap->index ||
482 1.1 takemura 256 < (cmap->index + cmap->count))
483 1.1 takemura return (EINVAL);
484 1.1 takemura
485 1.1 takemura #if 0
486 1.1 takemura if (!uvm_useracc(cmap->red, cmap->count, B_WRITE) ||
487 1.1 takemura !uvm_useracc(cmap->green, cmap->count, B_WRITE) ||
488 1.1 takemura !uvm_useracc(cmap->blue, cmap->count, B_WRITE))
489 1.1 takemura return (EFAULT);
490 1.1 takemura
491 1.1 takemura copyout(&bivideo_cmap_r[cmap->index], cmap->red, cmap->count);
492 1.1 takemura copyout(&bivideo_cmap_g[cmap->index], cmap->green,cmap->count);
493 1.1 takemura copyout(&bivideo_cmap_b[cmap->index], cmap->blue, cmap->count);
494 1.1 takemura #endif
495 1.1 takemura
496 1.1 takemura return (0);
497 1.1 takemura
498 1.1 takemura case WSDISPLAYIO_PUTCMAP:
499 1.1 takemura /*
500 1.1 takemura * This driver can't set color map.
501 1.1 takemura */
502 1.1 takemura return (EINVAL);
503 1.11 sato
504 1.11 sato case WSDISPLAYIO_SVIDEO:
505 1.11 sato if (*(int *)data == WSDISPLAYIO_VIDEO_OFF)
506 1.11 sato sc->sc_powerstate |= PWRSTAT_VIDEOOFF;
507 1.11 sato else
508 1.11 sato sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF;
509 1.11 sato mq200_update_powerstate(sc, PWRSTAT_ALL);
510 1.11 sato return 0;
511 1.11 sato
512 1.11 sato case WSDISPLAYIO_GVIDEO:
513 1.11 sato *(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ?
514 1.18 uch WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON;
515 1.11 sato return 0;
516 1.6 sato
517 1.6 sato case WSDISPLAYIO_GETPARAM:
518 1.6 sato dispparam = (struct wsdisplay_param*)data;
519 1.6 sato switch (dispparam->param) {
520 1.6 sato case WSDISPLAYIO_PARAM_BACKLIGHT:
521 1.14 sato VPRINTF("ioctl: GET:BACKLIGHT\n");
522 1.14 sato mq200_init_brightness(sc, 0);
523 1.14 sato mq200_init_backlight(sc, 0);
524 1.14 sato VPRINTF("ioctl: GET:(real)BACKLIGHT %d\n",
525 1.18 uch (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0);
526 1.10 sato dispparam->min = 0;
527 1.10 sato dispparam->max = 1;
528 1.10 sato if (sc->sc_max_brightness > 0)
529 1.18 uch dispparam->curval = sc->sc_brightness > 0
530 1.18 uch ? 1: 0;
531 1.10 sato else
532 1.10 sato dispparam->curval =
533 1.18 uch (sc->sc_powerstate&PWRSTAT_BACKLIGHT)
534 1.18 uch ? 1: 0;
535 1.14 sato VPRINTF("ioctl: GET:BACKLIGHT:%d(%s)\n",
536 1.18 uch dispparam->curval,
537 1.18 uch sc->sc_max_brightness > 0? "brightness": "light");
538 1.10 sato return 0;
539 1.10 sato break;
540 1.6 sato case WSDISPLAYIO_PARAM_CONTRAST:
541 1.14 sato VPRINTF("ioctl: GET:CONTRAST\n");
542 1.14 sato mq200_init_contrast(sc, 0);
543 1.10 sato if (sc->sc_max_contrast > 0) {
544 1.10 sato dispparam->min = 0;
545 1.10 sato dispparam->max = sc->sc_max_contrast;
546 1.10 sato dispparam->curval = sc->sc_contrast;
547 1.18 uch VPRINTF("ioctl: GET:CONTRAST"
548 1.18 uch " max=%d, current=%d\n",
549 1.18 uch sc->sc_max_contrast, sc->sc_contrast);
550 1.10 sato return 0;
551 1.10 sato } else {
552 1.14 sato VPRINTF("ioctl: GET:CONTRAST EINVAL\n");
553 1.10 sato return (EINVAL);
554 1.10 sato }
555 1.10 sato break;
556 1.6 sato case WSDISPLAYIO_PARAM_BRIGHTNESS:
557 1.14 sato VPRINTF("ioctl: GET:BRIGHTNESS\n");
558 1.14 sato mq200_init_brightness(sc, 0);
559 1.10 sato if (sc->sc_max_brightness > 0) {
560 1.10 sato dispparam->min = 0;
561 1.10 sato dispparam->max = sc->sc_max_brightness;
562 1.10 sato dispparam->curval = sc->sc_brightness;
563 1.18 uch VPRINTF("ioctl: GET:BRIGHTNESS"
564 1.18 uch " max=%d, current=%d\n",
565 1.18 uch sc->sc_max_brightness, sc->sc_brightness);
566 1.10 sato return 0;
567 1.10 sato } else {
568 1.14 sato VPRINTF("ioctl: GET:BRIGHTNESS EINVAL\n");
569 1.10 sato return (EINVAL);
570 1.10 sato }
571 1.6 sato return (EINVAL);
572 1.6 sato default:
573 1.6 sato return (EINVAL);
574 1.6 sato }
575 1.6 sato return (0);
576 1.6 sato
577 1.6 sato case WSDISPLAYIO_SETPARAM:
578 1.6 sato dispparam = (struct wsdisplay_param*)data;
579 1.6 sato switch (dispparam->param) {
580 1.6 sato case WSDISPLAYIO_PARAM_BACKLIGHT:
581 1.14 sato VPRINTF("ioctl: SET:BACKLIGHT\n");
582 1.10 sato if (dispparam->curval < 0 ||
583 1.10 sato 1 < dispparam->curval)
584 1.10 sato return (EINVAL);
585 1.14 sato mq200_init_brightness(sc, 0);
586 1.18 uch VPRINTF("ioctl: SET:max brightness=%d\n",
587 1.18 uch sc->sc_max_brightness);
588 1.10 sato if (sc->sc_max_brightness > 0) { /* dimmer */
589 1.10 sato if (dispparam->curval == 0){
590 1.18 uch sc->sc_brightness_save =
591 1.18 uch sc->sc_brightness;
592 1.18 uch mq200_set_brightness(sc, 0); /* min */
593 1.10 sato } else {
594 1.10 sato if (sc->sc_brightness_save == 0)
595 1.18 uch sc->sc_brightness_save =
596 1.18 uch sc->sc_max_brightness;
597 1.18 uch mq200_set_brightness(sc,
598 1.18 uch sc->sc_brightness_save);
599 1.10 sato }
600 1.18 uch VPRINTF("ioctl: SET:BACKLIGHT:"
601 1.18 uch " brightness=%d\n", sc->sc_brightness);
602 1.10 sato } else { /* off */
603 1.10 sato if (dispparam->curval == 0)
604 1.10 sato sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
605 1.10 sato else
606 1.10 sato sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
607 1.18 uch VPRINTF("ioctl: SET:BACKLIGHT:"
608 1.18 uch " powerstate %d\n",
609 1.18 uch (sc->sc_powerstate & PWRSTAT_BACKLIGHT)
610 1.18 uch ? 1 : 0);
611 1.10 sato mq200_update_powerstate(sc, PWRSTAT_BACKLIGHT);
612 1.14 sato VPRINTF("ioctl: SET:BACKLIGHT:%d\n",
613 1.18 uch (sc->sc_powerstate & PWRSTAT_BACKLIGHT)
614 1.18 uch ? 1 : 0);
615 1.10 sato }
616 1.10 sato return 0;
617 1.10 sato break;
618 1.6 sato case WSDISPLAYIO_PARAM_CONTRAST:
619 1.14 sato VPRINTF("ioctl: SET:CONTRAST\n");
620 1.14 sato mq200_init_contrast(sc, 0);
621 1.10 sato if (dispparam->curval < 0 ||
622 1.10 sato sc->sc_max_contrast < dispparam->curval)
623 1.10 sato return (EINVAL);
624 1.10 sato if (sc->sc_max_contrast > 0) {
625 1.10 sato int org = sc->sc_contrast;
626 1.18 uch mq200_set_contrast(sc, dispparam->curval);
627 1.18 uch VPRINTF("ioctl: SET:CONTRAST"
628 1.18 uch " org=%d, current=%d\n", org,
629 1.18 uch sc->sc_contrast);
630 1.18 uch VPRINTF("ioctl: SETPARAM:"
631 1.18 uch " CONTRAST org=%d, current=%d\n", org,
632 1.18 uch sc->sc_contrast);
633 1.10 sato return 0;
634 1.10 sato } else {
635 1.14 sato VPRINTF("ioctl: SET:CONTRAST EINVAL\n");
636 1.10 sato return (EINVAL);
637 1.10 sato }
638 1.10 sato break;
639 1.6 sato case WSDISPLAYIO_PARAM_BRIGHTNESS:
640 1.14 sato VPRINTF("ioctl: SET:BRIGHTNESS\n");
641 1.14 sato mq200_init_brightness(sc, 0);
642 1.10 sato if (dispparam->curval < 0 ||
643 1.10 sato sc->sc_max_brightness < dispparam->curval)
644 1.10 sato return (EINVAL);
645 1.10 sato if (sc->sc_max_brightness > 0) {
646 1.10 sato int org = sc->sc_brightness;
647 1.18 uch mq200_set_brightness(sc, dispparam->curval);
648 1.18 uch VPRINTF("ioctl: SET:BRIGHTNESS"
649 1.18 uch " org=%d, current=%d\n", org,
650 1.18 uch sc->sc_brightness);
651 1.10 sato return 0;
652 1.10 sato } else {
653 1.14 sato VPRINTF("ioctl: SET:BRIGHTNESS EINVAL\n");
654 1.10 sato return (EINVAL);
655 1.10 sato }
656 1.10 sato break;
657 1.6 sato default:
658 1.6 sato return (EINVAL);
659 1.6 sato }
660 1.6 sato return (0);
661 1.1 takemura
662 1.1 takemura case HPCFBIO_GCONF:
663 1.1 takemura fbconf = (struct hpcfb_fbconf *)data;
664 1.1 takemura if (fbconf->hf_conf_index != 0 &&
665 1.1 takemura fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
666 1.1 takemura return (EINVAL);
667 1.1 takemura }
668 1.1 takemura *fbconf = sc->sc_fbconf; /* structure assignment */
669 1.1 takemura return (0);
670 1.1 takemura case HPCFBIO_SCONF:
671 1.1 takemura fbconf = (struct hpcfb_fbconf *)data;
672 1.1 takemura if (fbconf->hf_conf_index != 0 &&
673 1.1 takemura fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
674 1.1 takemura return (EINVAL);
675 1.1 takemura }
676 1.1 takemura /*
677 1.1 takemura * nothing to do because we have only one configration
678 1.1 takemura */
679 1.1 takemura return (0);
680 1.1 takemura case HPCFBIO_GDSPCONF:
681 1.1 takemura dspconf = (struct hpcfb_dspconf *)data;
682 1.1 takemura if ((dspconf->hd_unit_index != 0 &&
683 1.18 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
684 1.1 takemura (dspconf->hd_conf_index != 0 &&
685 1.18 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
686 1.1 takemura return (EINVAL);
687 1.1 takemura }
688 1.1 takemura *dspconf = sc->sc_dspconf; /* structure assignment */
689 1.1 takemura return (0);
690 1.1 takemura case HPCFBIO_SDSPCONF:
691 1.1 takemura dspconf = (struct hpcfb_dspconf *)data;
692 1.1 takemura if ((dspconf->hd_unit_index != 0 &&
693 1.18 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
694 1.1 takemura (dspconf->hd_conf_index != 0 &&
695 1.18 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
696 1.1 takemura return (EINVAL);
697 1.1 takemura }
698 1.1 takemura /*
699 1.1 takemura * nothing to do
700 1.1 takemura * because we have only one unit and one configration
701 1.1 takemura */
702 1.1 takemura return (0);
703 1.1 takemura case HPCFBIO_GOP:
704 1.1 takemura case HPCFBIO_SOP:
705 1.1 takemura /*
706 1.1 takemura * curently not implemented...
707 1.1 takemura */
708 1.1 takemura return (EINVAL);
709 1.1 takemura }
710 1.1 takemura
711 1.19 atatat return (EPASSTHROUGH);
712 1.1 takemura }
713 1.1 takemura
714 1.1 takemura paddr_t
715 1.18 uch mq200_mmap(void *ctx, off_t offset, int prot)
716 1.1 takemura {
717 1.1 takemura struct mq200_softc *sc = (struct mq200_softc *)ctx;
718 1.1 takemura
719 1.3 takemura if (offset < 0 || MQ200_MAPSIZE <= offset)
720 1.1 takemura return -1;
721 1.1 takemura
722 1.3 takemura return mips_btop(sc->sc_baseaddr + offset);
723 1.10 sato }
724 1.10 sato
725 1.10 sato
726 1.10 sato void
727 1.18 uch mq200_init_backlight(struct mq200_softc *sc, int inattach)
728 1.10 sato {
729 1.10 sato int val = -1;
730 1.10 sato
731 1.14 sato if (sc->sc_lcd_inited&BACKLIGHT_INITED)
732 1.14 sato return;
733 1.14 sato
734 1.12 sato if (config_hook_call(CONFIG_HOOK_GET,
735 1.18 uch CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) {
736 1.14 sato /* we can get real light state */
737 1.14 sato VPRINTF("init_backlight: real backlight=%d\n", val);
738 1.12 sato if (val == 0)
739 1.12 sato sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
740 1.12 sato else
741 1.12 sato sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
742 1.14 sato sc->sc_lcd_inited |= BACKLIGHT_INITED;
743 1.14 sato } else if (inattach) {
744 1.14 sato /*
745 1.14 sato we cannot get real light state in attach time
746 1.14 sato because light device not yet attached.
747 1.14 sato we will retry in !inattach.
748 1.14 sato temporary assume light is on.
749 1.18 uch */
750 1.12 sato sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
751 1.14 sato } else {
752 1.14 sato /* we cannot get real light state, so work by myself state */
753 1.14 sato sc->sc_lcd_inited |= BACKLIGHT_INITED;
754 1.14 sato }
755 1.10 sato }
756 1.10 sato
757 1.10 sato void
758 1.18 uch mq200_init_brightness(struct mq200_softc *sc, int inattach)
759 1.10 sato {
760 1.10 sato int val = -1;
761 1.10 sato
762 1.14 sato if (sc->sc_lcd_inited&BRIGHTNESS_INITED)
763 1.14 sato return;
764 1.14 sato
765 1.13 takemura VPRINTF("init_brightness\n");
766 1.10 sato if (config_hook_call(CONFIG_HOOK_GET,
767 1.18 uch CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) {
768 1.14 sato /* we can get real brightness max */
769 1.14 sato VPRINTF("init_brightness: real brightness max=%d\n", val);
770 1.10 sato sc->sc_max_brightness = val;
771 1.14 sato val = -1;
772 1.14 sato if (config_hook_call(CONFIG_HOOK_GET,
773 1.18 uch CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
774 1.14 sato /* we can get real brightness */
775 1.14 sato VPRINTF("init_brightness: real brightness=%d\n", val);
776 1.14 sato sc->sc_brightness_save = sc->sc_brightness = val;
777 1.14 sato } else {
778 1.14 sato sc->sc_brightness_save =
779 1.18 uch sc->sc_brightness = sc->sc_max_brightness;
780 1.14 sato }
781 1.14 sato sc->sc_lcd_inited |= BRIGHTNESS_INITED;
782 1.14 sato } else if (inattach) {
783 1.14 sato /*
784 1.14 sato we cannot get real brightness in attach time
785 1.14 sato because brightness device not yet attached.
786 1.14 sato we will retry in !inattach.
787 1.18 uch */
788 1.14 sato sc->sc_max_brightness = -1;
789 1.14 sato sc->sc_brightness = -1;
790 1.14 sato sc->sc_brightness_save = -1;
791 1.14 sato } else {
792 1.14 sato /* we cannot get real brightness */
793 1.14 sato sc->sc_lcd_inited |= BRIGHTNESS_INITED;
794 1.10 sato }
795 1.14 sato
796 1.10 sato return;
797 1.10 sato }
798 1.10 sato
799 1.10 sato
800 1.10 sato void
801 1.18 uch mq200_init_contrast(struct mq200_softc *sc, int inattach)
802 1.10 sato {
803 1.10 sato int val = -1;
804 1.10 sato
805 1.14 sato if (sc->sc_lcd_inited&CONTRAST_INITED)
806 1.14 sato return;
807 1.14 sato
808 1.13 takemura VPRINTF("init_contrast\n");
809 1.10 sato if (config_hook_call(CONFIG_HOOK_GET,
810 1.18 uch CONFIG_HOOK_CONTRAST_MAX, &val) != -1) {
811 1.14 sato /* we can get real contrast max */
812 1.14 sato VPRINTF("init_contrast: real contrast max=%d\n", val);
813 1.10 sato sc->sc_max_contrast = val;
814 1.14 sato val = -1;
815 1.14 sato if (config_hook_call(CONFIG_HOOK_GET,
816 1.18 uch CONFIG_HOOK_CONTRAST, &val) != -1) {
817 1.14 sato /* we can get real contrast */
818 1.14 sato VPRINTF("init_contrast: real contrast=%d\n", val);
819 1.14 sato sc->sc_contrast = val;
820 1.14 sato } else {
821 1.14 sato sc->sc_contrast = sc->sc_max_contrast;
822 1.14 sato }
823 1.14 sato sc->sc_lcd_inited |= CONTRAST_INITED;
824 1.14 sato } else if (inattach) {
825 1.14 sato /*
826 1.14 sato we cannot get real contrast in attach time
827 1.14 sato because contrast device not yet attached.
828 1.14 sato we will retry in !inattach.
829 1.18 uch */
830 1.14 sato sc->sc_max_contrast = -1;
831 1.14 sato sc->sc_contrast = -1;
832 1.14 sato } else {
833 1.14 sato /* we cannot get real contrast */
834 1.14 sato sc->sc_lcd_inited |= CONTRAST_INITED;
835 1.10 sato }
836 1.14 sato
837 1.10 sato return;
838 1.10 sato }
839 1.14 sato
840 1.10 sato
841 1.10 sato void
842 1.18 uch mq200_set_brightness(struct mq200_softc *sc, int val)
843 1.10 sato {
844 1.10 sato sc->sc_brightness = val;
845 1.10 sato
846 1.10 sato config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
847 1.10 sato if (config_hook_call(CONFIG_HOOK_GET,
848 1.18 uch CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
849 1.10 sato sc->sc_brightness = val;
850 1.10 sato }
851 1.10 sato }
852 1.10 sato
853 1.10 sato void
854 1.18 uch mq200_set_contrast(struct mq200_softc *sc, int val)
855 1.10 sato {
856 1.10 sato sc->sc_contrast = val;
857 1.10 sato
858 1.10 sato config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
859 1.10 sato if (config_hook_call(CONFIG_HOOK_GET,
860 1.18 uch CONFIG_HOOK_CONTRAST, &val) != -1) {
861 1.10 sato sc->sc_contrast = val;
862 1.10 sato }
863 1.1 takemura }
864