summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/imx233/samsung-ypz5/backlight-ypz5.c
blob: b02c3a1d16c1b0d55a5e96216e25c4ef33062b59 (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
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 *
 * Copyright (C) 2013 by Lorenzo Miori
 *
 * 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 "system.h"
#include "lcd.h"
#include "backlight.h"
#include "backlight-target.h"
#include "pinctrl-imx233.h"

/**
 * AAT3151 Backlight Controller
 */

/* Timings */
#define TIME_OFF                500
#define TIME_LOW                50
#define TIME_HI                 50
#define TIME_LAT                500

/* Number of raising edges to select the particular register */
#define D1_D4_CURRENT_E           17
#define D1_D3_CURRENT_E           18
#define D4_CURRENT_E              19
#define MAX_CURRENT_E             20
#define LOW_CURRENT_E             21

/* The actual register address / number */
#define D1_D4_CURRENT           1
#define D1_D3_CURRENT           2
#define D4_CURRENT              3
#define MAX_CURRENT             4
#define LOW_CURRENT             5

/* Valid values for LOW_CURRENT register */
#define MAX_CURRENT_20                  1
#define MAX_CURRENT_30                  2
#define MAX_CURRENT_15                  3
#define MAX_CURRENT_LOW_CURRENT         4

static int current_level = -1;

static void create_raising_edges(int num)
{
    while (num--)
    {
        /* Setting a register takes a sufficient small amount of time,
         * in the order of 50 ns. Thus the necessary 2 delays TIME_LOW/TIME_HI
         * are not strictly necessary */
        imx233_pinctrl_set_gpio(3, 13, false);
        imx233_pinctrl_set_gpio(3, 13, true);
    }
}

static void aat3151_write(int addr, int data)
{
    create_raising_edges(16 + addr);
    udelay(TIME_LAT);
    create_raising_edges(data);
    udelay(TIME_LAT);
}

void backlight_hw_brightness(int level)
{
    /* Don't try to reset backlight if not necessary
     *  Moreover this helps to avoid flickering when
     *  being in some screens like USB mode and
     *  pressing some keys / touchpad...
     */
    if (current_level == level) return;

    /* Check for limits and adjust in case */
    level = MIN(MAX_BRIGHTNESS_SETTING, MAX(0, level));

    if (level == 0)
    {
        /* Set pin low for a sufficient time, puts the device into low-power consumption state
         * In other words backlight goes off
         */
        imx233_pinctrl_set_gpio(3, 13, false);
        udelay(TIME_OFF);
    }
    else
    {
        if (level > 3) {
            /* This enables 16 levels of backlight */
            aat3151_write(MAX_CURRENT, MAX_CURRENT_15);
            /* Set the value according Table 1 in datasheet
             * For MAX_CURRENT_15, the scale is from 0 mA to 15 mA in 16 steps
             */
            aat3151_write(D1_D3_CURRENT, 19 - level);
        }
        else {
            /* This enables other 4 levels of backlight */
            aat3151_write(MAX_CURRENT, MAX_CURRENT_LOW_CURRENT);
            /* Set the value according Table 1 in datasheet
             * For LOW_CURRENT, there is no "real" scale. We have scattered values.
             * We are interested in the last 3 -> 0.5 mA; 1 mA; 2 mA
             */
            aat3151_write(LOW_CURRENT, 13 + level);
        }
    }
    current_level = level;
}

bool backlight_hw_init(void)
{
    imx233_pinctrl_acquire(3, 13, "backlight");
    imx233_pinctrl_set_function(3, 13, PINCTRL_FUNCTION_GPIO);
    imx233_pinctrl_set_drive(3, 13, PINCTRL_DRIVE_4mA);
    imx233_pinctrl_enable_gpio(3, 13, true);
    imx233_pinctrl_set_gpio(3, 13, false);
    return true;
}

void backlight_hw_on(void)
{
#ifdef HAVE_LCD_ENABLE
    lcd_enable(true); /* power on lcd + visible display */
#endif
    /* restore the previous backlight level */
    backlight_hw_brightness(backlight_brightness);
}

void backlight_hw_off(void)
{
    /* there is no real on/off but we can set to 0 brightness */
    backlight_hw_brightness(0);
#ifdef HAVE_LCD_ENABLE
    lcd_enable(false); /* power off visible display */
#endif
}