1 /* $NetBSD: tx3912video.c,v 1.39 2008/04/28 20:23:21 martin Exp $ */
4 * Copyright (c) 1999-2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: tx3912video.c,v 1.39 2008/04/28 20:23:21 martin Exp $");
35 #define TX3912VIDEO_DEBUG
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 #include <sys/extent.h>
45 #include <sys/ioctl.h>
48 #include <uvm/uvm_extern.h>
50 #include <dev/cons.h> /* consdev */
52 #include <machine/bus.h>
53 #include <machine/bootinfo.h>
54 #include <machine/config_hook.h>
56 #include <hpcmips/tx/tx39var.h>
57 #include <hpcmips/tx/tx3912videovar.h>
58 #include <hpcmips/tx/tx3912videoreg.h>
61 #include <dev/wscons/wsdisplayvar.h>
62 #include <dev/rasops/rasops.h>
63 #include <dev/hpc/video_subr.h>
65 #include <dev/wscons/wsconsio.h>
66 #include <dev/hpc/hpcfbvar.h>
67 #include <dev/hpc/hpcfbio.h>
69 #include <dev/hpc/bivideovar.h>
72 #ifdef TX3912VIDEO_DEBUG
73 int tx3912video_debug
= 1;
74 #define DPRINTF(arg) if (tx3912video_debug) printf arg;
75 #define DPRINTFN(n, arg) if (tx3912video_debug > (n)) printf arg;
78 #define DPRINTFN(n, arg)
81 struct tx3912video_softc
{
83 void *sc_powerhook
; /* power management hook */
85 struct hpcfb_fbconf sc_fbconf
;
86 struct hpcfb_dspconf sc_dspconf
;
87 struct video_chip
*sc_chip
;
90 /* TX3912 built-in video chip itself */
91 static struct video_chip tx3912video_chip
;
93 int tx3912video_power(void *, int, long, void *);
94 void tx3912video_framebuffer_init(struct video_chip
*);
95 int tx3912video_framebuffer_alloc(struct video_chip
*, paddr_t
, paddr_t
*);
96 void tx3912video_reset(struct video_chip
*);
97 void tx3912video_resolution_init(struct video_chip
*);
98 int tx3912video_match(struct device
*, struct cfdata
*, void *);
99 void tx3912video_attach(struct device
*, struct device
*, void *);
100 int tx3912video_print(void *, const char *);
102 void tx3912video_hpcfbinit(struct tx3912video_softc
*);
103 int tx3912video_ioctl(void *, u_long
, void *, int, struct lwp
*);
104 paddr_t
tx3912video_mmap(void *, off_t
, int);
106 void tx3912video_clut_init(struct tx3912video_softc
*);
107 void tx3912video_clut_install(void *, struct rasops_info
*);
108 void tx3912video_clut_get(struct tx3912video_softc
*, u_int32_t
*, int,
111 static int __get_color8(int);
112 static int __get_color4(int);
114 CFATTACH_DECL(tx3912video
, sizeof(struct tx3912video_softc
),
115 tx3912video_match
, tx3912video_attach
, NULL
, NULL
);
117 struct hpcfb_accessops tx3912video_ha
= {
118 tx3912video_ioctl
, tx3912video_mmap
, 0, 0, 0, 0,
119 tx3912video_clut_install
123 tx3912video_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
125 return (ATTACH_NORMAL
);
129 tx3912video_attach(struct device
*parent
, struct device
*self
, void *aux
)
131 struct tx3912video_softc
*sc
= (void *)self
;
132 struct video_chip
*chip
;
133 static const char *const depth_print
[] = {
134 [TX3912_VIDEOCTRL1_BITSEL_MONOCHROME
] = "monochrome",
135 [TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE
] = "2bit greyscale",
136 [TX3912_VIDEOCTRL1_BITSEL_4BITGREYSCALE
] = "4bit greyscale",
137 [TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR
] = "8bit color"
139 struct hpcfb_attach_args ha
;
144 sc
->sc_console
= console
= cn_tab
? 0 : 1;
145 sc
->sc_chip
= chip
= &tx3912video_chip
;
147 /* print video module information */
148 printf(": %s, frame buffer 0x%08x-0x%08x\n",
149 depth_print
[(ffs(chip
->vc_fbdepth
) - 1) & 0x3],
150 (unsigned)chip
->vc_fbpaddr
,
151 (unsigned)(chip
->vc_fbpaddr
+ chip
->vc_fbsize
));
153 /* don't inverse VDAT[3:0] signal */
155 val
= tx_conf_read(tc
, TX3912_VIDEOCTRL1_REG
);
156 val
&= ~TX3912_VIDEOCTRL1_INVVID
;
157 tx_conf_write(tc
, TX3912_VIDEOCTRL1_REG
, val
);
159 /* install default CLUT */
160 tx3912video_clut_init(sc
);
162 /* if serial console, power off video module */
163 tx3912video_power(sc
, 0, 0, (void *)
164 (console
? PWR_RESUME
: PWR_SUSPEND
));
166 /* Add a hard power hook to power saving */
167 sc
->sc_powerhook
= config_hook(CONFIG_HOOK_PMEVENT
,
168 CONFIG_HOOK_PMEVENT_HARDPOWER
, CONFIG_HOOK_SHARE
,
169 tx3912video_power
, sc
);
170 if (sc
->sc_powerhook
== 0)
171 printf("WARNING unable to establish hard power hook");
173 #ifdef TX3912VIDEO_DEBUG
174 /* attach debug draw routine (debugging use) */
175 video_attach_drawfunc(sc
->sc_chip
);
176 tx_conf_register_video(tc
, sc
->sc_chip
);
179 /* Attach frame buffer device */
180 tx3912video_hpcfbinit(sc
);
182 if (console
&& hpcfb_cnattach(&sc
->sc_fbconf
) != 0) {
183 panic("tx3912video_attach: can't init fb console");
186 ha
.ha_console
= console
;
187 ha
.ha_accessops
= &tx3912video_ha
;
188 ha
.ha_accessctx
= sc
;
191 ha
.ha_fbconflist
= &sc
->sc_fbconf
;
192 ha
.ha_curdspconf
= 0;
194 ha
.ha_dspconflist
= &sc
->sc_dspconf
;
196 config_found(self
, &ha
, hpcfbprint
);
198 /* bivideo is no longer need */
199 bivideo_dont_attach
= 1;
200 #endif /* NBIVIDEO > 0 */
204 tx3912video_power(void *ctx
, int type
, long id
, void *msg
)
206 struct tx3912video_softc
*sc
= ctx
;
207 struct video_chip
*chip
= sc
->sc_chip
;
208 tx_chipset_tag_t tc
= chip
->vc_v
;
215 return (0); /* serial console */
217 DPRINTF(("%s: ON\n", sc
->sc_dev
.dv_xname
));
218 val
= tx_conf_read(tc
, TX3912_VIDEOCTRL1_REG
);
219 val
|= (TX3912_VIDEOCTRL1_DISPON
| TX3912_VIDEOCTRL1_ENVID
);
220 tx_conf_write(tc
, TX3912_VIDEOCTRL1_REG
, val
);
225 DPRINTF(("%s: OFF\n", sc
->sc_dev
.dv_xname
));
226 val
= tx_conf_read(tc
, TX3912_VIDEOCTRL1_REG
);
227 val
&= ~(TX3912_VIDEOCTRL1_DISPON
| TX3912_VIDEOCTRL1_ENVID
);
228 tx_conf_write(tc
, TX3912_VIDEOCTRL1_REG
, val
);
236 tx3912video_hpcfbinit(struct tx3912video_softc
*sc
)
238 struct video_chip
*chip
= sc
->sc_chip
;
239 struct hpcfb_fbconf
*fb
= &sc
->sc_fbconf
;
240 vaddr_t fbvaddr
= (vaddr_t
)MIPS_PHYS_TO_KSEG1(chip
->vc_fbpaddr
);
242 memset(fb
, 0, sizeof(struct hpcfb_fbconf
));
244 fb
->hf_conf_index
= 0; /* configuration index */
245 fb
->hf_nconfs
= 1; /* how many configurations */
246 strncpy(fb
->hf_name
, "TX3912 built-in video", HPCFB_MAXNAMELEN
);
247 /* frame buffer name */
248 strncpy(fb
->hf_conf_name
, "LCD", HPCFB_MAXNAMELEN
);
249 /* configuration name */
250 fb
->hf_height
= chip
->vc_fbheight
;
251 fb
->hf_width
= chip
->vc_fbwidth
;
252 fb
->hf_baseaddr
= (u_long
)fbvaddr
;
253 fb
->hf_offset
= (u_long
)fbvaddr
-
254 mips_ptob(mips_btop(fbvaddr
));
255 /* frame buffer start offset */
256 fb
->hf_bytes_per_line
= (chip
->vc_fbwidth
* chip
->vc_fbdepth
)
259 fb
->hf_bytes_per_plane
= chip
->vc_fbheight
* fb
->hf_bytes_per_line
;
261 fb
->hf_access_flags
|= HPCFB_ACCESS_BYTE
;
262 fb
->hf_access_flags
|= HPCFB_ACCESS_WORD
;
263 fb
->hf_access_flags
|= HPCFB_ACCESS_DWORD
;
264 if (video_reverse_color())
265 fb
->hf_access_flags
|= HPCFB_ACCESS_REVERSE
;
268 switch (chip
->vc_fbdepth
) {
270 panic("tx3912video_hpcfbinit: not supported color depth");
273 fb
->hf_class
= HPCFB_CLASS_GRAYSCALE
;
274 fb
->hf_access_flags
|= HPCFB_ACCESS_STATIC
;
275 fb
->hf_pack_width
= 8;
276 fb
->hf_pixels_per_pack
= 4;
277 fb
->hf_pixel_width
= 2;
278 fb
->hf_class_data_length
= sizeof(struct hf_gray_tag
);
279 /* reserved for future use */
280 fb
->hf_u
.hf_gray
.hf_flags
= 0;
283 fb
->hf_class
= HPCFB_CLASS_INDEXCOLOR
;
284 fb
->hf_access_flags
|= HPCFB_ACCESS_STATIC
;
285 fb
->hf_pack_width
= 8;
286 fb
->hf_pixels_per_pack
= 1;
287 fb
->hf_pixel_width
= 8;
288 fb
->hf_class_data_length
= sizeof(struct hf_indexed_tag
);
289 /* reserved for future use */
290 fb
->hf_u
.hf_indexed
.hf_flags
= 0;
296 tx3912video_init(paddr_t fb_start
, paddr_t
*fb_end
)
298 struct video_chip
*chip
= &tx3912video_chip
;
301 int fbdepth
, reverse
, error
;
303 reverse
= video_reverse_color();
304 chip
->vc_v
= tc
= tx_conf_get_tag();
306 reg
= tx_conf_read(tc
, TX3912_VIDEOCTRL1_REG
);
307 fbdepth
= 1 << (TX3912_VIDEOCTRL1_BITSEL(reg
));
311 bootinfo
->fb_type
= reverse
? BIFB_D2_M2L_3
: BIFB_D2_M2L_0
;
314 /* XXX should implement rasops4.c */
316 bootinfo
->fb_type
= reverse
? BIFB_D2_M2L_3
: BIFB_D2_M2L_0
;
317 reg
= tx_conf_read(tc
, TX3912_VIDEOCTRL1_REG
);
318 TX3912_VIDEOCTRL1_BITSEL_CLR(reg
);
319 reg
= TX3912_VIDEOCTRL1_BITSEL_SET(reg
,
320 TX3912_VIDEOCTRL1_BITSEL_2BITGREYSCALE
);
321 tx_conf_write(tc
, TX3912_VIDEOCTRL1_REG
, reg
);
324 bootinfo
->fb_type
= reverse
? BIFB_D8_FF
: BIFB_D8_00
;
328 chip
->vc_fbdepth
= fbdepth
;
329 chip
->vc_fbwidth
= bootinfo
->fb_width
;
330 chip
->vc_fbheight
= bootinfo
->fb_height
;
332 /* Allocate framebuffer area */
333 error
= tx3912video_framebuffer_alloc(chip
, fb_start
, fb_end
);
338 tx3912video_resolution_init(chip
);
340 /* Use Windows CE setting. */
342 /* Set DMA transfer address to VID module */
343 tx3912video_framebuffer_init(chip
);
345 /* Syncronize framebuffer addr to frame signal */
346 tx3912video_reset(chip
);
348 bootinfo
->fb_line_bytes
= (chip
->vc_fbwidth
* fbdepth
) / NBBY
;
349 bootinfo
->fb_addr
= (void *)MIPS_PHYS_TO_KSEG1(chip
->vc_fbpaddr
);
355 tx3912video_framebuffer_alloc(struct video_chip
*chip
, paddr_t fb_start
,
356 paddr_t
*fb_end
/* buffer allocation hint */)
358 struct extent_fixed ex_fixed
[10];
363 /* calcurate frame buffer size */
364 size
= (chip
->vc_fbwidth
* chip
->vc_fbheight
* chip
->vc_fbdepth
) /
367 /* extent V-RAM region */
368 ex
= extent_create("Frame buffer address", fb_start
, *fb_end
,
369 0, (void *)ex_fixed
, sizeof ex_fixed
,
374 /* Allocate V-RAM area */
375 error
= extent_alloc_subregion(ex
, fb_start
, fb_start
+ size
- 1,
376 size
, TX3912_FRAMEBUFFER_ALIGNMENT
,
377 TX3912_FRAMEBUFFER_BOUNDARY
, EX_FAST
|EX_NOWAIT
, &addr
);
383 chip
->vc_fbpaddr
= addr
;
384 chip
->vc_fbvaddr
= MIPS_PHYS_TO_KSEG1(addr
);
385 chip
->vc_fbsize
= size
;
387 *fb_end
= addr
+ size
;
393 tx3912video_framebuffer_init(struct video_chip
*chip
)
395 u_int32_t fb_addr
, fb_size
, vaddr
, bank
, base
;
397 tx_chipset_tag_t tc
= chip
->vc_v
;
399 fb_addr
= chip
->vc_fbpaddr
;
400 fb_size
= chip
->vc_fbsize
;
402 /* XXX currently I don't set DFVAL, so force DF signal toggled on
404 reg
= tx_conf_read(tc
, TX3912_VIDEOCTRL1_REG
);
405 reg
&= ~TX3912_VIDEOCTRL1_DFMODE
;
406 tx_conf_write(tc
, TX3912_VIDEOCTRL1_REG
, reg
);
408 /* Set DMA transfer start and end address */
410 bank
= TX3912_VIDEOCTRL3_VIDBANK(fb_addr
);
411 base
= TX3912_VIDEOCTRL3_VIDBASEHI(fb_addr
);
412 reg
= TX3912_VIDEOCTRL3_VIDBANK_SET(0, bank
);
413 /* Upper address counter */
414 reg
= TX3912_VIDEOCTRL3_VIDBASEHI_SET(reg
, base
);
415 tx_conf_write(tc
, TX3912_VIDEOCTRL3_REG
, reg
);
417 /* Lower address counter */
418 base
= TX3912_VIDEOCTRL4_VIDBASELO(fb_addr
+ fb_size
);
419 reg
= TX3912_VIDEOCTRL4_VIDBASELO_SET(0, base
);
421 /* Set DF-signal rate */
422 reg
= TX3912_VIDEOCTRL4_DFVAL_SET(reg
, 0); /* XXX not yet*/
424 /* Set VIDDONE signal delay after FRAME signal */
426 tx_conf_write(tc
, TX3912_VIDEOCTRL4_REG
, reg
);
428 /* Clear frame buffer */
429 vaddr
= MIPS_PHYS_TO_KSEG1(fb_addr
);
430 memset((void*)vaddr
, 0, fb_size
);
434 tx3912video_resolution_init(struct video_chip
*chip
)
436 int h
, v
, split
, bit8
, horzval
, lineval
;
437 tx_chipset_tag_t tc
= chip
->vc_v
;
441 h
= chip
->vc_fbwidth
;
442 v
= chip
->vc_fbheight
;
443 reg
= tx_conf_read(tc
, TX3912_VIDEOCTRL1_REG
);
444 split
= reg
& TX3912_VIDEOCTRL1_DISPSPLIT
;
445 bit8
= (TX3912_VIDEOCTRL1_BITSEL(reg
) ==
446 TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR
);
447 val
= TX3912_VIDEOCTRL1_BITSEL(reg
);
449 if ((val
== TX3912_VIDEOCTRL1_BITSEL_8BITCOLOR
) && !split
) {
450 /* (LCD horizontal pixels / 8bit) * RGB - 1 */
451 horzval
= (h
/ 8) * 3 - 1;
455 lineval
= (split
? v
/ 2 : v
) - 1;
459 * probably This value should be determined from DFINT and LCDINT
461 reg
= TX3912_VIDEOCTRL2_VIDRATE_SET(0, horzval
+ 1);
462 /* Horizontal size of LCD */
463 reg
= TX3912_VIDEOCTRL2_HORZVAL_SET(reg
, horzval
);
464 /* # of lines for the LCD */
465 reg
= TX3912_VIDEOCTRL2_LINEVAL_SET(reg
, lineval
);
467 tx_conf_write(tc
, TX3912_VIDEOCTRL2_REG
, reg
);
471 tx3912video_reset(struct video_chip
*chip
)
473 tx_chipset_tag_t tc
= chip
->vc_v
;
476 reg
= tx_conf_read(tc
, TX3912_VIDEOCTRL1_REG
);
478 /* Disable video logic at end of this frame */
479 reg
|= TX3912_VIDEOCTRL1_ENFREEZEFRAME
;
480 tx_conf_write(tc
, TX3912_VIDEOCTRL1_REG
, reg
);
482 /* Wait for end of frame */
485 /* Make sure to disable video logic */
486 reg
&= ~TX3912_VIDEOCTRL1_ENVID
;
487 tx_conf_write(tc
, TX3912_VIDEOCTRL1_REG
, reg
);
491 /* Enable video logic again */
492 reg
&= ~TX3912_VIDEOCTRL1_ENFREEZEFRAME
;
493 reg
|= TX3912_VIDEOCTRL1_ENVID
;
494 tx_conf_write(tc
, TX3912_VIDEOCTRL1_REG
, reg
);
500 tx3912video_ioctl(void *v
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
502 struct tx3912video_softc
*sc
= (struct tx3912video_softc
*)v
;
503 struct hpcfb_fbconf
*fbconf
;
504 struct hpcfb_dspconf
*dspconf
;
505 struct wsdisplay_cmap
*cmap
;
511 case WSDISPLAYIO_GETCMAP
:
512 cmap
= (struct wsdisplay_cmap
*)data
;
516 if (sc
->sc_fbconf
.hf_class
!= HPCFB_CLASS_INDEXCOLOR
||
517 sc
->sc_fbconf
.hf_pack_width
!= 8 ||
518 !LEGAL_CLUT_INDEX(idx
) ||
519 !LEGAL_CLUT_INDEX(idx
+ cnt
- 1)) {
523 error
= cmap_work_alloc(&r
, &g
, &b
, &rgb
, cnt
);
526 tx3912video_clut_get(sc
, rgb
, idx
, cnt
);
527 rgb24_decompose(rgb
, r
, g
, b
, cnt
);
529 error
= copyout(r
, cmap
->red
, cnt
);
532 error
= copyout(g
, cmap
->green
,cnt
);
535 error
= copyout(b
, cmap
->blue
, cnt
);
538 cmap_work_free(r
, g
, b
, rgb
);
541 case WSDISPLAYIO_PUTCMAP
:
543 * TX3912 can't change CLUT index. R:G:B = 3:3:2
548 fbconf
= (struct hpcfb_fbconf
*)data
;
549 if (fbconf
->hf_conf_index
!= 0 &&
550 fbconf
->hf_conf_index
!= HPCFB_CURRENT_CONFIG
) {
553 *fbconf
= sc
->sc_fbconf
; /* structure assignment */
557 fbconf
= (struct hpcfb_fbconf
*)data
;
558 if (fbconf
->hf_conf_index
!= 0 &&
559 fbconf
->hf_conf_index
!= HPCFB_CURRENT_CONFIG
) {
563 * nothing to do because we have only one configuration
567 case HPCFBIO_GDSPCONF
:
568 dspconf
= (struct hpcfb_dspconf
*)data
;
569 if ((dspconf
->hd_unit_index
!= 0 &&
570 dspconf
->hd_unit_index
!= HPCFB_CURRENT_UNIT
) ||
571 (dspconf
->hd_conf_index
!= 0 &&
572 dspconf
->hd_conf_index
!= HPCFB_CURRENT_CONFIG
)) {
575 *dspconf
= sc
->sc_dspconf
; /* structure assignment */
578 case HPCFBIO_SDSPCONF
:
579 dspconf
= (struct hpcfb_dspconf
*)data
;
580 if ((dspconf
->hd_unit_index
!= 0 &&
581 dspconf
->hd_unit_index
!= HPCFB_CURRENT_UNIT
) ||
582 (dspconf
->hd_conf_index
!= 0 &&
583 dspconf
->hd_conf_index
!= HPCFB_CURRENT_CONFIG
)) {
588 * because we have only one unit and one configuration
594 /* XXX not implemented yet */
598 return (EPASSTHROUGH
);
602 tx3912video_mmap(void *ctx
, off_t offset
, int prot
)
604 struct tx3912video_softc
*sc
= (struct tx3912video_softc
*)ctx
;
606 if (offset
< 0 || (sc
->sc_fbconf
.hf_bytes_per_plane
+
607 sc
->sc_fbconf
.hf_offset
) < offset
) {
611 return (mips_btop(sc
->sc_chip
->vc_fbpaddr
+ offset
));
617 static const struct {
620 [TX3912_VIDEO_DITHER_DUTYCYCLE_1
] = { 1, 1 },
621 [TX3912_VIDEO_DITHER_DUTYCYCLE_6_7
] = { 6, 7 },
622 [TX3912_VIDEO_DITHER_DUTYCYCLE_4_5
] = { 4, 5 },
623 [TX3912_VIDEO_DITHER_DUTYCYCLE_3_4
] = { 3, 4 },
624 [TX3912_VIDEO_DITHER_DUTYCYCLE_5_7
] = { 5, 7 },
625 [TX3912_VIDEO_DITHER_DUTYCYCLE_2_3
] = { 2, 3 },
626 [TX3912_VIDEO_DITHER_DUTYCYCLE_3_5
] = { 3, 5 },
627 [TX3912_VIDEO_DITHER_DUTYCYCLE_4_7
] = { 4, 7 },
628 [TX3912_VIDEO_DITHER_DUTYCYCLE_2_4
] = { 2, 4 },
629 [TX3912_VIDEO_DITHER_DUTYCYCLE_3_7
] = { 3, 7 },
630 [TX3912_VIDEO_DITHER_DUTYCYCLE_2_5
] = { 2, 5 },
631 [TX3912_VIDEO_DITHER_DUTYCYCLE_1_3
] = { 1, 3 },
632 [TX3912_VIDEO_DITHER_DUTYCYCLE_2_7
] = { 2, 7 },
633 [TX3912_VIDEO_DITHER_DUTYCYCLE_1_5
] = { 1, 5 },
634 [TX3912_VIDEO_DITHER_DUTYCYCLE_1_7
] = { 1, 7 },
635 [TX3912_VIDEO_DITHER_DUTYCYCLE_0
] = { 0, 1 }
638 static const int dither_level8
[8] = {
639 TX3912_VIDEO_DITHER_DUTYCYCLE_0
,
640 TX3912_VIDEO_DITHER_DUTYCYCLE_2_7
,
641 TX3912_VIDEO_DITHER_DUTYCYCLE_2_5
,
642 TX3912_VIDEO_DITHER_DUTYCYCLE_2_4
,
643 TX3912_VIDEO_DITHER_DUTYCYCLE_3_5
,
644 TX3912_VIDEO_DITHER_DUTYCYCLE_5_7
,
645 TX3912_VIDEO_DITHER_DUTYCYCLE_4_5
,
646 TX3912_VIDEO_DITHER_DUTYCYCLE_1
,
649 static const int dither_level4
[4] = {
650 TX3912_VIDEO_DITHER_DUTYCYCLE_0
,
651 TX3912_VIDEO_DITHER_DUTYCYCLE_1_3
,
652 TX3912_VIDEO_DITHER_DUTYCYCLE_5_7
,
653 TX3912_VIDEO_DITHER_DUTYCYCLE_1
,
657 __get_color8(int luti
)
659 KASSERT(luti
>=0 && luti
< 8);
660 dlp
= &dither_list
[dither_level8
[luti
]];
662 return ((0xff * dlp
->mul
) / dlp
->div
);
666 __get_color4(int luti
)
668 KASSERT(luti
>=0 && luti
< 4);
669 dlp
= &dither_list
[dither_level4
[luti
]];
671 return ((0xff * dlp
->mul
) / dlp
->div
);
675 tx3912video_clut_get(struct tx3912video_softc
*sc
, u_int32_t
*rgb
, int beg
,
681 KASSERT(LEGAL_CLUT_INDEX(beg
));
682 KASSERT(LEGAL_CLUT_INDEX(beg
+ cnt
- 1));
684 for (i
= beg
; i
< beg
+ cnt
; i
++) {
685 *rgb
++ = RGB24(__get_color8((i
>> 5) & 0x7),
686 __get_color8((i
>> 2) & 0x7),
687 __get_color4(i
& 0x3));
692 tx3912video_clut_install(void *ctx
, struct rasops_info
*ri
)
694 struct tx3912video_softc
*sc
= ctx
;
695 static const int system_cmap
[0x10] = {
704 TX3912VIDEO_DARK_BLACK
,
705 TX3912VIDEO_DARK_RED
,
706 TX3912VIDEO_DARK_GREEN
,
707 TX3912VIDEO_DARK_YELLOW
,
708 TX3912VIDEO_DARK_BLUE
,
709 TX3912VIDEO_DARK_MAGENTA
,
710 TX3912VIDEO_DARK_CYAN
,
711 TX3912VIDEO_DARK_WHITE
,
716 if (sc
->sc_chip
->vc_fbdepth
== 8) {
717 /* XXX 2bit gray scale LUT not supported */
718 memcpy(ri
->ri_devcmap
, system_cmap
, sizeof system_cmap
);
723 tx3912video_clut_init(struct tx3912video_softc
*sc
)
725 tx_chipset_tag_t tc
= sc
->sc_chip
->vc_v
;
727 if (sc
->sc_chip
->vc_fbdepth
!= 8) {
728 return; /* XXX 2bit gray scale LUT not supported */
732 * time-based dithering pattern (TOSHIBA recommended pattern)
735 tx_conf_write(tc
, TX3912_VIDEOCTRL8_REG
,
736 TX3912_VIDEOCTRL8_PAT2_3_DEFAULT
);
738 tx_conf_write(tc
, TX3912_VIDEOCTRL9_REG
,
739 (TX3912_VIDEOCTRL9_PAT3_4_DEFAULT
<< 16) |
740 TX3912_VIDEOCTRL9_PAT2_4_DEFAULT
);
742 tx_conf_write(tc
, TX3912_VIDEOCTRL10_REG
,
743 TX3912_VIDEOCTRL10_PAT4_5_DEFAULT
);
745 tx_conf_write(tc
, TX3912_VIDEOCTRL11_REG
,
746 TX3912_VIDEOCTRL11_PAT3_5_DEFAULT
);
748 tx_conf_write(tc
, TX3912_VIDEOCTRL12_REG
,
749 TX3912_VIDEOCTRL12_PAT6_7_DEFAULT
);
751 tx_conf_write(tc
, TX3912_VIDEOCTRL13_REG
,
752 TX3912_VIDEOCTRL13_PAT5_7_DEFAULT
);
754 tx_conf_write(tc
, TX3912_VIDEOCTRL14_REG
,
755 TX3912_VIDEOCTRL14_PAT4_7_DEFAULT
);
758 * dither-pattern look-up table. (selected by uch)
761 tx_conf_write(tc
, TX3912_VIDEOCTRL5_REG
,
762 (dither_level8
[7] << 28) |
763 (dither_level8
[6] << 24) |
764 (dither_level8
[5] << 20) |
765 (dither_level8
[4] << 16) |
766 (dither_level8
[3] << 12) |
767 (dither_level8
[2] << 8) |
768 (dither_level8
[1] << 4) |
769 (dither_level8
[0] << 0));
771 tx_conf_write(tc
, TX3912_VIDEOCTRL6_REG
,
772 (dither_level8
[7] << 28) |
773 (dither_level8
[6] << 24) |
774 (dither_level8
[5] << 20) |
775 (dither_level8
[4] << 16) |
776 (dither_level8
[3] << 12) |
777 (dither_level8
[2] << 8) |
778 (dither_level8
[1] << 4) |
779 (dither_level8
[0] << 0));
780 /* blue (2bit gray scale also use this look-up table) */
781 tx_conf_write(tc
, TX3912_VIDEOCTRL7_REG
,
782 (dither_level4
[3] << 12) |
783 (dither_level4
[2] << 8) |
784 (dither_level4
[1] << 4) |
785 (dither_level4
[0] << 0));
787 tx3912video_reset(sc
->sc_chip
);