summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/s3c2440/mini2440/backlight-mini2440.c
blob: a9e003b80a4a7a6d87de41fb17f43316dde94287 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2009 by Bob Cousins
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#include "config.h"
#include "cpu.h"
#include "system.h"
#include "backlight-target.h"
#include "backlight.h"
#include "lcd.h"
#include "power.h"


/* Dummy value at index 0, 1-12 used. */
static const unsigned char log_brightness[13] =
    {0,0,1,2,3,5,7,10,15,22,31,44,63};


static enum backlight_states
{
    BACKLIGHT_CONTROL_IDLE,
    BACKLIGHT_CONTROL_OFF,
    BACKLIGHT_CONTROL_ON,
    BACKLIGHT_CONTROL_SET,
    BACKLIGHT_CONTROL_FADE
} backlight_control;

static unsigned char _backlight_brightness;
static unsigned char backlight_target;


/* Assumes that the backlight has been initialized */
void _backlight_set_brightness(int brightness)
{
    /* stop the interrupt from messing us up */
    backlight_control = BACKLIGHT_CONTROL_IDLE;
    _backlight_brightness = log_brightness[brightness];
    backlight_control = BACKLIGHT_CONTROL_SET;
}

static void _backlight_set_state (unsigned int level)
{
    if (level == 0)
       GPGDAT &= ~GPIO_LCD_PWR;
    else
       GPGDAT |= GPIO_LCD_PWR;
}

/* led_control_service runs in interrupt context - be brief!
 * This service is called once per interrupt timer tick - 100 times a second.
 *
 * There should be at most only one i2c operation per call - if more are need
 *  the calls should be spread across calls.
 *
 * Putting all led servicing in one thread means that we wont step on any
 * i2c operations - they are all serialized here in the ISR tick. It also
 * insures that we get called at equal timing for good visual effect.
 */
#ifndef BOOTLOADER
static void led_control_service(void)
{
    switch (backlight_control)
    {
        case BACKLIGHT_CONTROL_IDLE:
            backlight_control = BACKLIGHT_CONTROL_IDLE;
            break;
        case BACKLIGHT_CONTROL_OFF:
            _backlight_set_brightness(0);
            backlight_control = BACKLIGHT_CONTROL_IDLE;
            break;
        case BACKLIGHT_CONTROL_ON:
            _backlight_set_brightness(255);
            backlight_control = BACKLIGHT_CONTROL_IDLE;
            break;
        case BACKLIGHT_CONTROL_SET:
            _backlight_set_brightness(255);
            backlight_control = BACKLIGHT_CONTROL_IDLE;
            break;
        case BACKLIGHT_CONTROL_FADE:
            _backlight_set_brightness(0);
            backlight_control = BACKLIGHT_CONTROL_IDLE;
            break;
        default:
            backlight_control = BACKLIGHT_CONTROL_IDLE;
            break;
    }
}
#endif /* BOOTLOADER */

static void __backlight_dim(bool dim_now)
{
    /* dont let the interrupt tick happen */
    backlight_control = BACKLIGHT_CONTROL_IDLE;
    backlight_target = dim_now ? 0 : _backlight_brightness;
    if(backlight_target==0 && _backlight_brightness==0)
    {
        if(dim_now == false)
            backlight_control = BACKLIGHT_CONTROL_ON;
        else
            backlight_control = BACKLIGHT_CONTROL_OFF;
    }
    else
        backlight_control = BACKLIGHT_CONTROL_FADE;
}

void _backlight_on(void)
{
#ifdef HAVE_LCD_ENABLE
    lcd_enable(true); /* power on lcd + visible display */
#endif
    __backlight_dim(false);
}

void _backlight_off(void)
{
    __backlight_dim(true);
}


bool _backlight_init(void)
{
    unsigned char brightness = log_brightness[DEFAULT_BRIGHTNESS_SETTING];
    _backlight_brightness = brightness;

    backlight_control = BACKLIGHT_CONTROL_ON;

    _backlight_set_state (1);
    S3C2440_GPIO_CONFIG (GPGCON, 4, GPIO_OUTPUT);    
    
#ifndef BOOTLOADER
    /* put the led control on the tick list */
    tick_add_task(led_control_service);
#endif
    return true;
}