tx3912video.c revision 1.14 1 1.14 uch /* $NetBSD: tx3912video.c,v 1.14 2000/05/12 18:09:55 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.14 uch /* reserved for future use */
234 1.14 uch fb->hf_u.hf_gray.hf_flags = 0;
235 1.11 uch break;
236 1.11 uch case 8:
237 1.12 uch fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
238 1.11 uch fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
239 1.11 uch fb->hf_pack_width = 8;
240 1.11 uch fb->hf_pixels_per_pack = 1;
241 1.11 uch fb->hf_pixel_width = 8;
242 1.11 uch fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
243 1.14 uch /* reserved for future use */
244 1.14 uch fb->hf_u.hf_indexed.hf_flags = 0;
245 1.11 uch break;
246 1.11 uch }
247 1.1 uch }
248 1.1 uch
249 1.1 uch int
250 1.10 uch tx3912video_init(fb_start, fb_end)
251 1.10 uch paddr_t fb_start, *fb_end;
252 1.10 uch {
253 1.10 uch struct tx3912video_chip *chip = &tx3912video_chip;
254 1.1 uch tx_chipset_tag_t tc;
255 1.7 uch txreg_t reg;
256 1.10 uch int fbdepth;
257 1.10 uch int error;
258 1.1 uch
259 1.10 uch chip->vc_tc = tc = tx_conf_get_tag();
260 1.10 uch
261 1.10 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
262 1.10 uch fbdepth = 1 << (TX3912_VIDEOCTRL1_BITSEL(reg));
263 1.7 uch
264 1.10 uch switch (fbdepth) {
265 1.7 uch case 2:
266 1.7 uch bootinfo->fb_type = BIFB_D2_M2L_0;
267 1.7 uch break;
268 1.7 uch case 4:
269 1.7 uch /* XXX should implement rasops4.c */
270 1.10 uch fbdepth = 2;
271 1.7 uch bootinfo->fb_type = BIFB_D2_M2L_0;
272 1.7 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
273 1.7 uch TX3912_VIDEOCTRL1_BITSEL_CLR(reg);
274 1.7 uch reg = TX3912_VIDEOCTRL1_BITSEL_SET(
275 1.7 uch reg, TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE);
276 1.7 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
277 1.7 uch break;
278 1.7 uch case 8:
279 1.7 uch bootinfo->fb_type = BIFB_D8_FF;
280 1.7 uch break;
281 1.7 uch }
282 1.7 uch
283 1.10 uch tx3912video_chip.vc_fbdepth = fbdepth;
284 1.10 uch tx3912video_chip.vc_fbwidth = bootinfo->fb_width;
285 1.10 uch tx3912video_chip.vc_fbheight= bootinfo->fb_height;
286 1.7 uch
287 1.1 uch /* Allocate framebuffer area */
288 1.10 uch error = tx3912video_framebuffer_alloc(chip, fb_start, fb_end);
289 1.10 uch if (error != 0)
290 1.10 uch return (1);
291 1.10 uch
292 1.1 uch #if notyet
293 1.10 uch tx3912video_resolution_init(chip);
294 1.1 uch #else
295 1.1 uch /* Use Windows CE setting. */
296 1.1 uch #endif
297 1.1 uch /* Set DMA transfer address to VID module */
298 1.10 uch tx3912video_framebuffer_init(chip);
299 1.1 uch
300 1.1 uch /* Syncronize framebuffer addr to frame signal */
301 1.10 uch tx3912video_reset(chip);
302 1.1 uch
303 1.10 uch bootinfo->fb_line_bytes = (chip->vc_fbwidth * fbdepth) / NBBY;
304 1.10 uch bootinfo->fb_addr = (void *)MIPS_PHYS_TO_KSEG1(chip->vc_fbaddr);
305 1.10 uch
306 1.10 uch return (0);
307 1.1 uch }
308 1.1 uch
309 1.1 uch int
310 1.10 uch tx3912video_framebuffer_alloc(chip, fb_start, fb_end)
311 1.10 uch struct tx3912video_chip *chip;
312 1.10 uch paddr_t fb_start, *fb_end; /* buffer allocation hint */
313 1.1 uch {
314 1.10 uch struct extent_fixed ex_fixed[10];
315 1.1 uch struct extent *ex;
316 1.1 uch u_long addr, size;
317 1.10 uch int error;
318 1.10 uch
319 1.10 uch /* calcurate frame buffer size */
320 1.10 uch size = (chip->vc_fbwidth * chip->vc_fbheight * chip->vc_fbdepth) /
321 1.10 uch NBBY;
322 1.10 uch
323 1.10 uch /* extent V-RAM region */
324 1.10 uch ex = extent_create("Frame buffer address", fb_start, *fb_end,
325 1.10 uch 0, (caddr_t)ex_fixed, sizeof ex_fixed,
326 1.10 uch EX_NOWAIT);
327 1.10 uch if (ex == 0)
328 1.10 uch return (1);
329 1.1 uch
330 1.1 uch /* Allocate V-RAM area */
331 1.14 uch error = extent_alloc_subregion(ex, fb_start, fb_start + size - 1,
332 1.14 uch size, TX3912_FRAMEBUFFER_ALIGNMENT,
333 1.10 uch TX3912_FRAMEBUFFER_BOUNDARY,
334 1.10 uch EX_FAST|EX_NOWAIT, &addr);
335 1.10 uch extent_destroy(ex);
336 1.10 uch
337 1.10 uch if (error != 0) {
338 1.10 uch return (1);
339 1.1 uch }
340 1.10 uch
341 1.10 uch chip->vc_fbaddr = addr;
342 1.10 uch chip->vc_fbsize = size;
343 1.6 uch
344 1.10 uch *fb_end = addr + size;
345 1.1 uch
346 1.10 uch return (0);
347 1.1 uch }
348 1.1 uch
349 1.1 uch void
350 1.10 uch tx3912video_framebuffer_init(chip)
351 1.10 uch struct tx3912video_chip *chip;
352 1.1 uch {
353 1.10 uch u_int32_t fb_addr, fb_size, vaddr, bank, base;
354 1.10 uch txreg_t reg;
355 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
356 1.10 uch
357 1.10 uch fb_addr = chip->vc_fbaddr;
358 1.10 uch fb_size = chip->vc_fbsize;
359 1.1 uch
360 1.1 uch /* XXX currently I don't set DFVAL, so force DF signal toggled on
361 1.1 uch * XXX each frame. */
362 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
363 1.1 uch reg &= ~TX3912_VIDEOCTRL1_DFMODE;
364 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
365 1.1 uch
366 1.1 uch /* Set DMA transfer start and end address */
367 1.10 uch
368 1.1 uch bank = TX3912_VIDEOCTRL3_VIDBANK(fb_addr);
369 1.1 uch base = TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr);
370 1.1 uch reg = TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank);
371 1.1 uch /* Upper address counter */
372 1.1 uch reg = TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg, base);
373 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL3_REG, reg);
374 1.1 uch
375 1.1 uch /* Lower address counter */
376 1.1 uch base = TX3912_VIDEOCTRL4_VIDBASELO(fb_addr + fb_size);
377 1.1 uch reg = TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base);
378 1.1 uch
379 1.1 uch /* Set DF-signal rate */
380 1.1 uch reg = TX3912_VIDEOCTRL4_DFVAL_SET(reg, 0); /* XXX not yet*/
381 1.1 uch
382 1.1 uch /* Set VIDDONE signal delay after FRAME signal */
383 1.1 uch /* XXX not yet*/
384 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL4_REG, reg);
385 1.1 uch
386 1.1 uch /* Clear frame buffer */
387 1.1 uch vaddr = MIPS_PHYS_TO_KSEG1(fb_addr);
388 1.10 uch memset((void*)vaddr, 0, fb_size);
389 1.1 uch }
390 1.1 uch
391 1.1 uch void
392 1.10 uch tx3912video_resolution_init(chip)
393 1.10 uch struct tx3912video_chip *chip;
394 1.1 uch {
395 1.10 uch int h, v, split, bit8, horzval, lineval;
396 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
397 1.10 uch txreg_t reg;
398 1.10 uch u_int32_t val;
399 1.10 uch
400 1.10 uch h = chip->vc_fbwidth;
401 1.10 uch v = chip->vc_fbheight;
402 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
403 1.1 uch split = reg & TX3912_VIDEOCTRL1_DISPSPLIT;
404 1.1 uch bit8 = (TX3912_VIDEOCTRL1_BITSEL(reg) ==
405 1.1 uch TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR);
406 1.1 uch val = TX3912_VIDEOCTRL1_BITSEL(reg);
407 1.1 uch
408 1.1 uch if ((val == TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR) &&
409 1.1 uch !split) {
410 1.3 uch /* (LCD horizontal pixels / 8bit) * RGB - 1 */
411 1.3 uch horzval = (h / 8) * 3 - 1;
412 1.1 uch } else {
413 1.1 uch horzval = h / 4 - 1;
414 1.1 uch }
415 1.1 uch lineval = (split ? v / 2 : v) - 1;
416 1.1 uch
417 1.1 uch /* Video rate */
418 1.3 uch /* XXX
419 1.3 uch * probably This value should be determined from DFINT and LCDINT
420 1.3 uch */
421 1.1 uch reg = TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval + 1);
422 1.1 uch /* Horizontal size of LCD */
423 1.1 uch reg = TX3912_VIDEOCTRL2_HORZVAL_SET(reg, horzval);
424 1.1 uch /* # of lines for the LCD */
425 1.1 uch reg = TX3912_VIDEOCTRL2_LINEVAL_SET(reg, lineval);
426 1.1 uch
427 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL2_REG, reg);
428 1.1 uch }
429 1.1 uch
430 1.1 uch void
431 1.10 uch tx3912video_reset(chip)
432 1.10 uch struct tx3912video_chip *chip;
433 1.1 uch {
434 1.10 uch tx_chipset_tag_t tc = chip->vc_tc;
435 1.10 uch txreg_t reg;
436 1.1 uch
437 1.1 uch reg = tx_conf_read(tc, TX3912_VIDEOCTRL1_REG);
438 1.3 uch
439 1.1 uch /* Disable video logic at end of this frame */
440 1.1 uch reg |= TX3912_VIDEOCTRL1_ENFREEZEFRAME;
441 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
442 1.3 uch
443 1.1 uch /* Wait for end of frame */
444 1.10 uch delay(30 * 1000);
445 1.3 uch
446 1.1 uch /* Make sure to disable video logic */
447 1.1 uch reg &= ~TX3912_VIDEOCTRL1_ENVID;
448 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
449 1.3 uch
450 1.1 uch delay(1000);
451 1.3 uch
452 1.1 uch /* Enable video logic again */
453 1.1 uch reg &= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME;
454 1.1 uch reg |= TX3912_VIDEOCTRL1_ENVID;
455 1.1 uch tx_conf_write(tc, TX3912_VIDEOCTRL1_REG, reg);
456 1.3 uch
457 1.1 uch delay(1000);
458 1.1 uch }
459 1.1 uch
460 1.11 uch int
461 1.11 uch tx3912video_ioctl(v, cmd, data, flag, p)
462 1.11 uch void *v;
463 1.11 uch u_long cmd;
464 1.11 uch caddr_t data;
465 1.11 uch int flag;
466 1.11 uch struct proc *p;
467 1.11 uch {
468 1.11 uch struct tx3912video_softc *sc = (struct tx3912video_softc *)v;
469 1.11 uch struct hpcfb_fbconf *fbconf;
470 1.11 uch struct hpcfb_dspconf *dspconf;
471 1.12 uch struct wsdisplay_cmap *cmap;
472 1.12 uch u_int8_t *r, *g, *b;
473 1.12 uch u_int32_t *rgb;
474 1.12 uch int idx, cnt, error;
475 1.11 uch
476 1.11 uch switch (cmd) {
477 1.11 uch case WSDISPLAYIO_GETCMAP:
478 1.12 uch cmap = (struct wsdisplay_cmap*)data;
479 1.12 uch cnt = cmap->count;
480 1.12 uch idx = cmap->index;
481 1.12 uch
482 1.12 uch if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
483 1.12 uch sc->sc_fbconf.hf_pack_width != 8 ||
484 1.12 uch !LEGAL_CLUT_INDEX(idx) ||
485 1.12 uch !LEGAL_CLUT_INDEX(idx + cnt -1)) {
486 1.12 uch return (EINVAL);
487 1.12 uch }
488 1.12 uch
489 1.12 uch if (!uvm_useracc(cmap->red, cnt, B_WRITE) ||
490 1.12 uch !uvm_useracc(cmap->green, cnt, B_WRITE) ||
491 1.12 uch !uvm_useracc(cmap->blue, cnt, B_WRITE)) {
492 1.12 uch return (EFAULT);
493 1.12 uch }
494 1.12 uch
495 1.12 uch error = cmap_work_alloc(&r, &g, &b, &rgb, cnt);
496 1.12 uch if (error != 0) {
497 1.12 uch cmap_work_free(r, g, b, rgb);
498 1.12 uch return (ENOMEM);
499 1.12 uch }
500 1.12 uch tx3912video_clut_get(sc, rgb, idx, cnt);
501 1.12 uch rgb24_decompose(rgb, r, g, b, cnt);
502 1.12 uch
503 1.12 uch copyout(r, cmap->red, cnt);
504 1.12 uch copyout(g, cmap->green,cnt);
505 1.12 uch copyout(b, cmap->blue, cnt);
506 1.12 uch
507 1.12 uch cmap_work_free(r, g, b, rgb);
508 1.12 uch
509 1.12 uch return (0);
510 1.11 uch
511 1.11 uch case WSDISPLAYIO_PUTCMAP:
512 1.12 uch /*
513 1.12 uch * TX3912 can't change CLUT index. R:G:B = 3:3:2
514 1.12 uch */
515 1.14 uch return (0);
516 1.11 uch
517 1.11 uch case HPCFBIO_GCONF:
518 1.11 uch fbconf = (struct hpcfb_fbconf *)data;
519 1.11 uch if (fbconf->hf_conf_index != 0 &&
520 1.11 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
521 1.11 uch return (EINVAL);
522 1.11 uch }
523 1.11 uch *fbconf = sc->sc_fbconf; /* structure assignment */
524 1.11 uch return (0);
525 1.11 uch
526 1.11 uch case HPCFBIO_SCONF:
527 1.11 uch fbconf = (struct hpcfb_fbconf *)data;
528 1.11 uch if (fbconf->hf_conf_index != 0 &&
529 1.11 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
530 1.11 uch return (EINVAL);
531 1.11 uch }
532 1.11 uch /*
533 1.11 uch * nothing to do because we have only one configration
534 1.11 uch */
535 1.11 uch return (0);
536 1.11 uch
537 1.11 uch case HPCFBIO_GDSPCONF:
538 1.11 uch dspconf = (struct hpcfb_dspconf *)data;
539 1.11 uch if ((dspconf->hd_unit_index != 0 &&
540 1.11 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
541 1.11 uch (dspconf->hd_conf_index != 0 &&
542 1.11 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
543 1.11 uch return (EINVAL);
544 1.11 uch }
545 1.11 uch *dspconf = sc->sc_dspconf; /* structure assignment */
546 1.11 uch return (0);
547 1.11 uch
548 1.11 uch case HPCFBIO_SDSPCONF:
549 1.11 uch dspconf = (struct hpcfb_dspconf *)data;
550 1.11 uch if ((dspconf->hd_unit_index != 0 &&
551 1.11 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
552 1.11 uch (dspconf->hd_conf_index != 0 &&
553 1.11 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
554 1.11 uch return (EINVAL);
555 1.11 uch }
556 1.11 uch /*
557 1.11 uch * nothing to do
558 1.11 uch * because we have only one unit and one configration
559 1.11 uch */
560 1.11 uch return (0);
561 1.11 uch
562 1.11 uch case HPCFBIO_GOP:
563 1.11 uch case HPCFBIO_SOP:
564 1.11 uch /* XXX not implemented yet */
565 1.11 uch return (EINVAL);
566 1.11 uch }
567 1.11 uch
568 1.11 uch return (ENOTTY);
569 1.11 uch }
570 1.11 uch
571 1.11 uch int
572 1.11 uch tx3912video_mmap(ctx, offset, prot)
573 1.11 uch void *ctx;
574 1.11 uch off_t offset;
575 1.11 uch int prot;
576 1.11 uch {
577 1.11 uch struct tx3912video_softc *sc = (struct tx3912video_softc *)ctx;
578 1.11 uch
579 1.11 uch if (offset < 0 || (sc->sc_fbconf.hf_bytes_per_plane +
580 1.11 uch sc->sc_fbconf.hf_offset) < offset) {
581 1.11 uch return (-1);
582 1.11 uch }
583 1.11 uch
584 1.11 uch return (mips_btop(sc->sc_chip->vc_fbaddr + offset));
585 1.12 uch }
586 1.12 uch
587 1.12 uch /*
588 1.12 uch * CLUT staff
589 1.12 uch */
590 1.12 uch static const struct {
591 1.12 uch int mul, div;
592 1.12 uch } dither_list [] = {
593 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_1] = { 1, 1 },
594 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_6_7] = { 6, 7 },
595 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_4_5] = { 4, 5 },
596 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_3_4] = { 3, 4 },
597 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_5_7] = { 5, 7 },
598 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_2_3] = { 2, 3 },
599 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_3_5] = { 3, 5 },
600 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_4_7] = { 4, 7 },
601 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_2_4] = { 2, 4 },
602 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_3_7] = { 3, 7 },
603 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_2_5] = { 2, 5 },
604 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_1_3] = { 1, 3 },
605 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_2_7] = { 2, 7 },
606 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_1_5] = { 1, 5 },
607 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_1_7] = { 1, 7 },
608 1.12 uch [TX3912_VIDEO_DITHER_DUTYCYCLE_0] = { 0, 1 }
609 1.12 uch }, *dlp;
610 1.12 uch
611 1.12 uch static const int dither_level8[8] = {
612 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_0,
613 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_2_7,
614 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_2_5,
615 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_2_4,
616 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_3_5,
617 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_5_7,
618 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_4_5,
619 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_1,
620 1.12 uch };
621 1.12 uch
622 1.12 uch static const int dither_level4[4] = {
623 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_0,
624 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_1_3,
625 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_5_7,
626 1.12 uch TX3912_VIDEO_DITHER_DUTYCYCLE_1,
627 1.12 uch };
628 1.12 uch
629 1.12 uch static int
630 1.12 uch __get_color8(luti)
631 1.12 uch int luti;
632 1.12 uch {
633 1.12 uch KASSERT(luti >=0 && luti < 8);
634 1.12 uch dlp = &dither_list[dither_level8[luti]];
635 1.12 uch
636 1.12 uch return ((0xff * dlp->mul) / dlp->div);
637 1.12 uch }
638 1.12 uch
639 1.12 uch static int
640 1.12 uch __get_color4(luti)
641 1.12 uch int luti;
642 1.12 uch {
643 1.12 uch KASSERT(luti >=0 && luti < 4);
644 1.12 uch dlp = &dither_list[dither_level4[luti]];
645 1.12 uch
646 1.12 uch return ((0xff * dlp->mul) / dlp->div);
647 1.12 uch }
648 1.12 uch
649 1.12 uch void
650 1.12 uch tx3912video_clut_get(sc, rgb, beg, cnt)
651 1.12 uch struct tx3912video_softc *sc;
652 1.12 uch u_int32_t *rgb;
653 1.12 uch int beg, cnt;
654 1.12 uch {
655 1.12 uch int i;
656 1.12 uch
657 1.12 uch KASSERT(rgb);
658 1.12 uch KASSERT(LEGAL_CLUT_INDEX(beg));
659 1.12 uch KASSERT(LEGAL_CLUT_INDEX(beg + cnt - 1));
660 1.12 uch
661 1.14 uch for (i = beg; i < beg + cnt; i++) {
662 1.14 uch *rgb++ = RGB24(__get_color8((i >> 5) & 0x7),
663 1.12 uch __get_color8((i >> 2) & 0x7),
664 1.12 uch __get_color4(i & 0x3));
665 1.12 uch }
666 1.12 uch }
667 1.12 uch
668 1.12 uch void
669 1.12 uch tx3912video_clut_install(ctx, ri)
670 1.12 uch void *ctx;
671 1.12 uch struct rasops_info *ri;
672 1.12 uch {
673 1.12 uch struct tx3912video_softc *sc = ctx;
674 1.12 uch const int system_cmap[0x10] = {
675 1.12 uch TX3912VIDEO_BLACK,
676 1.12 uch TX3912VIDEO_RED,
677 1.12 uch TX3912VIDEO_GREEN,
678 1.12 uch TX3912VIDEO_YELLOW,
679 1.12 uch TX3912VIDEO_BLUE,
680 1.12 uch TX3912VIDEO_MAGENTA,
681 1.12 uch TX3912VIDEO_CYAN,
682 1.12 uch TX3912VIDEO_WHITE,
683 1.12 uch TX3912VIDEO_DARK_BLACK,
684 1.12 uch TX3912VIDEO_DARK_RED,
685 1.12 uch TX3912VIDEO_DARK_GREEN,
686 1.12 uch TX3912VIDEO_DARK_YELLOW,
687 1.12 uch TX3912VIDEO_DARK_BLUE,
688 1.12 uch TX3912VIDEO_DARK_MAGENTA,
689 1.12 uch TX3912VIDEO_DARK_CYAN,
690 1.12 uch TX3912VIDEO_DARK_WHITE,
691 1.12 uch };
692 1.12 uch
693 1.12 uch KASSERT(ri);
694 1.12 uch
695 1.12 uch if (sc->sc_chip->vc_fbdepth == 8) {
696 1.12 uch /* XXX 2bit gray scale LUT not supported */
697 1.12 uch memcpy(ri->ri_devcmap, system_cmap, sizeof system_cmap);
698 1.12 uch }
699 1.12 uch }
700 1.12 uch
701 1.12 uch void
702 1.12 uch tx3912video_clut_init(sc)
703 1.12 uch struct tx3912video_softc *sc;
704 1.12 uch {
705 1.12 uch tx_chipset_tag_t tc = sc->sc_chip->vc_tc;
706 1.12 uch
707 1.12 uch if (sc->sc_chip->vc_fbdepth != 8) {
708 1.12 uch return; /* XXX 2bit gray scale LUT not supported */
709 1.12 uch }
710 1.12 uch
711 1.12 uch /*
712 1.12 uch * time-based dithering pattern (TOSHIBA recommended pattern)
713 1.12 uch */
714 1.12 uch /* 2/3, 1/3 */
715 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL8_REG,
716 1.12 uch TX3912_VIDEOCTRL8_PAT2_3_DEFAULT);
717 1.12 uch /* 3/4, 2/4 */
718 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL9_REG,
719 1.12 uch (TX3912_VIDEOCTRL9_PAT3_4_DEFAULT << 16) |
720 1.12 uch TX3912_VIDEOCTRL9_PAT2_4_DEFAULT);
721 1.12 uch /* 4/5, 1/5 */
722 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL10_REG,
723 1.12 uch TX3912_VIDEOCTRL10_PAT4_5_DEFAULT);
724 1.12 uch /* 3/5, 2/5 */
725 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL11_REG,
726 1.12 uch TX3912_VIDEOCTRL11_PAT3_5_DEFAULT);
727 1.12 uch /* 6/7, 1/7 */
728 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL12_REG,
729 1.12 uch TX3912_VIDEOCTRL12_PAT6_7_DEFAULT);
730 1.12 uch /* 5/7, 2/7 */
731 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL13_REG,
732 1.12 uch TX3912_VIDEOCTRL13_PAT5_7_DEFAULT);
733 1.12 uch /* 4/7, 3/7 */
734 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL14_REG,
735 1.12 uch TX3912_VIDEOCTRL14_PAT4_7_DEFAULT);
736 1.12 uch
737 1.12 uch /*
738 1.12 uch * dither-pattern look-up table. (selected by uch)
739 1.12 uch */
740 1.12 uch /* red */
741 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL5_REG,
742 1.12 uch (dither_level8[7] << 28) |
743 1.12 uch (dither_level8[6] << 24) |
744 1.12 uch (dither_level8[5] << 20) |
745 1.12 uch (dither_level8[4] << 16) |
746 1.12 uch (dither_level8[3] << 12) |
747 1.12 uch (dither_level8[2] << 8) |
748 1.12 uch (dither_level8[1] << 4) |
749 1.12 uch (dither_level8[0] << 0));
750 1.12 uch /* green */
751 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL6_REG,
752 1.12 uch (dither_level8[7] << 28) |
753 1.12 uch (dither_level8[6] << 24) |
754 1.12 uch (dither_level8[5] << 20) |
755 1.12 uch (dither_level8[4] << 16) |
756 1.12 uch (dither_level8[3] << 12) |
757 1.12 uch (dither_level8[2] << 8) |
758 1.12 uch (dither_level8[1] << 4) |
759 1.12 uch (dither_level8[0] << 0));
760 1.12 uch /* blue (2bit gray scale also use this look-up table) */
761 1.12 uch tx_conf_write(tc, TX3912_VIDEOCTRL7_REG,
762 1.12 uch (dither_level4[3] << 12) |
763 1.12 uch (dither_level4[2] << 8) |
764 1.12 uch (dither_level4[1] << 4) |
765 1.12 uch (dither_level4[0] << 0));
766 1.14 uch
767 1.14 uch tx3912video_reset(sc->sc_chip);
768 1.11 uch }
769 1.11 uch
770 1.6 uch /*
771 1.6 uch * Debug routines.
772 1.6 uch */
773 1.6 uch void
774 1.6 uch tx3912video_calibration_pattern()
775 1.6 uch {
776 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
777 1.6 uch int x, y;
778 1.6 uch
779 1.6 uch x = vc->vc_fbwidth - 40;
780 1.6 uch y = vc->vc_fbheight - 40;
781 1.6 uch tx3912video_line(40, 40, x , 40);
782 1.6 uch tx3912video_line(x , 40, x , y );
783 1.6 uch tx3912video_line(x , y , 40, y );
784 1.6 uch tx3912video_line(40, y , 40, 40);
785 1.6 uch tx3912video_line(40, 40, x , y );
786 1.6 uch tx3912video_line(x, 40, 40, y );
787 1.6 uch }
788 1.6 uch
789 1.6 uch #define BPP2 ({ \
790 1.6 uch u_int8_t bitmap; \
791 1.6 uch bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
792 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
793 1.6 uch (bitmap & ~(0x3 << ((3 - (x % 4)) * 2))); \
794 1.6 uch })
795 1.6 uch
796 1.6 uch #define BPP4 ({ \
797 1.6 uch u_int8_t bitmap; \
798 1.6 uch bitmap = *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr); \
799 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = \
800 1.6 uch (bitmap & ~(0xf << ((1 - (x % 2)) * 4))); \
801 1.6 uch })
802 1.6 uch
803 1.6 uch #define BPP8 ({ \
804 1.6 uch *(volatile u_int8_t*)MIPS_PHYS_TO_KSEG1(addr) = 0xff; \
805 1.6 uch })
806 1.6 uch
807 1.6 uch #define BRESENHAM(a, b, c, d, func) ({ \
808 1.6 uch u_int32_t fbaddr = vc->vc_fbaddr; \
809 1.6 uch u_int32_t fbwidth = vc->vc_fbwidth; \
810 1.6 uch u_int32_t fbdepth = vc->vc_fbdepth; \
811 1.6 uch len = a, step = b -1; \
812 1.6 uch if (step == 0) \
813 1.6 uch return; \
814 1.6 uch kstep = len == 0 ? 0 : 1; \
815 1.6 uch for (i = k = 0, j = step / 2; i <= step; i++) { \
816 1.6 uch x = xbase c; \
817 1.6 uch y = ybase d; \
818 1.6 uch addr = fbaddr + (((y * fbwidth + x) * fbdepth) >> 3); \
819 1.6 uch func; \
820 1.6 uch j -= len; \
821 1.6 uch while (j < 0) { \
822 1.6 uch j += step; \
823 1.6 uch k += kstep; \
824 1.6 uch } \
825 1.6 uch } \
826 1.6 uch })
827 1.6 uch
828 1.6 uch #define DRAWLINE(func) ({ \
829 1.6 uch if (x < 0) { \
830 1.6 uch if (y < 0) { \
831 1.6 uch if (_y < _x) { \
832 1.6 uch BRESENHAM(_y, _x, -i, -k, func); \
833 1.6 uch } else { \
834 1.6 uch BRESENHAM(_x, _y, -k, -i, func); \
835 1.6 uch } \
836 1.6 uch } else { \
837 1.6 uch if (_y < _x) { \
838 1.6 uch BRESENHAM(_y, _x, -i, +k, func); \
839 1.6 uch } else { \
840 1.6 uch BRESENHAM(_x, _y, -k, +i, func); \
841 1.6 uch } \
842 1.6 uch } \
843 1.6 uch } else { \
844 1.6 uch if (y < 0) { \
845 1.6 uch if (_y < _x) { \
846 1.6 uch BRESENHAM(_y, _x, +i, -k, func); \
847 1.6 uch } else { \
848 1.6 uch BRESENHAM(_x, _y, +k, -i, func); \
849 1.6 uch } \
850 1.6 uch } else { \
851 1.6 uch if (_y < _x) { \
852 1.6 uch BRESENHAM(_y, _x, +i, +k, func); \
853 1.6 uch } else { \
854 1.6 uch BRESENHAM(_x, _y, +k, +i, func); \
855 1.6 uch } \
856 1.6 uch } \
857 1.6 uch } \
858 1.6 uch })
859 1.6 uch
860 1.6 uch #define LINEFUNC(b) \
861 1.6 uch static void linebpp##b __P((int, int, int, int)); \
862 1.6 uch static void \
863 1.6 uch linebpp##b##(x0, y0, x1, y1) \
864 1.6 uch int x0, y0, x1, y1; \
865 1.6 uch { \
866 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip; \
867 1.6 uch u_int32_t addr; \
868 1.6 uch int i, j, k, len, step, kstep; \
869 1.6 uch int x, _x, y, _y; \
870 1.6 uch int xbase, ybase; \
871 1.6 uch x = x1 - x0; \
872 1.6 uch y = y1 - y0; \
873 1.6 uch _x = abs(x); \
874 1.6 uch _y = abs(y); \
875 1.6 uch xbase = x0; \
876 1.6 uch ybase = y0; \
877 1.6 uch DRAWLINE(BPP##b##); \
878 1.6 uch }
879 1.1 uch
880 1.6 uch #define DOTFUNC(b) \
881 1.6 uch static void dotbpp##b __P((int, int)); \
882 1.6 uch static void \
883 1.6 uch dotbpp##b##(x, y) \
884 1.6 uch int x, y; \
885 1.6 uch { \
886 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip; \
887 1.6 uch u_int32_t addr; \
888 1.6 uch addr = vc->vc_fbaddr + (((y * vc->vc_fbwidth + x) * \
889 1.6 uch vc->vc_fbdepth) >> 3); \
890 1.6 uch BPP##b; \
891 1.6 uch }
892 1.6 uch
893 1.6 uch static void linebpp_unimpl __P((int, int, int, int));
894 1.6 uch static void dotbpp_unimpl __P((int, int));
895 1.6 uch static
896 1.6 uch void linebpp_unimpl(x0, y0, x1, y1)
897 1.6 uch int x0, y0, x1, y1;
898 1.6 uch {
899 1.6 uch return;
900 1.6 uch }
901 1.6 uch static
902 1.6 uch void dotbpp_unimpl(x, y)
903 1.6 uch int x, y;
904 1.6 uch {
905 1.6 uch return;
906 1.6 uch }
907 1.6 uch
908 1.6 uch LINEFUNC(2)
909 1.6 uch LINEFUNC(4)
910 1.6 uch LINEFUNC(8)
911 1.6 uch DOTFUNC(2)
912 1.6 uch DOTFUNC(4)
913 1.6 uch DOTFUNC(8)
914 1.6 uch
915 1.6 uch void
916 1.10 uch __tx3912video_attach_drawfunc(vc)
917 1.6 uch struct tx3912video_chip *vc;
918 1.6 uch {
919 1.6 uch switch (vc->vc_fbdepth) {
920 1.6 uch default:
921 1.6 uch vc->vc_drawline = linebpp_unimpl;
922 1.6 uch vc->vc_drawdot = dotbpp_unimpl;
923 1.6 uch break;
924 1.6 uch case 8:
925 1.6 uch vc->vc_drawline = linebpp8;
926 1.6 uch vc->vc_drawdot = dotbpp8;
927 1.6 uch break;
928 1.6 uch case 4:
929 1.6 uch vc->vc_drawline = linebpp4;
930 1.6 uch vc->vc_drawdot = dotbpp4;
931 1.6 uch break;
932 1.6 uch case 2:
933 1.6 uch vc->vc_drawline = linebpp2;
934 1.6 uch vc->vc_drawdot = dotbpp2;
935 1.6 uch break;
936 1.6 uch }
937 1.6 uch }
938 1.6 uch
939 1.6 uch void
940 1.6 uch tx3912video_line(x0, y0, x1, y1)
941 1.6 uch int x0, y0, x1, y1;
942 1.6 uch {
943 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
944 1.13 uch if (vc->vc_drawline)
945 1.13 uch vc->vc_drawline(x0, y0, x1, y1);
946 1.6 uch }
947 1.6 uch
948 1.6 uch void
949 1.6 uch tx3912video_dot(x, y)
950 1.6 uch int x, y;
951 1.6 uch {
952 1.6 uch struct tx3912video_chip *vc = &tx3912video_chip;
953 1.13 uch if (vc->vc_drawdot)
954 1.13 uch vc->vc_drawdot(x, y);
955 1.6 uch }
956