Merge branch 'msm-video' of git://codeaurora.org/quic/kernel/dwalker/linux-msm
[pandora-kernel.git] / drivers / media / dvb / siano / smsir.c
index a56eac7..d0e4639 100644 (file)
@@ -4,6 +4,11 @@
  MDTV receiver kernel modules.
  Copyright (C) 2006-2009, Uri Shkolnik
 
+ Copyright (c) 2010 - Mauro Carvalho Chehab
+       - Ported the driver to use rc-core
+       - IR raw event decoding is now done at rc-core
+       - Code almost re-written
+
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 2 of the License, or
 #include "smsir.h"
 #include "sms-cards.h"
 
-/* In order to add new IR remote control -
- * 1) Add it to the <enum ir_kb_type> @ smsir,h,
- * 2) Add its map to keyboard_layout_maps below
- * 3) Set your board (sms-cards sub-module) to use it
- */
-
-static struct keyboard_layout_map_t keyboard_layout_maps[] = {
-               [SMS_IR_KB_DEFAULT_TV] = {
-                       .ir_protocol = IR_RC5,
-                       .rc5_kbd_address = KEYBOARD_ADDRESS_TV1,
-                       .keyboard_layout_map = {
-                                       KEY_0, KEY_1, KEY_2,
-                                       KEY_3, KEY_4, KEY_5,
-                                       KEY_6, KEY_7, KEY_8,
-                                       KEY_9, 0, 0, KEY_POWER,
-                                       KEY_MUTE, 0, 0,
-                                       KEY_VOLUMEUP, KEY_VOLUMEDOWN,
-                                       KEY_BRIGHTNESSUP,
-                                       KEY_BRIGHTNESSDOWN, KEY_CHANNELUP,
-                                       KEY_CHANNELDOWN,
-                                       0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-                       }
-               },
-               [SMS_IR_KB_HCW_SILVER] = {
-                       .ir_protocol = IR_RC5,
-                       .rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1,
-                       .keyboard_layout_map = {
-                                       KEY_0, KEY_1, KEY_2,
-                                       KEY_3, KEY_4, KEY_5,
-                                       KEY_6, KEY_7, KEY_8,
-                                       KEY_9, KEY_TEXT, KEY_RED,
-                                       KEY_RADIO, KEY_MENU,
-                                       KEY_SUBTITLE,
-                                       KEY_MUTE, KEY_VOLUMEUP,
-                                       KEY_VOLUMEDOWN, KEY_PREVIOUS, 0,
-                                       KEY_UP, KEY_DOWN, KEY_LEFT,
-                                       KEY_RIGHT, KEY_VIDEO, KEY_AUDIO,
-                                       KEY_MHP, KEY_EPG, KEY_TV,
-                                       0, KEY_NEXTSONG, KEY_EXIT,
-                                       KEY_CHANNELUP,  KEY_CHANNELDOWN,
-                                       KEY_CHANNEL, 0,
-                                       KEY_PREVIOUSSONG, KEY_ENTER,
-                                       KEY_SLEEP, 0, 0, KEY_BLUE,
-                                       0, 0, 0, 0, KEY_GREEN, 0,
-                                       KEY_PAUSE, 0, KEY_REWIND,
-                                       0, KEY_FASTFORWARD, KEY_PLAY,
-                                       KEY_STOP, KEY_RECORD,
-                                       KEY_YELLOW, 0, 0, KEY_SELECT,
-                                       KEY_ZOOM, KEY_POWER, 0, 0
-                       }
-               },
-               { } /* Terminating entry */
-};
-
-static u32 ir_pos;
-static u32 ir_word;
-static u32 ir_toggle;
-
-#define RC5_PUSH_BIT(dst, bit, pos)    \
-       { dst <<= 1; dst |= bit; pos++; }
-
-
-static void sms_ir_rc5_event(struct smscore_device_t *coredev,
-                               u32 toggle, u32 addr, u32 cmd)
-{
-       bool toggle_changed;
-       u16 keycode;
-
-       sms_log("IR RC5 word: address %d, command %d, toggle %d",
-                               addr, cmd, toggle);
-
-       toggle_changed = ir_toggle != toggle;
-       /* keep toggle */
-       ir_toggle = toggle;
-
-       if (addr !=
-               keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address)
-               return; /* Check for valid address */
-
-       keycode =
-               keyboard_layout_maps
-               [coredev->ir.ir_kb_type].keyboard_layout_map[cmd];
+#define MODULE_NAME "smsmdtv"
 
-       if (!toggle_changed &&
-                       (keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN))
-               return; /* accept only repeated volume, reject other keys */
-
-       sms_log("kernel input keycode (from ir) %d", keycode);
-       input_report_key(coredev->ir.input_dev, keycode, 1);
-       input_sync(coredev->ir.input_dev);
-
-}
-
-/* decode raw bit pattern to RC5 code */
-/* taken from ir-functions.c */
-static u32 ir_rc5_decode(unsigned int code)
+void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
 {
-/*     unsigned int org_code = code;*/
-       unsigned int pair;
-       unsigned int rc5 = 0;
        int i;
+       const s32 *samples = (const void *)buf;
 
-       for (i = 0; i < 14; ++i) {
-               pair = code & 0x3;
-               code >>= 2;
-
-               rc5 <<= 1;
-               switch (pair) {
-               case 0:
-               case 2:
-                       break;
-               case 1:
-                       rc5 |= 1;
-                       break;
-               case 3:
-/*     dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/
-                       sms_log("bad code");
-                       return 0;
-               }
-       }
-/*
-       dprintk(1, "ir-common: code=%x, rc5=%x, start=%x,
-               toggle=%x, address=%x, "
-               "instr=%x\n", rc5, org_code, RC5_START(rc5),
-               RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
-*/
-       return rc5;
-}
-
-static void sms_rc5_parse_word(struct smscore_device_t *coredev)
-{
-       #define RC5_START(x)    (((x)>>12)&3)
-       #define RC5_TOGGLE(x)   (((x)>>11)&1)
-       #define RC5_ADDR(x)     (((x)>>6)&0x1F)
-       #define RC5_INSTR(x)    ((x)&0x3F)
-
-       int i, j;
-       u32 rc5_word = 0;
-
-       /* Reverse the IR word direction */
-       for (i = 0 ; i < 28 ; i++)
-               RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j)
-
-       rc5_word = ir_rc5_decode(rc5_word);
-       /* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */
-
-       sms_ir_rc5_event(coredev,
-                               RC5_TOGGLE(rc5_word),
-                               RC5_ADDR(rc5_word),
-                               RC5_INSTR(rc5_word));
-}
-
-
-static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev,
-               s32 ir_sample)
-{
-       #define RC5_TIME_GRANULARITY    200
-       #define RC5_DEF_BIT_TIME                889
-       #define RC5_MAX_SAME_BIT_CONT   4
-       #define RC5_WORD_LEN                    27 /* 28 bit */
-
-       u32 i, j;
-       s32 delta_time;
-       u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample);
-       u32 level = (ir_sample < 0) ? 0 : 1;
-
-       for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) {
-               delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY;
-               if (delta_time < 0)
-                       continue; /* not so many consecutive bits */
-               if (delta_time > (2 * RC5_TIME_GRANULARITY)) {
-                       /* timeout */
-                       if (ir_pos == (RC5_WORD_LEN-1))
-                               /* complete last bit */
-                               RC5_PUSH_BIT(ir_word, level, ir_pos)
-
-                       if (ir_pos == RC5_WORD_LEN)
-                               sms_rc5_parse_word(coredev);
-                       else if (ir_pos) /* timeout within a word */
-                               sms_log("IR error parsing a word");
+       for (i = 0; i < len >> 2; i++) {
+               struct ir_raw_event ev;
 
-                       ir_pos = 0;
-                       ir_word = 0;
-                       /* sms_log("timeout %d", time); */
-                       break;
-               }
-               /* The time is within the range of this number of bits */
-               for (j = 0 ; j < i ; j++)
-                       RC5_PUSH_BIT(ir_word, level, ir_pos)
+               ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
+               ev.pulse = (samples[i] > 0) ? false : true;
 
-               break;
+               ir_raw_event_store(coredev->ir.input_dev, &ev);
        }
-}
-
-void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
-{
-       #define IR_DATA_RECEIVE_MAX_LEN 520 /* 128*4 + 4 + 4 */
-       u32 i;
-       enum ir_protocol ir_protocol =
-                       keyboard_layout_maps[coredev->ir.ir_kb_type]
-                                            .ir_protocol;
-       s32 *samples;
-       int count = len>>2;
-
-       samples = (s32 *)buf;
-/*     sms_log("IR buffer received, length = %d", count);*/
-
-       for (i = 0; i < count; i++)
-               if (ir_protocol == IR_RC5)
-                       sms_rc5_accumulate_bits(coredev, samples[i]);
-       /*  IR_RCMM not implemented */
+       ir_raw_event_handle(coredev->ir.input_dev);
 }
 
 int sms_ir_init(struct smscore_device_t *coredev)
 {
        struct input_dev *input_dev;
+       int board_id = smscore_get_board_id(coredev);
 
        sms_log("Allocating input device");
        input_dev = input_allocate_device();
@@ -256,33 +63,38 @@ int sms_ir_init(struct smscore_device_t *coredev)
        }
 
        coredev->ir.input_dev = input_dev;
-       coredev->ir.ir_kb_type =
-               sms_get_board(smscore_get_board_id(coredev))->ir_kb_type;
-       coredev->ir.keyboard_layout_map =
-               keyboard_layout_maps[coredev->ir.ir_kb_type].
-                               keyboard_layout_map;
-       sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type);
 
        coredev->ir.controller = 0;     /* Todo: vega/nova SPI number */
        coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
        sms_log("IR port %d, timeout %d ms",
                        coredev->ir.controller, coredev->ir.timeout);
 
-       snprintf(coredev->ir.name,
-                               IR_DEV_NAME_MAX_LEN,
-                               "SMS IR w/kbd type %d",
-                               coredev->ir.ir_kb_type);
+       snprintf(coredev->ir.name, sizeof(coredev->ir.name),
+                "SMS IR (%s)", sms_get_board(board_id)->name);
+
+       strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
+       strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
+
        input_dev->name = coredev->ir.name;
-       input_dev->phys = coredev->ir.name;
+       input_dev->phys = coredev->ir.phys;
        input_dev->dev.parent = coredev->device;
 
-       /* Key press events only */
-       input_dev->evbit[0] = BIT_MASK(EV_KEY);
-       input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+#if 0
+       /* TODO: properly initialize the parameters bellow */
+       input_dev->id.bustype = BUS_USB;
+       input_dev->id.version = 1;
+       input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+       input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+#endif
+
+       coredev->ir.props.priv = coredev;
+       coredev->ir.props.driver_type = RC_DRIVER_IR_RAW;
+       coredev->ir.props.allowed_protos = IR_TYPE_ALL;
 
        sms_log("Input device (IR) %s is set for key events", input_dev->name);
 
-       if (input_register_device(input_dev)) {
+       if (ir_input_register(input_dev, sms_get_board(board_id)->rc_codes,
+                             &coredev->ir.props, MODULE_NAME)) {
                sms_err("Failed to register device");
                input_free_device(input_dev);
                return -EACCES;
@@ -294,8 +106,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
 void sms_ir_exit(struct smscore_device_t *coredev)
 {
        if (coredev->ir.input_dev)
-               input_unregister_device(coredev->ir.input_dev);
+               ir_input_unregister(coredev->ir.input_dev);
 
        sms_log("");
 }
-