tx3912video.c revision 1.13 1 1.13 uch /* $NetBSD: tx3912video.c,v 1.13 2000/05/10 23:57:13 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.13 uch #undef TX3912VIDEO_DEBUG
29 1.10 uch
30 1.1 uch #include "opt_tx39_debug.h"
31 1.8 uch #include "hpcfb.h"
32 1.1 uch
33 1.1 uch #include <sys/param.h>
34 1.1 uch #include <sys/systm.h>
35 1.1 uch #include <sys/device.h>
36 1.1 uch #include <sys/extent.h>
37 1.1 uch
38 1.11 uch #include <sys/ioctl.h>
39 1.12 uch #include <sys/buf.h>
40 1.12 uch #include <vm/vm.h>
41 1.11 uch
42 1.1 uch #include <machine/bus.h>
43 1.10 uch #include <machine/bootinfo.h>
44 1.1 uch
45 1.1 uch #include <hpcmips/tx/tx39var.h>
46 1.1 uch #include <hpcmips/tx/tx3912videovar.h>
47 1.1 uch #include <hpcmips/tx/tx3912videoreg.h>
48 1.1 uch
49 1.12 uch /* CLUT */
50 1.12 uch #include <dev/wscons/wsdisplayvar.h>
51 1.12 uch #include <dev/rasops/rasops.h>
52 1.12 uch #include <arch/hpcmips/dev/video_subr.h>
53 1.12 uch
54 1.9 sato #include <dev/wscons/wsconsio.h>
55 1.8 uch #include <arch/hpcmips/dev/hpcfbvar.h>
56 1.8 uch #include <arch/hpcmips/dev/hpcfbio.h>
57 1.2 uch
58 1.10 uch static struct tx3912video_chip {
59 1.10 uch tx_chipset_tag_t vc_tc;
60 1.6 uch
61 1.10 uch paddr_t vc_fbaddr;
62 1.10 uch size_t vc_fbsize;
63 1.10 uch int vc_fbdepth;
64 1.10 uch int vc_fbwidth;
65 1.10 uch int vc_fbheight;
66 1.6 uch
67 1.11 uch void (*vc_drawline) __P((int, int, int, int)); /* for debug */
68 1.11 uch void (*vc_drawdot) __P((int, int)); /* for debug */
69 1.10 uch } tx3912video_chip;
70 1.6 uch
71 1.1 uch struct tx3912video_softc {
72 1.1 uch struct device sc_dev;
73 1.11 uch struct hpcfb_fbconf sc_fbconf;
74 1.11 uch struct hpcfb_dspconf sc_dspconf;
75 1.6 uch struct tx3912video_chip *sc_chip;
76 1.1 uch };
77 1.1 uch
78 1.11 uch void tx3912video_framebuffer_init __P((struct tx3912video_chip *));
79 1.11 uch int tx3912video_framebuffer_alloc __P((struct tx3912video_chip *, paddr_t,
80 1.10 uch paddr_t *));
81 1.11 uch void tx3912video_reset __P((struct tx3912video_chip *));
82 1.11 uch void tx3912video_resolution_init __P((struct tx3912video_chip *));
83 1.10 uch
84 1.10 uch int tx3912video_match __P((struct device *, struct cfdata *, void *));
85 1.10 uch void tx3912video_attach __P((struct device *, struct device *, void *));
86 1.10 uch int tx3912video_print __P((void *, const char *));
87 1.1 uch
88 1.11 uch void tx3912video_hpcfbinit __P((struct tx3912video_softc *));
89 1.11 uch int tx3912video_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
90 1.11 uch int tx3912video_mmap __P((void *, off_t, int));
91 1.11 uch
92 1.12 uch void tx3912video_clut_init __P((struct tx3912video_softc *));
93 1.12 uch void tx3912video_clut_install __P((void *, struct rasops_info *));
94 1.12 uch void tx3912video_clut_get __P((struct tx3912video_softc *,
95 1.12 uch u_int32_t *, int, int));
96 1.12 uch static int __get_color8 __P((int));
97 1.12 uch static int __get_color4 __P((int));
98 1.12 uch
99 1.1 uch struct cfattach tx3912video_ca = {
100 1.3 uch sizeof(struct tx3912video_softc), tx3912video_match,
101 1.3 uch tx3912video_attach
102 1.1 uch };
103 1.1 uch
104 1.11 uch struct hpcfb_accessops tx3912video_ha = {
105 1.12 uch tx3912video_ioctl, tx3912video_mmap, 0, 0, 0, 0,
106 1.12 uch tx3912video_clut_install
107 1.11 uch };
108 1.11 uch
109 1.10 uch void __tx3912video_attach_drawfunc __P((struct tx3912video_chip*));
110 1.6 uch
111 1.1 uch int
112 1.1 uch tx3912video_match(parent, cf, aux)
113 1.1 uch struct device *parent;
114 1.1 uch struct cfdata *cf;
115 1.1 uch void *aux;
116 1.1 uch {
117 1.10 uch return (1);
118 1.1 uch }
119 1.1 uch
120 1.1 uch void
121 1.1 uch tx3912video_attach(parent, self, aux)
122 1.1 uch struct device *parent;
123 1.1 uch struct device *self;
124 1.1 uch void *aux;
125 1.1 uch {
126 1.10 uch struct tx3912video_softc *sc = (void *)self;
127 1.10 uch struct tx3912video_chip *chip;
128 1.10 uch const char *depth_print[] = {
129 1.10 uch [TX3912_VIDEOCTRL1_BITSEL_MONOCHROME] = "monochrome",
130 1.10 uch [TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE] = "2bit greyscale",
131 1.10 uch [TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE] = "4bit greyscale",
132 1.10 uch [TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR] = "8bit color"
133 1.10 uch };
134 1.11 uch struct hpcfb_attach_args ha;
135 1.12 uch tx_chipset_tag_t tc;
136 1.12 uch txreg_t val;
137 1.11 uch int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
138 1.10 uch
139 1.10 uch sc->sc_chip = chip = &tx3912video_chip;
140 1.10 uch
141 1.10 uch /* print video module information */
142 1.10 uch printf(": %s, frame buffer 0x%08x-0x%08x\n",
143 1.10 uch depth_print[(ffs(chip->vc_fbdepth) - 1) & 0x3],
144 1.10 uch (unsigned)chip->vc_fbaddr,
145 1.10 uch (unsigned)(chip->vc_fbaddr + chip->vc_fbsize));
146 1.5 uch
147 1.12 uch /* don't inverse VDAT[3:0] signal */
148 1.12 uch tc = chip->vc_tc;
149 1.12 uch val = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
150 1.12 uch val &= ~TX3912_VIDEOCTRL1_INVVID;
151 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, val);
152 1.12 uch
153 1.12 uch /* install default CLUT */
154 1.12 uch tx3912video_clut_init(sc);
155 1.12 uch
156 1.10 uch /* if serial console, power off video module */
157 1.6 uch #ifndef TX3912VIDEO_DEBUG
158 1.11 uch if (!console) {
159 1.5 uch printf("%s: power off\n", sc->sc_dev.dv_xname);
160 1.13 uch val = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
161 1.13 uch val &= ~(TX3912_VIDEOCTRL1_DISPON |
162 1.4 uch TX3912_VIDEOCTRL1_ENVID);
163 1.13 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, val);
164 1.4 uch }
165 1.6 uch #endif /* TX3912VIDEO_DEBUG */
166 1.6 uch
167 1.13 uch #ifdef TX3912VIDEO_DEBUG
168 1.10 uch /* attach debug draw routine (debugging use) */
169 1.10 uch __tx3912video_attach_drawfunc(sc->sc_chip);
170 1.13 uch #endif
171 1.10 uch
172 1.1 uch /* Attach frame buffer device */
173 1.11 uch tx3912video_hpcfbinit(sc);
174 1.11 uch
175 1.11 uch if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
176 1.11 uch panic("tx3912video_attach: can't init fb console");
177 1.2 uch }
178 1.11 uch
179 1.11 uch ha.ha_console = console;
180 1.11 uch ha.ha_accessops = &tx3912video_ha;
181 1.11 uch ha.ha_accessctx = sc;
182 1.11 uch ha.ha_curfbconf = 0;
183 1.11 uch ha.ha_nfbconf = 1;
184 1.11 uch ha.ha_fbconflist = &sc->sc_fbconf;
185 1.11 uch ha.ha_curdspconf = 0;
186 1.11 uch ha.ha_ndspconf = 1;
187 1.11 uch ha.ha_dspconflist = &sc->sc_dspconf;
188 1.11 uch
189 1.11 uch config_found(self, &ha, hpcfbprint);
190 1.1 uch }
191 1.1 uch
192 1.11 uch void
193 1.11 uch tx3912video_hpcfbinit(sc)
194 1.11 uch struct tx3912video_softc *sc;
195 1.1 uch {
196 1.11 uch struct tx3912video_chip *chip = sc->sc_chip;
197 1.11 uch struct hpcfb_fbconf *fb = &sc->sc_fbconf;
198 1.13 uch vaddr_t fbvaddr = (vaddr_t)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
199 1.11 uch
200 1.11 uch memset(fb, 0, sizeof(struct hpcfb_fbconf));
201 1.11 uch
202 1.11 uch fb->hf_conf_index = 0; /* configuration index */
203 1.11 uch fb->hf_nconfs = 1; /* how many configurations */
204 1.12 uch strncpy(fb->hf_name, "TX3912 built-in video", HPCFB_MAXNAMELEN);
205 1.11 uch /* frame buffer name */
206 1.12 uch strncpy(fb->hf_conf_name, "LCD", HPCFB_MAXNAMELEN);
207 1.11 uch /* configuration name */
208 1.11 uch fb->hf_height = chip->vc_fbheight;
209 1.11 uch fb->hf_width = chip->vc_fbwidth;
210 1.13 uch fb->hf_baseaddr = mips_ptob(mips_btop(fbvaddr));
211 1.13 uch fb->hf_offset = (u_long)fbvaddr - fb->hf_baseaddr;
212 1.11 uch /* frame buffer start offset */
213 1.12 uch fb->hf_bytes_per_line = (chip->vc_fbwidth * chip->vc_fbdepth)
214 1.12 uch / NBBY;
215 1.11 uch fb->hf_nplanes = 1;
216 1.11 uch fb->hf_bytes_per_plane = chip->vc_fbheight * fb->hf_bytes_per_line;
217 1.11 uch
218 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
219 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_WORD;
220 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
221 1.11 uch
222 1.11 uch switch (chip->vc_fbdepth) {
223 1.11 uch default:
224 1.11 uch panic("tx3912video_hpcfbinit: not supported color depth\n");
225 1.11 uch /* NOTREACHED */
226 1.11 uch case 2:
227 1.11 uch fb->hf_class = HPCFB_CLASS_GRAYSCALE;
228 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
229 1.11 uch fb->hf_pack_width = 8;
230 1.11 uch fb->hf_pixels_per_pack = 4;
231 1.11 uch fb->hf_pixel_width = 2;
232 1.11 uch fb->hf_class_data_length = sizeof(struct hf_gray_tag);
233 1.11 uch fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
234 1.11 uch break;
235 1.11 uch case 8:
236 1.12 uch fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
237 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
238 1.11 uch fb->hf_pack_width = 8;
239 1.11 uch fb->hf_pixels_per_pack = 1;
240 1.11 uch fb->hf_pixel_width = 8;
241 1.11 uch fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
242 1.11 uch fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
243 1.11 uch break;
244 1.11 uch }
245 1.1 uch }
246 1.1 uch
247 1.1 uch int
248 1.10 uch tx3912video_init(fb_start, fb_end)
249 1.10 uch paddr_t fb_start, *fb_end;
250 1.10 uch {
251 1.10 uch struct tx3912video_chip *chip = &tx3912video_chip;
252 1.1 uch tx_chipset_tag_t tc;
253 1.7 uch txreg_t reg;
254 1.10 uch int fbdepth;
255 1.10 uch int error;
256 1.1 uch
257 1.10 uch chip->vc_tc = tc = tx_conf_get_tag();
258 1.10 uch
259 1.10 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
260 1.10 uch fbdepth = 1 << (TX3912_VIDEOCTRL1_BITSEL(reg));
261 1.7 uch
262 1.10 uch switch (fbdepth) {
263 1.7 uch case 2:
264 1.7 uch bootinfo->fb_type = BIFB_D2_M2L_0;
265 1.7 uch break;
266 1.7 uch case 4:
267 1.7 uch /* XXX should implement rasops4.c */
268 1.10 uch fbdepth = 2;
269 1.7 uch bootinfo->fb_type = BIFB_D2_M2L_0;
270 1.7 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
271 1.7 uch TX3912_VIDEOCTRL1_BITSEL_CLR(reg);
272 1.7 uch reg = TX3912_VIDEOCTRL1_BITSEL_SET(
273 1.7 uch reg, TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE);
274 1.7 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
275 1.7 uch break;
276 1.7 uch case 8:
277 1.7 uch bootinfo->fb_type = BIFB_D8_FF;
278 1.7 uch break;
279 1.7 uch }
280 1.7 uch
281 1.10 uch tx3912video_chip.vc_fbdepth = fbdepth;
282 1.10 uch tx3912video_chip.vc_fbwidth = bootinfo->fb_width;
283 1.10 uch tx3912video_chip.vc_fbheight= bootinfo->fb_height;
284 1.7 uch
285 1.1 uch /* Allocate framebuffer area */
286 1.10 uch error = tx3912video_framebuffer_alloc(chip, fb_start, fb_end);
287 1.10 uch if (error != 0)
288 1.10 uch return (1);
289 1.10 uch
290 1.1 uch #if notyet
291 1.10 uch tx3912video_resolution_init(chip);
292 1.1 uch #else
293 1.1 uch /* Use Windows CE setting. */
294 1.1 uch #endif
295 1.1 uch /* Set DMA transfer address to VID module */
296 1.10 uch tx3912video_framebuffer_init(chip);
297 1.1 uch
298 1.1 uch /* Syncronize framebuffer addr to frame signal */
299 1.10 uch tx3912video_reset(chip);
300 1.1 uch
301 1.10 uch bootinfo->fb_line_bytes = (chip->vc_fbwidth * fbdepth) / NBBY;
302 1.10 uch bootinfo->fb_addr = (void *)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
303 1.10 uch
304 1.10 uch return (0);
305 1.1 uch }
306 1.1 uch
307 1.1 uch int
308 1.10 uch tx3912video_framebuffer_alloc(chip, fb_start, fb_end)
309 1.10 uch struct tx3912video_chip *chip;
310 1.10 uch paddr_t fb_start, *fb_end; /* buffer allocation hint */
311 1.1 uch {
312 1.10 uch struct extent_fixed ex_fixed[10];
313 1.1 uch struct extent *ex;
314 1.1 uch u_long addr, size;
315 1.10 uch int error;
316 1.10 uch
317 1.10 uch /* calcurate frame buffer size */
318 1.10 uch size = (chip->vc_fbwidth * chip->vc_fbheight * chip->vc_fbdepth) /
319 1.10 uch NBBY;
320 1.10 uch
321 1.10 uch /* extent V-RAM region */
322 1.10 uch ex = extent_create("Frame buffer address", fb_start, *fb_end,
323 1.10 uch 0, (caddr_t)ex_fixed, sizeof ex_fixed,
324 1.10 uch EX_NOWAIT);
325 1.10 uch if (ex == 0)
326 1.10 uch return (1);
327 1.1 uch
328 1.1 uch /* Allocate V-RAM area */
329 1.10 uch error = extent_alloc_subregion(ex, fb_start, fb_start + size, size,
330 1.10 uch TX3912_FRAMEBUFFER_ALIGNMENT,
331 1.10 uch TX3912_FRAMEBUFFER_BOUNDARY,
332 1.10 uch EX_FAST|EX_NOWAIT, &addr);
333 1.10 uch extent_destroy(ex);
334 1.10 uch
335 1.10 uch if (error != 0) {
336 1.10 uch return (1);
337 1.1 uch }
338 1.10 uch
339 1.10 uch chip->vc_fbaddr = addr;
340 1.10 uch chip->vc_fbsize = size;
341 1.6 uch
342 1.10 uch *fb_end = addr + size;
343 1.1 uch
344 1.10 uch return (0);
345 1.1 uch }
346 1.1 uch
347 1.1 uch void
348 1.10 uch tx3912video_framebuffer_init(chip)
349 1.10 uch struct tx3912video_chip *chip;
350 1.1 uch {
351 1.10 uch u_int32_t fb_addr, fb_size, vaddr, bank, base;
352 1.10 uch txreg_t reg;
353 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
354 1.10 uch
355 1.10 uch fb_addr = chip->vc_fbaddr;
356 1.10 uch fb_size = chip->vc_fbsize;
357 1.1 uch
358 1.1 uch /* XXX currently I don't set DFVAL, so force DF signal toggled on
359 1.1 uch * XXX each frame. */
360 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
361 1.1 uch reg &= ~TX3912_VIDEOCTRL1_DFMODE;
362 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
363 1.1 uch
364 1.1 uch /* Set DMA transfer start and end address */
365 1.10 uch
366 1.1 uch bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
367 1.1 uch base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
368 1.1 uch reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
369 1.1 uch /* Upper address counter */
370 1.1 uch reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
371 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
372 1.1 uch
373 1.1 uch /* Lower address counter */
374 1.1 uch base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
375 1.1 uch reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
376 1.1 uch
377 1.1 uch /* Set DF-signal rate */
378 1.1 uch reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
379 1.1 uch
380 1.1 uch /* Set VIDDONE signal delay after FRAME signal */
381 1.1 uch /* XXX not yet*/
382 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
383 1.1 uch
384 1.1 uch /* Clear frame buffer */
385 1.1 uch vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
386 1.10 uch memset((void*)vaddr, 0, fb_size);
387 1.1 uch }
388 1.1 uch
389 1.1 uch void
390 1.10 uch tx3912video_resolution_init(chip)
391 1.10 uch struct tx3912video_chip *chip;
392 1.1 uch {
393 1.10 uch int h, v, split, bit8, horzval, lineval;
394 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
395 1.10 uch txreg_t reg;
396 1.10 uch u_int32_t val;
397 1.10 uch
398 1.10 uch h = chip->vc_fbwidth;
399 1.10 uch v = chip->vc_fbheight;
400 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
401 1.1 uch split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
402 1.1 uch bit8 = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
403 1.1 uch TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
404 1.1 uch val = TX3912_VIDEOCTRL1_BITSEL(reg);
405 1.1 uch
406 1.1 uch if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
407 1.1 uch !split) {
408 1.3 uch /* (LCD horizontal pixels / 8bit) * RGB - 1 */
409 1.3 uch horzval = (h / 8) * 3 - 1;
410 1.1 uch } else {
411 1.1 uch horzval = h / 4 - 1;
412 1.1 uch }
413 1.1 uch lineval = (split ? v / 2 : v) - 1;
414 1.1 uch
415 1.1 uch /* Video rate */
416 1.3 uch /* XXX
417 1.3 uch * probably This value should be determined from DFINT and LCDINT
418 1.3 uch */
419 1.1 uch reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
420 1.1 uch /* Horizontal size of LCD */
421 1.1 uch reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
422 1.1 uch /* # of lines for the LCD */
423 1.1 uch reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
424 1.1 uch
425 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
426 1.1 uch }
427 1.1 uch
428 1.1 uch void
429 1.10 uch tx3912video_reset(chip)
430 1.10 uch struct tx3912video_chip *chip;
431 1.1 uch {
432 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
433 1.10 uch txreg_t reg;
434 1.1 uch
435 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
436 1.3 uch
437 1.1 uch /* Disable video logic at end of this frame */
438 1.1 uch reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
439 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
440 1.3 uch
441 1.1 uch /* Wait for end of frame */
442 1.10 uch delay(30 * 1000);
443 1.3 uch
444 1.1 uch /* Make sure to disable video logic */
445 1.1 uch reg &= ~TX3912_VIDEOCTRL1_ENVID;
446 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
447 1.3 uch
448 1.1 uch delay(1000);
449 1.3 uch
450 1.1 uch /* Enable video logic again */
451 1.1 uch reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
452 1.1 uch reg |= TX3912_VIDEOCTRL1_ENVID;
453 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
454 1.3 uch
455 1.1 uch delay(1000);
456 1.1 uch }
457 1.1 uch
458 1.11 uch int
459 1.11 uch tx3912video_ioctl(v, cmd, data, flag, p)
460 1.11 uch void *v;
461 1.11 uch u_long cmd;
462 1.11 uch caddr_t data;
463 1.11 uch int flag;
464 1.11 uch struct proc *p;
465 1.11 uch {
466 1.11 uch struct tx3912video_softc *sc = (struct tx3912video_softc *)v;
467 1.11 uch struct hpcfb_fbconf *fbconf;
468 1.11 uch struct hpcfb_dspconf *dspconf;
469 1.12 uch struct wsdisplay_cmap *cmap;
470 1.12 uch u_int8_t *r, *g, *b;
471 1.12 uch u_int32_t *rgb;
472 1.12 uch int idx, cnt, error;
473 1.11 uch
474 1.11 uch switch (cmd) {
475 1.11 uch case WSDISPLAYIO_GETCMAP:
476 1.12 uch cmap = (struct wsdisplay_cmap*)data;
477 1.12 uch cnt = cmap->count;
478 1.12 uch idx = cmap->index;
479 1.12 uch
480 1.12 uch if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
481 1.12 uch sc->sc_fbconf.hf_pack_width != 8 ||
482 1.12 uch !LEGAL_CLUT_INDEX(idx) ||
483 1.12 uch !LEGAL_CLUT_INDEX(idx + cnt -1)) {
484 1.12 uch return (EINVAL);
485 1.12 uch }
486 1.12 uch
487 1.12 uch if (!uvm_useracc(cmap->red, cnt, B_WRITE) ||
488 1.12 uch !uvm_useracc(cmap->green, cnt, B_WRITE) ||
489 1.12 uch !uvm_useracc(cmap->blue, cnt, B_WRITE)) {
490 1.12 uch return (EFAULT);
491 1.12 uch }
492 1.12 uch
493 1.12 uch error = cmap_work_alloc(&r, &g, &b, &rgb, cnt);
494 1.12 uch if (error != 0) {
495 1.12 uch cmap_work_free(r, g, b, rgb);
496 1.12 uch return (ENOMEM);
497 1.12 uch }
498 1.12 uch tx3912video_clut_get(sc, rgb, idx, cnt);
499 1.12 uch rgb24_decompose(rgb, r, g, b, cnt);
500 1.12 uch
501 1.12 uch copyout(r, cmap->red, cnt);
502 1.12 uch copyout(g, cmap->green,cnt);
503 1.12 uch copyout(b, cmap->blue, cnt);
504 1.12 uch
505 1.12 uch cmap_work_free(r, g, b, rgb);
506 1.12 uch
507 1.12 uch return (0);
508 1.11 uch
509 1.11 uch case WSDISPLAYIO_PUTCMAP:
510 1.12 uch /*
511 1.12 uch * TX3912 can't change CLUT index. R:G:B = 3:3:2
512 1.12 uch */
513 1.11 uch return (EINVAL);
514 1.11 uch
515 1.11 uch case HPCFBIO_GCONF:
516 1.11 uch fbconf = (struct hpcfb_fbconf *)data;
517 1.11 uch if (fbconf->hf_conf_index != 0 &&
518 1.11 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
519 1.11 uch return (EINVAL);
520 1.11 uch }
521 1.11 uch *fbconf = sc->sc_fbconf; /* structure assignment */
522 1.11 uch return (0);
523 1.11 uch
524 1.11 uch case HPCFBIO_SCONF:
525 1.11 uch fbconf = (struct hpcfb_fbconf *)data;
526 1.11 uch if (fbconf->hf_conf_index != 0 &&
527 1.11 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
528 1.11 uch return (EINVAL);
529 1.11 uch }
530 1.11 uch /*
531 1.11 uch * nothing to do because we have only one configration
532 1.11 uch */
533 1.11 uch return (0);
534 1.11 uch
535 1.11 uch case HPCFBIO_GDSPCONF:
536 1.11 uch dspconf = (struct hpcfb_dspconf *)data;
537 1.11 uch if ((dspconf->hd_unit_index != 0 &&
538 1.11 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
539 1.11 uch (dspconf->hd_conf_index != 0 &&
540 1.11 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
541 1.11 uch return (EINVAL);
542 1.11 uch }
543 1.11 uch *dspconf = sc->sc_dspconf; /* structure assignment */
544 1.11 uch return (0);
545 1.11 uch
546 1.11 uch case HPCFBIO_SDSPCONF:
547 1.11 uch dspconf = (struct hpcfb_dspconf *)data;
548 1.11 uch if ((dspconf->hd_unit_index != 0 &&
549 1.11 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
550 1.11 uch (dspconf->hd_conf_index != 0 &&
551 1.11 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
552 1.11 uch return (EINVAL);
553 1.11 uch }
554 1.11 uch /*
555 1.11 uch * nothing to do
556 1.11 uch * because we have only one unit and one configration
557 1.11 uch */
558 1.11 uch return (0);
559 1.11 uch
560 1.11 uch case HPCFBIO_GOP:
561 1.11 uch case HPCFBIO_SOP:
562 1.11 uch /* XXX not implemented yet */
563 1.11 uch return (EINVAL);
564 1.11 uch }
565 1.11 uch
566 1.11 uch return (ENOTTY);
567 1.11 uch }
568 1.11 uch
569 1.11 uch int
570 1.11 uch tx3912video_mmap(ctx, offset, prot)
571 1.11 uch void *ctx;
572 1.11 uch off_t offset;
573 1.11 uch int prot;
574 1.11 uch {
575 1.11 uch struct tx3912video_softc *sc = (struct tx3912video_softc *)ctx;
576 1.11 uch
577 1.11 uch if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane +
578 1.11 uch sc->sc_fbconf.hf_offset) < offset) {
579 1.11 uch return (-1);
580 1.11 uch }
581 1.11 uch
582 1.11 uch return (mips_btop(sc->sc_chip->vc_fbaddr + offset));
583 1.12 uch }
584 1.12 uch
585 1.12 uch /*
586 1.12 uch * CLUT staff
587 1.12 uch */
588 1.12 uch static const struct {
589 1.12 uch int mul, div;
590 1.12 uch } dither_list [] = {
591 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_1] = { 1, 1 },
592 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_6_7] = { 6, 7 },
593 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_4_5] = { 4, 5 },
594 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_3_4] = { 3, 4 },
595 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_5_7] = { 5, 7 },
596 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_2_3] = { 2, 3 },
597 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_3_5] = { 3, 5 },
598 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_4_7] = { 4, 7 },
599 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_2_4] = { 2, 4 },
600 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_3_7] = { 3, 7 },
601 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_2_5] = { 2, 5 },
602 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_1_3] = { 1, 3 },
603 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_2_7] = { 2, 7 },
604 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_1_5] = { 1, 5 },
605 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_1_7] = { 1, 7 },
606 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_0] = { 0, 1 }
607 1.12 uch }, *dlp;
608 1.12 uch
609 1.12 uch static const int dither_level8[8] = {
610 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_0,
611 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_2_7,
612 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_2_5,
613 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_2_4,
614 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_3_5,
615 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_5_7,
616 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_4_5,
617 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_1,
618 1.12 uch };
619 1.12 uch
620 1.12 uch static const int dither_level4[4] = {
621 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_0,
622 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_1_3,
623 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_5_7,
624 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_1,
625 1.12 uch };
626 1.12 uch
627 1.12 uch static int
628 1.12 uch __get_color8(luti)
629 1.12 uch int luti;
630 1.12 uch {
631 1.12 uch KASSERT(luti >=0 && luti < 8);
632 1.12 uch dlp = &dither_list[dither_level8[luti]];
633 1.12 uch
634 1.12 uch return ((0xff * dlp->mul) / dlp->div);
635 1.12 uch }
636 1.12 uch
637 1.12 uch static int
638 1.12 uch __get_color4(luti)
639 1.12 uch int luti;
640 1.12 uch {
641 1.12 uch KASSERT(luti >=0 && luti < 4);
642 1.12 uch dlp = &dither_list[dither_level4[luti]];
643 1.12 uch
644 1.12 uch return ((0xff * dlp->mul) / dlp->div);
645 1.12 uch }
646 1.12 uch
647 1.12 uch void
648 1.12 uch tx3912video_clut_get(sc, rgb, beg, cnt)
649 1.12 uch struct tx3912video_softc *sc;
650 1.12 uch u_int32_t *rgb;
651 1.12 uch int beg, cnt;
652 1.12 uch {
653 1.12 uch int i;
654 1.12 uch
655 1.12 uch KASSERT(rgb);
656 1.12 uch KASSERT(LEGAL_CLUT_INDEX(beg));
657 1.12 uch KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1));
658 1.12 uch
659 1.12 uch for (i = 0; i < cnt; i++) {
660 1.12 uch rgb[i] = RGB24(__get_color8((i >> 5) & 0x7),
661 1.12 uch __get_color8((i >> 2) & 0x7),
662 1.12 uch __get_color4(i & 0x3));
663 1.12 uch }
664 1.12 uch }
665 1.12 uch
666 1.12 uch void
667 1.12 uch tx3912video_clut_install(ctx, ri)
668 1.12 uch void *ctx;
669 1.12 uch struct rasops_info *ri;
670 1.12 uch {
671 1.12 uch struct tx3912video_softc *sc = ctx;
672 1.12 uch const int system_cmap[0x10] = {
673 1.12 uch TX3912VIDEO_BLACK,
674 1.12 uch TX3912VIDEO_RED,
675 1.12 uch TX3912VIDEO_GREEN,
676 1.12 uch TX3912VIDEO_YELLOW,
677 1.12 uch TX3912VIDEO_BLUE,
678 1.12 uch TX3912VIDEO_MAGENTA,
679 1.12 uch TX3912VIDEO_CYAN,
680 1.12 uch TX3912VIDEO_WHITE,
681 1.12 uch TX3912VIDEO_DARK_BLACK,
682 1.12 uch TX3912VIDEO_DARK_RED,
683 1.12 uch TX3912VIDEO_DARK_GREEN,
684 1.12 uch TX3912VIDEO_DARK_YELLOW,
685 1.12 uch TX3912VIDEO_DARK_BLUE,
686 1.12 uch TX3912VIDEO_DARK_MAGENTA,
687 1.12 uch TX3912VIDEO_DARK_CYAN,
688 1.12 uch TX3912VIDEO_DARK_WHITE,
689 1.12 uch };
690 1.12 uch
691 1.12 uch KASSERT(ri);
692 1.12 uch
693 1.12 uch if (sc->sc_chip->vc_fbdepth == 8) {
694 1.12 uch /* XXX 2bit gray scale LUT not supported */
695 1.12 uch memcpy(ri->ri_devcmap, system_cmap, sizeof system_cmap);
696 1.12 uch }
697 1.12 uch }
698 1.12 uch
699 1.12 uch void
700 1.12 uch tx3912video_clut_init(sc)
701 1.12 uch struct tx3912video_softc *sc;
702 1.12 uch {
703 1.12 uch tx_chipset_tag_t tc = sc->sc_chip->vc_tc;
704 1.12 uch
705 1.12 uch if (sc->sc_chip->vc_fbdepth != 8) {
706 1.12 uch return; /* XXX 2bit gray scale LUT not supported */
707 1.12 uch }
708 1.12 uch
709 1.12 uch /*
710 1.12 uch * time-based dithering pattern (TOSHIBA recommended pattern)
711 1.12 uch */
712 1.12 uch /* 2/3, 1/3 */
713 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL8_REG,
714 1.12 uch TX3912_VIDEOCTRL8_PAT2_3_DEFAULT);
715 1.12 uch /* 3/4, 2/4 */
716 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL9_REG,
717 1.12 uch (TX3912_VIDEOCTRL9_PAT3_4_DEFAULT << 16) |
718 1.12 uch TX3912_VIDEOCTRL9_PAT2_4_DEFAULT);
719 1.12 uch /* 4/5, 1/5 */
720 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL10_REG,
721 1.12 uch TX3912_VIDEOCTRL10_PAT4_5_DEFAULT);
722 1.12 uch /* 3/5, 2/5 */
723 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL11_REG,
724 1.12 uch TX3912_VIDEOCTRL11_PAT3_5_DEFAULT);
725 1.12 uch /* 6/7, 1/7 */
726 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL12_REG,
727 1.12 uch TX3912_VIDEOCTRL12_PAT6_7_DEFAULT);
728 1.12 uch /* 5/7, 2/7 */
729 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL13_REG,
730 1.12 uch TX3912_VIDEOCTRL13_PAT5_7_DEFAULT);
731 1.12 uch /* 4/7, 3/7 */
732 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL14_REG,
733 1.12 uch TX3912_VIDEOCTRL14_PAT4_7_DEFAULT);
734 1.12 uch
735 1.12 uch /*
736 1.12 uch * dither-pattern look-up table. (selected by uch)
737 1.12 uch */
738 1.12 uch /* red */
739 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL5_REG,
740 1.12 uch (dither_level8[7] << 28) |
741 1.12 uch (dither_level8[6] << 24) |
742 1.12 uch (dither_level8[5] << 20) |
743 1.12 uch (dither_level8[4] << 16) |
744 1.12 uch (dither_level8[3] << 12) |
745 1.12 uch (dither_level8[2] << 8) |
746 1.12 uch (dither_level8[1] << 4) |
747 1.12 uch (dither_level8[0] << 0));
748 1.12 uch /* green */
749 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL6_REG,
750 1.12 uch (dither_level8[7] << 28) |
751 1.12 uch (dither_level8[6] << 24) |
752 1.12 uch (dither_level8[5] << 20) |
753 1.12 uch (dither_level8[4] << 16) |
754 1.12 uch (dither_level8[3] << 12) |
755 1.12 uch (dither_level8[2] << 8) |
756 1.12 uch (dither_level8[1] << 4) |
757 1.12 uch (dither_level8[0] << 0));
758 1.12 uch /* blue (2bit gray scale also use this look-up table) */
759 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL7_REG,
760 1.12 uch (dither_level4[3] << 12) |
761 1.12 uch (dither_level4[2] << 8) |
762 1.12 uch (dither_level4[1] << 4) |
763 1.12 uch (dither_level4[0] << 0));
764 1.11 uch }
765 1.11 uch
766 1.6 uch /*
767 1.6 uch * Debug routines.
768 1.6 uch */
769 1.6 uch void
770 1.6 uch tx3912video_calibration_pattern()
771 1.6 uch {
772 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
773 1.6 uch int x, y;
774 1.6 uch
775 1.6 uch x = vc->vc_fbwidth - 40;
776 1.6 uch y = vc->vc_fbheight - 40;
777 1.6 uch tx3912video_line(40, 40, x , 40);
778 1.6 uch tx3912video_line(x , 40, x , y );
779 1.6 uch tx3912video_line(x , y , 40, y );
780 1.6 uch tx3912video_line(40, y , 40, 40);
781 1.6 uch tx3912video_line(40, 40, x , y );
782 1.6 uch tx3912video_line(x, 40, 40, y );
783 1.6 uch }
784 1.6 uch
785 1.6 uch #define BPP2 ({ \
786 1.6 uch u_int8_t bitmap; \
787 1.6 uch bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
788 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
789 1.6 uch (bitmap & ~(0x3 << ((3 - (x % 4)) * 2))); \
790 1.6 uch })
791 1.6 uch
792 1.6 uch #define BPP4 ({ \
793 1.6 uch u_int8_t bitmap; \
794 1.6 uch bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
795 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
796 1.6 uch (bitmap & ~(0xf << ((1 - (x % 2)) * 4))); \
797 1.6 uch })
798 1.6 uch
799 1.6 uch #define BPP8 ({ \
800 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = 0xff; \
801 1.6 uch })
802 1.6 uch
803 1.6 uch #define BRESENHAM(a, b, c, d, func) ({ \
804 1.6 uch u_int32_t fbaddr = vc->vc_fbaddr; \
805 1.6 uch u_int32_t fbwidth = vc->vc_fbwidth; \
806 1.6 uch u_int32_t fbdepth = vc->vc_fbdepth; \
807 1.6 uch len = a, step = b -1; \
808 1.6 uch if (step == 0) \
809 1.6 uch return; \
810 1.6 uch kstep = len == 0 ? 0 : 1; \
811 1.6 uch for (i = k = 0, j = step / 2; i <= step; i++) { \
812 1.6 uch x = xbase c; \
813 1.6 uch y = ybase d; \
814 1.6 uch addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3); \
815 1.6 uch func; \
816 1.6 uch j -= len; \
817 1.6 uch while (j < 0) { \
818 1.6 uch j += step; \
819 1.6 uch k += kstep; \
820 1.6 uch } \
821 1.6 uch } \
822 1.6 uch })
823 1.6 uch
824 1.6 uch #define DRAWLINE(func) ({ \
825 1.6 uch if (x < 0) { \
826 1.6 uch if (y < 0) { \
827 1.6 uch if (_y < _x) { \
828 1.6 uch BRESENHAM(_y, _x, -i, -k, func); \
829 1.6 uch } else { \
830 1.6 uch BRESENHAM(_x, _y, -k, -i, func); \
831 1.6 uch } \
832 1.6 uch } else { \
833 1.6 uch if (_y < _x) { \
834 1.6 uch BRESENHAM(_y, _x, -i, +k, func); \
835 1.6 uch } else { \
836 1.6 uch BRESENHAM(_x, _y, -k, +i, func); \
837 1.6 uch } \
838 1.6 uch } \
839 1.6 uch } else { \
840 1.6 uch if (y < 0) { \
841 1.6 uch if (_y < _x) { \
842 1.6 uch BRESENHAM(_y, _x, +i, -k, func); \
843 1.6 uch } else { \
844 1.6 uch BRESENHAM(_x, _y, +k, -i, func); \
845 1.6 uch } \
846 1.6 uch } else { \
847 1.6 uch if (_y < _x) { \
848 1.6 uch BRESENHAM(_y, _x, +i, +k, func); \
849 1.6 uch } else { \
850 1.6 uch BRESENHAM(_x, _y, +k, +i, func); \
851 1.6 uch } \
852 1.6 uch } \
853 1.6 uch } \
854 1.6 uch })
855 1.6 uch
856 1.6 uch #define LINEFUNC(b) \
857 1.6 uch static void linebpp##b __P((int, int, int, int)); \
858 1.6 uch static void \
859 1.6 uch linebpp##b##(x0, y0, x1, y1) \
860 1.6 uch int x0, y0, x1, y1; \
861 1.6 uch { \
862 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip; \
863 1.6 uch u_int32_t addr; \
864 1.6 uch int i, j, k, len, step, kstep; \
865 1.6 uch int x, _x, y, _y; \
866 1.6 uch int xbase, ybase; \
867 1.6 uch x = x1 - x0; \
868 1.6 uch y = y1 - y0; \
869 1.6 uch _x = abs(x); \
870 1.6 uch _y = abs(y); \
871 1.6 uch xbase = x0; \
872 1.6 uch ybase = y0; \
873 1.6 uch DRAWLINE(BPP##b##); \
874 1.6 uch }
875 1.1 uch
876 1.6 uch #define DOTFUNC(b) \
877 1.6 uch static void dotbpp##b __P((int, int)); \
878 1.6 uch static void \
879 1.6 uch dotbpp##b##(x, y) \
880 1.6 uch int x, y; \
881 1.6 uch { \
882 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip; \
883 1.6 uch u_int32_t addr; \
884 1.6 uch addr = vc->vc_fbaddr + (((y * vc->vc_fbwidth + x) * \
885 1.6 uch vc->vc_fbdepth) >> 3); \
886 1.6 uch BPP##b; \
887 1.6 uch }
888 1.6 uch
889 1.6 uch static void linebpp_unimpl __P((int, int, int, int));
890 1.6 uch static void dotbpp_unimpl __P((int, int));
891 1.6 uch static
892 1.6 uch void linebpp_unimpl(x0, y0, x1, y1)
893 1.6 uch int x0, y0, x1, y1;
894 1.6 uch {
895 1.6 uch return;
896 1.6 uch }
897 1.6 uch static
898 1.6 uch void dotbpp_unimpl(x, y)
899 1.6 uch int x, y;
900 1.6 uch {
901 1.6 uch return;
902 1.6 uch }
903 1.6 uch
904 1.6 uch LINEFUNC(2)
905 1.6 uch LINEFUNC(4)
906 1.6 uch LINEFUNC(8)
907 1.6 uch DOTFUNC(2)
908 1.6 uch DOTFUNC(4)
909 1.6 uch DOTFUNC(8)
910 1.6 uch
911 1.6 uch void
912 1.10 uch __tx3912video_attach_drawfunc(vc)
913 1.6 uch struct tx3912video_chip *vc;
914 1.6 uch {
915 1.6 uch switch (vc->vc_fbdepth) {
916 1.6 uch default:
917 1.6 uch vc->vc_drawline = linebpp_unimpl;
918 1.6 uch vc->vc_drawdot = dotbpp_unimpl;
919 1.6 uch break;
920 1.6 uch case 8:
921 1.6 uch vc->vc_drawline = linebpp8;
922 1.6 uch vc->vc_drawdot = dotbpp8;
923 1.6 uch break;
924 1.6 uch case 4:
925 1.6 uch vc->vc_drawline = linebpp4;
926 1.6 uch vc->vc_drawdot = dotbpp4;
927 1.6 uch break;
928 1.6 uch case 2:
929 1.6 uch vc->vc_drawline = linebpp2;
930 1.6 uch vc->vc_drawdot = dotbpp2;
931 1.6 uch break;
932 1.6 uch }
933 1.6 uch }
934 1.6 uch
935 1.6 uch void
936 1.6 uch tx3912video_line(x0, y0, x1, y1)
937 1.6 uch int x0, y0, x1, y1;
938 1.6 uch {
939 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
940 1.13 uch if (vc->vc_drawline)
941 1.13 uch vc->vc_drawline(x0, y0, x1, y1);
942 1.6 uch }
943 1.6 uch
944 1.6 uch void
945 1.6 uch tx3912video_dot(x, y)
946 1.6 uch int x, y;
947 1.6 uch {
948 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
949 1.13 uch if (vc->vc_drawdot)
950 1.13 uch vc->vc_drawdot(x, y);
951 1.6 uch }
952