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