blob: 3769f7b7048e41d9edb587ef87783d9a6165177d [file] [log] [blame]
Francesco Salvatore6c17a232018-12-11 17:30:22 +01001/*
2 * Copyright 2018 Fairphone B.V.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <target/rgb_led.h>
16
17rgb_led_return_code led_init()
18{
19 /* Enable RGB module, Select Vph_pwr as power source */
20 pm8x41_reg_write( SLAVE_ID + RGB_DRIVER_BASE_ADDR + RGB_DRIVER_LED_SRC_SEL, 0x01);
21
22 return RGB_LED_SUCCESS;
23}
24
25rgb_led_return_code led_enable(uint8_t led, rgb_led_brightness brightness)
26{
27 uint32_t led_lpg_value = 0;
28 switch(led)
29 {
30 case RGB_LED_VALUE_RED:
31 led_lpg_value = LPG_DRIVER_LED_RED;
32 break;
33 case RGB_LED_VALUE_GREEN:
34 led_lpg_value = LPG_DRIVER_LED_GREEN;
35 break;
36 case RGB_LED_VALUE_BLUE:
37 led_lpg_value = LPG_DRIVER_LED_BLUE;
38 break;
39 default:
40 return RGB_LED_INVALID_PARAMETER;
41 }
42 /* Building LED specific base address */
43 const uint32_t led_lpg_base_address = SLAVE_ID + LPG_DRIVER_BASE_ADDR + led_lpg_value;
44 /* Enable selected LED, preserving the previous value */
45 uint8_t val = pm8x41_reg_read( SLAVE_ID + RGB_DRIVER_BASE_ADDR + RGB_DRIVER_EN_CTL );
46 val |= led;
47 pm8x41_reg_write( SLAVE_ID + RGB_DRIVER_BASE_ADDR + RGB_DRIVER_EN_CTL, val);
48 /*
49 * Enable PWM at requested duty cycle
50 * For a always-on behaviour no pattern is needed.
51 * PWM is set to 7-bit mode in order to be able to use both PWM channels (4 mA + 8 mA).
52 * PWM frequency is set to 390 Hz (Pre-divide=5, Exponent=7).
53 * The type config is not used here but is mandatory to set the register.
54 * PWM value acts here as brightness parameter. 0xFF is the full-scale value.
55 * PWM value MSB is useless here.
56 * PWM is enabled by writing 0xE4 in the enable register.
57 */
58 pm8x41_reg_write( led_lpg_base_address + LPG_PATTERN_CONFIG, 0x00);
59 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_SIZE_CLK, 0x13);
60 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_FREQ_PREDIV, 0x47);
61 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_TYPE_CONFIG, 0x00);
62 pm8x41_reg_write( led_lpg_base_address + LPG_VALUE_LSB, brightness);
63 pm8x41_reg_write( led_lpg_base_address + LPG_VALUE_MSB, 0x00);
64 pm8x41_reg_write( led_lpg_base_address + LPG_ENABLE_CONTROL, 0xE4);
65
66 return RGB_LED_SUCCESS;
67}
68
69rgb_led_return_code led_blink_enable(uint8_t led, uint8_t pwm_freq, uint8_t duty_cycle)
70{
71 if(duty_cycle > 0x3F)
72 {
73 return RGB_LED_INVALID_PARAMETER;
74 }
75
76 uint32_t led_lpg_value = 0;
77 switch(led)
78 {
79 case RGB_LED_VALUE_RED:
80 led_lpg_value = LPG_DRIVER_LED_RED;
81 break;
82 case RGB_LED_VALUE_GREEN:
83 led_lpg_value = LPG_DRIVER_LED_GREEN;
84 break;
85 case RGB_LED_VALUE_BLUE:
86 led_lpg_value = LPG_DRIVER_LED_BLUE;
87 break;
88 default:
89 return RGB_LED_INVALID_PARAMETER;
90 }
91 /* Building LED specific base address */
92 const uint32_t led_lpg_base_address = SLAVE_ID + LPG_DRIVER_BASE_ADDR + led_lpg_value;
93 /* Enable selected LED, preserving the previous value */
94 uint8_t val = pm8x41_reg_read( SLAVE_ID + RGB_DRIVER_BASE_ADDR + RGB_DRIVER_EN_CTL );
95 val |= led;
96 pm8x41_reg_write( SLAVE_ID + RGB_DRIVER_BASE_ADDR + RGB_DRIVER_EN_CTL, val);
97 /*
98 * Enable PWM at requested duty cycle
99 * For a simple blinking behaviour no pattern is needed.
100 * PWM is set to 6-bit mode. This results in a clock of 1 KHz.
101 * PWM frequency is set as desidered. Refer to docs to properly set this parameter.
102 * The type config is not used here but is mandatory to set the register.
103 * PWM value acts here as duty cycle value. 0x3F is the full-scale value.
104 * PWM value MSB is useless here.
105 * PWM is enabled by writing 0xE4 in the enable register.
106 */
107 pm8x41_reg_write( led_lpg_base_address + LPG_PATTERN_CONFIG, 0x00);
108 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_SIZE_CLK, 0x01);
109 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_FREQ_PREDIV, pwm_freq);
110 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_TYPE_CONFIG, 0x00);
111 pm8x41_reg_write( led_lpg_base_address + LPG_VALUE_LSB, duty_cycle);
112 pm8x41_reg_write( led_lpg_base_address + LPG_VALUE_MSB, 0x00);
113 pm8x41_reg_write( led_lpg_base_address + LPG_ENABLE_CONTROL, 0xE4);
114
115 return RGB_LED_SUCCESS;
116}
117
118rgb_led_return_code led_disable(uint8_t led)
119{
120 uint32_t led_lpg_value = 0;
121 switch(led)
122 {
123 case RGB_LED_VALUE_RED:
124 led_lpg_value = LPG_DRIVER_LED_RED;
125 break;
126 case RGB_LED_VALUE_GREEN:
127 led_lpg_value = LPG_DRIVER_LED_GREEN;
128 break;
129 case RGB_LED_VALUE_BLUE:
130 led_lpg_value = LPG_DRIVER_LED_BLUE;
131 break;
132 default:
133 return RGB_LED_INVALID_PARAMETER;
134 }
135 /* Building LED specific base address */
136 const uint32_t led_lpg_base_address = SLAVE_ID + LPG_DRIVER_BASE_ADDR + led_lpg_value;
137 /* Disable selected LED, preserving the previous value */
138 uint8_t val = pm8x41_reg_read( SLAVE_ID + RGB_DRIVER_BASE_ADDR + RGB_DRIVER_EN_CTL );
139 val &= ~(led);
140 pm8x41_reg_write( SLAVE_ID + RGB_DRIVER_BASE_ADDR + RGB_DRIVER_EN_CTL, val);
141
142 /* Clear LPG registers */
143 pm8x41_reg_write( led_lpg_base_address + LPG_PATTERN_CONFIG, 0x00);
144 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_SIZE_CLK, 0x00);
145 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_FREQ_PREDIV, 0x00);
146 pm8x41_reg_write( led_lpg_base_address + LPG_PWM_TYPE_CONFIG, 0x00);
147 pm8x41_reg_write( led_lpg_base_address + LPG_VALUE_LSB, 0x00);
148 pm8x41_reg_write( led_lpg_base_address + LPG_VALUE_MSB, 0x00);
149 pm8x41_reg_write( led_lpg_base_address + LPG_ENABLE_CONTROL, 0x00);
150
151 return RGB_LED_SUCCESS;
152}
153
154rgb_led_return_code led_deinit()
155{
156 rgb_led_return_code rc;
157 rc = led_disable(RGB_LED_VALUE_RED);
158 if(rc != RGB_LED_SUCCESS)
159 {
160 return rc;
161 }
162 rc = led_disable(RGB_LED_VALUE_GREEN);
163 if(rc != RGB_LED_SUCCESS)
164 {
165 return rc;
166 }
167 rc = led_disable(RGB_LED_VALUE_BLUE);
168 if(rc != RGB_LED_SUCCESS)
169 {
170 return rc;
171 }
172
173 /* Power off the RGB module by setting no power source */
174 pm8x41_reg_write( SLAVE_ID + RGB_DRIVER_BASE_ADDR + RGB_DRIVER_LED_SRC_SEL, 0x00);
175
176 return RGB_LED_SUCCESS;
177}