Linux-libre 3.16.85-gnu
[librecmc/linux-libre.git] / drivers / media / rc / img-ir / img-ir-sanyo.c
1 /*
2  * ImgTec IR Decoder setup for Sanyo protocol.
3  *
4  * Copyright 2012-2014 Imagination Technologies Ltd.
5  *
6  * From ir-sanyo-decoder.c:
7  *
8  * This protocol uses the NEC protocol timings. However, data is formatted as:
9  *      13 bits Custom Code
10  *      13 bits NOT(Custom Code)
11  *      8 bits Key data
12  *      8 bits NOT(Key data)
13  *
14  * According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon
15  * Information for this protocol is available at the Sanyo LC7461 datasheet.
16  */
17
18 #include "img-ir-hw.h"
19
20 /* Convert Sanyo data to a scancode */
21 static int img_ir_sanyo_scancode(int len, u64 raw, int *scancode, u64 protocols)
22 {
23         unsigned int addr, addr_inv, data, data_inv;
24         /* a repeat code has no data */
25         if (!len)
26                 return IMG_IR_REPEATCODE;
27         if (len != 42)
28                 return -EINVAL;
29         addr     = (raw >>  0) & 0x1fff;
30         addr_inv = (raw >> 13) & 0x1fff;
31         data     = (raw >> 26) & 0xff;
32         data_inv = (raw >> 34) & 0xff;
33         /* Validate data */
34         if ((data_inv ^ data) != 0xff)
35                 return -EINVAL;
36         /* Validate address */
37         if ((addr_inv ^ addr) != 0x1fff)
38                 return -EINVAL;
39
40         /* Normal Sanyo */
41         *scancode = addr << 8 | data;
42         return IMG_IR_SCANCODE;
43 }
44
45 /* Convert Sanyo scancode to Sanyo data filter */
46 static int img_ir_sanyo_filter(const struct rc_scancode_filter *in,
47                                struct img_ir_filter *out, u64 protocols)
48 {
49         unsigned int addr, addr_inv, data, data_inv;
50         unsigned int addr_m, data_m;
51
52         data = in->data & 0xff;
53         data_m = in->mask & 0xff;
54         data_inv = data ^ 0xff;
55
56         if (in->data & 0xff700000)
57                 return -EINVAL;
58
59         addr       = (in->data >> 8) & 0x1fff;
60         addr_m     = (in->mask >> 8) & 0x1fff;
61         addr_inv   = addr ^ 0x1fff;
62
63         out->data = (u64)data_inv << 34 |
64                     (u64)data     << 26 |
65                          addr_inv << 13 |
66                          addr;
67         out->mask = (u64)data_m << 34 |
68                     (u64)data_m << 26 |
69                          addr_m << 13 |
70                          addr_m;
71         return 0;
72 }
73
74 /* Sanyo decoder */
75 struct img_ir_decoder img_ir_sanyo = {
76         .type = RC_BIT_SANYO,
77         .control = {
78                 .decoden = 1,
79                 .code_type = IMG_IR_CODETYPE_PULSEDIST,
80         },
81         /* main timings */
82         .unit = 562500, /* 562.5 us */
83         .timings = {
84                 /* leader symbol */
85                 .ldr = {
86                         .pulse = { 16   /* 9ms */ },
87                         .space = { 8    /* 4.5ms */ },
88                 },
89                 /* 0 symbol */
90                 .s00 = {
91                         .pulse = { 1    /* 562.5 us */ },
92                         .space = { 1    /* 562.5 us */ },
93                 },
94                 /* 1 symbol */
95                 .s01 = {
96                         .pulse = { 1    /* 562.5 us */ },
97                         .space = { 3    /* 1687.5 us */ },
98                 },
99                 /* free time */
100                 .ft = {
101                         .minlen = 42,
102                         .maxlen = 42,
103                         .ft_min = 10,   /* 5.625 ms */
104                 },
105         },
106         /* repeat codes */
107         .repeat = 108,                  /* 108 ms */
108         .rtimings = {
109                 /* leader symbol */
110                 .ldr = {
111                         .space = { 4    /* 2.25 ms */ },
112                 },
113                 /* free time */
114                 .ft = {
115                         .minlen = 0,    /* repeat code has no data */
116                         .maxlen = 0,
117                 },
118         },
119         /* scancode logic */
120         .scancode = img_ir_sanyo_scancode,
121         .filter = img_ir_sanyo_filter,
122 };