> I'm attaching a test patch for "1" and "3". It's incomplete, breaks
> bttv, but it currently works with my Philips RC and Super 007 DVB-T
> board.

Well, the patch (against 2.6.30):

--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/common/ir-functions.c
@@ -260,47 +260,12 @@ int ir_decode_biphase(u32 *samples, int count, int low, 
int high)
 }
 EXPORT_SYMBOL_GPL(ir_decode_biphase);
 
-/* RC5 decoding stuff, moved from bttv-input.c to share it with
- * saa7134 */
-
-/* decode raw bit pattern to RC5 code */
-static u32 ir_rc5_decode(unsigned int code)
-{
-       unsigned int org_code = code;
-       unsigned int pair;
-       unsigned int rc5 = 0;
-       int i;
-
-       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);
-                       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;
-}
-
 void ir_rc5_timer_end(unsigned long data)
 {
        struct card_ir *ir = (struct card_ir *)data;
        struct timeval tv;
        unsigned long current_jiffies, timeout;
        u32 gap;
-       u32 rc5 = 0;
 
        /* get time */
        current_jiffies = jiffies;
@@ -317,46 +282,46 @@ void ir_rc5_timer_end(unsigned long data)
        /* signal we're ready to start a new code */
        ir->active = 0;
 
-       /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
-       if (gap < 28000) {
-               dprintk(1, "ir-common: spurious timer_end\n");
+       if (ir->last_bit == 1 && (ir->code & 2))
+               ir->last_bit--; /* bit1: 1 -> bit0: 0 doesn't generate an IRQ */
+
+       if (ir->last_bit) {
+               /* ignore spurious codes (caused by light/other remotes) */
+               dprintk(1, "ir-common: short code: %X\n", ir->code);
                return;
        }
 
-       if (ir->last_bit < 20) {
-               /* ignore spurious codes (caused by light/other remotes) */
-               dprintk(1, "ir-common: short code: %x\n", ir->code);
-       } else {
-               ir->code = (ir->code << ir->shift_by) | 1;
-               rc5 = ir_rc5_decode(ir->code);
-
-               /* two start bits? */
-               if (RC5_START(rc5) != ir->start) {
-                       dprintk(1, "ir-common: rc5 start bits invalid: %u\n", 
RC5_START(rc5));
-
-                       /* right address? */
-               } else if (RC5_ADDR(rc5) == ir->addr) {
-                       u32 toggle = RC5_TOGGLE(rc5);
-                       u32 instr = RC5_INSTR(rc5);
-
-                       /* Good code, decide if repeat/repress */
-                       if (toggle != RC5_TOGGLE(ir->last_rc5) ||
-                           instr != RC5_INSTR(ir->last_rc5)) {
-                               dprintk(1, "ir-common: instruction %x, toggle 
%x\n", instr,
-                                       toggle);
-                               ir_input_nokey(ir->dev, &ir->ir);
-                               ir_input_keydown(ir->dev, &ir->ir, instr,
-                                                instr);
-                       }
+       //ir->code = (ir->code << ir->shift_by) | 1; /* FIXME check bttv */
 
-                       /* Set/reset key-up timer */
-                       timeout = current_jiffies +
-                                 msecs_to_jiffies(ir->rc5_key_timeout);
-                       mod_timer(&ir->timer_keyup, timeout);
+       if (!RC5_ADDR(ir->code)) {
+               dprintk(1, "ir-common: bad RC5 code 0x%x\n", ir->code);
+               return;
+       }
 
-                       /* Save code for repeat test */
-                       ir->last_rc5 = rc5;
+       dprintk(1, "ir-common: rc5=0x%X, toggle=0x%X, address=0x%X, instr=%x\n",
+               ir->code, RC5_TOGGLE(ir->code), RC5_ADDR(ir->code),
+               RC5_INSTR(ir->code));
+
+       if (RC5_ADDR(ir->code) == ir->addr) {
+               u32 toggle = RC5_TOGGLE(ir->code);
+               u32 instr = RC5_INSTR(ir->code);
+
+               /* Good code, decide if repeat/repress */
+               if (toggle != RC5_TOGGLE(ir->last_rc5) ||
+                   instr != RC5_INSTR(ir->last_rc5)) {
+                       dprintk(1, "ir-common: instruction %x, toggle %x\n",
+                               instr, toggle);
+                       ir_input_nokey(ir->dev, &ir->ir);
+                       ir_input_keydown(ir->dev, &ir->ir, instr, instr);
                }
+
+               /* Set/reset key-up timer */
+               timeout = current_jiffies +
+                       msecs_to_jiffies(ir->rc5_key_timeout);
+               mod_timer(&ir->timer_keyup, timeout);
+
+               /* Save code for repeat test */
+               ir->last_rc5 = ir->code;
        }
 }
 EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -1487,6 +1487,53 @@ IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_pv951);
 
+/*
+  Philips RC2592 with MODE pressed, used by Philips TV sets
+  RC5 group = 8, commands are 7-bit wide (1 start bit)
+*/
+IR_KEYTAB_TYPE ir_codes_rc2592_sat[IR_KEYTAB_SIZE] = {
+       [ 0x00 ] = KEY_0,
+       [ 0x01 ] = KEY_1,
+       [ 0x02 ] = KEY_2,
+       [ 0x03 ] = KEY_3,
+       [ 0x04 ] = KEY_4,
+       [ 0x05 ] = KEY_5,
+       [ 0x06 ] = KEY_6,
+       [ 0x07 ] = KEY_7,
+       [ 0x08 ] = KEY_8,
+       [ 0x09 ] = KEY_9,
+
+       [ 0x0C ] = KEY_SUSPEND,
+
+       [ 0x6B ] = KEY_RED,
+       [ 0x6C ] = KEY_GREEN,
+       [ 0x6D ] = KEY_YELLOW,
+       [ 0x6E ] = KEY_BLUE,
+       [ 0x6F ] = KEY_OPTION,          /* white */
+
+       [ 0x2A ] = KEY_TIME,
+       [ 0x2C ] = KEY_QUESTION,
+       [ 0x2B ] = KEY_ZOOM,
+       [ 0x3C ] = KEY_TEXT,
+
+       [ 0x52 ] = KEY_MENU,
+       [ 0x57 ] = KEY_OK,
+       [ 0x50 ] = KEY_UP,
+       [ 0x51 ] = KEY_DOWN,
+       [ 0x55 ] = KEY_LEFT,
+       [ 0x56 ] = KEY_RIGHT,
+
+       [ 0x20 ] = KEY_CHANNELUP,
+       [ 0x21 ] = KEY_CHANNELDOWN,
+
+       [ 0x0F ] = KEY_INFO,            /* i+ */
+       [ 0x22 ] = KEY_PREVIOUS,        /* P<P */
+       [ 0x23 ] = KEY_LANGUAGE,        /* I-II */
+       [ 0x38 ] = KEY_SUBTITLE         /* [1][2] */
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_rc2592_sat);
+
 /* generic RC5 keytable                                          */
 /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */
 /* used by old (black) Hauppauge remotes                         */
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -6105,6 +6105,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_AVERMEDIA_307:
        case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
        case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
+       case SAA7134_BOARD_AVERMEDIA_SUPER_007:
        case SAA7134_BOARD_AVERMEDIA_777:
        case SAA7134_BOARD_AVERMEDIA_M135A:
 /*      case SAA7134_BOARD_SABRENT_SBTTVFM:  */ /* not finished yet */
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -695,9 +695,9 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev)
        if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) {
                if (dev->remote->mask_keydown & 0x10000)
                        irq2_mask |= SAA7134_IRQ2_INTE_GPIO16;
-               else if (dev->remote->mask_keydown & 0x40000)
+               if (dev->remote->mask_keydown & 0x40000)
                        irq2_mask |= SAA7134_IRQ2_INTE_GPIO18;
-               else if (dev->remote->mask_keyup & 0x40000)
+               if (dev->remote->mask_keyup & 0x40000)
                        irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A;
        }
 
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -374,7 +374,6 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct 
card_ir *ir)
                ir->timer_keyup.data = (unsigned long)ir;
                ir->shift_by = 2;
                ir->start = 0x2;
-               ir->addr = 0x17;
                ir->rc5_key_timeout = ir_rc5_key_timeout;
                ir->rc5_remote_gap = ir_rc5_remote_gap;
        } else if (ir->nec_gpio) {
@@ -402,6 +401,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        int rc5_gpio     = 0;
        int nec_gpio     = 0;
        int ir_type      = IR_TYPE_OTHER;
+       int addr         = 0;
        int err;
 
        if (dev->has_remote != SAA7134_REMOTE_GPIO)
@@ -483,6 +483,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
                saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
                break;
+       case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+               ir_codes     = ir_codes_rc2592_sat;
+               addr         = 8;
+               mask_keyup   = 0x40000;
+               rc5_gpio     = 1;
+               break;
        case SAA7134_BOARD_KWORLD_TERMINATOR:
                ir_codes     = ir_codes_pixelview;
                mask_keycode = 0x00001f;
@@ -562,6 +568,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
        case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
                ir_codes     = ir_codes_asus_pc39;
+               addr         = 0x17;
                mask_keydown = 0x0040000;
                rc5_gpio = 1;
                break;
@@ -623,6 +630,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        ir->mask_keyup   = mask_keyup;
        ir->polling      = polling;
        ir->rc5_gpio     = rc5_gpio;
+       ir->addr         = addr;
        ir->nec_gpio     = nec_gpio;
 
        /* init input device */
@@ -748,26 +756,60 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev)
                    tv.tv_usec - ir->base_time.tv_usec;
        }
 
+       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+       saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
+       printk(KERN_DEBUG "rc5 irq: %lu %lu %u gap %u\n", tv.tv_sec, tv.tv_usec,
+              (saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) / 0x40000) & 1, gap);
+
        /* active code => add bit */
        if (ir->active) {
                /* only if in the code (otherwise spurious IRQ or timer
                   late) */
-               if (ir->last_bit < 28) {
-                       ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
-                           ir_rc5_remote_gap;
-                       ir->code |= 1 << ir->last_bit;
+               gap = (gap + ir_rc5_remote_gap / 2) / ir_rc5_remote_gap;
+               if (ir->last_bit && ir->code) {
+                       u32 last = ir->code >> ir->last_bit;
+
+                       printk(KERN_DEBUG "RC5 gap %u last %X last_bit %u code "
+                              "0x%X\n", gap, last, ir->last_bit, ir->code);
+
+                       if ((last & 1) == 1) {
+                               if (gap == 2)           /* 1 -> 1 */
+                                       ir->code |= 1 << --ir->last_bit;
+                               else if (gap == 3)      /* 1 -> 00 */
+                                       ir->last_bit -= 2;
+                               else if (gap == 4)      /* 1 -> 01 */
+                                       ir->code |= 1 << (ir->last_bit -= 2);
+                               else
+                                       goto invalid;
+                       } else if ((last & 3) == 0) {
+                               if (gap == 2)           /* 00 -> 0 */
+                                       ir->last_bit--;
+                               else if (gap == 3)      /* 00 -> 1 */
+                                       ir->code |= 1 << --ir->last_bit;
+                               else
+                                       goto invalid;
+                       } else
+                               goto invalid;
+
+                       printk(KERN_DEBUG "RC5: last_bit %u, code 0x%X\n",
+                              ir->last_bit, ir->code);
                }
                /* starting new code */
        } else {
                ir->active = 1;
-               ir->code = 0;
-               ir->base_time = tv;
-               ir->last_bit = 0;
+               ir->code = 0x2000; /* start bit is always '1' */
+               ir->last_bit = 13;
 
                timeout = current_jiffies + (500 + 30 * HZ) / 1000;
                mod_timer(&ir->timer_end, timeout);
        }
 
+       ir->base_time = tv;
+       return 1;
+
+invalid:
+       ir->code = 0; /* mark as invalid */
        return 1;
 }
 
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -37,10 +37,10 @@
 #define IR_KEYCODE(tab,code)   (((unsigned)code < IR_KEYTAB_SIZE) \
                                 ? tab[code] : KEY_RESERVED)
 
-#define RC5_START(x)   (((x)>>12)&3)
+#define RC5_START(x)   (((x) >> 13) & 1)
 #define RC5_TOGGLE(x)  (((x)>>11)&1)
 #define RC5_ADDR(x)    (((x)>>6)&31)
-#define RC5_INSTR(x)   ((x)&63)
+#define RC5_INSTR(x)   ((((~(x)) >> 6) & 0x40) | ((x) & 0x3F))
 
 struct ir_input_state {
        /* configuration */
@@ -136,6 +136,7 @@ extern IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_rc2592_sat[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE];

-- 
Krzysztof Halasa
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to