[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     ! 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