Root/target/linux/ubicom32/files/arch/ubicom32/mach-common/ubicom32hid.c

1/*
2 * arch/ubicom32/mach-common/ubicom32hid.c
3 * I2C driver for HID coprocessor found on some DPF implementations.
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/gpio.h>
32#include <linux/delay.h>
33#include <linux/platform_device.h>
34#include <linux/i2c.h>
35#include <linux/backlight.h>
36#include <linux/fb.h>
37#include <linux/input.h>
38#include <linux/input-polldev.h>
39
40#include <asm/ubicom32hid.h>
41
42#define DRIVER_NAME "ubicom32hid"
43
44#ifdef DEBUG
45static int ubicom32hid_debug;
46#endif
47
48static const struct i2c_device_id ubicom32hid_id[] = {
49    { DRIVER_NAME, },
50    { }
51};
52MODULE_DEVICE_TABLE(i2c, ubicom32hid_id);
53
54/*
55 * Define this to make IR checking strict, in general, it's not needed
56 */
57#undef UBICOM32HID_STRICT_IR_CHECK
58
59#define UBICOM32HID_CMD_SET_PWM 0x01
60#define UBICOM32HID_CMD_SET_BL_EN 0x02
61#define UBICOM32HID_BL_EN_LOW 0x00
62#define UBICOM32HID_BL_EN_HIZ 0x01
63#define UBICOM32HID_BL_EN_HI 0x02
64#define UBICOM32HID_CMD_FLUSH 0x99
65#define UBICOM32HID_CMD_RESET 0x99
66#define UBICOM32HID_CMD_GET_IR_SWITCH 0xC0
67#define UBICOM32HID_CMD_GET_REVISION 0xfd
68#define UBICOM32HID_CMD_GET_DEVICE_ID 0xfe
69#define UBICOM32HID_CMD_GET_VERSION 0xff
70#define UBICOM32HID_DEVICE_ID 0x49
71
72#define UBICOM32HID_MAX_BRIGHTNESS_PWM 255
73
74/*
75 * Data structure returned by the HID device
76 */
77struct ubicom32hid_input_data {
78    uint32_t ircmd;
79    uint8_t sw_state;
80    uint8_t sw_changed;
81};
82
83/*
84 * Our private data
85 */
86struct ubicom32hid_data {
87    /*
88     * Pointer to the platform data structure, we need the settings.
89     */
90    const struct ubicom32hid_platform_data *pdata;
91
92    /*
93     * Backlight device
94     */
95    struct backlight_device *bldev;
96
97    /*
98     * I2C client, for sending messages to the HID device
99     */
100    struct i2c_client *client;
101
102    /*
103     * Current intensity, used for get_intensity.
104     */
105    int cur_intensity;
106
107    /*
108     * Input subsystem
109     * We won't register an input subsystem if there are no mappings.
110     */
111    struct input_polled_dev *poll_dev;
112};
113
114
115/*
116 * ubicom32hid_set_intensity
117 */
118static int ubicom32hid_set_intensity(struct backlight_device *bd)
119{
120    struct ubicom32hid_data *ud =
121        (struct ubicom32hid_data *)bl_get_data(bd);
122    int intensity = bd->props.brightness;
123    int reg;
124    u8_t val;
125    int ret;
126
127    /*
128     * If we're blanked the the intensity doesn't matter.
129     */
130    if ((bd->props.power != FB_BLANK_UNBLANK) ||
131        (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
132        intensity = 0;
133    }
134
135    /*
136     * Set the brightness based on the type of backlight
137     */
138    if (ud->pdata->type == UBICOM32HID_BL_TYPE_BINARY) {
139        reg = UBICOM32HID_CMD_SET_BL_EN;
140        if (intensity) {
141            val = ud->pdata->invert
142                ? UBICOM32HID_BL_EN_LOW : UBICOM32HID_BL_EN_HI;
143        } else {
144            val = ud->pdata->invert
145                ? UBICOM32HID_BL_EN_HI : UBICOM32HID_BL_EN_LOW;
146        }
147    } else {
148        reg = UBICOM32HID_CMD_SET_PWM;
149        val = ud->pdata->invert
150            ? (UBICOM32HID_MAX_BRIGHTNESS_PWM - intensity) :
151            intensity;
152    }
153
154    /*
155     * Send the command
156     */
157    ret = i2c_smbus_write_byte_data(ud->client, reg, val);
158    if (ret < 0) {
159        dev_warn(&ud->client->dev, "Unable to write backlight err=%d\n",
160             ret);
161        return ret;
162    }
163
164    ud->cur_intensity = intensity;
165
166    return 0;
167}
168
169/*
170 * ubicom32hid_get_intensity
171 * Return the current intensity of the backlight.
172 */
173static int ubicom32hid_get_intensity(struct backlight_device *bd)
174{
175    struct ubicom32hid_data *ud =
176        (struct ubicom32hid_data *)bl_get_data(bd);
177
178    return ud->cur_intensity;
179}
180
181/*
182 * ubicom32hid_verify_data
183 * Verify the data to see if there is any action to be taken
184 *
185 * Returns 0 if no action is to be taken, non-zero otherwise
186 */
187static int ubicom32hid_verify_data(struct ubicom32hid_data *ud,
188                   struct ubicom32hid_input_data *data)
189{
190    uint8_t *ircmd = (uint8_t *)&(data->ircmd);
191
192    /*
193     * ircmd == DEADBEEF means ir queue is empty. Since this is a
194     * meaningful code, that means the rest of the message is most likely
195     * correct, so only process the data if the switch state has changed.
196     */
197    if (data->ircmd == 0xDEADBEEF) {
198        return data->sw_changed != 0;
199    }
200
201    /*
202     * We have an ircmd which is not empty:
203     * Data[1] should be the complement of Data[0]
204     */
205    if (ircmd[0] != (u8_t)~ircmd[1]) {
206        return 0;
207    }
208
209#ifdef UBICOM32HID_STRICT_IR_CHECK
210    /*
211     * It seems that some remote controls don't follow the NEC protocol
212     * properly, so only do this check if the remote does indeed follow the
213     * spec. Data[3] should be the complement of Data[2]
214     */
215    if (ircmd[2] == (u8_t)~ircmd[3]) {
216        return 1;
217    }
218
219    /*
220     * For non-compliant remotes, check the system code according to what
221     * they send.
222     */
223    if ((ircmd[2] != UBICOM32HID_IR_SYSTEM_CODE_CHECK) ||
224        (ircmd[3] != UBICOM32HID_IR_SYSTEM_CODE)) {
225        return 0;
226    }
227#endif
228
229    /*
230     * Data checks out, process
231     */
232    return 1;
233}
234
235/*
236 * ubicom32hid_poll_input
237 * Poll the input from the HID device.
238 */
239static void ubicom32hid_poll_input(struct input_polled_dev *dev)
240{
241    struct ubicom32hid_data *ud = (struct ubicom32hid_data *)dev->private;
242    const struct ubicom32hid_platform_data *pdata = ud->pdata;
243    struct ubicom32hid_input_data data;
244    struct input_dev *id = dev->input;
245    int i;
246    int sync_needed = 0;
247    uint8_t cmd;
248    int ret;
249
250    /*
251     * Flush the queue
252     */
253    cmd = UBICOM32HID_CMD_FLUSH;
254    ret = i2c_master_send(ud->client, &cmd, 1);
255    if (ret < 0) {
256        return;
257    }
258
259    ret = i2c_smbus_read_i2c_block_data(
260        ud->client, UBICOM32HID_CMD_GET_IR_SWITCH, 6, (void *)&data);
261    if (ret < 0) {
262        return;
263    }
264
265    /*
266     * Verify the data to see if there is any action to be taken
267     */
268    if (!ubicom32hid_verify_data(ud, &data)) {
269        return;
270    }
271
272#ifdef DEBUG
273    if (ubicom32hid_debug) {
274        printk("Polled ircmd=%8x swstate=%2x swchanged=%2x\n",
275               data.ircmd, data.sw_state, data.sw_changed);
276    }
277#endif
278
279    /*
280     * Process changed switches
281     */
282    if (data.sw_changed) {
283        const struct ubicom32hid_button *ub = pdata->buttons;
284        for (i = 0; i < pdata->nbuttons; i++, ub++) {
285            uint8_t mask = (1 << ub->bit);
286            if (!(data.sw_changed & mask)) {
287                continue;
288            }
289
290            sync_needed = 1;
291            input_event(id, ub->type, ub->code,
292                    (data.sw_state & mask) ? 1 : 0);
293        }
294    }
295    if (sync_needed) {
296        input_sync(id);
297    }
298
299    /*
300     * Process ir codes
301     */
302    if (data.ircmd != 0xDEADBEEF) {
303        const struct ubicom32hid_ir *ui = pdata->ircodes;
304        for (i = 0; i < pdata->nircodes; i++, ui++) {
305            if (ui->ir_code == data.ircmd) {
306                /*
307                 * Simulate a up/down event
308                 */
309                input_event(id, ui->type, ui->code, 1);
310                input_sync(id);
311                input_event(id, ui->type, ui->code, 0);
312                input_sync(id);
313            }
314        }
315    }
316}
317
318
319/*
320 * Backlight ops
321 */
322static struct backlight_ops ubicom32hid_blops = {
323    .get_brightness = ubicom32hid_get_intensity,
324    .update_status = ubicom32hid_set_intensity,
325};
326
327/*
328 * ubicom32hid_probe
329 */
330static int ubicom32hid_probe(struct i2c_client *client,
331                 const struct i2c_device_id *id)
332{
333    struct ubicom32hid_platform_data *pdata;
334    struct ubicom32hid_data *ud;
335    int ret;
336    int i;
337    u8 version[2];
338    char buf[1];
339
340    pdata = client->dev.platform_data;
341    if (pdata == NULL) {
342        return -ENODEV;
343    }
344
345    /*
346     * See if we even have a device available before allocating memory.
347     *
348     * Hard reset the device
349     */
350    ret = gpio_request(pdata->gpio_reset, "ubicom32hid-reset");
351    if (ret < 0) {
352        return ret;
353    }
354    gpio_direction_output(pdata->gpio_reset, pdata->gpio_reset_polarity);
355    udelay(100);
356    gpio_set_value(pdata->gpio_reset, !pdata->gpio_reset_polarity);
357    udelay(100);
358
359    /*
360     * soft reset the device. It sometimes takes a while to do this.
361     */
362    for (i = 0; i < 50; i++) {
363        buf[0] = UBICOM32HID_CMD_RESET;
364        ret = i2c_master_send(client, buf, 1);
365        if (ret > 0) {
366            break;
367        }
368        udelay(10000);
369    }
370    if (i == 50) {
371        dev_warn(&client->dev, "Unable to reset device\n");
372        goto fail;
373    }
374
375    ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_DEVICE_ID);
376    if (ret != UBICOM32HID_DEVICE_ID) {
377        dev_warn(&client->dev, "Incorrect device id %02x\n", buf[0]);
378        ret = -ENODEV;
379        goto fail;
380    }
381
382    ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_VERSION);
383    if (ret < 0) {
384        dev_warn(&client->dev, "Unable to get version\n");
385        goto fail;
386    }
387    version[0] = ret;
388
389    ret = i2c_smbus_read_byte_data(client, UBICOM32HID_CMD_GET_REVISION);
390    if (ret < 0) {
391        dev_warn(&client->dev, "Unable to get revision\n");
392        goto fail;
393    }
394    version[1] = ret;
395
396    /*
397     * Allocate our private data
398     */
399    ud = kzalloc(sizeof(struct ubicom32hid_data), GFP_KERNEL);
400    if (!ud) {
401        ret = -ENOMEM;
402        goto fail;
403    }
404    ud->pdata = pdata;
405    ud->client = client;
406
407    /*
408     * Register our backlight device
409     */
410    ud->bldev = backlight_device_register(DRIVER_NAME, &client->dev,
411                          ud, &ubicom32hid_blops);
412    if (IS_ERR(ud->bldev)) {
413        ret = PTR_ERR(ud->bldev);
414        goto fail2;
415    }
416    platform_set_drvdata(client, ud);
417
418    /*
419     * Start up the backlight with the requested intensity
420     */
421    ud->bldev->props.power = FB_BLANK_UNBLANK;
422    ud->bldev->props.max_brightness =
423        (pdata->type == UBICOM32HID_BL_TYPE_PWM) ?
424        UBICOM32HID_MAX_BRIGHTNESS_PWM : 1;
425    if (pdata->default_intensity < ud->bldev->props.max_brightness) {
426        ud->bldev->props.brightness = pdata->default_intensity;
427    } else {
428        dev_warn(&client->dev, "Default brightness out of range, "
429             "setting to max\n");
430        ud->bldev->props.brightness = ud->bldev->props.max_brightness;
431    }
432
433    ubicom32hid_set_intensity(ud->bldev);
434
435    /*
436     * Check to see if we have any inputs
437     */
438    if (!pdata->nbuttons && !pdata->nircodes) {
439        goto done;
440    }
441
442    /*
443     * We have buttons or codes, we must register an input device
444     */
445    ud->poll_dev = input_allocate_polled_device();
446    if (!ud->poll_dev) {
447        ret = -ENOMEM;
448        goto fail3;
449    }
450
451    /*
452     * Setup the polling to default to 100ms
453     */
454    ud->poll_dev->poll = ubicom32hid_poll_input;
455    ud->poll_dev->poll_interval =
456        pdata->poll_interval ? pdata->poll_interval : 100;
457    ud->poll_dev->private = ud;
458
459    ud->poll_dev->input->name =
460        pdata->input_name ? pdata->input_name : "Ubicom32HID";
461    ud->poll_dev->input->phys = "ubicom32hid/input0";
462    ud->poll_dev->input->dev.parent = &client->dev;
463    ud->poll_dev->input->id.bustype = BUS_I2C;
464
465    /*
466     * Set the capabilities by running through the buttons and ir codes
467     */
468    for (i = 0; i < pdata->nbuttons; i++) {
469        const struct ubicom32hid_button *ub = &pdata->buttons[i];
470
471        input_set_capability(ud->poll_dev->input,
472                     ub->type ? ub->type : EV_KEY, ub->code);
473    }
474
475    for (i = 0; i < pdata->nircodes; i++) {
476        const struct ubicom32hid_ir *ui = &pdata->ircodes[i];
477
478        input_set_capability(ud->poll_dev->input,
479                     ui->type ? ui->type : EV_KEY, ui->code);
480    }
481
482    ret = input_register_polled_device(ud->poll_dev);
483    if (ret) {
484        goto fail3;
485    }
486
487done:
488    printk(KERN_INFO DRIVER_NAME ": enabled, version=%02x.%02x\n",
489           version[0], version[1]);
490
491    return 0;
492
493fail3:
494    gpio_free(ud->pdata->gpio_reset);
495    backlight_device_unregister(ud->bldev);
496fail2:
497    kfree(ud);
498fail:
499    gpio_free(pdata->gpio_reset);
500    return ret;
501}
502
503/*
504 * ubicom32hid_remove
505 */
506static int ubicom32hid_remove(struct i2c_client *client)
507{
508    struct ubicom32hid_data *ud =
509        (struct ubicom32hid_data *)platform_get_drvdata(client);
510
511    gpio_free(ud->pdata->gpio_reset);
512
513    backlight_device_unregister(ud->bldev);
514
515    if (ud->poll_dev) {
516        input_unregister_polled_device(ud->poll_dev);
517        input_free_polled_device(ud->poll_dev);
518    }
519
520    platform_set_drvdata(client, NULL);
521
522    kfree(ud);
523
524    return 0;
525}
526
527static struct i2c_driver ubicom32hid_driver = {
528    .driver = {
529        .name = DRIVER_NAME,
530        .owner = THIS_MODULE,
531    },
532    .probe = ubicom32hid_probe,
533    .remove = __exit_p(ubicom32hid_remove),
534    .id_table = ubicom32hid_id,
535};
536
537/*
538 * ubicom32hid_init
539 */
540static int __init ubicom32hid_init(void)
541{
542    return i2c_add_driver(&ubicom32hid_driver);
543}
544module_init(ubicom32hid_init);
545
546/*
547 * ubicom32hid_exit
548 */
549static void __exit ubicom32hid_exit(void)
550{
551    i2c_del_driver(&ubicom32hid_driver);
552}
553module_exit(ubicom32hid_exit);
554
555MODULE_AUTHOR("Pat Tjin <@ubicom.com>")
556MODULE_DESCRIPTION("Ubicom HID driver");
557MODULE_LICENSE("GPL");
558

Archive Download this file



interactive