1 /* $NetBSD: pxa2x0_lcd.c,v 1.26 2007/10/17 19:53:44 garbled Exp $ */
4 * Copyright (c) 2002 Genetec Corporation. All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project by
18 * Genetec Corporation.
19 * 4. The name of Genetec Corporation may not be used to endorse or
20 * promote products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
37 * Support PXA2[15]0's integrated LCD controller.
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: pxa2x0_lcd.c,v 1.26 2007/10/17 19:53:44 garbled Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
47 #include <sys/malloc.h>
48 #include <sys/kernel.h> /* for cold */
50 #include <uvm/uvm_extern.h>
53 #include <dev/wscons/wsconsio.h>
54 #include <dev/wscons/wsdisplayvar.h>
55 #include <dev/wscons/wscons_callbacks.h>
56 #include <dev/rasops/rasops.h>
57 #include <dev/wsfont/wsfont.h>
59 #include <machine/bus.h>
60 #include <machine/cpu.h>
61 #include <arm/cpufunc.h>
63 #include <arm/xscale/pxa2x0cpu.h>
64 #include <arm/xscale/pxa2x0var.h>
65 #include <arm/xscale/pxa2x0reg.h>
66 #include <arm/xscale/pxa2x0_lcd.h>
67 #include <arm/xscale/pxa2x0_gpio.h>
69 #include "wsdisplay.h"
72 * Console variables. These are necessary since console is setup very early,
73 * before devices get attached.
77 struct pxa2x0_wsscreen_descr
*descr
;
78 const struct lcd_panel_geometry
*geom
;
83 static void pxa2x0_lcd_initialize(struct pxa2x0_lcd_softc
*,
84 const struct lcd_panel_geometry
*);
85 static void pxa2x0_lcd_setup_rasops(struct pxa2x0_lcd_softc
*,
86 struct rasops_info
*, struct pxa2x0_wsscreen_descr
*,
87 const struct lcd_panel_geometry
*);
90 pxa2x0_lcd_geometry(struct pxa2x0_lcd_softc
*sc
,
91 const struct lcd_panel_geometry
*info
)
94 bus_space_handle_t ioh
;
104 ccr0
|= LCCR0_CMDIM
|LCCR0_RDSTM
|LCCR0_LDDALT
;
105 if (info
->panel_info
& LCDPANEL_ACTIVE
)
106 ccr0
|= LCCR0_PAS
; /* active mode */
107 if ((info
->panel_info
& (LCDPANEL_DUAL
|LCDPANEL_ACTIVE
))
109 ccr0
|= LCCR0_SDS
; /* dual panel */
110 if (info
->panel_info
& LCDPANEL_MONOCHROME
)
112 bus_space_write_4(iot
, ioh
, LCDC_LCCR0
, ccr0
);
114 bus_space_write_4(iot
, ioh
, LCDC_LCCR1
,
115 (info
->panel_width
-1)
116 | ((info
->hsync_pulse_width
-1)<<10)
117 | ((info
->end_line_wait
-1)<<16)
118 | ((info
->beg_line_wait
-1)<<24));
120 if (info
->panel_info
& LCDPANEL_DUAL
)
121 lines
= info
->panel_height
/2 + info
->extra_lines
;
123 lines
= info
->panel_height
+ info
->extra_lines
;
125 bus_space_write_4(iot
, ioh
, LCDC_LCCR2
,
127 | (info
->vsync_pulse_width
<<10)
128 | (info
->end_frame_wait
<<16)
129 | (info
->beg_frame_wait
<<24));
131 bus_space_write_4(iot
, ioh
, LCDC_LCCR3
,
132 (info
->pixel_clock_div
<<0)
133 | (info
->ac_bias
<< 8)
134 | ((info
->panel_info
&
135 (LCDPANEL_VSP
|LCDPANEL_HSP
|LCDPANEL_PCP
|LCDPANEL_OEP
))
137 | (4 << 24) /* 16bpp */
138 | ((info
->panel_info
& LCDPANEL_DPC
) ? (1<<27) : 0)
141 bus_space_write_4(iot
, ioh
, LCDC_LCCR4
, (info
->pcd_div
<< 31));
145 * Initialize the LCD controller.
148 pxa2x0_lcd_initialize(struct pxa2x0_lcd_softc
*sc
,
149 const struct lcd_panel_geometry
*geom
)
152 bus_space_handle_t ioh
;
153 uint32_t lccr0
, lscr
;
159 /* Check if LCD is enabled before programming, it should not
160 * be enabled while it is being reprogrammed, therefore disable
163 lccr0
= bus_space_read_4(iot
, ioh
, LCDC_LCCR0
);
164 if (lccr0
& LCCR0_ENB
) {
166 bus_space_write_4(iot
, ioh
, LCDC_LCCR0
, lccr0
);
167 lccr0
= bus_space_read_4(iot
, ioh
, LCDC_LCCR0
); /* paranoia */
169 bus_space_write_4(iot
, ioh
, LCDC_LCCR0
, lccr0
);
171 lscr
= bus_space_read_4(iot
, ioh
, LCDC_LCSR
);
172 } while (!(lscr
& LCSR_LDD
));
176 pxa2x0_clkman_config(CKEN_LCD
, 1);
180 lccr0
|= LCCR0_CMDIM
|LCCR0_RDSTM
;
181 bus_space_write_4(iot
, ioh
, LCDC_LCCR0
, lccr0
);
184 * setup GP[77:58] for LCD
186 /* Always use [FLP]CLK, ACBIAS */
187 pxa2x0_gpio_set_function(74, GPIO_ALT_FN_2_OUT
);
188 pxa2x0_gpio_set_function(75, GPIO_ALT_FN_2_OUT
);
189 pxa2x0_gpio_set_function(76, GPIO_ALT_FN_2_OUT
);
190 if (!ISSET(sc
->flags
, FLAG_NOUSE_ACBIAS
))
191 pxa2x0_gpio_set_function(77, GPIO_ALT_FN_2_OUT
);
193 if ((geom
->panel_info
& LCDPANEL_ACTIVE
) ||
194 ((geom
->panel_info
& (LCDPANEL_MONOCHROME
|LCDPANEL_DUAL
)) ==
196 /* active and color dual panel need L_DD[15:0] */
198 } else if ((geom
->panel_info
& LCDPANEL_DUAL
) ||
199 !(geom
->panel_info
& LCDPANEL_MONOCHROME
)) {
200 /* dual or color need L_DD[7:0] */
203 /* Otherwise just L_DD[3:0] */
208 pxa2x0_gpio_set_function(58 + nldd
, GPIO_ALT_FN_2_OUT
);
210 pxa2x0_lcd_geometry(sc
, geom
);
214 * Common driver attachment code.
217 pxa2x0_lcd_attach_sub(struct pxa2x0_lcd_softc
*sc
,
218 struct pxaip_attach_args
*pxa
, const struct lcd_panel_geometry
*geom
)
220 bus_space_tag_t iot
= pxa
->pxa_iot
;
221 bus_space_handle_t ioh
;
224 aprint_normal(": PXA2x0 LCD controller\n");
228 LIST_INIT(&sc
->screens
);
230 /* map controller registers */
231 error
= bus_space_map(iot
, PXA2X0_LCDC_BASE
, PXA2X0_LCDC_SIZE
, 0, &ioh
);
233 aprint_error_dev(sc
->dev
,
234 "failed to map registers (errno=%d)\n", error
);
240 sc
->dma_tag
= &pxa2x0_bus_dma_tag
;
242 sc
->ih
= pxa2x0_intr_establish(PXA2X0_INT_LCD
, IPL_BIO
, lcdintr
, sc
);
243 if (sc
->ih
== NULL
) {
244 aprint_error_dev(sc
->dev
,
245 "unable to establish interrupt at irq %d\n",
250 pxa2x0_lcd_initialize(sc
, geom
);
252 if (pxa2x0_lcd_console
.is_console
) {
253 struct pxa2x0_wsscreen_descr
*descr
= pxa2x0_lcd_console
.descr
;
254 struct pxa2x0_lcd_screen
*scr
;
255 struct rasops_info
*ri
;
258 error
= pxa2x0_lcd_new_screen(sc
, descr
->depth
, &scr
);
260 aprint_error_dev(sc
->dev
,
261 "unable to create new screen (errno=%d)", error
);
266 ri
->ri_hw
= (void *)scr
;
267 ri
->ri_bits
= scr
->buf_va
;
268 pxa2x0_lcd_setup_rasops(sc
, ri
, descr
, geom
);
271 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
273 pxa2x0_lcd_start_dma(sc
, scr
);
276 wsdisplay_cnattach(&descr
->c
, ri
, ri
->ri_ccol
, ri
->ri_crow
,
279 aprint_normal_dev(sc
->dev
, "console\n");
284 pxa2x0_lcd_cnattach(struct pxa2x0_wsscreen_descr
*descr
,
285 const struct lcd_panel_geometry
*geom
)
288 pxa2x0_lcd_console
.descr
= descr
;
289 pxa2x0_lcd_console
.geom
= geom
;
290 pxa2x0_lcd_console
.is_console
= 1;
301 struct pxa2x0_lcd_softc
*sc
= (struct pxa2x0_lcd_softc
*)arg
;
302 bus_space_tag_t iot
= sc
->iot
;
303 bus_space_handle_t ioh
= sc
->ioh
;
306 status
= bus_space_read_4(iot
, ioh
, LCDC_LCSR
);
307 /* Clear stickey status bits */
308 bus_space_write_4(iot
, ioh
, LCDC_LCSR
, status
);
314 * Enable DMA to cause the display to be refreshed periodically.
315 * This brings the screen to life...
318 pxa2x0_lcd_start_dma(struct pxa2x0_lcd_softc
*sc
,
319 struct pxa2x0_lcd_screen
*scr
)
322 bus_space_handle_t ioh
;
329 save
= disable_interrupts(I32_bit
);
331 switch (scr
->depth
) {
332 case 1: val
= 0; break;
333 case 2: val
= 1; break;
334 case 4: val
= 2; break;
335 case 8: val
= 3; break;
336 case 16: val
= 4; break;
337 case 18: val
= 5; break;
338 case 24: val
= 33; break;
343 tmp
= bus_space_read_4(iot
, ioh
, LCDC_LCCR3
);
345 bus_space_write_4(iot
, ioh
, LCDC_LCCR3
,
346 (tmp
& ~(LCCR3_BPP
|LCCR3_BPP3
)) | (val
<< LCCR3_BPP_SHIFT
));
348 bus_space_write_4(iot
, ioh
, LCDC_LCCR3
,
349 (tmp
& ~LCCR3_BPP
) | (val
<< LCCR3_BPP_SHIFT
));
352 bus_space_write_4(iot
, ioh
, LCDC_FDADR0
,
353 scr
->depth
>= 16 ? scr
->dma_desc_pa
:
354 scr
->dma_desc_pa
+ 2 * sizeof (struct lcd_dma_descriptor
));
355 bus_space_write_4(iot
, ioh
, LCDC_FDADR1
,
356 scr
->dma_desc_pa
+ 1 * sizeof (struct lcd_dma_descriptor
));
359 bus_space_write_4(iot
, ioh
, LCDC_LCSR
, 0);
361 delay(1000); /* ??? */
364 tmp
= bus_space_read_4(iot
, ioh
, LCDC_LCCR0
);
365 /*tmp &= ~LCCR0_SFM;*/
366 bus_space_write_4(iot
, ioh
, LCDC_LCCR0
, tmp
| LCCR0_ENB
);
368 restore_interrupts(save
);
373 * Disable screen refresh.
376 pxa2x0_lcd_stop_dma(struct pxa2x0_lcd_softc
*sc
)
379 /* Stop LCD DMA after current frame */
380 bus_space_write_4(sc
->iot
, sc
->ioh
, LCDC_LCCR0
,
382 bus_space_read_4(sc
->iot
, sc
->ioh
, LCDC_LCCR0
));
384 /* wait for disabling done.
385 XXX: use interrupt. */
387 bus_space_read_4(sc
->iot
, sc
->ioh
, LCDC_LCCR0
))
390 bus_space_write_4(sc
->iot
, sc
->ioh
, LCDC_LCCR0
,
392 bus_space_read_4(sc
->iot
, sc
->ioh
, LCDC_LCCR0
));
396 #define _rgb(r,g,b) (((r)<<11) | ((g)<<5) | b)
397 #define rgb(r,g,b) _rgb((r)>>1,g,(b)>>1)
399 #define L 0x1f /* low intensity */
400 #define H 0x3f /* high intensity */
402 static uint16_t basic_color_map
[] = {
403 rgb( 0, 0, 0), /* black */
404 rgb( L
, 0, 0), /* red */
405 rgb( 0, L
, 0), /* green */
406 rgb( L
, L
, 0), /* brown */
407 rgb( 0, 0, L
), /* blue */
408 rgb( L
, 0, L
), /* magenta */
409 rgb( 0, L
, L
), /* cyan */
410 _rgb(0x1c,0x38,0x1c), /* white */
412 rgb( L
, L
, L
), /* black */
413 rgb( H
, 0, 0), /* red */
414 rgb( 0, H
, 0), /* green */
415 rgb( H
, H
, 0), /* brown */
416 rgb( 0, 0, H
), /* blue */
417 rgb( H
, 0, H
), /* magenta */
418 rgb( 0, H
, H
), /* cyan */
426 init_palette(uint16_t *buf
, int depth
)
430 /* convert RGB332 to RGB565 */
435 for (i
=0; i
<= 255; ++i
) {
436 buf
[i
] = ((9 * ((i
>>5) & 0x07)) <<11) |
437 ((9 * ((i
>>2) & 0x07)) << 5) |
438 ((21 * (i
& 0x03))/2);
441 memcpy(buf
, basic_color_map
, sizeof basic_color_map
);
442 for (i
=16; i
< (1<<depth
); ++i
)
447 /* palette is not needed */
450 /* other depths are not supported */
456 * Create and initialize a new screen buffer.
459 pxa2x0_lcd_new_screen(struct pxa2x0_lcd_softc
*sc
, int depth
,
460 struct pxa2x0_lcd_screen
**scrpp
)
463 bus_space_handle_t ioh
;
464 bus_dma_tag_t dma_tag
;
465 const struct lcd_panel_geometry
*geometry
;
466 struct pxa2x0_lcd_screen
*scr
= NULL
;
469 int error
, palette_size
;
470 int busdma_flag
= (cold
? BUS_DMA_NOWAIT
: BUS_DMA_WAITOK
);
471 struct lcd_dma_descriptor
*desc
;
472 paddr_t buf_pa
, desc_pa
;
476 dma_tag
= sc
->dma_tag
;
477 geometry
= sc
->geometry
;
479 width
= geometry
->panel_width
;
480 height
= geometry
->panel_height
;
488 palette_size
= (1<<depth
) * sizeof (uint16_t);
491 size
= roundup(width
,4) * 2 * height
;
495 size
= roundup(width
,4) * 4 * height
;
499 aprint_error_dev(sc
->dev
, "Not supported depth (%d)\n", depth
);
502 aprint_error_dev(sc
->dev
, "Unknown depth (%d)\n", depth
);
506 scr
= malloc(sizeof(*scr
), M_DEVBUF
, M_NOWAIT
);
510 memset(scr
, 0, sizeof(*scr
));
514 scr
->buf_size
= size
;
516 size
= roundup(size
,16) + 3 * sizeof(struct lcd_dma_descriptor
)
519 error
= bus_dmamem_alloc(dma_tag
, size
, 16, 0, scr
->segs
, 1,
520 &scr
->nsegs
, busdma_flag
);
522 if (error
|| scr
->nsegs
!= 1) {
524 * Actually we can handle nsegs>1 case by means
525 * of multiple DMA descriptors for a panel. It
526 * will make code here a bit hairly.
533 error
= bus_dmamem_map(dma_tag
, scr
->segs
, scr
->nsegs
, size
,
534 (void **)&scr
->buf_va
, busdma_flag
| BUS_DMA_COHERENT
);
538 memset(scr
->buf_va
, 0, scr
->buf_size
);
540 /* map memory for DMA */
541 error
= bus_dmamap_create(dma_tag
, 1024*1024*2, 1, 1024*1024*2, 0,
542 busdma_flag
, &scr
->dma
);
546 error
= bus_dmamap_load(dma_tag
, scr
->dma
, scr
->buf_va
, size
,
551 buf_pa
= scr
->segs
[0].ds_addr
;
552 desc_pa
= buf_pa
+ roundup(size
, PAGE_SIZE
) - 3 * sizeof(*desc
);
554 /* make descriptors at the top of mapped memory */
555 desc
= (struct lcd_dma_descriptor
*)(
556 (char *)(scr
->buf_va
) + roundup(size
, PAGE_SIZE
) -
559 desc
[0].fdadr
= desc_pa
;
560 desc
[0].fsadr
= buf_pa
;
561 desc
[0].ldcmd
= scr
->buf_size
;
564 init_palette((uint16_t *)((char *)desc
- palette_size
), depth
);
566 desc
[2].fdadr
= desc_pa
; /* chain to panel 0 */
567 desc
[2].fsadr
= desc_pa
- palette_size
;
568 desc
[2].ldcmd
= palette_size
| LDCMD_PAL
;
571 if (geometry
->panel_info
& LCDPANEL_DUAL
) {
573 desc
[1].fdadr
= desc_pa
+ sizeof *desc
;
574 desc
[1].fsadr
= buf_pa
+ scr
->buf_size
/2;
575 desc
[0].ldcmd
= desc
[1].ldcmd
= scr
->buf_size
/2;
580 desc
[0].ldcmd
|= LDCMD_SOFINT
;
581 desc
[1].ldcmd
|= LDCMD_SOFINT
;
584 scr
->dma_desc
= desc
;
585 scr
->dma_desc_pa
= desc_pa
;
586 scr
->map_size
= size
; /* used when unmap this. */
588 LIST_INSERT_HEAD(&sc
->screens
, scr
, link
);
598 bus_dmamem_unmap(dma_tag
, scr
->buf_va
, size
);
600 bus_dmamem_free(dma_tag
, scr
->segs
, scr
->nsegs
);
608 * Initialize rasops for a screen, as well as struct wsscreen_descr if this
609 * is the first screen creation.
612 pxa2x0_lcd_setup_rasops(struct pxa2x0_lcd_softc
*sc
, struct rasops_info
*rinfo
,
613 struct pxa2x0_wsscreen_descr
*descr
,
614 const struct lcd_panel_geometry
*geom
)
617 rinfo
->ri_flg
= descr
->flags
;
618 rinfo
->ri_depth
= descr
->depth
;
619 rinfo
->ri_width
= geom
->panel_width
;
620 rinfo
->ri_height
= geom
->panel_height
;
621 rinfo
->ri_stride
= rinfo
->ri_width
* rinfo
->ri_depth
/ 8;
623 rinfo
->ri_wsfcookie
= -1; /* XXX */
627 if (descr
->depth
== 16) {
636 if (descr
->c
.nrows
== 0) {
637 /* get rasops to compute screen size the first time */
638 rasops_init(rinfo
, 100, 100);
640 rasops_init(rinfo
, descr
->c
.nrows
, descr
->c
.ncols
);
643 descr
->c
.nrows
= rinfo
->ri_rows
;
644 descr
->c
.ncols
= rinfo
->ri_cols
;
645 descr
->c
.capabilities
= rinfo
->ri_caps
;
646 descr
->c
.textops
= &rinfo
->ri_ops
;
653 pxa2x0_lcd_suspend(struct pxa2x0_lcd_softc
*sc
)
657 pxa2x0_lcd_stop_dma(sc
);
658 pxa2x0_clkman_config(CKEN_LCD
, 0);
663 pxa2x0_lcd_resume(struct pxa2x0_lcd_softc
*sc
)
667 pxa2x0_lcd_initialize(sc
, sc
->geometry
);
668 pxa2x0_lcd_start_dma(sc
, sc
->active
);
673 pxa2x0_lcd_power(int why
, void *v
)
675 struct pxa2x0_lcd_softc
*sc
= v
;
680 pxa2x0_lcd_suspend(sc
);
684 pxa2x0_lcd_resume(sc
);
691 * Initialize struct wsscreen_descr based on values calculated by
692 * raster operation subsystem.
695 pxa2x0_lcd_setup_wsscreen(struct pxa2x0_wsscreen_descr
*descr
,
696 const struct lcd_panel_geometry
*geom
,
697 const char *fontname
)
699 int width
= geom
->panel_width
;
700 int height
= geom
->panel_height
;
702 struct rasops_info rinfo
;
704 memset(&rinfo
, 0, sizeof rinfo
);
708 cookie
= wsfont_find(fontname
, 0, 0, 0,
709 WSDISPLAY_FONTORDER_L2R
, WSDISPLAY_FONTORDER_L2R
);
711 wsfont_lock(cookie
, &rinfo
.ri_font
))
715 /* let rasops_init() choose any font */
718 /* let rasops_init calculate # of cols and rows in character */
720 rinfo
.ri_depth
= descr
->depth
;
721 rinfo
.ri_bits
= NULL
;
722 rinfo
.ri_width
= width
;
723 rinfo
.ri_height
= height
;
724 rinfo
.ri_stride
= width
* rinfo
.ri_depth
/ 8;
725 #ifdef CPU_XSCALE_PXA270
726 if (rinfo
.ri_depth
> 16)
727 rinfo
.ri_stride
= width
* 4;
729 rinfo
.ri_wsfcookie
= cookie
;
731 rasops_init(&rinfo
, 100, 100);
733 descr
->c
.nrows
= rinfo
.ri_rows
;
734 descr
->c
.ncols
= rinfo
.ri_cols
;
735 descr
->c
.capabilities
= rinfo
.ri_caps
;
741 pxa2x0_lcd_show_screen(void *v
, void *cookie
, int waitok
,
742 void (*cb
)(void *, int, int), void *cbarg
)
744 struct pxa2x0_lcd_softc
*sc
= v
;
745 struct pxa2x0_lcd_screen
*scr
= cookie
, *old
;
752 pxa2x0_lcd_stop_dma(sc
);
754 pxa2x0_lcd_start_dma(sc
, scr
);
761 pxa2x0_lcd_alloc_screen(void *v
, const struct wsscreen_descr
*_type
,
762 void **cookiep
, int *curxp
, int *curyp
, long *attrp
)
764 struct pxa2x0_lcd_softc
*sc
= v
;
765 struct pxa2x0_lcd_screen
*scr
;
766 const struct pxa2x0_wsscreen_descr
*type
=
767 (const struct pxa2x0_wsscreen_descr
*)_type
;
770 error
= pxa2x0_lcd_new_screen(sc
, type
->depth
, &scr
);
775 * initialize raster operation for this screen.
777 scr
->rinfo
.ri_flg
= 0;
778 scr
->rinfo
.ri_depth
= type
->depth
;
779 scr
->rinfo
.ri_bits
= scr
->buf_va
;
780 scr
->rinfo
.ri_width
= sc
->geometry
->panel_width
;
781 scr
->rinfo
.ri_height
= sc
->geometry
->panel_height
;
782 scr
->rinfo
.ri_stride
= scr
->rinfo
.ri_width
* scr
->rinfo
.ri_depth
/ 8;
783 #ifdef CPU_XSCALE_PXA270
784 if (scr
->rinfo
.ri_depth
> 16)
785 scr
->rinfo
.ri_stride
= scr
->rinfo
.ri_width
* 4;
787 scr
->rinfo
.ri_wsfcookie
= -1; /* XXX */
789 rasops_init(&scr
->rinfo
, type
->c
.nrows
, type
->c
.ncols
);
791 (*scr
->rinfo
.ri_ops
.allocattr
)(&scr
->rinfo
, 0, 0, 0, attrp
);
801 pxa2x0_lcd_free_screen(void *v
, void *cookie
)
803 struct pxa2x0_lcd_softc
*sc
= v
;
804 struct pxa2x0_lcd_screen
*scr
= cookie
;
806 LIST_REMOVE(scr
, link
);
808 if (scr
== sc
->active
) {
809 /* at first, we need to stop LCD DMA */
812 printf("lcd_free on active screen\n");
814 pxa2x0_lcd_stop_dma(sc
);
818 bus_dmamem_unmap(sc
->dma_tag
, scr
->buf_va
, scr
->map_size
);
820 bus_dmamem_free(sc
->dma_tag
, scr
->segs
, scr
->nsegs
);
825 pxa2x0_lcd_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
828 struct pxa2x0_lcd_softc
*sc
= v
;
829 struct pxa2x0_lcd_screen
*scr
= sc
->active
; /* ??? */
830 struct wsdisplay_fbinfo
*wsdisp_info
;
834 case WSDISPLAYIO_GTYPE
:
835 *(int *)data
= WSDISPLAY_TYPE_PXALCD
;
838 case WSDISPLAYIO_GINFO
:
839 wsdisp_info
= (struct wsdisplay_fbinfo
*)data
;
840 wsdisp_info
->height
= sc
->geometry
->panel_height
;
841 wsdisp_info
->width
= sc
->geometry
->panel_width
;
842 wsdisp_info
->depth
= scr
->depth
;
843 wsdisp_info
->cmsize
= 0;
846 case WSDISPLAYIO_LINEBYTES
:
847 *(u_int
*)data
= scr
->rinfo
.ri_stride
;
850 case WSDISPLAYIO_GETCMAP
:
851 case WSDISPLAYIO_PUTCMAP
:
852 return EPASSTHROUGH
; /* XXX Colormap */
854 case WSDISPLAYIO_SVIDEO
:
855 if (*(int *)data
== WSDISPLAYIO_VIDEO_ON
) {
859 /* start LCD shutdown */
860 /* sleep until interrupt */
864 case WSDISPLAYIO_GVIDEO
:
865 ccr0
= bus_space_read_4(sc
->iot
, sc
->ioh
, LCDC_LCCR0
);
866 *(u_int
*)data
= (ccr0
& (LCCR0_ENB
|LCCR0_DIS
)) == LCCR0_ENB
?
867 WSDISPLAYIO_VIDEO_ON
: WSDISPLAYIO_VIDEO_OFF
;
870 case WSDISPLAYIO_GCURPOS
:
871 case WSDISPLAYIO_SCURPOS
:
872 case WSDISPLAYIO_GCURMAX
:
873 case WSDISPLAYIO_GCURSOR
:
874 case WSDISPLAYIO_SCURSOR
:
875 return EPASSTHROUGH
; /* XXX */
882 pxa2x0_lcd_mmap(void *v
, void *vs
, off_t offset
, int prot
)
884 struct pxa2x0_lcd_softc
*sc
= v
;
885 struct pxa2x0_lcd_screen
*scr
= sc
->active
; /* ??? */
891 offset
>= scr
->rinfo
.ri_stride
* scr
->rinfo
.ri_height
)
894 return bus_dmamem_mmap(sc
->dma_tag
, scr
->segs
, scr
->nsegs
,
895 offset
, prot
, BUS_DMA_WAITOK
|BUS_DMA_COHERENT
);
900 pxa2x0_lcd_cursor(void *cookie
, int on
, int row
, int col
)
902 struct pxa2x0_lcd_screen
*scr
= cookie
;
904 (*scr
->rinfo
.ri_ops
.cursor
)(&scr
->rinfo
, on
, row
, col
);
908 pxa2x0_lcd_mapchar(void *cookie
, int c
, unsigned int *cp
)
910 struct pxa2x0_lcd_screen
*scr
= cookie
;
912 return (*scr
->rinfo
.ri_ops
.mapchar
)(&scr
->rinfo
, c
, cp
);
916 pxa2x0_lcd_putchar(void *cookie
, int row
, int col
, u_int uc
, long attr
)
918 struct pxa2x0_lcd_screen
*scr
= cookie
;
920 (*scr
->rinfo
.ri_ops
.putchar
)(&scr
->rinfo
, row
, col
, uc
, attr
);
924 pxa2x0_lcd_copycols(void *cookie
, int row
, int src
, int dst
, int num
)
926 struct pxa2x0_lcd_screen
*scr
= cookie
;
928 (*scr
->rinfo
.ri_ops
.copycols
)(&scr
->rinfo
, row
, src
, dst
, num
);
932 pxa2x0_lcd_erasecols(void *cookie
, int row
, int col
, int num
, long attr
)
934 struct pxa2x0_lcd_screen
*scr
= cookie
;
936 (*scr
->rinfo
.ri_ops
.erasecols
)(&scr
->rinfo
, row
, col
, num
, attr
);
940 pxa2x0_lcd_copyrows(void *cookie
, int src
, int dst
, int num
)
942 struct pxa2x0_lcd_screen
*scr
= cookie
;
944 (*scr
->rinfo
.ri_ops
.copyrows
)(&scr
->rinfo
, src
, dst
, num
);
948 pxa2x0_lcd_eraserows(void *cookie
, int row
, int num
, long attr
)
950 struct pxa2x0_lcd_screen
*scr
= cookie
;
952 (*scr
->rinfo
.ri_ops
.eraserows
)(&scr
->rinfo
, row
, num
, attr
);
956 pxa2x0_lcd_alloc_attr(void *cookie
, int fg
, int bg
, int flg
, long *attr
)
958 struct pxa2x0_lcd_screen
*scr
= cookie
;
960 return (*scr
->rinfo
.ri_ops
.allocattr
)(&scr
->rinfo
, fg
, bg
, flg
, attr
);
963 const struct wsdisplay_emulops pxa2x0_lcd_emulops
= {
968 pxa2x0_lcd_erasecols
,
970 pxa2x0_lcd_eraserows
,
971 pxa2x0_lcd_alloc_attr
974 #endif /* NWSDISPLAY > 0 */