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