~ubuntu-branches/ubuntu/precise/linux-linaro-u8500/precise

« back to all changes in this revision

Viewing changes to drivers/leds/leds-88pm860x.c

  • Committer: Bazaar Package Importer
  • Author(s): John Rigby, Upstream Fixes, Andy Green, John Rigby
  • Date: 2011-04-14 12:16:06 UTC
  • Revision ID: james.westby@ubuntu.com-20110414121606-b77podkyqgr2oix7
Tags: 2.6.38-1002.3
[ Upstream Fixes ]

* MUSB: shutdown: Make sure block is awake before doing shutdown
  - LP: #745737
* Fixed gpio polarity of gpio USB-phy reset.
  - LP: #747639

[ Andy Green ]

* LINARO: SAUCE: disable CONFIG_OMAP_RESET_CLOCKS
  - LP: #752900

[ John Rigby ]

* Rebase to new upstreams:
  Linux v2.6.38.1
  linaro-linux-2.6.38-upstream-29Mar2011
  Ubuntu-2.6.38-7.35
* SAUCE: OMAP4: clock: wait for module to become accessible on
  a clk enable
  - LP: #745737
* Rebase to new upstreams:
  Linux v2.6.38.2
  linaro-linux-2.6.38-upstream-5Apr2011
  Ubuntu-2.6.38-8.41
  - LP: #732842
* Update configs for device tree, dvfs and lttng
* LINARO: add building of dtb's
* LINARO: SAUCE: Disable lowest operating freqs on omap34xx
  - LP: #732912

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
#include <linux/leds.h>
18
18
#include <linux/slab.h>
19
19
#include <linux/workqueue.h>
 
20
#include <linux/mfd/core.h>
20
21
#include <linux/mfd/88pm860x.h>
21
22
 
22
23
#define LED_PWM_SHIFT           (3)
118
119
 
119
120
        struct pm860x_led *led;
120
121
        struct pm860x_chip *chip;
121
 
        int mask;
 
122
        unsigned char buf[3];
 
123
        int mask, ret;
122
124
 
123
125
        led = container_of(work, struct pm860x_led, work);
124
126
        chip = led->chip;
128
130
                        pm860x_set_bits(led->i2c, __led_off(led->port),
129
131
                                        LED_CURRENT_MASK, led->iset);
130
132
                }
 
133
                pm860x_set_bits(led->i2c, __blink_off(led->port),
 
134
                                LED_BLINK_MASK, LED_ON_CONTINUOUS);
131
135
                mask = __blink_ctl_mask(led->port);
132
136
                pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
133
 
        } else if (led->brightness == 0) {
134
 
                pm860x_set_bits(led->i2c, __led_off(led->port),
135
 
                                LED_CURRENT_MASK, 0);
136
 
                mask = __blink_ctl_mask(led->port);
137
 
                pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
138
137
        }
139
138
        pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK,
140
139
                        led->brightness);
 
140
 
 
141
        if (led->brightness == 0) {
 
142
                pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf);
 
143
                ret = buf[0] & LED_PWM_MASK;
 
144
                ret |= buf[1] & LED_PWM_MASK;
 
145
                ret |= buf[2] & LED_PWM_MASK;
 
146
                if (ret == 0) {
 
147
                        /* unset current since no led is lighting */
 
148
                        pm860x_set_bits(led->i2c, __led_off(led->port),
 
149
                                        LED_CURRENT_MASK, 0);
 
150
                        mask = __blink_ctl_mask(led->port);
 
151
                        pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
 
152
                }
 
153
        }
141
154
        led->current_brightness = led->brightness;
142
155
        dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
143
156
                __led_off(led->port), led->brightness);
153
166
        schedule_work(&data->work);
154
167
}
155
168
 
156
 
static int __check_device(struct pm860x_led_pdata *pdata, char *name)
157
 
{
158
 
        struct pm860x_led_pdata *p = pdata;
159
 
        int ret = -EINVAL;
160
 
 
161
 
        while (p && p->id) {
162
 
                if ((p->id != PM8606_ID_LED) || (p->flags < 0))
163
 
                        break;
164
 
 
165
 
                if (!strncmp(name, pm860x_led_name[p->flags],
166
 
                        MFD_NAME_SIZE)) {
167
 
                        ret = (int)p->flags;
168
 
                        break;
169
 
                }
170
 
                p++;
171
 
        }
172
 
        return ret;
173
 
}
174
 
 
175
169
static int pm860x_led_probe(struct platform_device *pdev)
176
170
{
177
171
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
178
 
        struct pm860x_platform_data *pm860x_pdata;
179
172
        struct pm860x_led_pdata *pdata;
180
173
        struct pm860x_led *data;
 
174
        struct mfd_cell *cell;
181
175
        struct resource *res;
182
176
        int ret;
183
177
 
187
181
                return -EINVAL;
188
182
        }
189
183
 
190
 
        if (pdev->dev.parent->platform_data) {
191
 
                pm860x_pdata = pdev->dev.parent->platform_data;
192
 
                pdata = pm860x_pdata->led;
193
 
        } else {
 
184
        cell = pdev->dev.platform_data;
 
185
        if (cell == NULL)
 
186
                return -ENODEV;
 
187
        pdata = cell->mfd_data;
 
188
        if (pdata == NULL) {
194
189
                dev_err(&pdev->dev, "No platform data!\n");
195
190
                return -EINVAL;
196
191
        }
198
193
        data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
199
194
        if (data == NULL)
200
195
                return -ENOMEM;
201
 
        strncpy(data->name, res->name, MFD_NAME_SIZE);
 
196
        strncpy(data->name, res->name, MFD_NAME_SIZE - 1);
202
197
        dev_set_drvdata(&pdev->dev, data);
203
198
        data->chip = chip;
204
199
        data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
205
200
        data->iset = pdata->iset;
206
 
        data->port = __check_device(pdata, data->name);
 
201
        data->port = pdata->flags;
207
202
        if (data->port < 0) {
208
203
                dev_err(&pdev->dev, "check device failed\n");
209
204
                kfree(data);
221
216
                dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
222
217
                goto out;
223
218
        }
 
219
        pm860x_led_set(&data->cdev, 0);
224
220
        return 0;
225
221
out:
226
222
        kfree(data);