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