linux/drivers/media/rc/img-ir/img-ir-rc6.c
<<
>>
Prefs
   1/*
   2 * ImgTec IR Decoder setup for Philips RC-6 protocol.
   3 *
   4 * Copyright 2012-2014 Imagination Technologies Ltd.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by the
   8 * Free Software Foundation; either version 2 of the License, or (at your
   9 * option) any later version.
  10 */
  11
  12#include "img-ir-hw.h"
  13
  14/* Convert RC6 data to a scancode */
  15static int img_ir_rc6_scancode(int len, u64 raw, u64 enabled_protocols,
  16                                struct img_ir_scancode_req *request)
  17{
  18        unsigned int addr, cmd, mode, trl1, trl2;
  19
  20        /*
  21         * Due to a side effect of the decoder handling the double length
  22         * Trailer bit, the header information is a bit scrambled, and the
  23         * raw data is shifted incorrectly.
  24         * This workaround effectively recovers the header bits.
  25         *
  26         * The Header field should look like this:
  27         *
  28         * StartBit ModeBit2 ModeBit1 ModeBit0 TrailerBit
  29         *
  30         * But what we get is:
  31         *
  32         * ModeBit2 ModeBit1 ModeBit0 TrailerBit1 TrailerBit2
  33         *
  34         * The start bit is not important to recover the scancode.
  35         */
  36
  37        raw     >>= 27;
  38
  39        trl1    = (raw >>  17)  & 0x01;
  40        trl2    = (raw >>  16)  & 0x01;
  41
  42        mode    = (raw >>  18)  & 0x07;
  43        addr    = (raw >>   8)  & 0xff;
  44        cmd     =  raw          & 0xff;
  45
  46        /*
  47         * Due to the above explained irregularity the trailer bits cannot
  48         * have the same value.
  49         */
  50        if (trl1 == trl2)
  51                return -EINVAL;
  52
  53        /* Only mode 0 supported for now */
  54        if (mode)
  55                return -EINVAL;
  56
  57        request->protocol = RC_TYPE_RC6_0;
  58        request->scancode = addr << 8 | cmd;
  59        request->toggle   = trl2;
  60        return IMG_IR_SCANCODE;
  61}
  62
  63/* Convert RC6 scancode to RC6 data filter */
  64static int img_ir_rc6_filter(const struct rc_scancode_filter *in,
  65                                 struct img_ir_filter *out, u64 protocols)
  66{
  67        /* Not supported by the hw. */
  68        return -EINVAL;
  69}
  70
  71/*
  72 * RC-6 decoder
  73 * see http://www.sbprojects.com/knowledge/ir/rc6.php
  74 */
  75struct img_ir_decoder img_ir_rc6 = {
  76        .type           = RC_BIT_RC6_0,
  77        .control        = {
  78                .bitorien       = 1,
  79                .code_type      = IMG_IR_CODETYPE_BIPHASE,
  80                .decoden        = 1,
  81                .decodinpol     = 1,
  82        },
  83        /* main timings */
  84        .tolerance      = 20,
  85        /*
  86         * Due to a quirk in the img-ir decoder, default header values do
  87         * not work, the values described below were extracted from
  88         * successful RTL test cases.
  89         */
  90        .timings        = {
  91                /* leader symbol */
  92                .ldr = {
  93                        .pulse  = { 650 },
  94                        .space  = { 660 },
  95                },
  96                /* 0 symbol */
  97                .s00 = {
  98                        .pulse  = { 370 },
  99                        .space  = { 370 },
 100                },
 101                /* 01 symbol */
 102                .s01 = {
 103                        .pulse  = { 370 },
 104                        .space  = { 370 },
 105                },
 106                /* free time */
 107                .ft  = {
 108                        .minlen = 21,
 109                        .maxlen = 21,
 110                        .ft_min = 2666, /* 2.666 ms */
 111                },
 112        },
 113
 114        /* scancode logic */
 115        .scancode       = img_ir_rc6_scancode,
 116        .filter         = img_ir_rc6_filter,
 117};
 118