aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilippe Rétornaz <philippe.retornaz@epfl.ch>2010-05-19 03:24:31 -0400
committerRichard Purdie <rpurdie@linux.intel.com>2010-05-26 08:07:56 -0400
commit7fdcef8a414eaeb367b3696005b25283d62d195d (patch)
treea33a3229159a044f6db675ad56bf463c20c924a1
parent1e653accf7d2b02e75af550963b261b3243ac20e (diff)
leds: Add mc13783 LED support
This add basic led support for Freescale MC13783 PMIC. Signed-off-by: Philippe Rétornaz <philippe.retornaz@epfl.ch> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-mc13783.c403
-rw-r--r--drivers/mfd/mc13783-core.c4
-rw-r--r--include/linux/mfd/mc13783.h66
5 files changed, 481 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index ecb6932c3636..f98d17a7108b 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -295,6 +295,13 @@ config LEDS_DELL_NETBOOKS
295 This adds support for the Latitude 2100 and similar 295 This adds support for the Latitude 2100 and similar
296 notebooks that have an external LED. 296 notebooks that have an external LED.
297 297
298config LEDS_MC13783
299 tristate "LED Support for MC13783 PMIC"
300 depends on MFD_MC13783
301 help
302 This option enable support for on-chip LED drivers found
303 on Freescale Semiconductor MC13783 PMIC.
304
298config LEDS_TRIGGERS 305config LEDS_TRIGGERS
299 bool "LED Trigger support" 306 bool "LED Trigger support"
300 help 307 help
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 77119f2e26b3..2493de499374 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o
36obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o 36obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
37obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o 37obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o
38obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o 38obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o
39obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
39 40
40# LED SPI Drivers 41# LED SPI Drivers
41obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 42obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
new file mode 100644
index 000000000000..f05bb08d0f09
--- /dev/null
+++ b/drivers/leds/leds-mc13783.c
@@ -0,0 +1,403 @@
1/*
2 * LEDs driver for Freescale MC13783
3 *
4 * Copyright (C) 2010 Philippe Rétornaz
5 *
6 * Based on leds-da903x:
7 * Copyright (C) 2008 Compulab, Ltd.
8 * Mike Rapoport <mike@compulab.co.il>
9 *
10 * Copyright (C) 2006-2008 Marvell International Ltd.
11 * Eric Miao <eric.miao@marvell.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/leds.h>
23#include <linux/workqueue.h>
24#include <linux/mfd/mc13783.h>
25#include <linux/slab.h>
26
27struct mc13783_led {
28 struct led_classdev cdev;
29 struct work_struct work;
30 struct mc13783 *master;
31 enum led_brightness new_brightness;
32 int id;
33};
34
35#define MC13783_REG_LED_CONTROL_0 51
36#define MC13783_LED_C0_ENABLE_BIT (1 << 0)
37#define MC13783_LED_C0_TRIODE_MD_BIT (1 << 7)
38#define MC13783_LED_C0_TRIODE_AD_BIT (1 << 8)
39#define MC13783_LED_C0_TRIODE_KP_BIT (1 << 9)
40#define MC13783_LED_C0_BOOST_BIT (1 << 10)
41#define MC13783_LED_C0_ABMODE_MASK 0x7
42#define MC13783_LED_C0_ABMODE 11
43#define MC13783_LED_C0_ABREF_MASK 0x3
44#define MC13783_LED_C0_ABREF 14
45
46#define MC13783_REG_LED_CONTROL_1 52
47#define MC13783_LED_C1_TC1HALF_BIT (1 << 18)
48
49#define MC13783_REG_LED_CONTROL_2 53
50#define MC13783_LED_C2_BL_P_MASK 0xf
51#define MC13783_LED_C2_MD_P 9
52#define MC13783_LED_C2_AD_P 13
53#define MC13783_LED_C2_KP_P 17
54#define MC13783_LED_C2_BL_C_MASK 0x7
55#define MC13783_LED_C2_MD_C 0
56#define MC13783_LED_C2_AD_C 3
57#define MC13783_LED_C2_KP_C 6
58
59#define MC13783_REG_LED_CONTROL_3 54
60#define MC13783_LED_C3_TC_P 6
61#define MC13783_LED_C3_TC_P_MASK 0x1f
62
63#define MC13783_REG_LED_CONTROL_4 55
64#define MC13783_REG_LED_CONTROL_5 56
65
66#define MC13783_LED_Cx_PERIOD 21
67#define MC13783_LED_Cx_PERIOD_MASK 0x3
68#define MC13783_LED_Cx_SLEWLIM_BIT (1 << 23)
69#define MC13783_LED_Cx_TRIODE_TC_BIT (1 << 23)
70#define MC13783_LED_Cx_TC_C_MASK 0x3
71
72static void mc13783_led_work(struct work_struct *work)
73{
74 struct mc13783_led *led = container_of(work, struct mc13783_led, work);
75 int reg = 0;
76 int mask = 0;
77 int value = 0;
78 int bank, off, shift;
79
80 switch (led->id) {
81 case MC13783_LED_MD:
82 reg = MC13783_REG_LED_CONTROL_2;
83 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_MD_P;
84 value = (led->new_brightness >> 4) << MC13783_LED_C2_MD_P;
85 break;
86 case MC13783_LED_AD:
87 reg = MC13783_REG_LED_CONTROL_2;
88 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_AD_P;
89 value = (led->new_brightness >> 4) << MC13783_LED_C2_AD_P;
90 break;
91 case MC13783_LED_KP:
92 reg = MC13783_REG_LED_CONTROL_2;
93 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_KP_P;
94 value = (led->new_brightness >> 4) << MC13783_LED_C2_KP_P;
95 break;
96 case MC13783_LED_R1:
97 case MC13783_LED_G1:
98 case MC13783_LED_B1:
99 case MC13783_LED_R2:
100 case MC13783_LED_G2:
101 case MC13783_LED_B2:
102 case MC13783_LED_R3:
103 case MC13783_LED_G3:
104 case MC13783_LED_B3:
105 off = led->id - MC13783_LED_R1;
106 bank = off/3;
107 reg = MC13783_REG_LED_CONTROL_3 + off/3;
108 shift = (off - bank * 3) * 5 + MC13783_LED_C3_TC_P;
109 value = (led->new_brightness >> 3) << shift;
110 mask = MC13783_LED_C3_TC_P_MASK << shift;
111 break;
112 }
113
114 mc13783_lock(led->master);
115
116 mc13783_reg_rmw(led->master, reg, mask, value);
117
118 mc13783_unlock(led->master);
119}
120
121static void mc13783_led_set(struct led_classdev *led_cdev,
122 enum led_brightness value)
123{
124 struct mc13783_led *led;
125
126 led = container_of(led_cdev, struct mc13783_led, cdev);
127 led->new_brightness = value;
128 schedule_work(&led->work);
129}
130
131static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
132{
133 int shift = 0;
134 int mask = 0;
135 int value = 0;
136 int reg = 0;
137 int ret, bank;
138
139 switch (led->id) {
140 case MC13783_LED_MD:
141 shift = MC13783_LED_C2_MD_C;
142 mask = MC13783_LED_C2_BL_C_MASK;
143 value = max_current & MC13783_LED_C2_BL_C_MASK;
144 reg = MC13783_REG_LED_CONTROL_2;
145 break;
146 case MC13783_LED_AD:
147 shift = MC13783_LED_C2_AD_C;
148 mask = MC13783_LED_C2_BL_C_MASK;
149 value = max_current & MC13783_LED_C2_BL_C_MASK;
150 reg = MC13783_REG_LED_CONTROL_2;
151 break;
152 case MC13783_LED_KP:
153 shift = MC13783_LED_C2_KP_C;
154 mask = MC13783_LED_C2_BL_C_MASK;
155 value = max_current & MC13783_LED_C2_BL_C_MASK;
156 reg = MC13783_REG_LED_CONTROL_2;
157 break;