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

Annotation of sys/arch/arm/xscale/pxa2x0_lcd.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: pxa2x0_lcd.c,v 1.22 2007/05/27 16:12:11 matthieu Exp $ */
                      2: /* $NetBSD: pxa2x0_lcd.c,v 1.8 2003/10/03 07:24:05 bsh Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 2002  Genetec Corporation.  All rights reserved.
                      6:  * Written by Hiroyuki Bessho for Genetec Corporation.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed for the NetBSD Project by
                     19:  *     Genetec Corporation.
                     20:  * 4. The name of Genetec Corporation may not be used to endorse or
                     21:  *    promote products derived from this software without specific prior
                     22:  *    written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     26:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     27:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
                     28:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     29:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     30:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     31:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     32:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     33:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     34:  * POSSIBILITY OF SUCH DAMAGE.
                     35:  */
                     36:
                     37: /*
                     38:  * Support PXA2[15]0's integrated LCD controller.
                     39:  */
                     40:
                     41: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/conf.h>
                     44: #include <sys/uio.h>
                     45: #include <sys/malloc.h>
                     46: #include <sys/kernel.h>                        /* for cold */
                     47:
                     48: #include <uvm/uvm_extern.h>
                     49:
                     50: #include <dev/cons.h>
                     51:
                     52: #include <dev/wscons/wsconsio.h>
                     53: #include <dev/wscons/wsdisplayvar.h>
                     54: #include <dev/rasops/rasops.h>
                     55:
                     56: #include <machine/bus.h>
                     57: #include <machine/cpu.h>
                     58: #include <arm/cpufunc.h>
                     59:
                     60: #include <arm/xscale/pxa2x0var.h>
                     61: #include <arm/xscale/pxa2x0reg.h>
                     62: #include <arm/xscale/pxa2x0_lcd.h>
                     63: #include <arm/xscale/pxa2x0_gpio.h>
                     64:
                     65: /*
                     66:  * Console variables. These are necessary since console is setup very early,
                     67:  * before devices get attached.
                     68:  */
                     69: struct {
                     70:        bus_space_tag_t                  iot;
                     71:        bus_space_handle_t               ioh;
                     72:        bus_dma_tag_t                    dma_tag;
                     73:        const struct lcd_panel_geometry *geometry;
                     74:        struct pxa2x0_lcd_screen         scr;
                     75: } pxa2x0_lcd_console;
                     76:
                     77: int    lcdintr(void *);
                     78: void   pxa2x0_lcd_geometry(bus_space_tag_t, bus_space_handle_t,
                     79:            const struct lcd_panel_geometry *);
                     80: void   pxa2x0_lcd_initialize(bus_space_tag_t, bus_space_handle_t,
                     81:            const struct lcd_panel_geometry *, void (*)(u_int, int));
                     82: int    pxa2x0_lcd_new_screen(struct pxa2x0_lcd_softc *,
                     83:            struct pxa2x0_lcd_screen *, int);
                     84: void   pxa2x0_lcd_setup_console(struct pxa2x0_lcd_softc *,
                     85:            const struct pxa2x0_wsscreen_descr *);
                     86: void   pxa2x0_lcd_setup_rasops(struct rasops_info *,
                     87:            struct pxa2x0_wsscreen_descr *,
                     88:            const struct lcd_panel_geometry *);
                     89: void   pxa2x0_lcd_start_dma(bus_space_tag_t, bus_space_handle_t,
                     90:            struct pxa2x0_lcd_screen *);
                     91: void   pxa2x0_lcd_stop_dma(bus_space_tag_t, bus_space_handle_t);
                     92:
                     93: /*
                     94:  * Setup display geometry parameters.
                     95:  */
                     96: void
                     97: pxa2x0_lcd_geometry(bus_space_tag_t iot, bus_space_handle_t ioh,
                     98:     const struct lcd_panel_geometry *info)
                     99: {
                    100:        int lines;
                    101:        uint32_t ccr0;
                    102:
                    103:        ccr0 = LCCR0_IMASK;
                    104:        if (info->panel_info & LCDPANEL_ACTIVE)
                    105:                ccr0 |= LCCR0_PAS;      /* active mode */
                    106:        if ((info->panel_info & (LCDPANEL_DUAL | LCDPANEL_ACTIVE))
                    107:            == LCDPANEL_DUAL)
                    108:                ccr0 |= LCCR0_SDS; /* dual panel */
                    109:        if (info->panel_info & LCDPANEL_MONOCHROME)
                    110:                ccr0 |= LCCR0_CMS;
                    111:        /* XXX - Zaurus C3000 */
                    112:        ccr0 |= LCCR0_LDDALT |
                    113:            LCCR0_OUC |
                    114:            LCCR0_CMDIM |
                    115:            LCCR0_RDSTM;
                    116:
                    117:        bus_space_write_4(iot, ioh, LCDC_LCCR0, ccr0);
                    118:
                    119:        bus_space_write_4(iot, ioh, LCDC_LCCR1,
                    120:            (info->panel_width - 1)
                    121:            | ((info->hsync_pulse_width - 1) << 10)
                    122:            | ((info->end_line_wait - 1) << 16)
                    123:            | ((info->beg_line_wait - 1) << 24));
                    124:
                    125:        if (info->panel_info & LCDPANEL_DUAL)
                    126:                lines = info->panel_height / 2 + info->extra_lines;
                    127:        else
                    128:                lines = info->panel_height + info->extra_lines;
                    129:
                    130:        bus_space_write_4(iot, ioh, LCDC_LCCR2,
                    131:            (lines - 1)
                    132:            | (info->vsync_pulse_width << 10)
                    133:            | (info->end_frame_wait << 16)
                    134:            | (info->beg_frame_wait << 24));
                    135:
                    136:        bus_space_write_4(iot, ioh, LCDC_LCCR3,
                    137:            (info->pixel_clock_div << 0)
                    138:            | (info->ac_bias << 8)
                    139:            | ((info->panel_info &
                    140:                (LCDPANEL_VSP | LCDPANEL_HSP | LCDPANEL_PCP | LCDPANEL_OEP))
                    141:                << 20)
                    142:            | (4 << 24) /* 16bpp */
                    143:            | ((info->panel_info & LCDPANEL_DPC) ? (1 << 27) : 0)
                    144:            );
                    145: }
                    146:
                    147: /*
                    148:  * Initialize the LCD controller.
                    149:  */
                    150: void
                    151: pxa2x0_lcd_initialize(bus_space_tag_t iot, bus_space_handle_t ioh,
                    152:     const struct lcd_panel_geometry *geom, void (*clkman)(u_int, int))
                    153: {
                    154:        int nldd;
                    155:        u_int32_t lccr0, lscr;
                    156:
                    157:        /* Check if LCD is enabled before programming, it should not
                    158:         * be enabled while it is being reprogrammed, therefore disable
                    159:         * it first.
                    160:         */
                    161:        lccr0 = bus_space_read_4(iot, ioh, LCDC_LCCR0);
                    162:        if (lccr0 & LCCR0_ENB) {
                    163:                lccr0 |= LCCR0_LDM;
                    164:                bus_space_write_4(iot, ioh, LCDC_LCCR0, lccr0);
                    165:                lccr0 = bus_space_read_4(iot, ioh, LCDC_LCCR0); /* paranoia */
                    166:                lccr0 |= LCCR0_DIS;
                    167:                bus_space_write_4(iot, ioh, LCDC_LCCR0, lccr0);
                    168:                do {
                    169:                        lscr = bus_space_read_4(iot, ioh, LCDC_LCSR);
                    170:                } while (!(lscr & LCSR_LDD));
                    171:        }
                    172:
                    173:        /* enable clock */
                    174:        (*clkman)(CKEN_LCD, 1);
                    175:
                    176:        bus_space_write_4(iot, ioh, LCDC_LCCR0, LCCR0_IMASK);
                    177:
                    178:        /*
                    179:         * setup GP[77:58] for LCD
                    180:         */
                    181:        /* Always use [FLP]CLK, ACBIAS */
                    182:        pxa2x0_gpio_set_function(74, GPIO_ALT_FN_2_OUT);
                    183:        pxa2x0_gpio_set_function(75, GPIO_ALT_FN_2_OUT);
                    184:        pxa2x0_gpio_set_function(76, GPIO_ALT_FN_2_OUT);
                    185:        pxa2x0_gpio_set_function(77, GPIO_ALT_FN_2_OUT);
                    186:
                    187:        if ((geom->panel_info & LCDPANEL_ACTIVE) ||
                    188:            ((geom->panel_info & (LCDPANEL_MONOCHROME|LCDPANEL_DUAL)) ==
                    189:            LCDPANEL_DUAL)) {
                    190:                /* active and color dual panel need L_DD[15:0] */
                    191:                nldd = 16;
                    192:        } else if ((geom->panel_info & LCDPANEL_DUAL) ||
                    193:            !(geom->panel_info & LCDPANEL_MONOCHROME)) {
                    194:                /* dual or color need L_DD[7:0] */
                    195:                nldd = 8;
                    196:        } else {
                    197:                /* Otherwise just L_DD[3:0] */
                    198:                nldd = 4;
                    199:        }
                    200:
                    201:        while (nldd--)
                    202:                pxa2x0_gpio_set_function(58 + nldd, GPIO_ALT_FN_2_OUT);
                    203:
                    204:        pxa2x0_lcd_geometry(iot, ioh, geom);
                    205: }
                    206:
                    207: /*
                    208:  * Common driver attachment code.
                    209:  */
                    210: void
                    211: pxa2x0_lcd_attach_sub(struct pxa2x0_lcd_softc *sc,
                    212:     struct pxaip_attach_args *pxa, struct pxa2x0_wsscreen_descr *descr,
                    213:     const struct lcd_panel_geometry *geom, int console)
                    214: {
                    215:        bus_space_tag_t iot;
                    216:        bus_space_handle_t ioh;
                    217:        int error;
                    218:
                    219:        sc->n_screens = 0;
                    220:        LIST_INIT(&sc->screens);
                    221:
                    222:        /* map controller registers if not console */
                    223:        if (console != 0) {
                    224:                iot = pxa2x0_lcd_console.iot;
                    225:                ioh = pxa2x0_lcd_console.ioh;
                    226:        } else {
                    227:                iot = pxa->pxa_iot;
                    228:                error = bus_space_map(iot, PXA2X0_LCDC_BASE, PXA2X0_LCDC_SIZE,
                    229:                    0, &ioh);
                    230:                if (error) {
                    231:                        printf(": failed to map registers %d", error);
                    232:                        return;
                    233:                }
                    234:        }
                    235:
                    236:        sc->iot = iot;
                    237:        sc->ioh = ioh;
                    238:        sc->dma_tag = &pxa2x0_bus_dma_tag;
                    239:
                    240:        sc->ih = pxa2x0_intr_establish(17, IPL_BIO, lcdintr, sc,
                    241:            sc->dev.dv_xname);
                    242:        if (sc->ih == NULL)
                    243:                printf("%s: unable to establish interrupt at irq %d",
                    244:                    sc->dev.dv_xname, 17);
                    245:
                    246:        sc->geometry = geom;
                    247:
                    248:        if (console != 0) {
                    249:                /* complete console attachment */
                    250:                pxa2x0_lcd_setup_console(sc, descr);
                    251:        } else {
                    252:                struct rasops_info dummy;
                    253:
                    254:                pxa2x0_lcd_initialize(iot, ioh, geom, pxa2x0_clkman_config);
                    255:
                    256:                /*
                    257:                 * Initialize a dummy rasops_info to compute fontsize and
                    258:                 * the screen size in chars.
                    259:                 */
                    260:                bzero(&dummy, sizeof(dummy));
                    261:                pxa2x0_lcd_setup_rasops(&dummy, descr, geom);
                    262:        }
                    263: }
                    264:
                    265: /*
                    266:  * Interrupt handler.
                    267:  */
                    268: int
                    269: lcdintr(void *arg)
                    270: {
                    271:        struct pxa2x0_lcd_softc *sc = arg;
                    272:        bus_space_tag_t iot = sc->iot;
                    273:        bus_space_handle_t ioh = sc->ioh;
                    274:
                    275:        static uint32_t status;
                    276:
                    277:        status = bus_space_read_4(iot, ioh, LCDC_LCSR);
                    278:        /* Clear sticky status bits */
                    279:        bus_space_write_4(iot, ioh, LCDC_LCSR, status);
                    280:
                    281:        return 1;
                    282: }
                    283:
                    284: /*
                    285:  * Enable DMA to cause the display to be refreshed periodically.
                    286:  * This brings the screen to life...
                    287:  */
                    288: void
                    289: pxa2x0_lcd_start_dma(bus_space_tag_t iot, bus_space_handle_t ioh,
                    290:     struct pxa2x0_lcd_screen *scr)
                    291: {
                    292:        uint32_t tmp;
                    293:        int val, save;
                    294:
                    295:        save = disable_interrupts(I32_bit);
                    296:
                    297:        switch (scr->depth) {
                    298:        case 1: val = 0; break;
                    299:        case 2: val = 1; break;
                    300:        case 4: val = 2; break;
                    301:        case 8: val = 3; break;
                    302:        case 16:
                    303:                /* FALLTHROUGH */
                    304:        default:
                    305:                val = 4; break;
                    306:        }
                    307:
                    308:        tmp = bus_space_read_4(iot, ioh, LCDC_LCCR3);
                    309:        bus_space_write_4(iot, ioh, LCDC_LCCR3,
                    310:            (tmp & ~LCCR3_BPP) | (val << LCCR3_BPP_SHIFT));
                    311:
                    312:        bus_space_write_4(iot, ioh, LCDC_FDADR0,
                    313:            scr->depth == 16 ? scr->dma_desc_pa :
                    314:            scr->dma_desc_pa + 2 * sizeof (struct lcd_dma_descriptor));
                    315:        bus_space_write_4(iot, ioh, LCDC_FDADR1,
                    316:            scr->dma_desc_pa + 1 * sizeof (struct lcd_dma_descriptor));
                    317:
                    318:        /* clear status */
                    319:        bus_space_write_4(iot, ioh, LCDC_LCSR, 0);
                    320:
                    321:        delay(1000);                    /* ??? */
                    322:
                    323:        /* Enable LCDC */
                    324:        tmp = bus_space_read_4(iot, ioh, LCDC_LCCR0);
                    325:        /*tmp &= ~LCCR0_SFM;*/
                    326:        bus_space_write_4(iot, ioh, LCDC_LCCR0, tmp | LCCR0_ENB);
                    327:
                    328:        restore_interrupts(save);
                    329: }
                    330:
                    331: /*
                    332:  * Disable screen refresh.
                    333:  */
                    334: void
                    335: pxa2x0_lcd_stop_dma(bus_space_tag_t iot, bus_space_handle_t ioh)
                    336: {
                    337:
                    338:        /* Stop LCD DMA after current frame */
                    339:        bus_space_write_4(iot, ioh, LCDC_LCCR0,
                    340:            LCCR0_DIS |
                    341:            bus_space_read_4(iot, ioh, LCDC_LCCR0));
                    342:
                    343:        /* wait for disabling done.
                    344:           XXX: use interrupt. */
                    345:        while (LCCR0_ENB &
                    346:            bus_space_read_4(iot, ioh, LCDC_LCCR0))
                    347:                ;
                    348:
                    349:        bus_space_write_4(iot, ioh, LCDC_LCCR0,
                    350:            ~LCCR0_DIS &
                    351:            bus_space_read_4(iot, ioh, LCDC_LCCR0));
                    352: }
                    353:
                    354: #define _rgb(r,g,b)    (((r)<<11) | ((g)<<5) | b)
                    355: #define rgb(r,g,b)     _rgb((r)>>1,g,(b)>>1)
                    356:
                    357: #define L      0x1f                    /* low intensity */
                    358: #define H      0x3f                    /* high intensity */
                    359:
                    360: static uint16_t basic_color_map[] = {
                    361:        rgb(    0,   0,   0),           /* black */
                    362:        rgb(    L,   0,   0),           /* red */
                    363:        rgb(    0,   L,   0),           /* green */
                    364:        rgb(    L,   L,   0),           /* brown */
                    365:        rgb(    0,   0,   L),           /* blue */
                    366:        rgb(    L,   0,   L),           /* magenta */
                    367:        rgb(    0,   L,   L),           /* cyan */
                    368:        rgb( 0x31,0x31,0x31),           /* white */
                    369:
                    370:        rgb(    L,   L,   L),           /* black */
                    371:        rgb(    H,   0,   0),           /* red */
                    372:        rgb(    0,   H,   0),           /* green */
                    373:        rgb(    H,   H,   0),           /* brown */
                    374:        rgb(    0,   0,   H),           /* blue */
                    375:        rgb(    H,   0,   H),           /* magenta */
                    376:        rgb(    0,   H,   H),           /* cyan */
                    377:        rgb(    H,   H,   H)
                    378: };
                    379:
                    380: #undef H
                    381: #undef L
                    382:
                    383: static void
                    384: init_palette(uint16_t *buf, int depth)
                    385: {
                    386:        int i;
                    387:
                    388:        /* convert RGB332 to RGB565 */
                    389:        switch (depth) {
                    390:        case 8:
                    391:        case 4:
                    392: #if 0
                    393:                for (i = 0; i <= 255; ++i) {
                    394:                        buf[i] = ((9 * ((i >> 5) & 0x07)) << 11) |
                    395:                            ((9 * ((i >> 2) & 0x07)) << 5) |
                    396:                            ((21 * (i & 0x03)) / 2);
                    397:                }
                    398: #else
                    399:                memcpy(buf, basic_color_map, sizeof basic_color_map);
                    400:                for (i = 16; i < (1 << depth); ++i)
                    401:                        buf[i] = 0xffff;
                    402: #endif
                    403:                break;
                    404:        case 16:
                    405:                /* palette is not needed */
                    406:                break;
                    407:        default:
                    408:                /* other depths are not supported */
                    409:                break;
                    410:        }
                    411: }
                    412:
                    413: /*
                    414:  * Create and initialize a new screen buffer.
                    415:  */
                    416: int
                    417: pxa2x0_lcd_new_screen(struct pxa2x0_lcd_softc *sc,
                    418:     struct pxa2x0_lcd_screen *scr, int depth)
                    419: {
                    420:        bus_space_tag_t iot;
                    421:        bus_space_handle_t ioh;
                    422:        bus_dma_tag_t dma_tag;
                    423:        const struct lcd_panel_geometry *geometry;
                    424:        int width, height;
                    425:        bus_size_t size;
                    426:        int error, palette_size;
                    427:        int busdma_flag = (cold ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
                    428:        struct lcd_dma_descriptor *desc;
                    429:        paddr_t buf_pa, desc_pa;
                    430:
                    431:        if (sc != NULL) {
                    432:                iot = sc->iot;
                    433:                ioh = sc->ioh;
                    434:                dma_tag = sc->dma_tag;
                    435:                geometry = sc->geometry;
                    436:        } else {
                    437:                /* We are creating the console screen. */
                    438:                iot = pxa2x0_lcd_console.iot;
                    439:                ioh = pxa2x0_lcd_console.ioh;
                    440:                dma_tag = pxa2x0_lcd_console.dma_tag;
                    441:                geometry = pxa2x0_lcd_console.geometry;
                    442:        }
                    443:
                    444:        width = geometry->panel_width;
                    445:        height = geometry->panel_height;
                    446:        palette_size = 0;
                    447:
                    448:        switch (depth) {
                    449:        case 1:
                    450:        case 2:
                    451:        case 4:
                    452:        case 8:
                    453:                palette_size = (1 << depth) * sizeof (uint16_t);
                    454:                /* FALLTHROUGH */
                    455:        case 16:
                    456:                size = roundup(width, 4) * depth / 8 * height;
                    457:                break;
                    458:        default:
                    459:                printf("%s: Unknown depth (%d)\n",
                    460:                    sc != NULL ? sc->dev.dv_xname : "console", depth);
                    461:                return (EINVAL);
                    462:        }
                    463:
                    464:        bzero(scr, sizeof *scr);
                    465:
                    466:        scr->nsegs = 0;
                    467:        scr->depth = depth;
                    468:        scr->buf_size = size;
                    469:        scr->buf_va = NULL;
                    470:        size = roundup(size, 16) + 3 * sizeof (struct lcd_dma_descriptor)
                    471:            + palette_size;
                    472:
                    473:        error = bus_dmamem_alloc(dma_tag, size, 16, 0,
                    474:            scr->segs, 1, &(scr->nsegs), busdma_flag);
                    475:        if (error != 0 || scr->nsegs != 1) {
                    476:                /* XXX: Actually we can handle nsegs > 1 case by means
                    477:                   of multiple DMA descriptors for a panel.  It would
                    478:                    make code here a bit hairy */
                    479:                if (error == 0)
                    480:                        error = E2BIG;
                    481:                goto bad;
                    482:        }
                    483:
                    484:        error = bus_dmamem_map(dma_tag, scr->segs, scr->nsegs,
                    485:            size, (caddr_t *)&(scr->buf_va), busdma_flag | BUS_DMA_COHERENT);
                    486:        if (error != 0)
                    487:                goto bad;
                    488:
                    489:        memset(scr->buf_va, 0, scr->buf_size);
                    490:
                    491:        /* map memory for DMA */
                    492:        if (bus_dmamap_create(dma_tag, 1024 * 1024 * 2, 1,
                    493:            1024 * 1024 * 2, 0,  busdma_flag, &scr->dma))
                    494:                goto bad;
                    495:        error = bus_dmamap_load(dma_tag, scr->dma,
                    496:            scr->buf_va, size, NULL, busdma_flag);
                    497:        if (error != 0) {
                    498:                goto bad;
                    499:        }
                    500:
                    501:        buf_pa = scr->segs[0].ds_addr;
                    502:        desc_pa = buf_pa + roundup(size, PAGE_SIZE) - 3 * sizeof *desc;
                    503:
                    504:        /* make descriptors at the top of mapped memory */
                    505:        desc = (struct lcd_dma_descriptor *)
                    506:            ((caddr_t)(scr->buf_va) + roundup(size, PAGE_SIZE) -
                    507:             3 * sizeof *desc);
                    508:
                    509:        desc[0].fdadr = desc_pa;
                    510:        desc[0].fsadr = buf_pa;
                    511:        desc[0].ldcmd = scr->buf_size;
                    512:
                    513:        if (palette_size) {
                    514:                init_palette((uint16_t *)((char *)desc - palette_size), depth);
                    515:
                    516:                desc[2].fdadr = desc_pa; /* chain to panel 0 */
                    517:                desc[2].fsadr = desc_pa - palette_size;
                    518:                desc[2].ldcmd = palette_size | LDCMD_PAL;
                    519:        }
                    520:
                    521:        if (geometry->panel_info & LCDPANEL_DUAL) {
                    522:                /* Dual panel */
                    523:                desc[1].fdadr = desc_pa + sizeof *desc;
                    524:                desc[1].fsadr = buf_pa + scr->buf_size / 2;
                    525:                desc[0].ldcmd = desc[1].ldcmd = scr->buf_size / 2;
                    526:
                    527:        }
                    528:
                    529: #if 0
                    530:        desc[0].ldcmd |= LDCMD_SOFINT;
                    531:        desc[1].ldcmd |= LDCMD_SOFINT;
                    532: #endif
                    533:
                    534:        scr->dma_desc = desc;
                    535:        scr->dma_desc_pa = desc_pa;
                    536:        scr->map_size = size;           /* used when unmap this. */
                    537:
                    538:        if (sc != NULL) {
                    539:                LIST_INSERT_HEAD(&(sc->screens), scr, link);
                    540:                sc->n_screens++;
                    541:        }
                    542:
                    543:        return (0);
                    544:
                    545:  bad:
                    546:        if (scr->buf_va)
                    547:                bus_dmamem_unmap(dma_tag, scr->buf_va, size);
                    548:        if (scr->nsegs)
                    549:                bus_dmamem_free(dma_tag, scr->segs, scr->nsegs);
                    550:        return (error);
                    551: }
                    552:
                    553: /*
                    554:  * Initialize rasops for a screen, as well as struct wsscreen_descr if this
                    555:  * is the first screen creation.
                    556:  */
                    557: void
                    558: pxa2x0_lcd_setup_rasops(struct rasops_info *rinfo,
                    559:     struct pxa2x0_wsscreen_descr *descr,
                    560:     const struct lcd_panel_geometry *geom)
                    561: {
                    562:
                    563:        rinfo->ri_flg = descr->flags;
                    564:        rinfo->ri_depth = descr->depth;
                    565:        rinfo->ri_width = geom->panel_width;
                    566:        rinfo->ri_height = geom->panel_height;
                    567:        rinfo->ri_stride = rinfo->ri_width * rinfo->ri_depth / 8;
                    568: #ifdef notyet
                    569:        rinfo->ri_wsfcookie = -1;       /* XXX */
                    570: #endif
                    571:
                    572:        /* swap B and R */
                    573:        if (descr->depth == 16) {
                    574:                rinfo->ri_rnum = 5;
                    575:                rinfo->ri_rpos = 11;
                    576:                rinfo->ri_gnum = 6;
                    577:                rinfo->ri_gpos = 5;
                    578:                rinfo->ri_bnum = 5;
                    579:                rinfo->ri_bpos = 0;
                    580:        }
                    581:
                    582:        if (descr->c.nrows == 0) {
                    583:                /* get rasops to compute screen size the first time */
                    584:                rasops_init(rinfo, 100, 100);
                    585:        } else
                    586: #ifndef __zaurus__
                    587:                rasops_init(rinfo, descr->c.nrows, descr->c.ncols);
                    588: #else
                    589:                /* XXX swap rows/cols for second call because of rotation */
                    590:                rasops_init(rinfo, descr->c.ncols, descr->c.nrows);
                    591: #endif
                    592:
                    593:        descr->c.nrows = rinfo->ri_rows;
                    594:        descr->c.ncols = rinfo->ri_cols;
                    595:        descr->c.capabilities = rinfo->ri_caps;
                    596:        descr->c.textops = &rinfo->ri_ops;
                    597: }
                    598:
                    599: /*
                    600:  * Early console attachment.
                    601:  * This initializes the LCD, then creates and displays a screen buffer.
                    602:  * This screen will be accounted for in the softc when the lcd device attaches.
                    603:  */
                    604: int
                    605: pxa2x0_lcd_cnattach(struct pxa2x0_wsscreen_descr *descr,
                    606:     const struct lcd_panel_geometry *geom, void (*clkman)(u_int, int))
                    607: {
                    608:        struct rasops_info *ri;
                    609:        long defattr;
                    610:        int error;
                    611:
                    612:        /* map controller registers */
                    613:        pxa2x0_lcd_console.iot = &pxa2x0_bs_tag;
                    614:        error = bus_space_map(pxa2x0_lcd_console.iot,
                    615:            PXA2X0_LCDC_BASE, PXA2X0_LCDC_SIZE, 0, &pxa2x0_lcd_console.ioh);
                    616:        if (error != 0)
                    617:                return (error);
                    618:
                    619:        pxa2x0_lcd_console.dma_tag = &pxa2x0_bus_dma_tag;
                    620:        pxa2x0_lcd_console.geometry = geom;
                    621:
                    622:        pxa2x0_lcd_initialize(pxa2x0_lcd_console.iot, pxa2x0_lcd_console.ioh,
                    623:            pxa2x0_lcd_console.geometry, clkman);
                    624:
                    625:        error = pxa2x0_lcd_new_screen(NULL, &pxa2x0_lcd_console.scr,
                    626:            descr->depth);
                    627:        if (error != 0)
                    628:                return (error);
                    629:
                    630:        ri = &pxa2x0_lcd_console.scr.rinfo;
                    631:        ri->ri_hw = (void *)&pxa2x0_lcd_console.scr;
                    632:        ri->ri_bits = pxa2x0_lcd_console.scr.buf_va;
                    633:        pxa2x0_lcd_setup_rasops(ri, descr, pxa2x0_lcd_console.geometry);
                    634:
                    635:        /* assumes 16 bpp */
                    636:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
                    637:
                    638:        pxa2x0_lcd_start_dma(pxa2x0_lcd_console.iot, pxa2x0_lcd_console.ioh,
                    639:            &pxa2x0_lcd_console.scr);
                    640:
                    641:        wsdisplay_cnattach(&descr->c, ri, ri->ri_ccol, ri->ri_crow, defattr);
                    642:
                    643:        return (0);
                    644: }
                    645:
                    646: /*
                    647:  * Do the necessary accounting to bring the console variables in the softc.
                    648:  */
                    649: void
                    650: pxa2x0_lcd_setup_console(struct pxa2x0_lcd_softc *sc,
                    651:     const struct pxa2x0_wsscreen_descr *descr)
                    652: {
                    653:        struct pxa2x0_lcd_screen *scr = &pxa2x0_lcd_console.scr;
                    654:
                    655:        /*
                    656:         * Register the console screen as if it had been created
                    657:         * when the lcd device attached.
                    658:         */
                    659:        LIST_INSERT_HEAD(&(sc->screens), &pxa2x0_lcd_console.scr, link);
                    660:        sc->n_screens++;
                    661:        sc->active = scr;
                    662: }
                    663:
                    664: /*
                    665:  * wsdisplay accessops
                    666:  */
                    667:
                    668: int
                    669: pxa2x0_lcd_show_screen(void *v, void *cookie, int waitok,
                    670:     void (*cb)(void *, int, int), void *cbarg)
                    671: {
                    672:        struct pxa2x0_lcd_softc *sc = v;
                    673:        struct rasops_info *ri = cookie;
                    674:        struct pxa2x0_lcd_screen *scr = ri->ri_hw, *old;
                    675:
                    676:        old = sc->active;
                    677:        if (old == scr)
                    678:                return 0;
                    679:
                    680:        if (old)
                    681:                pxa2x0_lcd_stop_dma(sc->iot, sc->ioh);
                    682:
                    683:        pxa2x0_lcd_start_dma(sc->iot, sc->ioh, scr);
                    684:
                    685:        sc->active = scr;
                    686:        return 0;
                    687: }
                    688:
                    689: int
                    690: pxa2x0_lcd_alloc_screen(void *v, const struct wsscreen_descr *_type,
                    691:     void **cookiep, int *curxp, int *curyp, long *attrp)
                    692: {
                    693:        struct pxa2x0_lcd_softc *sc = v;
                    694:        struct pxa2x0_lcd_screen *scr;
                    695:        struct rasops_info *ri;
                    696:        struct pxa2x0_wsscreen_descr *type =
                    697:            (struct pxa2x0_wsscreen_descr *)_type;
                    698:        int error;
                    699:
                    700:        scr = malloc(sizeof *scr, M_DEVBUF, (cold ? M_NOWAIT : M_WAITOK));
                    701:        if (scr == NULL)
                    702:                return (ENOMEM);
                    703:
                    704:        error = pxa2x0_lcd_new_screen(sc, scr, type->depth);
                    705:        if (error != 0) {
                    706:                free(scr, M_DEVBUF);
                    707:                return (error);
                    708:        }
                    709:
                    710:        /*
                    711:         * initialize raster operation for this screen.
                    712:         */
                    713:        ri = &scr->rinfo;
                    714:        ri->ri_hw = (void *)scr;
                    715:        ri->ri_bits = scr->buf_va;
                    716:        pxa2x0_lcd_setup_rasops(ri, type, sc->geometry);
                    717:
                    718:        /* assumes 16 bpp */
                    719:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
                    720:
                    721:        *cookiep = ri;
                    722:        *curxp = 0;
                    723:        *curyp = 0;
                    724:
                    725:        return 0;
                    726: }
                    727:
                    728: void
                    729: pxa2x0_lcd_free_screen(void *v, void *cookie)
                    730: {
                    731:        struct pxa2x0_lcd_softc *sc = v;
                    732:        struct rasops_info *ri = cookie;
                    733:        struct pxa2x0_lcd_screen *scr = ri->ri_hw;
                    734:
                    735:        LIST_REMOVE(scr, link);
                    736:        sc->n_screens--;
                    737:        if (scr == sc->active) {
                    738:                /* at first, we need to stop LCD DMA */
                    739:                sc->active = NULL;
                    740:
                    741: #ifdef DEBUG
                    742:                printf("lcd_free on active screen\n");
                    743: #endif
                    744:
                    745:                pxa2x0_lcd_stop_dma(sc->iot, sc->ioh);
                    746:        }
                    747:
                    748:        if (scr->buf_va)
                    749:                bus_dmamem_unmap(sc->dma_tag, scr->buf_va, scr->map_size);
                    750:
                    751:        if (scr->nsegs > 0)
                    752:                bus_dmamem_free(sc->dma_tag, scr->segs, scr->nsegs);
                    753:
                    754:        free(scr, M_DEVBUF);
                    755: }
                    756:
                    757: int
                    758: pxa2x0_lcd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
                    759: {
                    760:        struct pxa2x0_lcd_softc *sc = v;
                    761:        struct wsdisplay_fbinfo *wsdisp_info;
                    762:        struct pxa2x0_lcd_screen *scr = sc->active;  /* ??? */
                    763:
                    764:        switch (cmd) {
                    765:        case WSDISPLAYIO_GTYPE:
                    766:                *(u_int *)data = WSDISPLAY_TYPE_PXALCD; /* XXX */
                    767:                break;
                    768:
                    769:        case WSDISPLAYIO_GINFO:
                    770:                wsdisp_info = (struct wsdisplay_fbinfo *)data;
                    771:
                    772:                wsdisp_info->height = sc->geometry->panel_height;
                    773:                wsdisp_info->width = sc->geometry->panel_width;
                    774:                wsdisp_info->depth = 16; /* XXX */
                    775:                wsdisp_info->cmsize = 0;
                    776:                break;
                    777:
                    778:        case WSDISPLAYIO_GETSUPPORTEDDEPTH:
                    779:                *(u_int *)data = WSDISPLAYIO_DEPTH_16;
                    780:                break;
                    781:
                    782:        case WSDISPLAYIO_GETCMAP:
                    783:        case WSDISPLAYIO_PUTCMAP:
                    784:                return EINVAL;  /* XXX Colormap */
                    785:
                    786:        case WSDISPLAYIO_SVIDEO:
                    787:        case WSDISPLAYIO_GVIDEO:
                    788:                break;
                    789:
                    790:        case WSDISPLAYIO_GCURPOS:
                    791:        case WSDISPLAYIO_SCURPOS:
                    792:        case WSDISPLAYIO_GCURMAX:
                    793:        case WSDISPLAYIO_GCURSOR:
                    794:        case WSDISPLAYIO_SCURSOR:
                    795:        default:
                    796:                return -1;      /* not implemented */
                    797:
                    798:         case WSDISPLAYIO_LINEBYTES:
                    799:                *(u_int *)data = scr->rinfo.ri_stride;
                    800:                break;
                    801:        }
                    802:        return (0);
                    803: }
                    804:
                    805: paddr_t
                    806: pxa2x0_lcd_mmap(void *v, off_t offset, int prot)
                    807: {
                    808:        struct pxa2x0_lcd_softc *sc = v;
                    809:        struct pxa2x0_lcd_screen *screen = sc->active;  /* ??? */
                    810:
                    811:        if ((offset & PAGE_MASK) != 0)
                    812:                return (-1);
                    813:
                    814:        if (screen == NULL)
                    815:                return (-1);
                    816:
                    817:        if (offset < 0 ||
                    818:            offset >= screen->rinfo.ri_stride * screen->rinfo.ri_height)
                    819:                return (-1);
                    820:
                    821:        return (bus_dmamem_mmap(sc->dma_tag, screen->segs, screen->nsegs,
                    822:            offset, prot, BUS_DMA_WAITOK | BUS_DMA_COHERENT));
                    823: }
                    824:
                    825: void
                    826: pxa2x0_lcd_suspend(struct pxa2x0_lcd_softc *sc)
                    827: {
                    828:
                    829:        if (sc->active != NULL) {
                    830:                pxa2x0_lcd_stop_dma(sc->iot, sc->ioh);
                    831:
                    832:                pxa2x0_clkman_config(CKEN_LCD, 0);
                    833:        }
                    834: }
                    835:
                    836: void
                    837: pxa2x0_lcd_resume(struct pxa2x0_lcd_softc *sc)
                    838: {
                    839:
                    840:        if (sc->active != NULL) {
                    841:                pxa2x0_lcd_initialize(sc->iot, sc->ioh, sc->geometry,
                    842:                    pxa2x0_clkman_config);
                    843:                pxa2x0_lcd_start_dma(sc->iot, sc->ioh, sc->active);
                    844:        }
                    845: }
                    846:
                    847: void
                    848: pxa2x0_lcd_power(int why, void *v)
                    849: {
                    850:        struct pxa2x0_lcd_softc *sc = v;
                    851:
                    852:        switch (why) {
                    853:        case PWR_SUSPEND:
                    854:        case PWR_STANDBY:
                    855:                pxa2x0_lcd_suspend(sc);
                    856:                break;
                    857:
                    858:        case PWR_RESUME:
                    859:                pxa2x0_lcd_resume(sc);
                    860:                break;
                    861:        }
                    862: }

CVSweb