[BACK]Return to s3c24x0_lcd.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / s3c2xx0

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