~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/leds/leds-lt3593.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * LEDs driver for LT3593 controllers
 
3
 *
 
4
 * See the datasheet at http://cds.linear.com/docs/Datasheet/3593f.pdf
 
5
 *
 
6
 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
 
7
 *
 
8
 * Based on leds-gpio.c,
 
9
 *
 
10
 *   Copyright (C) 2007 8D Technologies inc.
 
11
 *   Raphael Assenat <raph@8d.com>
 
12
 *   Copyright (C) 2008 Freescale Semiconductor, Inc.
 
13
 *
 
14
 * This program is free software; you can redistribute it and/or modify
 
15
 * it under the terms of the GNU General Public License version 2 as
 
16
 * published by the Free Software Foundation.
 
17
 */
 
18
 
 
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/delay.h>
 
25
#include <linux/gpio.h>
 
26
#include <linux/slab.h>
 
27
 
 
28
struct lt3593_led_data {
 
29
        struct led_classdev cdev;
 
30
        unsigned gpio;
 
31
        struct work_struct work;
 
32
        u8 new_level;
 
33
};
 
34
 
 
35
static void lt3593_led_work(struct work_struct *work)
 
36
{
 
37
        int pulses;
 
38
        struct lt3593_led_data *led_dat =
 
39
                container_of(work, struct lt3593_led_data, work);
 
40
 
 
41
        /*
 
42
         * The LT3593 resets its internal current level register to the maximum
 
43
         * level on the first falling edge on the control pin. Each following
 
44
         * falling edge decreases the current level by 625uA. Up to 32 pulses
 
45
         * can be sent, so the maximum power reduction is 20mA.
 
46
         * After a timeout of 128us, the value is taken from the register and
 
47
         * applied is to the output driver.
 
48
         */
 
49
 
 
50
        if (led_dat->new_level == 0) {
 
51
                gpio_set_value_cansleep(led_dat->gpio, 0);
 
52
                return;
 
53
        }
 
54
 
 
55
        pulses = 32 - (led_dat->new_level * 32) / 255;
 
56
 
 
57
        if (pulses == 0) {
 
58
                gpio_set_value_cansleep(led_dat->gpio, 0);
 
59
                mdelay(1);
 
60
                gpio_set_value_cansleep(led_dat->gpio, 1);
 
61
                return;
 
62
        }
 
63
 
 
64
        gpio_set_value_cansleep(led_dat->gpio, 1);
 
65
 
 
66
        while (pulses--) {
 
67
                gpio_set_value_cansleep(led_dat->gpio, 0);
 
68
                udelay(1);
 
69
                gpio_set_value_cansleep(led_dat->gpio, 1);
 
70
                udelay(1);
 
71
        }
 
72
}
 
73
 
 
74
static void lt3593_led_set(struct led_classdev *led_cdev,
 
75
        enum led_brightness value)
 
76
{
 
77
        struct lt3593_led_data *led_dat =
 
78
                container_of(led_cdev, struct lt3593_led_data, cdev);
 
79
 
 
80
        led_dat->new_level = value;
 
81
        schedule_work(&led_dat->work);
 
82
}
 
83
 
 
84
static int __devinit create_lt3593_led(const struct gpio_led *template,
 
85
        struct lt3593_led_data *led_dat, struct device *parent)
 
86
{
 
87
        int ret, state;
 
88
 
 
89
        /* skip leds on GPIOs that aren't available */
 
90
        if (!gpio_is_valid(template->gpio)) {
 
91
                printk(KERN_INFO "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
 
92
                                KBUILD_MODNAME, template->gpio, template->name);
 
93
                return 0;
 
94
        }
 
95
 
 
96
        ret = gpio_request(template->gpio, template->name);
 
97
        if (ret < 0)
 
98
                return ret;
 
99
 
 
100
        led_dat->cdev.name = template->name;
 
101
        led_dat->cdev.default_trigger = template->default_trigger;
 
102
        led_dat->gpio = template->gpio;
 
103
 
 
104
        led_dat->cdev.brightness_set = lt3593_led_set;
 
105
 
 
106
        state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
 
107
        led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
 
108
 
 
109
        if (!template->retain_state_suspended)
 
110
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
111
 
 
112
        ret = gpio_direction_output(led_dat->gpio, state);
 
113
        if (ret < 0)
 
114
                goto err;
 
115
 
 
116
        INIT_WORK(&led_dat->work, lt3593_led_work);
 
117
 
 
118
        ret = led_classdev_register(parent, &led_dat->cdev);
 
119
        if (ret < 0)
 
120
                goto err;
 
121
 
 
122
        printk(KERN_INFO "%s: registered LT3593 LED '%s' at GPIO %d\n",
 
123
                KBUILD_MODNAME, template->name, template->gpio);
 
124
 
 
125
        return 0;
 
126
 
 
127
err:
 
128
        gpio_free(led_dat->gpio);
 
129
        return ret;
 
130
}
 
131
 
 
132
static void delete_lt3593_led(struct lt3593_led_data *led)
 
133
{
 
134
        if (!gpio_is_valid(led->gpio))
 
135
                return;
 
136
 
 
137
        led_classdev_unregister(&led->cdev);
 
138
        cancel_work_sync(&led->work);
 
139
        gpio_free(led->gpio);
 
140
}
 
141
 
 
142
static int __devinit lt3593_led_probe(struct platform_device *pdev)
 
143
{
 
144
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 
145
        struct lt3593_led_data *leds_data;
 
146
        int i, ret = 0;
 
147
 
 
148
        if (!pdata)
 
149
                return -EBUSY;
 
150
 
 
151
        leds_data = kzalloc(sizeof(struct lt3593_led_data) * pdata->num_leds,
 
152
                                GFP_KERNEL);
 
153
        if (!leds_data)
 
154
                return -ENOMEM;
 
155
 
 
156
        for (i = 0; i < pdata->num_leds; i++) {
 
157
                ret = create_lt3593_led(&pdata->leds[i], &leds_data[i],
 
158
                                      &pdev->dev);
 
159
                if (ret < 0)
 
160
                        goto err;
 
161
        }
 
162
 
 
163
        platform_set_drvdata(pdev, leds_data);
 
164
 
 
165
        return 0;
 
166
 
 
167
err:
 
168
        for (i = i - 1; i >= 0; i--)
 
169
                delete_lt3593_led(&leds_data[i]);
 
170
 
 
171
        kfree(leds_data);
 
172
 
 
173
        return ret;
 
174
}
 
175
 
 
176
static int __devexit lt3593_led_remove(struct platform_device *pdev)
 
177
{
 
178
        int i;
 
179
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 
180
        struct lt3593_led_data *leds_data;
 
181
 
 
182
        leds_data = platform_get_drvdata(pdev);
 
183
 
 
184
        for (i = 0; i < pdata->num_leds; i++)
 
185
                delete_lt3593_led(&leds_data[i]);
 
186
 
 
187
        kfree(leds_data);
 
188
 
 
189
        return 0;
 
190
}
 
191
 
 
192
static struct platform_driver lt3593_led_driver = {
 
193
        .probe          = lt3593_led_probe,
 
194
        .remove         = __devexit_p(lt3593_led_remove),
 
195
        .driver         = {
 
196
                .name   = "leds-lt3593",
 
197
                .owner  = THIS_MODULE,
 
198
        },
 
199
};
 
200
 
 
201
MODULE_ALIAS("platform:leds-lt3593");
 
202
 
 
203
static int __init lt3593_led_init(void)
 
204
{
 
205
        return platform_driver_register(&lt3593_led_driver);
 
206
}
 
207
 
 
208
static void __exit lt3593_led_exit(void)
 
209
{
 
210
        platform_driver_unregister(&lt3593_led_driver);
 
211
}
 
212
 
 
213
module_init(lt3593_led_init);
 
214
module_exit(lt3593_led_exit);
 
215
 
 
216
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
 
217
MODULE_DESCRIPTION("LED driver for LT3593 controllers");
 
218
MODULE_LICENSE("GPL");