pxa2x0_lcd.c revision 1.1 1 /* $Id: pxa2x0_lcd.c,v 1.1 2002/10/19 19:31:40 bsh Exp $ */
2
3 /*
4 * Copyright (c) 2002 Genetec Corporation. All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec Corporation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
21 * written permission.
22 *
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.
34 */
35
36 /*
37 * Support PXA2[15]0's integrated LCD controller.
38 */
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/conf.h>
42 #include <sys/uio.h>
43 #include <sys/malloc.h>
44 #include <sys/kernel.h> /* for cold */
45
46 #include <dev/cons.h>
47 #include <dev/wscons/wsconsio.h>
48 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/wscons/wscons_callbacks.h>
50 #include <dev/rasops/rasops.h>
51 #include <dev/wsfont/wsfont.h>
52
53 #include <machine/bus.h>
54 #include <machine/cpu.h>
55 #include <arm/cpufunc.h>
56
57 #include <arm/xscale/pxa2x0var.h>
58 #include <arm/xscale/pxa2x0reg.h>
59 #include <arm/xscale/pxa2x0_lcd.h>
60
61 #include "wsdisplay.h"
62
63 int lcdintr(void *);
64
65 void
66 pxa2x0_lcd_geometry( struct pxa2x0_lcd_softc *sc,
67 const struct lcd_panel_geometry *info )
68 {
69 int lines;
70 bus_space_tag_t iot = sc->iot;
71 bus_space_handle_t ioh = sc->ioh;
72 uint32_t ccr0;
73
74 sc->geometry = info;
75
76 ccr0 = LCCR0_IMASK;
77 if( info->panel_info & LCDPANEL_ACTIVE )
78 ccr0 |= LCCR0_PAS; /* passive mode */
79 if( (info->panel_info & (LCDPANEL_DUAL|LCDPANEL_ACTIVE))
80 == LCDPANEL_DUAL )
81 ccr0 |= LCCR0_SDS; /* dual panel */
82 if( info->panel_info & LCDPANEL_MONOCHROME )
83 ccr0 |= LCCR0_CMS;
84 bus_space_write_4( iot, ioh, LCDC_LCCR0, ccr0 );
85
86 bus_space_write_4( iot, ioh, LCDC_LCCR1,
87 (info->panel_width-1)
88 | ((info->hsync_pulse_width-1)<<10)
89 | ((info->end_line_wait-1)<<16)
90 | ((info->beg_line_wait-1)<<24) );
91
92 if( info->panel_info & LCDPANEL_DUAL )
93 lines = info->panel_height/2 + info->extra_lines;
94 else
95 lines = info->panel_height + info->extra_lines;
96
97 bus_space_write_4( iot, ioh, LCDC_LCCR2,
98 (lines-1)
99 | (info->vsync_pulse_width<<10)
100 | (info->end_frame_wait<<16)
101 | (info->beg_frame_wait<<24) );
102
103 bus_space_write_4( iot, ioh, LCDC_LCCR3,
104 (info->pixel_clock_div<<0)
105 | (info->ac_bias << 8)
106 | ((info->panel_info &
107 (LCDPANEL_VSP|LCDPANEL_HSP|LCDPANEL_PCP|LCDPANEL_OEP))
108 <<20)
109 | ( 4 << 24 ) /* 16bpp */
110 | ((info->panel_info & LCDPANEL_DPC) ? (1<<27) : 0)
111 );
112 }
113
114 void
115 pxa2x0_lcd_attach_sub( struct pxa2x0_softc *parent,
116 struct pxa2x0_lcd_softc *sc,
117 const struct lcd_panel_geometry *geom )
118 {
119 bus_space_tag_t iot;
120 bus_space_handle_t ioh;
121 uint32_t tmp;
122 int error;
123
124
125 iot = parent->saip.sc_iot;
126
127 sc->n_screens = 0;
128 LIST_INIT(&sc->screens);
129
130 /* map controller registers */
131 error = bus_space_map( iot, PXA2X0_LCDC_BASE,
132 PXA2X0_LCDC_SIZE, 0, &ioh );
133 if( error ){
134 printf( ": failed to map registers %d", error );
135 return;
136 }
137
138 sc->iot = iot;
139 sc->ioh = ioh;
140 sc->dma_tag = &pxa2x0_bus_dma_tag;
141
142 sc->ih = pxa2x0_intr_establish(17, IPL_BIO, lcdintr, sc);
143 if (sc->ih == NULL)
144 printf("%s: unable to establish interrupt at irq %d",
145 sc->dev.dv_xname, 17);
146
147 /* Initialize LCD controller */
148
149 /* enable clock */
150 tmp = bus_space_read_4( iot, parent->sc_clkman_ioh, CLKMAN_CKEN );
151 bus_space_write_4( iot, parent->sc_clkman_ioh, CLKMAN_CKEN,
152 tmp | (1U<<16) );
153
154 bus_space_write_4( iot, ioh, LCDC_LCCR0, LCCR0_IMASK );
155
156 /*
157 * setup GP[77:58] for LCD
158 */
159 {
160 bus_space_handle_t gpioh = parent->saip.sc_gpioh;
161 uint32_t gafr1, gafr2, gpdr1, gpdr2;
162 int panelinfo = geom->panel_info;
163
164 gpdr1 = bus_space_read_4( iot, gpioh, GPIO_GPDR1 );
165 gpdr2 = bus_space_read_4( iot, gpioh, GPIO_GPDR2 );
166 gafr1 = bus_space_read_4( iot, gpioh, GPIO_GAFR1_U );
167 gafr2 = bus_space_read_4( iot, gpioh, GPIO_GAFR2_L );
168
169 /* Always use L_DD[3:0], [FLP]CLK, ACBIAS */
170 gafr1 = (gafr1 & ~(0xff<<20)) | (0xaa<<20);
171 gafr2 = (gafr2 & ~(0xff<<20)) | (0xaa<<20);
172 gpdr1 |= 0x0f<<26;
173 gpdr2 |= 0x0f<<10;
174
175 if( (panelinfo & LCDPANEL_ACTIVE) ||
176 ((panelinfo & (LCDPANEL_MONOCHROME|LCDPANEL_DUAL))
177 == LCDPANEL_DUAL ) ){
178 /* active and color dual panel need L_DD[15:0] */
179 gafr1 = (gafr1 & ~(0x0f<<28)) | (0x0a<<28);
180 gafr2 = (gafr2 & ~0xfffff) | 0xaaaaa;
181 gpdr1 |= 0x03<<30;
182 gpdr2 |= 0x3ff;
183 }
184 else if( (panelinfo & LCDPANEL_DUAL) ||
185 !(panelinfo & LCDPANEL_MONOCHROME ) ){
186 /* dual or color need L_DD[7:0] */
187
188 gafr1 = (gafr1 & ~(0x0f<<28)) | (0x0a<<28);
189 gafr2 = (gafr2 & ~0x0f) | 0x0a;
190 gpdr1 |= 0x03<<30;
191 gpdr2 |= 0x03;
192 }
193
194
195 bus_space_write_4( iot, gpioh, GPIO_GAFR1_U, gafr1 );
196 bus_space_write_4( iot, gpioh, GPIO_GAFR2_L, gafr2 );
197 bus_space_write_4( iot, gpioh, GPIO_GPDR1, gpdr1 );
198 bus_space_write_4( iot, gpioh, GPIO_GPDR2, gpdr2 );
199 }
200
201
202
203
204 pxa2x0_lcd_geometry( sc, geom );
205 }
206
207
208 int
209 lcdintr(void *arg)
210 {
211 struct pxa2x0_lcd_softc *sc = arg;
212 bus_space_tag_t iot = sc->iot;
213 bus_space_handle_t ioh = sc->ioh;
214
215 static uint32_t status;
216
217 status = bus_space_read_4( iot, ioh, LCDC_LCSR );
218 /* Clear stickey status bits */
219 bus_space_write_4( iot, ioh, LCDC_LCSR, status );
220
221 return 1;
222 }
223
224 void
225 pxa2x0_lcd_start_dma( struct pxa2x0_lcd_softc *sc,
226 struct pxa2x0_lcd_screen *scr )
227 {
228 uint32_t tmp;
229 bus_space_tag_t iot = sc->iot;
230 bus_space_handle_t ioh = sc->ioh;
231 int val, save;
232
233 save = disable_interrupts( I32_bit );
234
235 switch( scr->depth ){
236 case 1: val = 0; break;
237 case 2: val = 1; break;
238 case 4: val = 2; break;
239 case 8: val = 3; break;
240 case 16: /* FALLTHROUGH */
241 default:
242 val = 4; break;
243 }
244
245 tmp = bus_space_read_4( iot, ioh, LCDC_LCCR3 );
246 bus_space_write_4( iot, ioh, LCDC_LCCR3,
247 (tmp & ~LCCR3_BPP) | (val << LCCR3_BPP_SHIFT) );
248
249 bus_space_write_4( iot, ioh, LCDC_FDADR0,
250 scr->depth == 16 ? scr->dma_desc_pa :
251 scr->dma_desc_pa + 2 * sizeof (struct lcd_dma_descriptor) );
252 bus_space_write_4( iot, ioh, LCDC_FDADR1,
253 scr->dma_desc_pa + 1 * sizeof (struct lcd_dma_descriptor) );
254
255 /* clear status */
256 bus_space_write_4( iot, ioh, LCDC_LCSR, 0 );
257
258 delay(1000); /* ??? */
259
260 /* Enable LCDC */
261 tmp = bus_space_read_4( iot, ioh, LCDC_LCCR0 );
262 /*tmp &= ~LCCR0_SFM;*/
263 bus_space_write_4( iot, ioh, LCDC_LCCR0, tmp | LCCR0_ENB );
264
265 restore_interrupts( save );
266
267 }
268
269
270 static void
271 pxa2x0_lcd_stop_dma( struct pxa2x0_lcd_softc *sc )
272 {
273 /* Stop LCD DMA after current frame */
274 bus_space_write_4( sc->iot, sc->ioh, LCDC_LCCR0,
275 LCCR0_DIS |
276 bus_space_read_4( sc->iot, sc->ioh, LCDC_LCCR0 ) );
277
278 /* wait for disabling done.
279 XXX: use interrupt. */
280 while( LCCR0_ENB &
281 bus_space_read_4( sc->iot, sc->ioh, LCDC_LCCR0 ) )
282 ;
283
284 bus_space_write_4( sc->iot, sc->ioh, LCDC_LCCR0,
285 ~LCCR0_DIS &
286 bus_space_read_4( sc->iot, sc->ioh, LCDC_LCCR0 ) );
287 }
288
289 #define _rgb(r,g,b) (((r)<<11) | ((g)<<5) | b)
290 #define rgb(r,g,b) _rgb((r)>>1,g,(b)>>1)
291
292 #define L 0x1f /* low intensity */
293 #define H 0x3f /* hight intensity */
294
295 static uint16_t basic_color_map[] = {
296 rgb( 0, 0, 0), /* black */
297 rgb( L, 0, 0), /* red */
298 rgb( 0, L, 0), /* green */
299 rgb( L, L, 0), /* brown */
300 rgb( 0, 0, L), /* blue */
301 rgb( L, 0, L), /* magenta */
302 rgb( 0, L, L), /* cyan */
303 _rgb(0x1c,0x38,0x1c), /* white */
304
305 rgb( L, L, L), /* black */
306 rgb( H, 0, 0), /* red */
307 rgb( 0, H, 0), /* green */
308 rgb( H, H, 0), /* brown */
309 rgb( 0, 0, H), /* blue */
310 rgb( H, 0, H), /* magenta */
311 rgb( 0, H, H), /* cyan */
312 rgb( H, H, H)
313 };
314
315 #undef H
316 #undef L
317
318 static void
319 init_pallet( uint16_t *buf, int depth )
320 {
321 int i;
322
323 /* convert RGB332 to RGB565 */
324 switch( depth ){
325 case 8:
326 case 4:
327 #if 0
328 for( i=0; i <= 255; ++i ){
329 buf[i] = ((9 * ((i>>5) & 0x07)) <<11) |
330 ((9 * ((i>>2) & 0x07)) << 5) |
331 ((21 * (i & 0x03))/2 );
332 }
333 #else
334 memcpy( buf, basic_color_map, sizeof basic_color_map );
335 for( i=16; i < (1<<depth); ++i )
336 buf[i] = 0xffff;
337 #endif
338 break;
339 default:
340 }
341 }
342
343 struct pxa2x0_lcd_screen *
344 pxa2x0_lcd_new_screen( struct pxa2x0_lcd_softc *sc,
345 int depth )
346 {
347 struct pxa2x0_lcd_screen *scr = NULL;
348 int width, height;
349 bus_size_t size;
350 int error, pallet_size;
351 int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
352 struct lcd_dma_descriptor *desc;
353 paddr_t buf_pa, desc_pa;
354
355 width = sc->geometry->panel_width;
356 height = sc->geometry->panel_height;
357 pallet_size = 0;
358
359 switch( depth ){
360 case 1:
361 case 2:
362 case 4:
363 case 8:
364 pallet_size = (1<<depth) * sizeof (uint16_t);
365 /* FALLTHROUGH */
366 case 16:
367 size = roundup(width,4)*depth/8 * height;
368 break;
369 default:
370 printf( "%s: Unknown depth (%d)\n", sc->dev.dv_xname, depth );
371 return NULL;
372 }
373
374 scr = malloc( sizeof *scr, M_DEVBUF,
375 M_ZERO | (cold ? M_NOWAIT : M_WAITOK) );
376
377 if( scr == NULL )
378 return NULL;
379
380 scr->nsegs = 0;
381 scr->depth = depth;
382 scr->buf_size = size;
383 scr->buf_va = NULL;
384 size = roundup(size,16) + 3 * sizeof (struct lcd_dma_descriptor)
385 + pallet_size;
386
387 error = bus_dmamem_alloc( sc->dma_tag, size, 16, 0,
388 scr->segs, 1, &(scr->nsegs), busdma_flag );
389
390 if( error || scr->nsegs != 1 ){
391 /* XXX: Actually we can handle nsegs>1 case by means
392 of multiple DMA descriptors for a panel. it will
393 makes code here a bit hairly */
394 goto bad;
395 }
396
397 error = bus_dmamem_map( sc->dma_tag, scr->segs, scr->nsegs,
398 size, (caddr_t *)&(scr->buf_va), busdma_flag | BUS_DMA_COHERENT );
399 if( error )
400 goto bad;
401
402
403 memset( scr->buf_va, 0, scr->buf_size );
404
405 /* map memory for DMA */
406 if( bus_dmamap_create( sc->dma_tag, 1024*1024*2, 1,
407 1024*1024*2, 0, busdma_flag, &scr->dma ) )
408 goto bad;
409 error = bus_dmamap_load( sc->dma_tag, scr->dma,
410 scr->buf_va, size, NULL, busdma_flag );
411 if( error ){
412 goto bad;
413 }
414
415 buf_pa = scr->segs[0].ds_addr;
416 desc_pa = buf_pa + roundup(size, NBPG) - 3*sizeof *desc;
417
418 /* make descriptors at the top of mapped memory */
419 desc = (struct lcd_dma_descriptor *)(
420 (caddr_t)(scr->buf_va) + roundup(size, NBPG) - 3*sizeof *desc);
421
422 desc[0].fdadr = desc_pa;
423 desc[0].fsadr = buf_pa;
424 desc[0].ldcmd = scr->buf_size;
425
426 if( pallet_size ){
427 init_pallet( (uint16_t *)((char *)desc - pallet_size), depth );
428
429 desc[2].fdadr = desc_pa; /* chain to panel 0 */
430 desc[2].fsadr = desc_pa - pallet_size;
431 desc[2].ldcmd = pallet_size | LDCMD_PAL;
432 }
433
434 if( sc->geometry->panel_info & LCDPANEL_DUAL ){
435 /* Dual panel */
436 desc[1].fdadr = desc_pa + sizeof *desc;
437 desc[1].fsadr = buf_pa + scr->buf_size/2;
438 desc[0].ldcmd = desc[1].ldcmd = scr->buf_size/2;
439
440 }
441
442 #if 0
443 desc[0].ldcmd |= LDCMD_SOFINT;
444 desc[1].ldcmd |= LDCMD_SOFINT;
445 #endif
446
447 scr->dma_desc = desc;
448 scr->dma_desc_pa = desc_pa;
449 scr->map_size = size; /* used when unmap this. */
450
451 LIST_INSERT_HEAD( &(sc->screens), scr, link );
452 sc->n_screens++;
453
454 return scr;
455
456 bad:
457 if( scr ){
458 if( scr->buf_va )
459 bus_dmamem_unmap( sc->dma_tag, scr->buf_va, size );
460 if( scr->nsegs )
461 bus_dmamem_free( sc->dma_tag, scr->segs, scr->nsegs );
462 free( scr, M_DEVBUF );
463 }
464 return NULL;
465 }
466
467
468 #if NWSDISPLAY > 0
469
470 /*
471 * Initialize struct wsscreen_descr based on values calculated by
472 * raster operation subsystem.
473 */
474 int
475 pxa2x0_lcd_setup_wsscreen(struct pxa2x0_wsscreen_descr *descr,
476 const struct lcd_panel_geometry *geom,
477 const char *fontname )
478 {
479 int width = geom->panel_width;
480 int height = geom->panel_height;
481 int cookie = -1;
482 struct rasops_info rinfo;
483
484 memset( &rinfo, 0, sizeof rinfo );
485
486 if( fontname ){
487 wsfont_init();
488 cookie = wsfont_find( (char *)fontname, 0, 0, 0,
489 WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R );
490 if( cookie < 0 ||
491 wsfont_lock(cookie, &rinfo.ri_font) )
492 return -1;
493 }
494 else {
495 /* let rasops_init() choose any font */
496 }
497
498 /* let rasops_init calculate # of cols and rows in character */
499 rinfo.ri_flg = 0;
500 rinfo.ri_depth = descr->depth;
501 rinfo.ri_bits = NULL;
502 rinfo.ri_width = width;
503 rinfo.ri_height = height;
504 rinfo.ri_stride = width * rinfo.ri_depth / 8;
505 rinfo.ri_wsfcookie = cookie;
506
507 rasops_init( &rinfo, 100, 100 );
508
509 descr->c.nrows = rinfo.ri_rows;
510 descr->c.ncols = rinfo.ri_cols;
511 descr->c.capabilities = rinfo.ri_caps;
512
513 return cookie;
514 }
515
516
517 int
518 pxa2x0_lcd_show_screen(void *v, void *cookie, int waitok,
519 void (*cb)(void *, int, int), void *cbarg)
520 {
521 struct pxa2x0_lcd_softc *sc = v;
522 struct pxa2x0_lcd_screen *scr = cookie, *old;
523
524 old = sc->active;
525 if( old == scr )
526 return 0;
527
528 if( old )
529 pxa2x0_lcd_stop_dma( sc );
530
531 pxa2x0_lcd_start_dma( sc, scr );
532
533 sc->active = scr;
534 return 0;
535 }
536
537 int
538 pxa2x0_lcd_alloc_screen(void *v, const struct wsscreen_descr *_type,
539 void **cookiep, int *curxp, int *curyp, long *attrp)
540 {
541 struct pxa2x0_lcd_softc *sc = v;
542 struct pxa2x0_lcd_screen *scr;
543 struct pxa2x0_wsscreen_descr *type = (struct pxa2x0_wsscreen_descr *)_type;
544
545 scr = pxa2x0_lcd_new_screen( sc, type->depth );
546 if( scr == NULL )
547 return -1;
548
549 /*
550 * initialize raster operation for this screen.
551 */
552 scr->rinfo.ri_flg = 0;
553 scr->rinfo.ri_depth = type->depth;
554 scr->rinfo.ri_bits = scr->buf_va;
555 scr->rinfo.ri_width = sc->geometry->panel_width;
556 scr->rinfo.ri_height = sc->geometry->panel_height;
557 scr->rinfo.ri_stride = scr->rinfo.ri_width * scr->rinfo.ri_depth / 8;
558 scr->rinfo.ri_wsfcookie = -1; /* XXX */
559
560 rasops_init( &scr->rinfo, type->c.nrows, type->c.ncols );
561
562 (* scr->rinfo.ri_ops.allocattr)(&scr->rinfo, 0, 0, 0, attrp );
563
564 *cookiep = scr;
565 *curxp = 0;
566 *curyp = 0;
567
568 return 0;
569 }
570
571
572 void
573 pxa2x0_lcd_free_screen(void *v, void *cookie)
574 {
575 struct pxa2x0_lcd_softc *sc = v;
576 struct pxa2x0_lcd_screen *scr = cookie;
577
578 LIST_REMOVE( scr, link );
579 sc->n_screens--;
580 if( scr == sc->active ){
581 /* at first, we need to stop LCD DMA */
582 sc->active = NULL;
583
584 printf( "lcd_free on active screen\n" );
585
586 pxa2x0_lcd_stop_dma(sc);
587 }
588
589 if( scr->buf_va )
590 bus_dmamem_unmap( sc->dma_tag, scr->buf_va, scr->map_size );
591
592 if( scr->nsegs > 0 )
593 bus_dmamem_free( sc->dma_tag, scr->segs, scr->nsegs );
594
595 free( scr, M_DEVBUF );
596 }
597
598 int
599 pxa2x0_lcd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
600 {
601 struct pxa2x0_lcd_softc *sc = v;
602 struct wsdisplay_fbinfo *wsdisp_info;
603 uint32_t ccr0;
604
605 switch (cmd) {
606 case WSDISPLAYIO_GTYPE:
607 *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */
608 return 0;
609
610 case WSDISPLAYIO_GINFO:
611 wsdisp_info = (struct wsdisplay_fbinfo *)data;
612
613 wsdisp_info->height = sc->geometry->panel_height;
614 wsdisp_info->width = sc->geometry->panel_width;
615 wsdisp_info->depth = 16; /* XXX */
616 wsdisp_info->cmsize = 0;
617 return 0;
618
619 case WSDISPLAYIO_GETCMAP:
620 case WSDISPLAYIO_PUTCMAP:
621 return EPASSTHROUGH; /* XXX Colormap */
622
623 case WSDISPLAYIO_SVIDEO:
624 if( *(int *)data == WSDISPLAYIO_VIDEO_ON ){
625 /* turn it on */
626 }
627 else {
628 /* start LCD shutdown */
629 /* sleep until interrupt */
630 }
631 return 0;
632
633 case WSDISPLAYIO_GVIDEO:
634 ccr0 = bus_space_read_4( sc->iot, sc->ioh, LCDC_LCCR0 );
635 *(u_int *)data = (ccr0 & (LCCR0_ENB|LCCR0_DIS)) == LCCR0_ENB ?
636 WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF;
637 return 0;
638
639
640
641 case WSDISPLAYIO_GCURPOS:
642 case WSDISPLAYIO_SCURPOS:
643 case WSDISPLAYIO_GCURMAX:
644 case WSDISPLAYIO_GCURSOR:
645 case WSDISPLAYIO_SCURSOR:
646 return EPASSTHROUGH; /* XXX */
647 }
648
649 return EPASSTHROUGH;
650 }
651
652 paddr_t
653 pxa2x0_lcd_mmap(void *v, off_t offset, int prot)
654 {
655 struct pxa2x0_lcd_softc *sc = v;
656 struct pxa2x0_lcd_screen *screen = sc->active; /* ??? */
657
658 if( screen == NULL )
659 return -1;
660
661 return bus_dmamem_mmap( sc->dma_tag, screen->segs, screen->nsegs,
662 offset, prot, BUS_DMA_WAITOK|BUS_DMA_COHERENT );
663 return -1;
664 }
665
666
667 static void
668 pxa2x0_lcd_cursor( void *cookie, int on, int row, int col )
669 {
670 struct pxa2x0_lcd_screen *scr = cookie;
671
672 (* scr->rinfo.ri_ops.cursor)( &scr->rinfo, on, row, col );
673 }
674
675 static int
676 pxa2x0_lcd_mapchar( void *cookie, int c, unsigned int *cp )
677 {
678 struct pxa2x0_lcd_screen *scr = cookie;
679
680 return (* scr->rinfo.ri_ops.mapchar)( &scr->rinfo, c, cp );
681 }
682
683 static void
684 pxa2x0_lcd_putchar( void *cookie, int row, int col, u_int uc, long attr )
685 {
686 struct pxa2x0_lcd_screen *scr = cookie;
687
688 (* scr->rinfo.ri_ops.putchar)( &scr->rinfo,
689 row, col, uc, attr );
690 }
691
692 static void
693 pxa2x0_lcd_copycols( void *cookie, int row, int src, int dst, int num)
694 {
695 struct pxa2x0_lcd_screen *scr = cookie;
696
697 (* scr->rinfo.ri_ops.copycols)( &scr->rinfo,
698 row, src, dst, num );
699 }
700
701 static void
702 pxa2x0_lcd_erasecols( void *cookie, int row, int col, int num, long attr)
703 {
704 struct pxa2x0_lcd_screen *scr = cookie;
705
706 (* scr->rinfo.ri_ops.erasecols)( &scr->rinfo,
707 row, col, num, attr );
708 }
709
710 static void
711 pxa2x0_lcd_copyrows( void *cookie, int src, int dst, int num )
712 {
713 struct pxa2x0_lcd_screen *scr = cookie;
714
715 (* scr->rinfo.ri_ops.copyrows)( &scr->rinfo,
716 src, dst, num );
717 }
718
719 static void
720 pxa2x0_lcd_eraserows( void *cookie, int row, int num, long attr )
721 {
722 struct pxa2x0_lcd_screen *scr = cookie;
723
724 (* scr->rinfo.ri_ops.eraserows)( &scr->rinfo,
725 row, num, attr );
726 }
727
728 static int
729 pxa2x0_lcd_alloc_attr( void *cookie, int fg, int bg, int flg, long *attr)
730 {
731 struct pxa2x0_lcd_screen *scr = cookie;
732
733 return (* scr->rinfo.ri_ops.allocattr)( &scr->rinfo,
734 fg, bg, flg, attr );
735 }
736
737
738 const struct wsdisplay_emulops pxa2x0_lcd_emulops = {
739 pxa2x0_lcd_cursor,
740 pxa2x0_lcd_mapchar,
741 pxa2x0_lcd_putchar,
742 pxa2x0_lcd_copycols,
743 pxa2x0_lcd_erasecols,
744 pxa2x0_lcd_copyrows,
745 pxa2x0_lcd_eraserows,
746 pxa2x0_lcd_alloc_attr
747 };
748
749 #endif /* NWSDISPLAY > 0 */
750