[BACK]Return to zaurus_lcd.c CVS log [TXT][DIR] Up to [local] / sys / arch / zaurus / zaurus

Annotation of sys/arch/zaurus/zaurus/zaurus_lcd.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: zaurus_lcd.c,v 1.21 2006/11/29 12:13:54 miod Exp $    */
                      2: /* $NetBSD: lubbock_lcd.c,v 1.1 2003/08/09 19:38:53 bsh Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 2002, 2003  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. The name of Genetec Corporation may not be used to endorse or
                     17:  *    promote products derived from this software without specific prior
                     18:  *    written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: /*
                     34:  * LCD driver for Sharp Zaurus (based on the Intel Lubbock driver).
                     35:  *
                     36:  * Controlling LCD is almost completely done through PXA2X0's
                     37:  * integrated LCD controller.  Codes for it is arm/xscale/pxa2x0_lcd.c.
                     38:  *
                     39:  * Codes in this file provide platform specific things including:
                     40:  *   LCD on/off switch and backlight brightness
                     41:  *   LCD panel geometry
                     42:  */
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/conf.h>
                     47: #include <sys/uio.h>
                     48: #include <sys/malloc.h>
                     49:
                     50: #include <dev/cons.h>
                     51: #include <dev/wscons/wsconsio.h>
                     52: #include <dev/wscons/wsdisplayvar.h>
                     53: #include <dev/wscons/wscons_callbacks.h>
                     54:
                     55: #include <machine/bus.h>
                     56: #include <arm/xscale/pxa2x0var.h>
                     57: #include <arm/xscale/pxa2x0reg.h>
                     58: #include <arm/xscale/pxa2x0_lcd.h>
                     59:
                     60: #include <zaurus/dev/zaurus_scoopvar.h>
                     61: #include <zaurus/dev/zaurus_sspvar.h>
                     62:
                     63: #include <dev/rasops/rasops.h>
                     64:
                     65: void   lcd_attach(struct device *, struct device *, void *);
                     66: int    lcd_match(struct device *, void *, void *);
                     67: int    lcd_cnattach(void (*)(u_int, int));
                     68:
                     69: /*
                     70:  * wsdisplay glue
                     71:  */
                     72: struct pxa2x0_wsscreen_descr
                     73: lcd_bpp16_screen = {
                     74:        {
                     75:                "std"
                     76:        },
                     77:        16,                             /* bits per pixel */
                     78:        RI_ROTATE_CW                    /* quarter clockwise rotation */
                     79: };
                     80:
                     81: static const struct wsscreen_descr *lcd_scr_descr[] = {
                     82:        &lcd_bpp16_screen.c
                     83: };
                     84:
                     85: const struct wsscreen_list lcd_screen_list = {
                     86:        sizeof lcd_scr_descr / sizeof lcd_scr_descr[0], lcd_scr_descr
                     87: };
                     88:
                     89: int    lcd_ioctl(void *, u_long, caddr_t, int, struct proc *);
                     90: void   lcd_burner(void *, u_int, u_int);
                     91: int    lcd_show_screen(void *, void *, int,
                     92:            void (*)(void *, int, int), void *);
                     93:
                     94: int    lcd_param(struct pxa2x0_lcd_softc *, u_long,
                     95:     struct wsdisplay_param *);
                     96:
                     97: const struct wsdisplay_accessops lcd_accessops = {
                     98:        lcd_ioctl,
                     99:        pxa2x0_lcd_mmap,
                    100:        pxa2x0_lcd_alloc_screen,
                    101:        pxa2x0_lcd_free_screen,
                    102:        lcd_show_screen,
                    103:        NULL,   /* load_font */
                    104:        NULL,   /* scrollback */
                    105:        NULL,   /* getchar */
                    106:        lcd_burner
                    107: };
                    108:
                    109: struct cfattach lcd_pxaip_ca = {
                    110:        sizeof (struct pxa2x0_lcd_softc), lcd_match, lcd_attach
                    111: };
                    112:
                    113: struct cfdriver lcd_cd = {
                    114:        NULL, "lcd", DV_DULL
                    115: };
                    116:
                    117: #define CURRENT_DISPLAY &sharp_zaurus_C3000
                    118:
                    119: const struct lcd_panel_geometry sharp_zaurus_C3000 =
                    120: {
                    121:        480,                    /* Width */
                    122:        640,                    /* Height */
                    123:        0,                      /* No extra lines */
                    124:
                    125:        LCDPANEL_ACTIVE | LCDPANEL_VSP | LCDPANEL_HSP,
                    126:        1,                      /* clock divider */
                    127:        0,                      /* AC bias pin freq */
                    128:
                    129:        0x28,                   /* horizontal sync pulse width */
                    130:        0x2e,                   /* BLW */
                    131:        0x7d,                   /* ELW */
                    132:
                    133:        2,                      /* vertical sync pulse width */
                    134:        1,                      /* BFW */
                    135:        0,                      /* EFW */
                    136: };
                    137:
                    138: struct sharp_lcd_backlight {
                    139:        int     duty;           /* LZ9JG18 DAC value */
                    140:        int     cont;           /* BACKLIGHT_CONT signal */
                    141:        int     on;             /* BACKLIGHT_ON signal */
                    142: };
                    143:
                    144: #define CURRENT_BACKLIGHT sharp_zaurus_C3000_bl
                    145:
                    146: const struct sharp_lcd_backlight sharp_zaurus_C3000_bl[] = {
                    147:        { 0x00, 0, 0 },         /* 0:     Off */
                    148:        { 0x00, 0, 1 },         /* 1:      0% */
                    149:        { 0x01, 0, 1 },         /* 2:     20% */
                    150:        { 0x07, 0, 1 },         /* 3:     40% */
                    151:        { 0x01, 1, 1 },         /* 4:     60% */
                    152:        { 0x07, 1, 1 },         /* 5:     80% */
                    153:        { 0x11, 1, 1 },         /* 6:    100% */
                    154:        { -1, -1, -1 }          /* 7: Invalid */
                    155: };
                    156:
                    157: int    lcd_max_brightness(void);
                    158: int    lcd_get_brightness(void);
                    159: void   lcd_set_brightness(int);
                    160: void   lcd_set_brightness_internal(int);
                    161: int    lcd_get_backlight(void);
                    162: void   lcd_set_backlight(int);
                    163: void   lcd_blank(int);
                    164: void   lcd_power(int, void *);
                    165:
                    166: int
                    167: lcd_match(struct device *parent, void *cf, void *aux)
                    168: {
                    169:        return 1;
                    170: }
                    171:
                    172: void
                    173: lcd_attach(struct device *parent, struct device *self, void *aux)
                    174: {
                    175:        struct pxa2x0_lcd_softc *sc = (struct pxa2x0_lcd_softc *)self;
                    176:        struct wsemuldisplaydev_attach_args aa;
                    177:        extern int glass_console;
                    178:
                    179:        printf("\n");
                    180:
                    181:        pxa2x0_lcd_attach_sub(sc, aux, &lcd_bpp16_screen, CURRENT_DISPLAY,
                    182:            glass_console);
                    183:
                    184:        aa.console = glass_console;
                    185:        aa.scrdata = &lcd_screen_list;
                    186:        aa.accessops = &lcd_accessops;
                    187:        aa.accesscookie = sc;
                    188:        aa.defaultscreens = 0;
                    189:
                    190:        (void)config_found(self, &aa, wsemuldisplaydevprint);
                    191:
                    192:        /* Start with approximately 40% of full brightness. */
                    193:        lcd_set_brightness(3);
                    194:
                    195:        (void)powerhook_establish(lcd_power, sc);
                    196: }
                    197:
                    198: int
                    199: lcd_cnattach(void (*clkman)(u_int, int))
                    200: {
                    201:        return
                    202:            (pxa2x0_lcd_cnattach(&lcd_bpp16_screen, CURRENT_DISPLAY, clkman));
                    203: }
                    204:
                    205: /*
                    206:  * wsdisplay accessops overrides
                    207:  */
                    208:
                    209: int
                    210: lcd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
                    211: {
                    212:        struct pxa2x0_lcd_softc *sc = v;
                    213:        int res = EINVAL;
                    214:
                    215:        switch (cmd) {
                    216:        case WSDISPLAYIO_GETPARAM:
                    217:        case WSDISPLAYIO_SETPARAM:
                    218:                res = lcd_param(sc, cmd, (struct wsdisplay_param *)data);
                    219:                break;
                    220:        }
                    221:
                    222:        if (res == EINVAL)
                    223:                res = pxa2x0_lcd_ioctl(v, cmd, data, flag, p);
                    224:
                    225:        return res;
                    226: }
                    227:
                    228: void
                    229: lcd_burner(void *v, u_int on, u_int flags)
                    230: {
                    231:
                    232:        lcd_set_brightness(on ? lcd_get_brightness() : 0);
                    233: }
                    234:
                    235: int
                    236: lcd_show_screen(void *v, void *cookie, int waitok,
                    237:     void (*cb)(void *, int, int), void *cbarg)
                    238: {
                    239:        int rc;
                    240:
                    241:        if ((rc = pxa2x0_lcd_show_screen(v, cookie, waitok, cb, cbarg)) != 0)
                    242:                return (rc);
                    243:
                    244:        /* Turn on LCD */
                    245:        lcd_burner(v, 1, 0);
                    246:
                    247:        return (0);
                    248: }
                    249:
                    250: /*
                    251:  * wsdisplay I/O controls
                    252:  */
                    253:
                    254: int
                    255: lcd_param(struct pxa2x0_lcd_softc *sc, u_long cmd,
                    256:     struct wsdisplay_param *dp)
                    257: {
                    258:        int res = EINVAL;
                    259:
                    260:        switch (dp->param) {
                    261:        case WSDISPLAYIO_PARAM_BACKLIGHT:
                    262:                if (cmd == WSDISPLAYIO_GETPARAM) {
                    263:                        dp->min = 0;
                    264:                        dp->max = 1;
                    265:                        dp->curval = lcd_get_backlight();
                    266:                        res = 0;
                    267:                } else if (cmd == WSDISPLAYIO_SETPARAM) {
                    268:                        lcd_set_backlight(dp->curval);
                    269:                        res = 0;
                    270:                }
                    271:                break;
                    272:
                    273:        case WSDISPLAYIO_PARAM_CONTRAST:
                    274:                /* unsupported */
                    275:                res = ENOTTY;
                    276:                break;
                    277:
                    278:        case WSDISPLAYIO_PARAM_BRIGHTNESS:
                    279:                if (cmd == WSDISPLAYIO_GETPARAM) {
                    280:                        dp->min = 1;
                    281:                        dp->max = lcd_max_brightness();
                    282:                        dp->curval = lcd_get_brightness();
                    283:                        res = 0;
                    284:                } else if (cmd == WSDISPLAYIO_SETPARAM) {
                    285:                        lcd_set_brightness(dp->curval);
                    286:                        res = 0;
                    287:                }
                    288:                break;
                    289:        }
                    290:
                    291:        return res;
                    292: }
                    293:
                    294: /*
                    295:  * LCD backlight
                    296:  */
                    297:
                    298: static int lcdbrightnesscurval = 1;
                    299: static int lcdislit = 1;
                    300: static int lcdisblank = 0;
                    301:
                    302: int
                    303: lcd_max_brightness(void)
                    304: {
                    305:        int i;
                    306:
                    307:        for (i = 0; CURRENT_BACKLIGHT[i].duty != -1; i++)
                    308:                ;
                    309:        return i - 1;
                    310: }
                    311:
                    312: int
                    313: lcd_get_brightness(void)
                    314: {
                    315:
                    316:        return lcdbrightnesscurval;
                    317: }
                    318:
                    319: void
                    320: lcd_set_brightness(int newval)
                    321: {
                    322:        int max;
                    323:
                    324:        max = lcd_max_brightness();
                    325:        if (newval < 0)
                    326:                newval = 0;
                    327:        else if (newval > max)
                    328:                newval = max;
                    329:
                    330:        if (lcd_get_backlight() && !lcdisblank)
                    331:                lcd_set_brightness_internal(newval);
                    332:
                    333:        if (newval > 0)
                    334:                lcdbrightnesscurval = newval;
                    335: }
                    336:
                    337: void
                    338: lcd_set_brightness_internal(int newval)
                    339: {
                    340:        static int curval = 1;
                    341:        int i;
                    342:
                    343:        /*
                    344:         * It appears that the C3000 backlight can draw too much power if we
                    345:         * switch it from a low to a high brightness.  Increasing brightness
                    346:         * in steps avoids this issue.
                    347:         */
                    348:        if (newval > curval) {
                    349:                for (i = curval + 1; i <= newval; i++) {
                    350:                        (void)zssp_ic_send(ZSSP_IC_LZ9JG18,
                    351:                            CURRENT_BACKLIGHT[i].duty);
                    352:                        scoop_set_backlight(CURRENT_BACKLIGHT[i].on,
                    353:                            CURRENT_BACKLIGHT[i].cont);
                    354:                        delay(5000);
                    355:                }
                    356:        } else {
                    357:                (void)zssp_ic_send(ZSSP_IC_LZ9JG18,
                    358:                    CURRENT_BACKLIGHT[newval].duty);
                    359:                scoop_set_backlight(CURRENT_BACKLIGHT[newval].on,
                    360:                    CURRENT_BACKLIGHT[newval].cont);
                    361:        }
                    362:
                    363:        curval = newval;
                    364: }
                    365:
                    366: int
                    367: lcd_get_backlight(void)
                    368: {
                    369:
                    370:        return lcdislit;
                    371: }
                    372:
                    373: void
                    374: lcd_set_backlight(int on)
                    375: {
                    376:
                    377:        if (!on) {
                    378:                lcd_set_brightness(0);
                    379:                lcdislit = 0;
                    380:        } else {
                    381:                lcdislit = 1;
                    382:                lcd_set_brightness(lcd_get_brightness());
                    383:        }
                    384: }
                    385:
                    386: void
                    387: lcd_blank(int blank)
                    388: {
                    389:
                    390:        if (blank) {
                    391:                lcd_set_brightness(0);
                    392:                lcdisblank = 1;
                    393:        } else {
                    394:                lcdisblank = 0;
                    395:                lcd_set_brightness(lcd_get_brightness());
                    396:        }
                    397: }
                    398:
                    399: void
                    400: lcd_power(int why, void *v)
                    401: {
                    402:
                    403:        switch (why) {
                    404:        case PWR_SUSPEND:
                    405:        case PWR_STANDBY:
                    406:                lcd_set_brightness(0);
                    407:                pxa2x0_lcd_power(why, v);
                    408:                break;
                    409:
                    410:        case PWR_RESUME:
                    411:                pxa2x0_lcd_power(why, v);
                    412:                lcd_set_brightness(lcd_get_brightness());
                    413:                break;
                    414:        }
                    415: }

CVSweb