Annotation of sys/arch/arm/s3c2xx0/s3c24x0_lcd.c, Revision 1.1.1.1
1.1 nbrk 1: /* $NetBSD: s3c24x0_lcd.c,v 1.5 2007/03/04 05:59:38 christos Exp $ */
2:
3: /*
4: * Copyright (c) 2004 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. The name of Genetec Corporation may not be used to endorse or
16: * promote products derived from this software without specific prior
17: * written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
20: * 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 GENETEC CORPORATION
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.
30: */
31:
32: /*
33: * Support S3C24[10]0's integrated LCD controller.
34: */
35:
36: #include <sys/cdefs.h>
37: __KERNEL_RCSID(0, "$NetBSD: s3c24x0_lcd.c,v 1.5 2007/03/04 05:59:38 christos Exp $");
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 <uvm/uvm_extern.h>
47:
48: #include <dev/cons.h>
49: #include <dev/wscons/wsconsio.h>
50: #include <dev/wscons/wsdisplayvar.h>
51: #include <dev/wscons/wscons_callbacks.h>
52: #include <dev/rasops/rasops.h>
53: #include <dev/wsfont/wsfont.h>
54:
55: #include <machine/bus.h>
56: #include <machine/cpu.h>
57: #include <arm/cpufunc.h>
58:
59: #include <arm/s3c2xx0/s3c24x0var.h>
60: #include <arm/s3c2xx0/s3c24x0reg.h>
61: #include <arm/s3c2xx0/s3c24x0_lcd.h>
62:
63: #include "wsdisplay.h"
64:
65: int lcdintr(void *);
66: static void init_palette(struct s3c24x0_lcd_softc *,
67: struct s3c24x0_lcd_screen *);
68:
69: #ifdef LCD_DEBUG
70: static void
71: dump_lcdcon(const char *title, bus_space_tag_t iot, bus_space_handle_t ioh)
72: {
73: int i;
74:
75: printf("%s\n", title);
76: for(i=LCDC_LCDCON1; i <= LCDC_LCDSADDR3; i+=4) {
77: if (i%16 == 0)
78: printf("\n%03x: ", i);
79: printf("%08x ", bus_space_read_4(iot, ioh, i));
80: }
81:
82: printf("\n");
83: }
84:
85: void draw_test_pattern(struct s3c24x0_lcd_softc *,
86: struct s3c24x0_lcd_screen *scr);
87:
88: #endif
89:
90: void
91: s3c24x0_set_lcd_panel_info(struct s3c24x0_lcd_softc *sc,
92: const struct s3c24x0_lcd_panel_info *info)
93: {
94: bus_space_tag_t iot = sc->iot;
95: bus_space_handle_t ioh = sc->ioh;
96: uint32_t reg;
97: int clkval;
98: int tft = s3c24x0_lcd_panel_tft(info);
99: int hclk = s3c2xx0_softc->sc_hclk;
100:
101: sc->panel_info = info;
102:
103: /* Set LCDCON1. BPPMODE and ENVID are set later */
104: if (tft)
105: clkval = (hclk / info->pixel_clock / 2) - 1;
106: else {
107: /* STN display */
108: clkval = max(2, hclk / info->pixel_clock / 2);
109: }
110:
111: reg = (info->lcdcon1 & ~LCDCON1_CLKVAL_MASK) |
112: (clkval << LCDCON1_CLKVAL_SHIFT);
113: reg &= ~LCDCON1_ENVID;
114: bus_space_write_4(iot, ioh, LCDC_LCDCON1, reg);
115:
116: #if 0
117: printf("hclk=%d pixel clock=%d, clkval = %x lcdcon1=%x\n",
118: hclk, info->pixel_clock, clkval, reg);
119: #endif
120:
121: bus_space_write_4(iot, ioh, LCDC_LCDCON2, info->lcdcon2);
122: bus_space_write_4(iot, ioh, LCDC_LCDCON3, info->lcdcon3);
123: bus_space_write_4(iot, ioh, LCDC_LCDCON4, info->lcdcon4);
124: bus_space_write_4(iot, ioh, LCDC_LCDCON5, info->lcdcon5);
125: bus_space_write_4(iot, ioh, LCDC_LPCSEL, info->lpcsel);
126: }
127:
128: void
129: s3c24x0_lcd_attach_sub(struct s3c24x0_lcd_softc *sc,
130: struct s3c2xx0_attach_args *sa,
131: const struct s3c24x0_lcd_panel_info *panel_info)
132: {
133: bus_space_tag_t iot = sa->sa_iot;
134: bus_space_handle_t ioh;
135: int error;
136:
137: sc->n_screens = 0;
138: LIST_INIT(&sc->screens);
139:
140: /* map controller registers */
141: error = bus_space_map(iot, sa->sa_addr, S3C24X0_LCDC_SIZE, 0, &ioh);
142: if (error) {
143: printf(": failed to map registers %d", error);
144: return;
145: }
146:
147: sc->iot = iot;
148: sc->ioh = ioh;
149: sc->dma_tag = sa->sa_dmat;
150:
151: #ifdef notyet
152: sc->ih = s3c24x0_intr_establish(sa->sa_intr, IPL_BIO, lcdintr, sc);
153: if (sc->ih == NULL)
154: printf("%s: unable to establish interrupt at irq %d",
155: sc->dev.dv_xname, sa->sa_intr);
156: #endif
157:
158: /* mask LCD interrupts */
159: bus_space_write_4(iot, ioh, LCDC_LCDINTMSK, LCDINT_FICNT|LCDINT_FRSYN);
160:
161: /* Initialize controller registers based on panel geometry*/
162: s3c24x0_set_lcd_panel_info(sc, panel_info);
163:
164: /* XXX: enable clock to LCD controller */
165: }
166:
167:
168: #ifdef notyet
169: int
170: lcdintr(void *arg)
171: {
172: struct s3c24x0_lcd_softc *sc = arg;
173: bus_space_tag_t iot = sc->iot;
174: bus_space_handle_t ioh = sc->ioh;
175:
176: static uint32_t status;
177:
178: return 1;
179: }
180: #endif
181:
182: int
183: s3c24x0_lcd_start_dma(struct s3c24x0_lcd_softc *sc,
184: struct s3c24x0_lcd_screen *scr)
185: {
186: bus_space_tag_t iot = sc->iot;
187: bus_space_handle_t ioh = sc->ioh;
188: const struct s3c24x0_lcd_panel_info *info = sc->panel_info;
189: int tft = s3c24x0_lcd_panel_tft(info);
190: int dual_panel =
191: (info->lcdcon1 & LCDCON1_PNRMODE_MASK) == LCDCON1_PNRMODE_DUALSTN4;
192: uint32_t lcdcon1, val;
193: paddr_t pa;
194: int depth = scr->depth;
195: int stride = scr->stride;
196: int panel_height = info->panel_height;
197: int panel_width = info->panel_width;
198: int offsize;
199:
200: switch (depth) {
201: case 1: val = LCDCON1_BPPMODE_STN1; break;
202: case 2: val = LCDCON1_BPPMODE_STN2; break;
203: case 4: val = LCDCON1_BPPMODE_STN4; break;
204: case 8: val = LCDCON1_BPPMODE_STN8; break;
205: case 12:
206: if (tft)
207: return -1;
208: val = LCDCON1_BPPMODE_STN12;
209: break;
210: case 16:
211: if (!tft)
212: return -1;
213: val = LCDCON1_BPPMODE_TFT16;
214: break;
215: case 24:
216: if (!tft)
217: return -1;
218: val = LCDCON1_BPPMODE_TFT24;
219: break;
220: default:
221: return -1;
222: }
223:
224: if (tft)
225: val |= LCDCON1_BPPMODE_TFTX;
226:
227: lcdcon1 = bus_space_read_4(iot, ioh, LCDC_LCDCON1);
228: lcdcon1 &= ~(LCDCON1_BPPMODE_MASK|LCDCON1_ENVID);
229: lcdcon1 |= val;
230: bus_space_write_4(iot, ioh, LCDC_LCDCON1, lcdcon1);
231:
232: /* Adjust LCDCON3.HOZVAL to meet with restriction */
233: val = roundup(panel_width, 16 / depth);
234: bus_space_write_4(iot, ioh, LCDC_LCDCON3,
235: (info->lcdcon3 & ~LCDCON3_HOZVAL_MASK) |
236: (val - 1) << LCDCON3_HOZVAL_SHIFT);
237:
238: pa = scr->segs[0].ds_addr;
239: bus_space_write_4(iot, ioh, LCDC_LCDSADDR1, pa >> 1);
240:
241: if (dual_panel) {
242: /* XXX */
243: }
244: else {
245: pa += stride * panel_height;
246: bus_space_write_4(iot, ioh, LCDC_LCDSADDR2, pa >> 1);
247: }
248:
249: offsize = stride / sizeof (uint16_t) - (panel_width * depth / 16);
250: bus_space_write_4(iot, ioh, LCDC_LCDSADDR3,
251: (offsize << LCDSADDR3_OFFSIZE_SHIFT) |
252: (panel_width * depth / 16));
253:
254: /* set byte- or halfword- swap based on the depth */
255: val = bus_space_read_4(iot, ioh, LCDC_LCDCON5);
256: val &= ~(LCDCON5_BSWP|LCDCON5_HWSWP);
257: switch(depth) {
258: case 2:
259: case 4:
260: case 8:
261: val |= LCDCON5_BSWP;
262: break;
263: case 16:
264: val |= LCDCON5_HWSWP;
265: break;
266: }
267: bus_space_write_4(iot, ioh, LCDC_LCDCON5, val);
268:
269:
270: init_palette(sc, scr);
271:
272: #if 0
273: bus_space_write_4(iot, ioh, LCDC_TPAL, TPAL_TPALEN|
274: (0xff<<TPAL_BLUE_SHIFT));
275: #endif
276:
277: /* Enable LCDC */
278: bus_space_write_4(iot, ioh, LCDC_LCDCON1, lcdcon1 | LCDCON1_ENVID);
279:
280: sc->lcd_on = 1;
281:
282: #ifdef LCD_DEBUG
283: dump_lcdcon(__FUNCTION__, iot, ioh);
284: #endif
285:
286: return 0;
287: }
288:
289: void
290: s3c24x0_lcd_power(struct s3c24x0_lcd_softc *sc, int on)
291: {
292: bus_space_tag_t iot = sc->iot;
293: bus_space_handle_t ioh = sc->ioh;
294: uint32_t reg;
295:
296: reg = bus_space_read_4(iot, ioh, LCDC_LCDCON5);
297:
298: if (on)
299: reg |= LCDCON5_PWREN;
300: else
301: reg &= ~LCDCON5_PWREN;
302:
303: bus_space_write_4(iot, ioh, LCDC_LCDCON5, reg);
304: }
305:
306: struct s3c24x0_lcd_screen *
307: s3c24x0_lcd_new_screen(struct s3c24x0_lcd_softc *sc,
308: int virtual_width, int virtual_height, int depth)
309: {
310: struct s3c24x0_lcd_screen *scr = NULL;
311: int width, height;
312: bus_size_t size;
313: int error, pallet_size;
314: int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
315: BUS_DMA_WRITE;
316: paddr_t align;
317: const struct s3c24x0_lcd_panel_info *panel_info = sc->panel_info;
318:
319:
320: #ifdef DIAGNOSTIC
321: if (size > 1 << 22) {
322: aprint_error("%s: too big screen size\n", sc->dev.dv_xname);
323: return NULL;
324: }
325: #endif
326:
327: width = panel_info->panel_width;
328: height = panel_info->panel_height;
329: pallet_size = 0;
330:
331: switch (depth) {
332: case 1: case 2: case 4: case 8:
333: virtual_width = roundup(virtual_width, 16 / depth);
334: break;
335: case 16:
336: break;
337: case 12: case 24:
338: default:
339: aprint_error("%s: Unknown depth (%d)\n",
340: sc->dev.dv_xname, depth);
341: return NULL;
342: }
343:
344: scr = malloc(sizeof *scr, M_DEVBUF,
345: M_ZERO | (cold ? M_NOWAIT : M_WAITOK));
346:
347: if (scr == NULL)
348: return NULL;
349:
350: scr->nsegs = 0;
351: scr->depth = depth;
352: scr->stride = virtual_width * depth / 8;
353: scr->buf_size = size = scr->stride * virtual_height;
354: scr->buf_va = NULL;
355:
356: /* calculate the alignment for LCD frame buffer.
357: the buffer can't across 4MB boundary */
358: align = 1 << 20;
359: while (align < size)
360: align <<= 1;
361:
362: error = bus_dmamem_alloc(sc->dma_tag, size, align, 0,
363: scr->segs, 1, &(scr->nsegs), busdma_flag);
364:
365: if (error || scr->nsegs != 1)
366: goto bad;
367:
368: error = bus_dmamem_map(sc->dma_tag, scr->segs, scr->nsegs,
369: size, (void **)&(scr->buf_va), busdma_flag | BUS_DMA_COHERENT);
370: if (error)
371: goto bad;
372:
373:
374: memset (scr->buf_va, 0, scr->buf_size);
375:
376: /* map memory for DMA */
377: if (bus_dmamap_create(sc->dma_tag, 1024*1024*2, 1,
378: 1024*1024*2, 0, busdma_flag, &scr->dma))
379: goto bad;
380: error = bus_dmamap_load(sc->dma_tag, scr->dma,
381: scr->buf_va, size, NULL, busdma_flag);
382: if (error)
383: goto bad;
384:
385: LIST_INSERT_HEAD(&(sc->screens), scr, link);
386: sc->n_screens++;
387:
388: #ifdef LCD_DEBUG
389: draw_test_pattern(sc, scr);
390: dump_lcdcon(__FUNCTION__, sc->iot, sc->ioh);
391: #endif
392: return scr;
393:
394: bad:
395: if (scr) {
396: if (scr->buf_va)
397: bus_dmamem_unmap(sc->dma_tag, scr->buf_va, size);
398: if (scr->nsegs)
399: bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs);
400: free(scr, M_DEVBUF);
401: }
402: return NULL;
403: }
404:
405:
406: #define _rgb(r,g,b) (((r)<<11) | ((g)<<5) | b)
407: #define rgb(r,g,b) _rgb((r)>>1,g,(b)>>1)
408:
409: #define L 0x30 /* low intensity */
410: #define H 0x3f /* hight intensity */
411:
412: static const uint16_t basic_color_map[] = {
413: rgb( 0, 0, 0), /* black */
414: rgb( L, 0, 0), /* red */
415: rgb( 0, L, 0), /* green */
416: rgb( L, L, 0), /* brown */
417: rgb( 0, 0, L), /* blue */
418: rgb( L, 0, L), /* magenta */
419: rgb( 0, L, L), /* cyan */
420: _rgb(0x1c,0x38,0x1c), /* white */
421:
422: rgb( L, L, L), /* black */
423: rgb( H, 0, 0), /* red */
424: rgb( 0, H, 0), /* green */
425: rgb( H, H, 0), /* brown */
426: rgb( 0, 0, H), /* blue */
427: rgb( H, 0, H), /* magenta */
428: rgb( 0, H, H), /* cyan */
429: rgb( H, H, H), /* white */
430: };
431:
432: #define COLORMAP_LEN (sizeof basic_color_map / sizeof basic_color_map[0])
433:
434: #undef H
435: #undef L
436:
437: static void
438: init_palette(struct s3c24x0_lcd_softc *sc, struct s3c24x0_lcd_screen *scr)
439: {
440: int depth = scr->depth;
441: bus_space_tag_t iot = sc->iot;
442: bus_space_handle_t ioh = sc->ioh;
443: int i;
444:
445: i = 0;
446:
447: switch(depth) {
448: default:
449: case 16: /* not using palette */
450: return;
451: case 8:
452: while (i < COLORMAP_LEN) {
453: bus_space_write_4(iot, ioh, LCDC_PALETTE + 4*i,
454: basic_color_map[i]);
455: ++i;
456: }
457: break;
458: case 4:
459: case 2:
460: /* XXX */
461: break;
462: case 1:
463: bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i,
464: basic_color_map[i]); /* black */
465: ++i;
466: bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i,
467: basic_color_map[7]); /* white */
468: break;
469: }
470:
471: #ifdef DIAGNOSTIC
472: /* Fill unused entries */
473: for ( ; i < 256; ++i )
474: bus_space_write_4(iot, ioh, LCDC_PALETTE + 4 * i,
475: basic_color_map[1]); /* red */
476: #endif
477: }
478:
479:
480: #if NWSDISPLAY > 0
481:
482: static void
483: s3c24x0_lcd_stop_dma(struct s3c24x0_lcd_softc *sc)
484: {
485: /* Stop LCD output */
486: bus_space_write_4(sc->iot, sc->ioh, LCDC_LCDCON1,
487: ~LCDCON1_ENVID &
488: bus_space_read_4(sc->iot, sc->ioh, LCDC_LCDCON1));
489:
490:
491: sc->lcd_on = 0;
492: }
493:
494: int
495: s3c24x0_lcd_show_screen(void *v, void *cookie, int waitok,
496: void (*cb)(void *, int, int), void *cbarg)
497: {
498: struct s3c24x0_lcd_softc *sc = v;
499: struct s3c24x0_lcd_screen *scr = cookie, *old;
500:
501: /* XXX: make sure the clock is provided for LCD controller */
502:
503: old = sc->active;
504: if (old == scr && sc->lcd_on)
505: return 0;
506:
507: if (old)
508: s3c24x0_lcd_stop_dma(sc);
509:
510: s3c24x0_lcd_start_dma(sc, scr);
511: sc->active = scr;
512: s3c24x0_lcd_power(sc, 1);
513:
514: /* XXX: callback */
515:
516: return 0;
517: }
518:
519: int
520: s3c24x0_lcd_alloc_screen(void *v, const struct wsscreen_descr *_type,
521: void **cookiep, int *curxp, int *curyp, long *attrp)
522: {
523: struct s3c24x0_lcd_softc *sc = v;
524: struct s3c24x0_lcd_screen *scr;
525: const struct s3c24x0_wsscreen_descr *type =
526: (const struct s3c24x0_wsscreen_descr *)_type;
527:
528: int width, height;
529:
530: width = type->c.ncols * type->c.fontwidth;
531: height = type->c.nrows * type->c.fontwidth;
532:
533: if (width < sc->panel_info->panel_width)
534: width = sc->panel_info->panel_width;
535: if (height < sc->panel_info->panel_height)
536: height = sc->panel_info->panel_height;
537:
538:
539: scr = s3c24x0_lcd_new_screen(sc, width, height, type->depth);
540: if (scr == NULL)
541: return -1;
542:
543: /*
544: * initialize raster operation for this screen.
545: */
546: scr->rinfo.ri_flg = 0;
547: scr->rinfo.ri_depth = type->depth;
548: scr->rinfo.ri_bits = scr->buf_va;
549: scr->rinfo.ri_width = width;
550: scr->rinfo.ri_height = height;
551: scr->rinfo.ri_stride = scr->stride;
552:
553: if (type->c.fontwidth || type->c.fontheight) {
554: /*
555: * find a font with specified size
556: */
557: int cookie;
558:
559: wsfont_init();
560:
561: cookie = wsfont_find(NULL, type->c.fontwidth,
562: type->c.fontheight, 0, WSDISPLAY_FONTORDER_L2R,
563: WSDISPLAY_FONTORDER_L2R);
564:
565: if (cookie > 0) {
566: if (wsfont_lock(cookie, &scr->rinfo.ri_font))
567: scr->rinfo.ri_wsfcookie = cookie;
568: }
569: }
570:
571: rasops_init(&scr->rinfo, type->c.nrows, type->c.ncols);
572:
573: (* scr->rinfo.ri_ops.allocattr)(&scr->rinfo, 0, 0, 0, attrp);
574:
575: if (type->c.nrows != scr->rinfo.ri_rows ||
576: type->c.ncols != scr->rinfo.ri_cols) {
577:
578: aprint_error("%s: can't allocate a screen with requested size:"
579: "%d x %d -> %d x %d\n",
580: sc->dev.dv_xname,
581: type->c.ncols, type->c.nrows,
582: scr->rinfo.ri_cols, scr->rinfo.ri_rows);
583: }
584:
585: *cookiep = scr;
586: *curxp = 0;
587: *curyp = 0;
588:
589: return 0;
590: }
591:
592:
593: void
594: s3c24x0_lcd_free_screen(void *v, void *cookie)
595: {
596: struct s3c24x0_lcd_softc *sc = v;
597: struct s3c24x0_lcd_screen *scr = cookie;
598:
599: LIST_REMOVE(scr, link);
600: sc->n_screens--;
601: if (scr == sc->active) {
602: sc->active = NULL;
603:
604: /* XXX: We need a good procedure to shutdown the LCD. */
605:
606: s3c24x0_lcd_stop_dma(sc);
607: s3c24x0_lcd_power(sc, 0);
608: }
609:
610: if (scr->buf_va)
611: bus_dmamem_unmap(sc->dma_tag, scr->buf_va, scr->map_size);
612:
613: if (scr->nsegs > 0)
614: bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs);
615:
616: free(scr, M_DEVBUF);
617: }
618:
619: int
620: s3c24x0_lcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
621: struct lwp *l)
622: {
623: struct s3c24x0_lcd_softc *sc = v;
624: struct wsdisplay_fbinfo *wsdisp_info;
625: struct s3c24x0_lcd_screen *scr;
626:
627:
628: switch (cmd) {
629: case WSDISPLAYIO_GTYPE:
630: *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */
631: return 0;
632:
633: case WSDISPLAYIO_GINFO:
634: wsdisp_info = (struct wsdisplay_fbinfo *)data;
635:
636: wsdisp_info->height = sc->panel_info->panel_height;
637: wsdisp_info->width = sc->panel_info->panel_width;
638: wsdisp_info->depth = 16; /* XXX */
639: wsdisp_info->cmsize = 0;
640: return 0;
641:
642: case WSDISPLAYIO_GETCMAP:
643: case WSDISPLAYIO_PUTCMAP:
644: return EPASSTHROUGH; /* XXX Colormap */
645:
646: case WSDISPLAYIO_SVIDEO:
647: if (*(int *)data == WSDISPLAYIO_VIDEO_ON) {
648: scr = sc->active;
649: if (scr == NULL)
650: scr = LIST_FIRST(&sc->screens);
651:
652: if (scr == NULL)
653: return ENXIO;
654:
655: s3c24x0_lcd_show_screen(sc, scr, 1, NULL, NULL);
656: }
657: else {
658: s3c24x0_lcd_stop_dma(sc);
659: s3c24x0_lcd_power(sc, 0);
660: }
661: return 0;
662:
663: case WSDISPLAYIO_GVIDEO:
664: *(u_int *)data = sc->lcd_on;
665: return 0;
666:
667: case WSDISPLAYIO_GCURPOS:
668: case WSDISPLAYIO_SCURPOS:
669: case WSDISPLAYIO_GCURMAX:
670: case WSDISPLAYIO_GCURSOR:
671: case WSDISPLAYIO_SCURSOR:
672: return EPASSTHROUGH; /* XXX */
673: }
674:
675: return EPASSTHROUGH;
676: }
677:
678: paddr_t
679: s3c24x0_lcd_mmap(void *v, void *vs, off_t offset, int prot)
680: {
681: struct s3c24x0_lcd_softc *sc = v;
682: struct s3c24x0_lcd_screen *screen = sc->active; /* ??? */
683:
684: if (screen == NULL)
685: return -1;
686:
687: return bus_dmamem_mmap(sc->dma_tag, screen->segs, screen->nsegs,
688: offset, prot, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
689: return -1;
690: }
691:
692:
693: static void
694: s3c24x0_lcd_cursor(void *cookie, int on, int row, int col)
695: {
696: struct s3c24x0_lcd_screen *scr = cookie;
697:
698: (* scr->rinfo.ri_ops.cursor)(&scr->rinfo, on, row, col);
699: }
700:
701: static int
702: s3c24x0_lcd_mapchar(void *cookie, int c, unsigned int *cp)
703: {
704: struct s3c24x0_lcd_screen *scr = cookie;
705:
706: return (* scr->rinfo.ri_ops.mapchar)(&scr->rinfo, c, cp);
707: }
708:
709: static void
710: s3c24x0_lcd_putchar(void *cookie, int row, int col, u_int uc, long attr)
711: {
712: struct s3c24x0_lcd_screen *scr = cookie;
713:
714: (* scr->rinfo.ri_ops.putchar)(&scr->rinfo,
715: row, col, uc, attr);
716: }
717:
718: static void
719: s3c24x0_lcd_copycols(void *cookie, int row, int src, int dst, int num)
720: {
721: struct s3c24x0_lcd_screen *scr = cookie;
722:
723: (* scr->rinfo.ri_ops.copycols)(&scr->rinfo,
724: row, src, dst, num);
725: }
726:
727: static void
728: s3c24x0_lcd_erasecols(void *cookie, int row, int col, int num, long attr)
729: {
730: struct s3c24x0_lcd_screen *scr = cookie;
731:
732: (* scr->rinfo.ri_ops.erasecols)(&scr->rinfo,
733: row, col, num, attr);
734: }
735:
736: static void
737: s3c24x0_lcd_copyrows(void *cookie, int src, int dst, int num)
738: {
739: struct s3c24x0_lcd_screen *scr = cookie;
740:
741: (* scr->rinfo.ri_ops.copyrows)(&scr->rinfo,
742: src, dst, num);
743: }
744:
745: static void
746: s3c24x0_lcd_eraserows(void *cookie, int row, int num, long attr)
747: {
748: struct s3c24x0_lcd_screen *scr = cookie;
749:
750: (* scr->rinfo.ri_ops.eraserows)(&scr->rinfo,
751: row, num, attr);
752: }
753:
754: static int
755: s3c24x0_lcd_alloc_attr(void *cookie, int fg, int bg, int flg, long *attr)
756: {
757: struct s3c24x0_lcd_screen *scr = cookie;
758:
759: return (* scr->rinfo.ri_ops.allocattr)(&scr->rinfo,
760: fg, bg, flg, attr);
761: }
762:
763:
764: const struct wsdisplay_emulops s3c24x0_lcd_emulops = {
765: s3c24x0_lcd_cursor,
766: s3c24x0_lcd_mapchar,
767: s3c24x0_lcd_putchar,
768: s3c24x0_lcd_copycols,
769: s3c24x0_lcd_erasecols,
770: s3c24x0_lcd_copyrows,
771: s3c24x0_lcd_eraserows,
772: s3c24x0_lcd_alloc_attr
773: };
774:
775: #endif /* NWSDISPLAY > 0 */
CVSweb