tx3912video.c revision 1.11 1 1.11 uch /* $NetBSD: tx3912video.c,v 1.11 2000/05/02 17:50:52 uch Exp $ */
2 1.1 uch
3 1.11 uch /*-
4 1.11 uch * Copyright (c) 1999, 2000 UCHIYAMA Yasushi. All rights reserved.
5 1.1 uch *
6 1.1 uch * Redistribution and use in source and binary forms, with or without
7 1.1 uch * modification, are permitted provided that the following conditions
8 1.1 uch * are met:
9 1.1 uch * 1. Redistributions of source code must retain the above copyright
10 1.1 uch * notice, this list of conditions and the following disclaimer.
11 1.10 uch * 2. Redistributions in binary form must reproduce the above copyright
12 1.10 uch * notice, this list of conditions and the following disclaimer in the
13 1.10 uch * documentation and/or other materials provided with the distribution.
14 1.11 uch * 3. The name of the author may not be used to endorse or promote products
15 1.11 uch * derived from this software without specific prior written permission.
16 1.1 uch *
17 1.10 uch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 1.10 uch * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 1.10 uch * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 1.10 uch * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 1.10 uch * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 1.10 uch * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 1.10 uch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 1.10 uch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 1.11 uch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 1.11 uch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 1.1 uch */
28 1.10 uch
29 1.1 uch #include "opt_tx39_debug.h"
30 1.8 uch #include "hpcfb.h"
31 1.1 uch
32 1.1 uch #include <sys/param.h>
33 1.1 uch #include <sys/systm.h>
34 1.1 uch #include <sys/device.h>
35 1.1 uch #include <sys/extent.h>
36 1.1 uch
37 1.11 uch #include <sys/ioctl.h>
38 1.11 uch
39 1.1 uch #include <machine/bus.h>
40 1.10 uch #include <machine/bootinfo.h>
41 1.1 uch
42 1.1 uch #include <hpcmips/tx/tx39var.h>
43 1.1 uch #include <hpcmips/tx/tx3912videovar.h>
44 1.1 uch #include <hpcmips/tx/tx3912videoreg.h>
45 1.1 uch
46 1.9 sato #include <dev/wscons/wsconsio.h>
47 1.8 uch #include <arch/hpcmips/dev/hpcfbvar.h>
48 1.8 uch #include <arch/hpcmips/dev/hpcfbio.h>
49 1.2 uch
50 1.10 uch #define TX3912VIDEO_DEBUG
51 1.10 uch
52 1.10 uch static struct tx3912video_chip {
53 1.10 uch tx_chipset_tag_t vc_tc;
54 1.6 uch
55 1.10 uch paddr_t vc_fbaddr;
56 1.10 uch size_t vc_fbsize;
57 1.10 uch int vc_fbdepth;
58 1.10 uch int vc_fbwidth;
59 1.10 uch int vc_fbheight;
60 1.6 uch
61 1.11 uch void (*vc_drawline) __P((int, int, int, int)); /* for debug */
62 1.11 uch void (*vc_drawdot) __P((int, int)); /* for debug */
63 1.10 uch } tx3912video_chip;
64 1.6 uch
65 1.1 uch struct tx3912video_softc {
66 1.1 uch struct device sc_dev;
67 1.11 uch struct hpcfb_fbconf sc_fbconf;
68 1.11 uch struct hpcfb_dspconf sc_dspconf;
69 1.6 uch struct tx3912video_chip *sc_chip;
70 1.1 uch };
71 1.1 uch
72 1.11 uch void tx3912video_framebuffer_init __P((struct tx3912video_chip *));
73 1.11 uch int tx3912video_framebuffer_alloc __P((struct tx3912video_chip *, paddr_t,
74 1.10 uch paddr_t *));
75 1.11 uch void tx3912video_reset __P((struct tx3912video_chip *));
76 1.11 uch void tx3912video_resolution_init __P((struct tx3912video_chip *));
77 1.10 uch
78 1.10 uch int tx3912video_match __P((struct device *, struct cfdata *, void *));
79 1.10 uch void tx3912video_attach __P((struct device *, struct device *, void *));
80 1.10 uch int tx3912video_print __P((void *, const char *));
81 1.1 uch
82 1.11 uch void tx3912video_hpcfbinit __P((struct tx3912video_softc *));
83 1.11 uch int tx3912video_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
84 1.11 uch int tx3912video_mmap __P((void *, off_t, int));
85 1.11 uch
86 1.1 uch struct cfattach tx3912video_ca = {
87 1.3 uch sizeof(struct tx3912video_softc), tx3912video_match,
88 1.3 uch tx3912video_attach
89 1.1 uch };
90 1.1 uch
91 1.11 uch struct hpcfb_accessops tx3912video_ha = {
92 1.11 uch tx3912video_ioctl, tx3912video_mmap
93 1.11 uch };
94 1.11 uch
95 1.10 uch void __tx3912video_attach_drawfunc __P((struct tx3912video_chip*));
96 1.6 uch
97 1.1 uch int
98 1.1 uch tx3912video_match(parent, cf, aux)
99 1.1 uch struct device *parent;
100 1.1 uch struct cfdata *cf;
101 1.1 uch void *aux;
102 1.1 uch {
103 1.10 uch return (1);
104 1.1 uch }
105 1.1 uch
106 1.1 uch void
107 1.1 uch tx3912video_attach(parent, self, aux)
108 1.1 uch struct device *parent;
109 1.1 uch struct device *self;
110 1.1 uch void *aux;
111 1.1 uch {
112 1.10 uch struct tx3912video_softc *sc = (void *)self;
113 1.10 uch struct tx3912video_chip *chip;
114 1.10 uch const char *depth_print[] = {
115 1.10 uch [TX3912_VIDEOCTRL1_BITSEL_MONOCHROME] = "monochrome",
116 1.10 uch [TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE] = "2bit greyscale",
117 1.10 uch [TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE] = "4bit greyscale",
118 1.10 uch [TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR] = "8bit color"
119 1.10 uch };
120 1.11 uch struct hpcfb_attach_args ha;
121 1.11 uch int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
122 1.10 uch
123 1.10 uch sc->sc_chip = chip = &tx3912video_chip;
124 1.10 uch
125 1.10 uch /* print video module information */
126 1.10 uch printf(": %s, frame buffer 0x%08x-0x%08x\n",
127 1.10 uch depth_print[(ffs(chip->vc_fbdepth) - 1) & 0x3],
128 1.10 uch (unsigned)chip->vc_fbaddr,
129 1.10 uch (unsigned)(chip->vc_fbaddr + chip->vc_fbsize));
130 1.5 uch
131 1.10 uch /* if serial console, power off video module */
132 1.6 uch #ifndef TX3912VIDEO_DEBUG
133 1.11 uch if (!console) {
134 1.10 uch tx_chipset_tag_t tc = ta->ta_tc;
135 1.10 uch txreg_t reg;
136 1.5 uch printf("%s: power off\n", sc->sc_dev.dv_xname);
137 1.4 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
138 1.4 uch reg &= ~(TX3912_VIDEOCTRL1_DISPON |
139 1.4 uch TX3912_VIDEOCTRL1_ENVID);
140 1.4 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
141 1.4 uch }
142 1.6 uch #endif /* TX3912VIDEO_DEBUG */
143 1.6 uch
144 1.10 uch /* attach debug draw routine (debugging use) */
145 1.10 uch __tx3912video_attach_drawfunc(sc->sc_chip);
146 1.10 uch
147 1.1 uch /* Attach frame buffer device */
148 1.11 uch tx3912video_hpcfbinit(sc);
149 1.11 uch
150 1.11 uch if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
151 1.11 uch panic("tx3912video_attach: can't init fb console");
152 1.2 uch }
153 1.11 uch
154 1.11 uch ha.ha_console = console;
155 1.11 uch ha.ha_accessops = &tx3912video_ha;
156 1.11 uch ha.ha_accessctx = sc;
157 1.11 uch ha.ha_curfbconf = 0;
158 1.11 uch ha.ha_nfbconf = 1;
159 1.11 uch ha.ha_fbconflist = &sc->sc_fbconf;
160 1.11 uch ha.ha_curdspconf = 0;
161 1.11 uch ha.ha_ndspconf = 1;
162 1.11 uch ha.ha_dspconflist = &sc->sc_dspconf;
163 1.11 uch
164 1.11 uch config_found(self, &ha, hpcfbprint);
165 1.1 uch }
166 1.1 uch
167 1.11 uch void
168 1.11 uch tx3912video_hpcfbinit(sc)
169 1.11 uch struct tx3912video_softc *sc;
170 1.1 uch {
171 1.11 uch struct tx3912video_chip *chip = sc->sc_chip;
172 1.11 uch struct hpcfb_fbconf *fb = &sc->sc_fbconf;
173 1.11 uch caddr_t fbcaddr = (caddr_t)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
174 1.11 uch
175 1.11 uch memset(fb, 0, sizeof(struct hpcfb_fbconf));
176 1.11 uch
177 1.11 uch fb->hf_conf_index = 0; /* configuration index */
178 1.11 uch fb->hf_nconfs = 1; /* how many configurations */
179 1.11 uch strcpy(fb->hf_name, "TX3912 built-in video");
180 1.11 uch /* frame buffer name */
181 1.11 uch strcpy(fb->hf_conf_name, "LCD");
182 1.11 uch /* configuration name */
183 1.11 uch fb->hf_height = chip->vc_fbheight;
184 1.11 uch fb->hf_width = chip->vc_fbwidth;
185 1.11 uch fb->hf_baseaddr = mips_ptob(mips_btop(fbcaddr));
186 1.11 uch fb->hf_offset = (u_long)fbcaddr - fb->hf_baseaddr;
187 1.11 uch /* frame buffer start offset */
188 1.11 uch fb->hf_bytes_per_line = (chip->vc_fbwidth * chip->vc_fbdepth) / NBBY;
189 1.11 uch fb->hf_nplanes = 1;
190 1.11 uch fb->hf_bytes_per_plane = chip->vc_fbheight * fb->hf_bytes_per_line;
191 1.11 uch
192 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
193 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_WORD;
194 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
195 1.11 uch
196 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_REVERSE; /* XXX */
197 1.11 uch switch (chip->vc_fbdepth) {
198 1.11 uch default:
199 1.11 uch panic("tx3912video_hpcfbinit: not supported color depth\n");
200 1.11 uch /* NOTREACHED */
201 1.11 uch case 2:
202 1.11 uch fb->hf_class = HPCFB_CLASS_GRAYSCALE;
203 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
204 1.11 uch fb->hf_pack_width = 8;
205 1.11 uch fb->hf_pixels_per_pack = 4;
206 1.11 uch fb->hf_pixel_width = 2;
207 1.11 uch fb->hf_class_data_length = sizeof(struct hf_gray_tag);
208 1.11 uch fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
209 1.11 uch break;
210 1.11 uch case 8:
211 1.11 uch fb->hf_class = HPCFB_CLASS_INDEXCOLOR; /* XXX */
212 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
213 1.11 uch fb->hf_pack_width = 8;
214 1.11 uch fb->hf_pixels_per_pack = 1;
215 1.11 uch fb->hf_pixel_width = 8;
216 1.11 uch fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
217 1.11 uch fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
218 1.11 uch break;
219 1.11 uch }
220 1.1 uch }
221 1.1 uch
222 1.1 uch int
223 1.10 uch tx3912video_init(fb_start, fb_end)
224 1.10 uch paddr_t fb_start, *fb_end;
225 1.10 uch {
226 1.10 uch struct tx3912video_chip *chip = &tx3912video_chip;
227 1.1 uch tx_chipset_tag_t tc;
228 1.7 uch txreg_t reg;
229 1.10 uch int fbdepth;
230 1.10 uch int error;
231 1.1 uch
232 1.10 uch chip->vc_tc = tc = tx_conf_get_tag();
233 1.10 uch
234 1.10 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
235 1.10 uch fbdepth = 1 << (TX3912_VIDEOCTRL1_BITSEL(reg));
236 1.7 uch
237 1.10 uch switch (fbdepth) {
238 1.7 uch case 2:
239 1.7 uch bootinfo->fb_type = BIFB_D2_M2L_0;
240 1.7 uch break;
241 1.7 uch case 4:
242 1.7 uch /* XXX should implement rasops4.c */
243 1.10 uch fbdepth = 2;
244 1.7 uch bootinfo->fb_type = BIFB_D2_M2L_0;
245 1.7 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
246 1.7 uch TX3912_VIDEOCTRL1_BITSEL_CLR(reg);
247 1.7 uch reg = TX3912_VIDEOCTRL1_BITSEL_SET(
248 1.7 uch reg, TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE);
249 1.7 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
250 1.7 uch break;
251 1.7 uch case 8:
252 1.7 uch bootinfo->fb_type = BIFB_D8_FF;
253 1.7 uch break;
254 1.7 uch }
255 1.7 uch
256 1.10 uch tx3912video_chip.vc_fbdepth = fbdepth;
257 1.10 uch tx3912video_chip.vc_fbwidth = bootinfo->fb_width;
258 1.10 uch tx3912video_chip.vc_fbheight= bootinfo->fb_height;
259 1.7 uch
260 1.1 uch /* Allocate framebuffer area */
261 1.10 uch error = tx3912video_framebuffer_alloc(chip, fb_start, fb_end);
262 1.10 uch if (error != 0)
263 1.10 uch return (1);
264 1.10 uch
265 1.1 uch #if notyet
266 1.10 uch tx3912video_resolution_init(chip);
267 1.1 uch #else
268 1.1 uch /* Use Windows CE setting. */
269 1.1 uch #endif
270 1.1 uch /* Set DMA transfer address to VID module */
271 1.10 uch tx3912video_framebuffer_init(chip);
272 1.1 uch
273 1.1 uch /* Syncronize framebuffer addr to frame signal */
274 1.10 uch tx3912video_reset(chip);
275 1.1 uch
276 1.10 uch bootinfo->fb_line_bytes = (chip->vc_fbwidth * fbdepth) / NBBY;
277 1.10 uch bootinfo->fb_addr = (void *)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
278 1.10 uch
279 1.10 uch return (0);
280 1.1 uch }
281 1.1 uch
282 1.1 uch int
283 1.10 uch tx3912video_framebuffer_alloc(chip, fb_start, fb_end)
284 1.10 uch struct tx3912video_chip *chip;
285 1.10 uch paddr_t fb_start, *fb_end; /* buffer allocation hint */
286 1.1 uch {
287 1.10 uch struct extent_fixed ex_fixed[10];
288 1.1 uch struct extent *ex;
289 1.1 uch u_long addr, size;
290 1.10 uch int error;
291 1.10 uch
292 1.10 uch /* calcurate frame buffer size */
293 1.10 uch size = (chip->vc_fbwidth * chip->vc_fbheight * chip->vc_fbdepth) /
294 1.10 uch NBBY;
295 1.10 uch
296 1.10 uch /* extent V-RAM region */
297 1.10 uch ex = extent_create("Frame buffer address", fb_start, *fb_end,
298 1.10 uch 0, (caddr_t)ex_fixed, sizeof ex_fixed,
299 1.10 uch EX_NOWAIT);
300 1.10 uch if (ex == 0)
301 1.10 uch return (1);
302 1.1 uch
303 1.1 uch /* Allocate V-RAM area */
304 1.10 uch error = extent_alloc_subregion(ex, fb_start, fb_start + size, size,
305 1.10 uch TX3912_FRAMEBUFFER_ALIGNMENT,
306 1.10 uch TX3912_FRAMEBUFFER_BOUNDARY,
307 1.10 uch EX_FAST|EX_NOWAIT, &addr);
308 1.10 uch extent_destroy(ex);
309 1.10 uch
310 1.10 uch if (error != 0) {
311 1.10 uch return (1);
312 1.1 uch }
313 1.10 uch
314 1.10 uch chip->vc_fbaddr = addr;
315 1.10 uch chip->vc_fbsize = size;
316 1.6 uch
317 1.10 uch *fb_end = addr + size;
318 1.1 uch
319 1.10 uch return (0);
320 1.1 uch }
321 1.1 uch
322 1.1 uch void
323 1.10 uch tx3912video_framebuffer_init(chip)
324 1.10 uch struct tx3912video_chip *chip;
325 1.1 uch {
326 1.10 uch u_int32_t fb_addr, fb_size, vaddr, bank, base;
327 1.10 uch txreg_t reg;
328 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
329 1.10 uch
330 1.10 uch fb_addr = chip->vc_fbaddr;
331 1.10 uch fb_size = chip->vc_fbsize;
332 1.1 uch
333 1.1 uch /* XXX currently I don't set DFVAL, so force DF signal toggled on
334 1.1 uch * XXX each frame. */
335 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
336 1.1 uch reg &= ~TX3912_VIDEOCTRL1_DFMODE;
337 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
338 1.1 uch
339 1.1 uch /* Set DMA transfer start and end address */
340 1.10 uch
341 1.1 uch bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
342 1.1 uch base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
343 1.1 uch reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
344 1.1 uch /* Upper address counter */
345 1.1 uch reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
346 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
347 1.1 uch
348 1.1 uch /* Lower address counter */
349 1.1 uch base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
350 1.1 uch reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
351 1.1 uch
352 1.1 uch /* Set DF-signal rate */
353 1.1 uch reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
354 1.1 uch
355 1.1 uch /* Set VIDDONE signal delay after FRAME signal */
356 1.1 uch /* XXX not yet*/
357 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
358 1.1 uch
359 1.1 uch /* Clear frame buffer */
360 1.1 uch vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
361 1.10 uch memset((void*)vaddr, 0, fb_size);
362 1.1 uch }
363 1.1 uch
364 1.1 uch void
365 1.10 uch tx3912video_resolution_init(chip)
366 1.10 uch struct tx3912video_chip *chip;
367 1.1 uch {
368 1.10 uch int h, v, split, bit8, horzval, lineval;
369 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
370 1.10 uch txreg_t reg;
371 1.10 uch u_int32_t val;
372 1.10 uch
373 1.10 uch h = chip->vc_fbwidth;
374 1.10 uch v = chip->vc_fbheight;
375 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
376 1.1 uch split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
377 1.1 uch bit8 = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
378 1.1 uch TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
379 1.1 uch val = TX3912_VIDEOCTRL1_BITSEL(reg);
380 1.1 uch
381 1.1 uch if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
382 1.1 uch !split) {
383 1.3 uch /* (LCD horizontal pixels / 8bit) * RGB - 1 */
384 1.3 uch horzval = (h / 8) * 3 - 1;
385 1.1 uch } else {
386 1.1 uch horzval = h / 4 - 1;
387 1.1 uch }
388 1.1 uch lineval = (split ? v / 2 : v) - 1;
389 1.1 uch
390 1.1 uch /* Video rate */
391 1.3 uch /* XXX
392 1.3 uch * probably This value should be determined from DFINT and LCDINT
393 1.3 uch */
394 1.1 uch reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
395 1.1 uch /* Horizontal size of LCD */
396 1.1 uch reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
397 1.1 uch /* # of lines for the LCD */
398 1.1 uch reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
399 1.1 uch
400 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
401 1.1 uch }
402 1.1 uch
403 1.1 uch void
404 1.10 uch tx3912video_reset(chip)
405 1.10 uch struct tx3912video_chip *chip;
406 1.1 uch {
407 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
408 1.10 uch txreg_t reg;
409 1.1 uch
410 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
411 1.3 uch
412 1.1 uch /* Disable video logic at end of this frame */
413 1.1 uch reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
414 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
415 1.3 uch
416 1.1 uch /* Wait for end of frame */
417 1.10 uch delay(30 * 1000);
418 1.3 uch
419 1.1 uch /* Make sure to disable video logic */
420 1.1 uch reg &= ~TX3912_VIDEOCTRL1_ENVID;
421 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
422 1.3 uch
423 1.1 uch delay(1000);
424 1.3 uch
425 1.1 uch /* Enable video logic again */
426 1.1 uch reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
427 1.1 uch reg |= TX3912_VIDEOCTRL1_ENVID;
428 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
429 1.3 uch
430 1.1 uch delay(1000);
431 1.1 uch }
432 1.1 uch
433 1.11 uch int
434 1.11 uch tx3912video_ioctl(v, cmd, data, flag, p)
435 1.11 uch void *v;
436 1.11 uch u_long cmd;
437 1.11 uch caddr_t data;
438 1.11 uch int flag;
439 1.11 uch struct proc *p;
440 1.11 uch {
441 1.11 uch struct tx3912video_softc *sc = (struct tx3912video_softc *)v;
442 1.11 uch struct hpcfb_fbconf *fbconf;
443 1.11 uch struct hpcfb_dspconf *dspconf;
444 1.11 uch
445 1.11 uch switch (cmd) {
446 1.11 uch case WSDISPLAYIO_GETCMAP:
447 1.11 uch /* XXX not implemented yet */
448 1.11 uch return (EINVAL);
449 1.11 uch
450 1.11 uch case WSDISPLAYIO_PUTCMAP:
451 1.11 uch /* XXX not implemented yet */
452 1.11 uch return (EINVAL);
453 1.11 uch
454 1.11 uch case HPCFBIO_GCONF:
455 1.11 uch fbconf = (struct hpcfb_fbconf *)data;
456 1.11 uch if (fbconf->hf_conf_index != 0 &&
457 1.11 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
458 1.11 uch return (EINVAL);
459 1.11 uch }
460 1.11 uch *fbconf = sc->sc_fbconf; /* structure assignment */
461 1.11 uch return (0);
462 1.11 uch
463 1.11 uch case HPCFBIO_SCONF:
464 1.11 uch fbconf = (struct hpcfb_fbconf *)data;
465 1.11 uch if (fbconf->hf_conf_index != 0 &&
466 1.11 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
467 1.11 uch return (EINVAL);
468 1.11 uch }
469 1.11 uch /*
470 1.11 uch * nothing to do because we have only one configration
471 1.11 uch */
472 1.11 uch return (0);
473 1.11 uch
474 1.11 uch case HPCFBIO_GDSPCONF:
475 1.11 uch dspconf = (struct hpcfb_dspconf *)data;
476 1.11 uch if ((dspconf->hd_unit_index != 0 &&
477 1.11 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
478 1.11 uch (dspconf->hd_conf_index != 0 &&
479 1.11 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
480 1.11 uch return (EINVAL);
481 1.11 uch }
482 1.11 uch *dspconf = sc->sc_dspconf; /* structure assignment */
483 1.11 uch return (0);
484 1.11 uch
485 1.11 uch case HPCFBIO_SDSPCONF:
486 1.11 uch dspconf = (struct hpcfb_dspconf *)data;
487 1.11 uch if ((dspconf->hd_unit_index != 0 &&
488 1.11 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
489 1.11 uch (dspconf->hd_conf_index != 0 &&
490 1.11 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
491 1.11 uch return (EINVAL);
492 1.11 uch }
493 1.11 uch /*
494 1.11 uch * nothing to do
495 1.11 uch * because we have only one unit and one configration
496 1.11 uch */
497 1.11 uch return (0);
498 1.11 uch
499 1.11 uch case HPCFBIO_GOP:
500 1.11 uch case HPCFBIO_SOP:
501 1.11 uch /* XXX not implemented yet */
502 1.11 uch return (EINVAL);
503 1.11 uch }
504 1.11 uch
505 1.11 uch return (ENOTTY);
506 1.11 uch }
507 1.11 uch
508 1.11 uch int
509 1.11 uch tx3912video_mmap(ctx, offset, prot)
510 1.11 uch void *ctx;
511 1.11 uch off_t offset;
512 1.11 uch int prot;
513 1.11 uch {
514 1.11 uch struct tx3912video_softc *sc = (struct tx3912video_softc *)ctx;
515 1.11 uch
516 1.11 uch if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane +
517 1.11 uch sc->sc_fbconf.hf_offset) < offset) {
518 1.11 uch return (-1);
519 1.11 uch }
520 1.11 uch
521 1.11 uch return (mips_btop(sc->sc_chip->vc_fbaddr + offset));
522 1.11 uch }
523 1.11 uch
524 1.6 uch /*
525 1.6 uch * Debug routines.
526 1.6 uch */
527 1.6 uch void
528 1.6 uch tx3912video_calibration_pattern()
529 1.6 uch {
530 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
531 1.6 uch int x, y;
532 1.6 uch
533 1.6 uch x = vc->vc_fbwidth - 40;
534 1.6 uch y = vc->vc_fbheight - 40;
535 1.6 uch tx3912video_line(40, 40, x , 40);
536 1.6 uch tx3912video_line(x , 40, x , y );
537 1.6 uch tx3912video_line(x , y , 40, y );
538 1.6 uch tx3912video_line(40, y , 40, 40);
539 1.6 uch tx3912video_line(40, 40, x , y );
540 1.6 uch tx3912video_line(x, 40, 40, y );
541 1.6 uch }
542 1.6 uch
543 1.6 uch #define BPP2 ({ \
544 1.6 uch u_int8_t bitmap; \
545 1.6 uch bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
546 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
547 1.6 uch (bitmap & ~(0x3 << ((3 - (x % 4)) * 2))); \
548 1.6 uch })
549 1.6 uch
550 1.6 uch #define BPP4 ({ \
551 1.6 uch u_int8_t bitmap; \
552 1.6 uch bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
553 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
554 1.6 uch (bitmap & ~(0xf << ((1 - (x % 2)) * 4))); \
555 1.6 uch })
556 1.6 uch
557 1.6 uch #define BPP8 ({ \
558 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = 0xff; \
559 1.6 uch })
560 1.6 uch
561 1.6 uch #define BRESENHAM(a, b, c, d, func) ({ \
562 1.6 uch u_int32_t fbaddr = vc->vc_fbaddr; \
563 1.6 uch u_int32_t fbwidth = vc->vc_fbwidth; \
564 1.6 uch u_int32_t fbdepth = vc->vc_fbdepth; \
565 1.6 uch len = a, step = b -1; \
566 1.6 uch if (step == 0) \
567 1.6 uch return; \
568 1.6 uch kstep = len == 0 ? 0 : 1; \
569 1.6 uch for (i = k = 0, j = step / 2; i <= step; i++) { \
570 1.6 uch x = xbase c; \
571 1.6 uch y = ybase d; \
572 1.6 uch addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3); \
573 1.6 uch func; \
574 1.6 uch j -= len; \
575 1.6 uch while (j < 0) { \
576 1.6 uch j += step; \
577 1.6 uch k += kstep; \
578 1.6 uch } \
579 1.6 uch } \
580 1.6 uch })
581 1.6 uch
582 1.6 uch #define DRAWLINE(func) ({ \
583 1.6 uch if (x < 0) { \
584 1.6 uch if (y < 0) { \
585 1.6 uch if (_y < _x) { \
586 1.6 uch BRESENHAM(_y, _x, -i, -k, func); \
587 1.6 uch } else { \
588 1.6 uch BRESENHAM(_x, _y, -k, -i, func); \
589 1.6 uch } \
590 1.6 uch } else { \
591 1.6 uch if (_y < _x) { \
592 1.6 uch BRESENHAM(_y, _x, -i, +k, func); \
593 1.6 uch } else { \
594 1.6 uch BRESENHAM(_x, _y, -k, +i, func); \
595 1.6 uch } \
596 1.6 uch } \
597 1.6 uch } else { \
598 1.6 uch if (y < 0) { \
599 1.6 uch if (_y < _x) { \
600 1.6 uch BRESENHAM(_y, _x, +i, -k, func); \
601 1.6 uch } else { \
602 1.6 uch BRESENHAM(_x, _y, +k, -i, func); \
603 1.6 uch } \
604 1.6 uch } else { \
605 1.6 uch if (_y < _x) { \
606 1.6 uch BRESENHAM(_y, _x, +i, +k, func); \
607 1.6 uch } else { \
608 1.6 uch BRESENHAM(_x, _y, +k, +i, func); \
609 1.6 uch } \
610 1.6 uch } \
611 1.6 uch } \
612 1.6 uch })
613 1.6 uch
614 1.6 uch #define LINEFUNC(b) \
615 1.6 uch static void linebpp##b __P((int, int, int, int)); \
616 1.6 uch static void \
617 1.6 uch linebpp##b##(x0, y0, x1, y1) \
618 1.6 uch int x0, y0, x1, y1; \
619 1.6 uch { \
620 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip; \
621 1.6 uch u_int32_t addr; \
622 1.6 uch int i, j, k, len, step, kstep; \
623 1.6 uch int x, _x, y, _y; \
624 1.6 uch int xbase, ybase; \
625 1.6 uch x = x1 - x0; \
626 1.6 uch y = y1 - y0; \
627 1.6 uch _x = abs(x); \
628 1.6 uch _y = abs(y); \
629 1.6 uch xbase = x0; \
630 1.6 uch ybase = y0; \
631 1.6 uch DRAWLINE(BPP##b##); \
632 1.6 uch }
633 1.1 uch
634 1.6 uch #define DOTFUNC(b) \
635 1.6 uch static void dotbpp##b __P((int, int)); \
636 1.6 uch static void \
637 1.6 uch dotbpp##b##(x, y) \
638 1.6 uch int x, y; \
639 1.6 uch { \
640 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip; \
641 1.6 uch u_int32_t addr; \
642 1.6 uch addr = vc->vc_fbaddr + (((y * vc->vc_fbwidth + x) * \
643 1.6 uch vc->vc_fbdepth) >> 3); \
644 1.6 uch BPP##b; \
645 1.6 uch }
646 1.6 uch
647 1.6 uch static void linebpp_unimpl __P((int, int, int, int));
648 1.6 uch static void dotbpp_unimpl __P((int, int));
649 1.6 uch static
650 1.6 uch void linebpp_unimpl(x0, y0, x1, y1)
651 1.6 uch int x0, y0, x1, y1;
652 1.6 uch {
653 1.6 uch return;
654 1.6 uch }
655 1.6 uch static
656 1.6 uch void dotbpp_unimpl(x, y)
657 1.6 uch int x, y;
658 1.6 uch {
659 1.6 uch return;
660 1.6 uch }
661 1.6 uch
662 1.6 uch LINEFUNC(2)
663 1.6 uch LINEFUNC(4)
664 1.6 uch LINEFUNC(8)
665 1.6 uch DOTFUNC(2)
666 1.6 uch DOTFUNC(4)
667 1.6 uch DOTFUNC(8)
668 1.6 uch
669 1.6 uch void
670 1.10 uch __tx3912video_attach_drawfunc(vc)
671 1.6 uch struct tx3912video_chip *vc;
672 1.6 uch {
673 1.6 uch switch (vc->vc_fbdepth) {
674 1.6 uch default:
675 1.6 uch vc->vc_drawline = linebpp_unimpl;
676 1.6 uch vc->vc_drawdot = dotbpp_unimpl;
677 1.6 uch break;
678 1.6 uch case 8:
679 1.6 uch vc->vc_drawline = linebpp8;
680 1.6 uch vc->vc_drawdot = dotbpp8;
681 1.6 uch break;
682 1.6 uch case 4:
683 1.6 uch vc->vc_drawline = linebpp4;
684 1.6 uch vc->vc_drawdot = dotbpp4;
685 1.6 uch break;
686 1.6 uch case 2:
687 1.6 uch vc->vc_drawline = linebpp2;
688 1.6 uch vc->vc_drawdot = dotbpp2;
689 1.6 uch break;
690 1.6 uch }
691 1.6 uch }
692 1.6 uch
693 1.6 uch void
694 1.6 uch tx3912video_line(x0, y0, x1, y1)
695 1.6 uch int x0, y0, x1, y1;
696 1.6 uch {
697 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
698 1.6 uch vc->vc_drawline(x0, y0, x1, y1);
699 1.6 uch }
700 1.6 uch
701 1.6 uch void
702 1.6 uch tx3912video_dot(x, y)
703 1.6 uch int x, y;
704 1.6 uch {
705 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
706 1.6 uch vc->vc_drawdot(x, y);
707 1.6 uch }
708