aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-08-28 12:56:49 -0400
committerOlof Johansson <olof@lixom.net>2013-08-28 12:56:49 -0400
commitf0a108b7227c4328c7a32514ee6a4ceffaaed886 (patch)
treea4e32410c2c0a2e22f7d6b0d10049d2699a767f8 /drivers
parentb36f4be3de1b123d8601de062e7dbfc904f305fb (diff)
parent98724b7ec9d34d875fc193660c87d6dd0d17ceb7 (diff)
Merge tag 'renesas-cleanup2-for-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/renesas
From Simon Horman: Second round of Renesas ARM based SoC cleanups for v3.12 * Remove mach/hardware.h which has no useful contents * Remove ag5evm board support * Remove kota2 board support * Use pm-rmobile on sh7372 and r8a7740 SoCs only, it is otherwise unneeded * Remove use of INTC header on r8a7779 and r8a7740 SoCs * Cleanup registration of usb phy in r8a7779 SoC * Remove '0x's from R8A7779 DTS file for r8a7779 SoC * tag 'renesas-cleanup2-for-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas: (74 commits) ARM: shmobile: r8a7779: Remove '0x's from R8A7779 DTS file ARM: shmobile: r8a7779: cleanup registration of usb phy ARM: shmobile: No need to use INTC header on r8a7779 ARM: shmobile: No need to use INTC demux on r8a7740 ARM: shmobile: Use pm-rmobile on sh7372 and r8a7740 only ARM: shmobile: r8a73a4: Remove ->init_machine() special case ARM: shmobile: Remove include <mach/hardware.h> ARM: shmobile: Remove Marzen use of <mach/hardware.h> ARM: shmobile: Remove r8a7779 use of <mach/hardware.h> ARM: shmobile: Remove EMEV2 use of <mach/hardware.h> ARM: shmobile: Remove sh7372 use of <mach/hardware.h> ARM: shmobile: Remove sh73a0 use of <mach/hardware.h> ARCH: ARM: shmobile: Remove ag5evm board support ARCH: ARM: shmobile: Remove kota2 board support leds: Remove leds-renesas-tpu driver ARM: shmobile: sh73a0: Remove all GPIOs ARM: shmobile: kota2: Use leds-pwm + pwm-rmob ARM: shmobile: armadillo800eva: Add backlight support ARM: shmobile: Setup r8a7790 arch timer based on MD pins ARM: shmobile: Introduce r8a7790_read_mode_pins() ... Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/leds/Kconfig12
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-renesas-tpu.c337
-rw-r--r--drivers/video/backlight/Kconfig19
-rw-r--r--drivers/video/backlight/Makefile3
-rw-r--r--drivers/video/backlight/bd6107.c213
-rw-r--r--drivers/video/backlight/gpio_backlight.c133
-rw-r--r--drivers/video/backlight/lv5207lp.c171
8 files changed, 539 insertions, 350 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e43402dd1dea..074bcb3892b5 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -429,18 +429,6 @@ config LEDS_ASIC3
429 cannot be used. This driver supports hardware blinking with an on+off 429 cannot be used. This driver supports hardware blinking with an on+off
430 period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700. 430 period from 62ms to 125s. Say Y to enable LEDs on the HP iPAQ hx4700.
431 431
432config LEDS_RENESAS_TPU
433 bool "LED support for Renesas TPU"
434 depends on LEDS_CLASS=y && HAVE_CLK && GPIOLIB
435 help
436 This option enables build of the LED TPU platform driver,
437 suitable to drive any TPU channel on newer Renesas SoCs.
438 The driver controls the GPIO pin connected to the LED via
439 the GPIO framework and expects the LED to be connected to
440 a pin that can be driven in both GPIO mode and using TPU
441 pin function. The latter to support brightness control.
442 Brightness control is supported but hardware blinking is not.
443
444config LEDS_TCA6507 432config LEDS_TCA6507
445 tristate "LED Support for TCA6507 I2C chip" 433 tristate "LED Support for TCA6507 I2C chip"
446 depends on LEDS_CLASS && I2C 434 depends on LEDS_CLASS && I2C
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index ac2897732b02..ae4b6135f665 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -49,7 +49,6 @@ obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
49obj-$(CONFIG_LEDS_NS2) += leds-ns2.o 49obj-$(CONFIG_LEDS_NS2) += leds-ns2.o
50obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o 50obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
51obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o 51obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
52obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o
53obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o 52obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o
54obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o 53obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o
55obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o 54obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
deleted file mode 100644
index adebf4931e1e..000000000000
--- a/drivers/leds/leds-renesas-tpu.c
+++ /dev/null
@@ -1,337 +0,0 @@
1/*
2 * LED control using Renesas TPU
3 *
4 * Copyright (C) 2011 Magnus Damm
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/platform_device.h>
23#include <linux/spinlock.h>
24#include <linux/printk.h>
25#include <linux/ioport.h>
26#include <linux/io.h>
27#include <linux/clk.h>
28#include <linux/leds.h>
29#include <linux/platform_data/leds-renesas-tpu.h>
30#include <linux/gpio.h>
31#include <linux/err.h>
32#include <linux/slab.h>
33#include <linux/pm_runtime.h>
34#include <linux/workqueue.h>
35
36enum r_tpu_pin { R_TPU_PIN_UNUSED, R_TPU_PIN_GPIO, R_TPU_PIN_GPIO_FN };
37enum r_tpu_timer { R_TPU_TIMER_UNUSED, R_TPU_TIMER_ON };
38
39struct r_tpu_priv {
40 struct led_classdev ldev;
41 void __iomem *mapbase;
42 struct clk *clk;
43 struct platform_device *pdev;
44 enum r_tpu_pin pin_state;
45 enum r_tpu_timer timer_state;
46 unsigned long min_rate;
47 unsigned int refresh_rate;
48 struct work_struct work;
49 enum led_brightness new_brightness;
50};
51
52static DEFINE_SPINLOCK(r_tpu_lock);
53
54#define TSTR -1 /* Timer start register (shared register) */
55#define TCR 0 /* Timer control register (+0x00) */
56#define TMDR 1 /* Timer mode register (+0x04) */
57#define TIOR 2 /* Timer I/O control register (+0x08) */
58#define TIER 3 /* Timer interrupt enable register (+0x0c) */
59#define TSR 4 /* Timer status register (+0x10) */
60#define TCNT 5 /* Timer counter (+0x14) */
61#define TGRA 6 /* Timer general register A (+0x18) */
62#define TGRB 7 /* Timer general register B (+0x1c) */
63#define TGRC 8 /* Timer general register C (+0x20) */
64#define TGRD 9 /* Timer general register D (+0x24) */
65
66static inline u16 r_tpu_read(struct r_tpu_priv *p, int reg_nr)
67{
68 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
69 void __iomem *base = p->mapbase;
70 unsigned long offs = reg_nr << 2;
71
72 if (reg_nr == TSTR)
73 return ioread16(base - cfg->channel_offset);
74
75 return ioread16(base + offs);
76}
77
78static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr, u16 value)
79{
80 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
81 void __iomem *base = p->mapbase;
82 unsigned long offs = reg_nr << 2;
83
84 if (reg_nr == TSTR) {
85 iowrite16(value, base - cfg->channel_offset);
86 return;
87 }
88
89 iowrite16(value, base + offs);
90}
91
92static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start)
93{
94 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
95 unsigned long flags;
96 u16 value;
97
98 /* start stop register shared by multiple timer channels */
99 spin_lock_irqsave(&r_tpu_lock, flags);
100 value = r_tpu_read(p, TSTR);
101
102 if (start)
103 value |= 1 << cfg->timer_bit;
104 else
105 value &= ~(1 << cfg->timer_bit);
106
107 r_tpu_write(p, TSTR, value);
108 spin_unlock_irqrestore(&r_tpu_lock, flags);
109}
110
111static int r_tpu_enable(struct r_tpu_priv *p, enum led_brightness brightness)
112{
113 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
114 int prescaler[] = { 1, 4, 16, 64 };
115 int k, ret;
116 unsigned long rate, tmp;
117
118 if (p->timer_state == R_TPU_TIMER_ON)
119 return 0;
120
121 /* wake up device and enable clock */
122 pm_runtime_get_sync(&p->pdev->dev);
123 ret = clk_enable(p->clk);
124 if (ret) {
125 dev_err(&p->pdev->dev, "cannot enable clock\n");
126 return ret;
127 }
128
129 /* make sure channel is disabled */
130 r_tpu_start_stop_ch(p, 0);
131
132 /* get clock rate after enabling it */
133 rate = clk_get_rate(p->clk);
134
135 /* pick the lowest acceptable rate */
136 for (k = ARRAY_SIZE(prescaler) - 1; k >= 0; k--)
137 if ((rate / prescaler[k]) >= p->min_rate)
138 break;
139
140 if (k < 0) {
141 dev_err(&p->pdev->dev, "clock rate mismatch\n");
142 goto err0;
143 }
144 dev_dbg(&p->pdev->dev, "rate = %lu, prescaler %u\n",
145 rate, prescaler[k]);
146
147 /* clear TCNT on TGRB match, count on rising edge, set prescaler */
148 r_tpu_write(p, TCR, 0x0040 | k);
149
150 /* output 0 until TGRA, output 1 until TGRB */
151 r_tpu_write(p, TIOR, 0x0002);
152
153 rate /= prescaler[k] * p->refresh_rate;
154 r_tpu_write(p, TGRB, rate);
155 dev_dbg(&p->pdev->dev, "TRGB = 0x%04lx\n", rate);
156
157 tmp = (cfg->max_brightness - brightness) * rate;
158 r_tpu_write(p, TGRA, tmp / cfg->max_brightness);
159 dev_dbg(&p->pdev->dev, "TRGA = 0x%04lx\n", tmp / cfg->max_brightness);
160
161 /* PWM mode */
162 r_tpu_write(p, TMDR, 0x0002);
163
164 /* enable channel */
165 r_tpu_start_stop_ch(p, 1);
166
167 p->timer_state = R_TPU_TIMER_ON;
168 return 0;
169 err0:
170 clk_disable(p->clk);
171 pm_runtime_put_sync(&p->pdev->dev);
172 return -ENOTSUPP;
173}
174
175static void r_tpu_disable(struct r_tpu_priv *p)
176{
177 if (p->timer_state == R_TPU_TIMER_UNUSED)
178 return;
179
180 /* disable channel */
181 r_tpu_start_stop_ch(p, 0);
182
183 /* stop clock and mark device as idle */
184 clk_disable(p->clk);
185 pm_runtime_put_sync(&p->pdev->dev);
186
187 p->timer_state = R_TPU_TIMER_UNUSED;
188}
189
190static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state,
191 enum led_brightness brightness)
192{
193 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data;
194
195 if (p->pin_state == new_state) {
196 if (p->pin_state == R_TPU_PIN_GPIO)
197 gpio_set_value(cfg->pin_gpio, brightness);
198 return;
199 }
200
201 if (p->pin_state == R_TPU_PIN_GPIO)
202 gpio_free(cfg->pin_gpio);
203
204 if (p->pin_state == R_TPU_PIN_GPIO_FN)
205 gpio_free(cfg->pin_gpio_fn);
206
207 if (new_state == R_TPU_PIN_GPIO)
208 gpio_request_one(cfg->pin_gpio, !!brightness ?
209 GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
210 cfg->name);
211
212 if (new_state == R_TPU_PIN_GPIO_FN)
213 gpio_request(cfg->pin_gpio_fn, cfg->name);
214
215 p->pin_state = new_state;
216}
217
218static void r_tpu_work(struct work_struct *work)
219{
220 struct r_tpu_priv *p = container_of(work, struct r_tpu_priv, work);
221 enum led_brightness brightness = p->new_brightness;
222
223 r_tpu_disable(p);
224
225 /* off and maximum are handled as GPIO pins, in between PWM */
226 if ((brightness == 0) || (brightness == p->ldev.max_brightness))
227 r_tpu_set_pin(p, R_TPU_PIN_GPIO, brightness);
228 else {
229 r_tpu_set_pin(p, R_TPU_PIN_GPIO_FN, 0);
230 r_tpu_enable(p, brightness);
231 }
232}
233
234static void r_tpu_set_brightness(struct led_classdev *ldev,
235 enum led_brightness brightness)
236{
237 struct r_tpu_priv *p = container_of(ldev, struct r_tpu_priv, ldev);
238 p->new_brightness = brightness;
239 schedule_work(&p->work);
240}
241
242static int r_tpu_probe(struct platform_device *pdev)
243{
244 struct led_renesas_tpu_config *cfg = pdev->dev.platform_data;
245 struct r_tpu_priv *p;
246 struct resource *res;
247 int ret;
248
249 if (!cfg) {
250 dev_err(&pdev->dev, "missing platform data\n");
251 return -ENODEV;
252 }
253
254 p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
255 if (p == NULL) {
256 dev_err(&pdev->dev, "failed to allocate driver data\n");
257 return -ENOMEM;
258 }
259
260 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
261 if (!res) {
262 dev_err(&pdev->dev, "failed to get I/O memory\n");
263 return -ENXIO;
264 }
265
266 /* map memory, let mapbase point to our channel */
267 p->mapbase = devm_ioremap_nocache(&pdev->dev, res->start,
268 resource_size(res));
269 if (p->mapbase == NULL) {
270 dev_err(&pdev->dev, "failed to remap I/O memory\n");
271 return -ENXIO;
272 }
273
274 /* get hold of clock */
275 p->clk = devm_clk_get(&pdev->dev, NULL);
276 if (IS_ERR(p->clk)) {
277 dev_err(&pdev->dev, "cannot get clock\n");
278 return PTR_ERR(p->clk);
279 }
280
281 p->pdev = pdev;
282 p->pin_state = R_TPU_PIN_UNUSED;
283 p->timer_state = R_TPU_TIMER_UNUSED;
284 p->refresh_rate = cfg->refresh_rate ? cfg->refresh_rate : 100;
285 r_tpu_set_pin(p, R_TPU_PIN_GPIO, LED_OFF);
286 platform_set_drvdata(pdev, p);
287
288 INIT_WORK(&p->work, r_tpu_work);
289
290 p->ldev.name = cfg->name;
291 p->ldev.brightness = LED_OFF;
292 p->ldev.max_brightness = cfg->max_brightness;
293 p->ldev.brightness_set = r_tpu_set_brightness;
294 p->ldev.flags |= LED_CORE_SUSPENDRESUME;
295 ret = led_classdev_register(&pdev->dev, &p->ldev);
296 if (ret < 0)
297 goto err0;
298
299 /* max_brightness may be updated by the LED core code */
300 p->min_rate = p->ldev.max_brightness * p->refresh_rate;
301
302 pm_runtime_enable(&pdev->dev);
303 return 0;
304
305 err0:
306 r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
307 return ret;
308}
309
310static int r_tpu_remove(struct platform_device *pdev)
311{
312 struct r_tpu_priv *p = platform_get_drvdata(pdev);
313
314 r_tpu_set_brightness(&p->ldev, LED_OFF);
315 led_classdev_unregister(&p->ldev);
316 cancel_work_sync(&p->work);
317 r_tpu_disable(p);
318 r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF);
319
320 pm_runtime_disable(&pdev->dev);
321
322 return 0;
323}
324
325static struct platform_driver r_tpu_device_driver = {
326 .probe = r_tpu_probe,
327 .remove = r_tpu_remove,
328 .driver = {
329 .name = "leds-renesas-tpu",
330 }
331};
332
333module_platform_driver(r_tpu_device_driver);
334
335MODULE_AUTHOR("Magnus Damm");
336MODULE_DESCRIPTION("Renesas TPU LED Driver");
337MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index d5ab6583f440..d4a7a351d67c 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -425,6 +425,25 @@ config BACKLIGHT_AS3711
425 If you have an Austrian Microsystems AS3711 say Y to enable the 425 If you have an Austrian Microsystems AS3711 say Y to enable the
426 backlight driver. 426 backlight driver.
427 427
428config BACKLIGHT_GPIO
429 tristate "Generic GPIO based Backlight Driver"
430 depends on GPIOLIB
431 help
432 If you have a LCD backlight adjustable by GPIO, say Y to enable
433 this driver.
434
435config BACKLIGHT_LV5207LP
436 tristate "Sanyo LV5207LP Backlight"
437 depends on I2C
438 help
439 If you have a Sanyo LV5207LP say Y to enable the backlight driver.
440
441config BACKLIGHT_BD6107
442 tristate "Rohm BD6107 Backlight"
443 depends on I2C
444 help
445 If you have a Rohm BD6107 say Y to enable the backlight driver.
446
428endif # BACKLIGHT_CLASS_DEVICE 447endif # BACKLIGHT_CLASS_DEVICE
429 448
430endif # BACKLIGHT_LCD_SUPPORT 449endif # BACKLIGHT_LCD_SUPPORT
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 92711fe60464..38e1babb1946 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -26,12 +26,14 @@ obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
26obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o 26obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
27obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o 27obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o
28obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o 28obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
29obj-$(CONFIG_BACKLIGHT_BD6107) += bd6107.o
29obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o 30obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
30obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 31obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
31obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o 32obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
32obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o 33obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o
33obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o 34obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o
34obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o 35obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o
36obj-$(CONFIG_BACKLIGHT_GPIO) += gpio_backlight.o
35obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o 37obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
36obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o 38obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
37obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o 39obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o
@@ -40,6 +42,7 @@ obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o
40obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o 42obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
41obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o 43obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o
42obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o 44obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o
45obj-$(CONFIG_BACKLIGHT_LV5207LP) += lv5207lp.o
43obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o 46obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
44obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o 47obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
45obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o 48obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
diff --git a/drivers/video/backlight/bd6107.c b/drivers/video/backlight/bd6107.c
new file mode 100644
index 000000000000..15e3294b29fe
--- /dev/null
+++ b/drivers/video/backlight/bd6107.c
@@ -0,0 +1,213 @@
1/*
2 * ROHM Semiconductor BD6107 LED Driver
3 *
4 * Copyright (C) 2013 Ideas on board SPRL
5 *
6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/backlight.h>
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/fb.h>
17#include <linux/gpio.h>
18#include <linux/i2c.h>
19#include <linux/module.h>
20#include <linux/platform_data/bd6107.h>
21#include <linux/slab.h>
22
23#define BD6107_PSCNT1 0x00
24#define BD6107_PSCNT1_PSCNTREG2 (1 << 2)
25#define BD6107_PSCNT1_PSCNTREG1 (1 << 0)
26#define BD6107_REGVSET 0x02
27#define BD6107_REGVSET_REG1VSET_2_85V (1 << 2)
28#define BD6107_REGVSET_REG1VSET_2_80V (0 << 2)
29#define BD6107_LEDCNT1 0x03
30#define BD6107_LEDCNT1_LEDONOFF2 (1 << 1)
31#define BD6107_LEDCNT1_LEDONOFF1 (1 << 0)
32#define BD6107_PORTSEL 0x04
33#define BD6107_PORTSEL_LEDM(n) (1 << (n))
34#define BD6107_RGB1CNT1 0x05
35#define BD6107_RGB1CNT2 0x06
36#define BD6107_RGB1CNT3 0x07
37#define BD6107_RGB1CNT4 0x08
38#define BD6107_RGB1CNT5 0x09
39#define BD6107_RGB1FLM 0x0a
40#define BD6107_RGB2CNT1 0x0b
41#define BD6107_RGB2CNT2 0x0c
42#define BD6107_RGB2CNT3 0x0d
43#define BD6107_RGB2CNT4 0x0e
44#define BD6107_RGB2CNT5 0x0f
45#define BD6107_RGB2FLM 0x10
46#define BD6107_PSCONT3 0x11
47#define BD6107_SMMONCNT 0x12
48#define BD6107_DCDCCNT 0x13
49#define BD6107_IOSEL 0x14
50#define BD6107_OUT1 0x15
51#define BD6107_OUT2 0x16
52#define BD6107_MASK1 0x17
53#define BD6107_MASK2 0x18
54#define BD6107_FACTOR1 0x19
55#define BD6107_FACTOR2 0x1a
56#define BD6107_CLRFACT1 0x1b
57#define BD6107_CLRFACT2 0x1c
58#define BD6107_STATE1 0x1d
59#define BD6107_LSIVER 0x1e
60#define BD6107_GRPSEL 0x1f
61#define BD6107_LEDCNT2 0x20
62#define BD6107_LEDCNT3 0x21
63#define BD6107_MCURRENT 0x22
64#define BD6107_MAINCNT1 0x23
65#define BD6107_MAINCNT2 0x24
66#define BD6107_SLOPECNT 0x25
67#define BD6107_MSLOPE 0x26
68#define BD6107_RGBSLOPE 0x27
69#define BD6107_TEST 0x29
70#define BD6107_SFTRST 0x2a
71#define BD6107_SFTRSTGD 0x2b
72
73struct bd6107 {
74 struct i2c_client *client;
75 struct backlight_device *backlight;
76 struct bd6107_platform_data *pdata;
77};
78
79static int bd6107_write(struct bd6107 *bd, u8 reg, u8 data)
80{
81 return i2c_smbus_write_byte_data(bd->client, reg, data);
82}
83
84static int bd6107_backlight_update_status(struct backlight_device *backlight)
85{
86 struct bd6107 *bd = bl_get_data(backlight);
87 int brightness = backlight->props.brightness;
88
89 if (backlight->props.power != FB_BLANK_UNBLANK ||
90 backlight->props.fb_blank != FB_BLANK_UNBLANK ||
91 backlight->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
92 brightness = 0;
93
94 if (brightness) {
95 bd6107_write(bd, BD6107_PORTSEL, BD6107_PORTSEL_LEDM(2) |
96 BD6107_PORTSEL_LEDM(1) | BD6107_PORTSEL_LEDM(0));
97 bd6107_write(bd, BD6107_MAINCNT1, brightness);
98 bd6107_write(bd, BD6107_LEDCNT1, BD6107_LEDCNT1_LEDONOFF1);
99 } else {
100 gpio_set_value(bd->pdata->reset, 0);
101 msleep(24);
102 gpio_set_value(bd->pdata->reset, 1);
103 }
104
105 return 0;
106}
107
108static int bd6107_backlight_get_brightness(struct backlight_device *backlight)
109{
110 return backlight->props.brightness;
111}
112
113static int bd6107_backlight_check_fb(struct backlight_device *backlight,
114 struct fb_info *info)
115{
116 struct bd6107 *bd = bl_get_data(backlight);
117
118 return bd->pdata->fbdev == NULL || bd->pdata->fbdev == info->dev;
119}
120
121static const struct backlight_ops bd6107_backlight_ops = {
122 .options = BL_CORE_SUSPENDRESUME,
123 .update_status = bd6107_backlight_update_status,
124 .get_brightness = bd6107_backlight_get_brightness,
125 .check_fb = bd6107_backlight_check_fb,
126};
127
128static int bd6107_probe(struct i2c_client *client,
129 const struct i2c_device_id *id)
130{
131 struct bd6107_platform_data *pdata = client->dev.platform_data;
132 struct backlight_device *backlight;
133 struct backlight_properties props;
134 struct bd6107 *bd;
135 int ret;
136
137 if (pdata == NULL || !pdata->reset) {
138 dev_err(&client->dev, "No reset GPIO in platform data\n");
139 return -EINVAL;
140 }
141
142 if (!i2c_check_functionality(client->adapter,
143 I2C_FUNC_SMBUS_BYTE_DATA)) {
144 dev_warn(&client->dev,
145 "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
146 return -EIO;
147 }
148
149 bd = devm_kzalloc(&client->dev, sizeof(*bd), GFP_KERNEL);
150 if (!bd)
151 return -ENOMEM;
152
153 bd->client = client;
154 bd->pdata = pdata;
155
156 ret = devm_gpio_request_one(&client->dev, pdata->reset,
157 GPIOF_DIR_OUT | GPIOF_INIT_LOW, "reset");
158 if (ret < 0) {
159 dev_err(&client->dev, "unable to request reset GPIO\n");
160 return ret;
161 }
162
163 memset(&props, 0, sizeof(props));
164 props.type = BACKLIGHT_RAW;
165 props.max_brightness = 128;
166 props.brightness = clamp_t(unsigned int, pdata->def_value, 0,
167 props.max_brightness);
168
169 backlight = backlight_device_register(dev_name(&client->dev),
170 &bd->client->dev, bd,
171 &bd6107_backlight_ops, &props);
172 if (IS_ERR(backlight)) {
173 dev_err(&client->dev, "failed to register backlight\n");
174 return PTR_ERR(backlight);
175 }
176
177 backlight_update_status(backlight);
178 i2c_set_clientdata(client, backlight);
179
180 return 0;
181}
182
183static int bd6107_remove(struct i2c_client *client)
184{
185 struct backlight_device *backlight = i2c_get_clientdata(client);
186
187 backlight->props.brightness = 0;
188 backlight_update_status(backlight);
189 backlight_device_unregister(backlight);
190
191 return 0;
192}
193
194static const struct i2c_device_id bd6107_ids[] = {
195 { "bd6107", 0 },
196 { }
197};
198MODULE_DEVICE_TABLE(i2c, bd6107_ids);
199
200static struct i2c_driver bd6107_driver = {
201 .driver = {
202 .name = "bd6107",
203 },
204 .probe = bd6107_probe,
205 .remove = bd6107_remove,
206 .id_table = bd6107_ids,
207};
208
209module_i2c_driver(bd6107_driver);
210
211MODULE_DESCRIPTION("Rohm BD6107 Backlight Driver");
212MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
213MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c
new file mode 100644
index 000000000000..5fa217f9f445
--- /dev/null
+++ b/drivers/video/backlight/gpio_backlight.c
@@ -0,0 +1,133 @@
1/*
2 * gpio_backlight.c - Simple GPIO-controlled backlight
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 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/backlight.h>
10#include <linux/err.h>
11#include <linux/fb.h>
12#include <linux/gpio.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/platform_data/gpio_backlight.h>
17#include <linux/platform_device.h>
18#include <linux/slab.h>
19
20struct gpio_backlight {
21 struct device *dev;
22 struct device *fbdev;
23
24 int gpio;
25 int active;
26};
27
28static int gpio_backlight_update_status(struct backlight_device *bl)
29{
30 struct gpio_backlight *gbl = bl_get_data(bl);
31 int brightness = bl->props.brightness;
32
33 if (bl->props.power != FB_BLANK_UNBLANK ||
34 bl->props.fb_blank != FB_BLANK_UNBLANK ||
35 bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
36 brightness = 0;
37
38 gpio_set_value(gbl->gpio, brightness ? gbl->active : !gbl->active);
39
40 return 0;
41}
42
43static int gpio_backlight_get_brightness(struct backlight_device *bl)
44{
45 return bl->props.brightness;
46}
47
48static int gpio_backlight_check_fb(struct backlight_device *bl,
49 struct fb_info *info)
50{
51 struct gpio_backlight *gbl = bl_get_data(bl);
52
53 return gbl->fbdev == NULL || gbl->fbdev == info->dev;
54}
55
56static const struct backlight_ops gpio_backlight_ops = {
57 .options = BL_CORE_SUSPENDRESUME,
58 .update_status = gpio_backlight_update_status,
59 .get_brightness = gpio_backlight_get_brightness,
60 .check_fb = gpio_backlight_check_fb,
61};
62
63static int gpio_backlight_probe(struct platform_device *pdev)
64{
65 struct gpio_backlight_platform_data *pdata = pdev->dev.platform_data;
66 struct backlight_properties props;
67 struct backlight_device *bl;
68 struct gpio_backlight *gbl;
69 int ret;
70
71 if (!pdata) {
72 dev_err(&pdev->dev, "failed to find platform data\n");
73 return -ENODEV;
74 }
75
76 gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL);
77 if (gbl == NULL)
78 return -ENOMEM;
79
80 gbl->dev = &pdev->dev;
81 gbl->fbdev = pdata->fbdev;
82 gbl->gpio = pdata->gpio;
83 gbl->active = pdata->active_low ? 0 : 1;
84
85 ret = devm_gpio_request_one(gbl->dev, gbl->gpio, GPIOF_DIR_OUT |
86 (gbl->active ? GPIOF_INIT_LOW
87 : GPIOF_INIT_HIGH),
88 pdata->name);
89 if (ret < 0) {
90 dev_err(&pdev->dev, "unable to request GPIO\n");
91 return ret;
92 }
93
94 memset(&props, 0, sizeof(props));
95 props.type = BACKLIGHT_RAW;
96 props.max_brightness = 1;
97 bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, gbl,
98 &gpio_backlight_ops, &props);
99 if (IS_ERR(bl)) {
100 dev_err(&pdev->dev, "failed to register backlight\n");
101 return PTR_ERR(bl);
102 }
103
104 bl->props.brightness = pdata->def_value;
105 backlight_update_status(bl);
106
107 platform_set_drvdata(pdev, bl);
108 return 0;
109}
110
111static int gpio_backlight_remove(struct platform_device *pdev)
112{
113 struct backlight_device *bl = platform_get_drvdata(pdev);
114
115 backlight_device_unregister(bl);
116 return 0;
117}
118
119static struct platform_driver gpio_backlight_driver = {
120 .driver = {
121 .name = "gpio-backlight",
122 .owner = THIS_MODULE,
123 },
124 .probe = gpio_backlight_probe,
125 .remove = gpio_backlight_remove,
126};
127
128module_platform_driver(gpio_backlight_driver);
129
130MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
131MODULE_DESCRIPTION("GPIO-based Backlight Driver");
132MODULE_LICENSE("GPL");
133MODULE_ALIAS("platform:gpio-backlight");
diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c
new file mode 100644
index 000000000000..498fd73d59b9
--- /dev/null
+++ b/drivers/video/backlight/lv5207lp.c
@@ -0,0 +1,171 @@
1/*
2 * Sanyo LV5207LP LED Driver
3 *
4 * Copyright (C) 2013 Ideas on board SPRL
5 *
6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/backlight.h>
14#include <linux/err.h>
15#include <linux/fb.h>
16#include <linux/i2c.h>
17#include <linux/module.h>
18#include <linux/platform_data/lv5207lp.h>
19#include <linux/slab.h>
20
21#define LV5207LP_CTRL1 0x00
22#define LV5207LP_CPSW (1 << 7)
23#define LV5207LP_SCTEN (1 << 6)
24#define LV5207LP_C10 (1 << 5)
25#define LV5207LP_CKSW (1 << 4)
26#define LV5207LP_RSW (1 << 3)
27#define LV5207LP_GSW (1 << 2)
28#define LV5207LP_BSW (1 << 1)
29#define LV5207LP_CTRL2 0x01
30#define LV5207LP_MSW (1 << 7)
31#define LV5207LP_MLED4 (1 << 6)
32#define LV5207LP_RED 0x02
33#define LV5207LP_GREEN 0x03
34#define LV5207LP_BLUE 0x04
35
36#define LV5207LP_MAX_BRIGHTNESS 32
37
38struct lv5207lp {
39 struct i2c_client *client;
40 struct backlight_device *backlight;
41 struct lv5207lp_platform_data *pdata;
42};
43
44static int lv5207lp_write(struct lv5207lp *lv, u8 reg, u8 data)
45{
46 return i2c_smbus_write_byte_data(lv->client, reg, data);
47}
48
49static int lv5207lp_backlight_update_status(struct backlight_device *backlight)
50{
51 struct lv5207lp *lv = bl_get_data(backlight);
52 int brightness = backlight->props.brightness;
53
54 if (backlight->props.power != FB_BLANK_UNBLANK ||
55 backlight->props.fb_blank != FB_BLANK_UNBLANK ||
56 backlight->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
57 brightness = 0;
58
59 if (brightness) {
60 lv5207lp_write(lv, LV5207LP_CTRL1,
61 LV5207LP_CPSW | LV5207LP_C10 | LV5207LP_CKSW);
62 lv5207lp_write(lv, LV5207LP_CTRL2,
63 LV5207LP_MSW | LV5207LP_MLED4 |
64 (brightness - 1));
65 } else {
66 lv5207lp_write(lv, LV5207LP_CTRL1, 0);
67 lv5207lp_write(lv, LV5207LP_CTRL2, 0);
68 }
69
70 return 0;
71}
72
73static int lv5207lp_backlight_get_brightness(struct backlight_device *backlight)
74{
75 return backlight->props.brightness;
76}
77
78static int lv5207lp_backlight_check_fb(struct backlight_device *backlight,
79 struct fb_info *info)
80{
81 struct lv5207lp *lv = bl_get_data(backlight);
82
83 return lv->pdata->fbdev == NULL || lv->pdata->fbdev == info->dev;
84}
85
86static const struct backlight_ops lv5207lp_backlight_ops = {
87 .options = BL_CORE_SUSPENDRESUME,
88 .update_status = lv5207lp_backlight_update_status,
89 .get_brightness = lv5207lp_backlight_get_brightness,
90 .check_fb = lv5207lp_backlight_check_fb,
91};
92
93static int lv5207lp_probe(struct i2c_client *client,
94 const struct i2c_device_id *id)
95{
96 struct lv5207lp_platform_data *pdata = client->dev.platform_data;
97 struct backlight_device *backlight;
98 struct backlight_properties props;
99 struct lv5207lp *lv;
100
101 if (pdata == NULL) {
102 dev_err(&client->dev, "No platform data supplied\n");
103 return -EINVAL;
104 }
105
106 if (!i2c_check_functionality(client->adapter,
107 I2C_FUNC_SMBUS_BYTE_DATA)) {
108 dev_warn(&client->dev,
109 "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
110 return -EIO;
111 }
112
113 lv = devm_kzalloc(&client->dev, sizeof(*lv), GFP_KERNEL);
114 if (!lv)
115 return -ENOMEM;
116
117 lv->client = client;
118 lv->pdata = pdata;
119
120 memset(&props, 0, sizeof(props));
121 props.type = BACKLIGHT_RAW;
122 props.max_brightness = min_t(unsigned int, pdata->max_value,
123 LV5207LP_MAX_BRIGHTNESS);
124 props.brightness = clamp_t(unsigned int, pdata->def_value, 0,
125 props.max_brightness);
126
127 backlight = backlight_device_register(dev_name(&client->dev),
128 &lv->client->dev, lv,
129 &lv5207lp_backlight_ops, &props);
130 if (IS_ERR(backlight)) {
131 dev_err(&client->dev, "failed to register backlight\n");
132 return PTR_ERR(backlight);
133 }
134
135 backlight_update_status(backlight);
136 i2c_set_clientdata(client, backlight);
137
138 return 0;
139}
140
141static int lv5207lp_remove(struct i2c_client *client)
142{
143 struct backlight_device *backlight = i2c_get_clientdata(client);
144
145 backlight->props.brightness = 0;
146 backlight_update_status(backlight);
147 backlight_device_unregister(backlight);
148
149 return 0;
150}
151
152static const struct i2c_device_id lv5207lp_ids[] = {
153 { "lv5207lp", 0 },
154 { }
155};
156MODULE_DEVICE_TABLE(i2c, lv5207lp_ids);
157
158static struct i2c_driver lv5207lp_driver = {
159 .driver = {
160 .name = "lv5207lp",
161 },
162 .probe = lv5207lp_probe,
163 .remove = lv5207lp_remove,
164 .id_table = lv5207lp_ids,
165};
166
167module_i2c_driver(lv5207lp_driver);
168
169MODULE_DESCRIPTION("Sanyo LV5207LP Backlight Driver");
170MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
171MODULE_LICENSE("GPL");