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