12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e72b21abSJames Hogan /*
3e72b21abSJames Hogan * ImgTec IR Decoder setup for Sony (SIRC) protocol.
4e72b21abSJames Hogan *
5e72b21abSJames Hogan * Copyright 2012-2014 Imagination Technologies Ltd.
6e72b21abSJames Hogan */
7e72b21abSJames Hogan
8e72b21abSJames Hogan #include "img-ir-hw.h"
9e72b21abSJames Hogan
10e72b21abSJames Hogan /* Convert Sony data to a scancode */
img_ir_sony_scancode(int len,u64 raw,u64 enabled_protocols,struct img_ir_scancode_req * request)11ab93ce06SSifan Naeem static int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols,
12ab93ce06SSifan Naeem struct img_ir_scancode_req *request)
13e72b21abSJames Hogan {
14e72b21abSJames Hogan unsigned int dev, subdev, func;
15e72b21abSJames Hogan
16e72b21abSJames Hogan switch (len) {
17e72b21abSJames Hogan case 12:
186d741bfeSSean Young if (!(enabled_protocols & RC_PROTO_BIT_SONY12))
19e72b21abSJames Hogan return -EINVAL;
20e72b21abSJames Hogan func = raw & 0x7f; /* first 7 bits */
21e72b21abSJames Hogan raw >>= 7;
22e72b21abSJames Hogan dev = raw & 0x1f; /* next 5 bits */
23e72b21abSJames Hogan subdev = 0;
246d741bfeSSean Young request->protocol = RC_PROTO_SONY12;
25e72b21abSJames Hogan break;
26e72b21abSJames Hogan case 15:
276d741bfeSSean Young if (!(enabled_protocols & RC_PROTO_BIT_SONY15))
28e72b21abSJames Hogan return -EINVAL;
29e72b21abSJames Hogan func = raw & 0x7f; /* first 7 bits */
30e72b21abSJames Hogan raw >>= 7;
31e72b21abSJames Hogan dev = raw & 0xff; /* next 8 bits */
32e72b21abSJames Hogan subdev = 0;
336d741bfeSSean Young request->protocol = RC_PROTO_SONY15;
34e72b21abSJames Hogan break;
35e72b21abSJames Hogan case 20:
366d741bfeSSean Young if (!(enabled_protocols & RC_PROTO_BIT_SONY20))
37e72b21abSJames Hogan return -EINVAL;
38e72b21abSJames Hogan func = raw & 0x7f; /* first 7 bits */
39e72b21abSJames Hogan raw >>= 7;
40e72b21abSJames Hogan dev = raw & 0x1f; /* next 5 bits */
41e72b21abSJames Hogan raw >>= 5;
42e72b21abSJames Hogan subdev = raw & 0xff; /* next 8 bits */
436d741bfeSSean Young request->protocol = RC_PROTO_SONY20;
44e72b21abSJames Hogan break;
45e72b21abSJames Hogan default:
46e72b21abSJames Hogan return -EINVAL;
47e72b21abSJames Hogan }
48ab93ce06SSifan Naeem request->scancode = dev << 16 | subdev << 8 | func;
49e72b21abSJames Hogan return IMG_IR_SCANCODE;
50e72b21abSJames Hogan }
51e72b21abSJames Hogan
52e72b21abSJames Hogan /* Convert NEC scancode to NEC data filter */
img_ir_sony_filter(const struct rc_scancode_filter * in,struct img_ir_filter * out,u64 protocols)53e72b21abSJames Hogan static int img_ir_sony_filter(const struct rc_scancode_filter *in,
54e72b21abSJames Hogan struct img_ir_filter *out, u64 protocols)
55e72b21abSJames Hogan {
56e72b21abSJames Hogan unsigned int dev, subdev, func;
57e72b21abSJames Hogan unsigned int dev_m, subdev_m, func_m;
58e72b21abSJames Hogan unsigned int len = 0;
59e72b21abSJames Hogan
60e72b21abSJames Hogan dev = (in->data >> 16) & 0xff;
61e72b21abSJames Hogan dev_m = (in->mask >> 16) & 0xff;
62e72b21abSJames Hogan subdev = (in->data >> 8) & 0xff;
63e72b21abSJames Hogan subdev_m = (in->mask >> 8) & 0xff;
64e72b21abSJames Hogan func = (in->data >> 0) & 0x7f;
65e72b21abSJames Hogan func_m = (in->mask >> 0) & 0x7f;
66e72b21abSJames Hogan
676d741bfeSSean Young protocols &= RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 |
686d741bfeSSean Young RC_PROTO_BIT_SONY20;
690751d33cSSean Young
700751d33cSSean Young /*
710751d33cSSean Young * If only one bit is set, we were requested to do an exact
720751d33cSSean Young * protocol. This should be the case for wakeup filters; for
730751d33cSSean Young * normal filters, guess the protocol from the scancode.
740751d33cSSean Young */
750751d33cSSean Young if (!is_power_of_2(protocols)) {
760751d33cSSean Young if (subdev & subdev_m)
776d741bfeSSean Young protocols = RC_PROTO_BIT_SONY20;
780751d33cSSean Young else if (dev & dev_m & 0xe0)
796d741bfeSSean Young protocols = RC_PROTO_BIT_SONY15;
800751d33cSSean Young else
816d741bfeSSean Young protocols = RC_PROTO_BIT_SONY12;
820751d33cSSean Young }
830751d33cSSean Young
846d741bfeSSean Young if (protocols == RC_PROTO_BIT_SONY20) {
85e72b21abSJames Hogan /* can't encode subdev and higher device bits */
86e72b21abSJames Hogan if (dev & dev_m & 0xe0)
87e72b21abSJames Hogan return -EINVAL;
88e72b21abSJames Hogan len = 20;
89e72b21abSJames Hogan dev_m &= 0x1f;
906d741bfeSSean Young } else if (protocols == RC_PROTO_BIT_SONY15) {
91e72b21abSJames Hogan len = 15;
92e72b21abSJames Hogan subdev_m = 0;
93e72b21abSJames Hogan } else {
94e72b21abSJames Hogan /*
95e72b21abSJames Hogan * The hardware mask cannot distinguish high device bits and low
96e72b21abSJames Hogan * extended bits, so logically AND those bits of the masks
97e72b21abSJames Hogan * together.
98e72b21abSJames Hogan */
99e72b21abSJames Hogan subdev_m &= (dev_m >> 5) | 0xf8;
100e72b21abSJames Hogan dev_m &= 0x1f;
101e72b21abSJames Hogan }
102e72b21abSJames Hogan
103e72b21abSJames Hogan /* ensure there aren't any bits straying between fields */
104e72b21abSJames Hogan dev &= dev_m;
105e72b21abSJames Hogan subdev &= subdev_m;
106e72b21abSJames Hogan
107e72b21abSJames Hogan /* write the hardware filter */
108e72b21abSJames Hogan out->data = func |
109e72b21abSJames Hogan dev << 7 |
110e72b21abSJames Hogan subdev << 15;
111e72b21abSJames Hogan out->mask = func_m |
112e72b21abSJames Hogan dev_m << 7 |
113e72b21abSJames Hogan subdev_m << 15;
114e72b21abSJames Hogan
115e72b21abSJames Hogan if (len) {
116e72b21abSJames Hogan out->minlen = len;
117e72b21abSJames Hogan out->maxlen = len;
118e72b21abSJames Hogan }
119e72b21abSJames Hogan return 0;
120e72b21abSJames Hogan }
121e72b21abSJames Hogan
122e72b21abSJames Hogan /*
123e72b21abSJames Hogan * Sony SIRC decoder
124e72b21abSJames Hogan * See also http://www.sbprojects.com/knowledge/ir/sirc.php
125e72b21abSJames Hogan * http://picprojects.org.uk/projects/sirc/sonysirc.pdf
126e72b21abSJames Hogan */
127e72b21abSJames Hogan struct img_ir_decoder img_ir_sony = {
1286d741bfeSSean Young .type = RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 | RC_PROTO_BIT_SONY20,
129e72b21abSJames Hogan .control = {
130e72b21abSJames Hogan .decoden = 1,
131e72b21abSJames Hogan .code_type = IMG_IR_CODETYPE_PULSELEN,
132e72b21abSJames Hogan },
133e72b21abSJames Hogan /* main timings */
134e72b21abSJames Hogan .unit = 600000, /* 600 us */
135e72b21abSJames Hogan .timings = {
136e72b21abSJames Hogan /* leader symbol */
137e72b21abSJames Hogan .ldr = {
138e72b21abSJames Hogan .pulse = { 4 /* 2.4 ms */ },
139e72b21abSJames Hogan .space = { 1 /* 600 us */ },
140e72b21abSJames Hogan },
141e72b21abSJames Hogan /* 0 symbol */
142e72b21abSJames Hogan .s00 = {
143e72b21abSJames Hogan .pulse = { 1 /* 600 us */ },
144e72b21abSJames Hogan .space = { 1 /* 600 us */ },
145e72b21abSJames Hogan },
146e72b21abSJames Hogan /* 1 symbol */
147e72b21abSJames Hogan .s01 = {
148e72b21abSJames Hogan .pulse = { 2 /* 1.2 ms */ },
149e72b21abSJames Hogan .space = { 1 /* 600 us */ },
150e72b21abSJames Hogan },
151e72b21abSJames Hogan /* free time */
152e72b21abSJames Hogan .ft = {
153e72b21abSJames Hogan .minlen = 12,
154e72b21abSJames Hogan .maxlen = 20,
155e72b21abSJames Hogan .ft_min = 10, /* 6 ms */
156e72b21abSJames Hogan },
157e72b21abSJames Hogan },
158e72b21abSJames Hogan /* scancode logic */
159e72b21abSJames Hogan .scancode = img_ir_sony_scancode,
160e72b21abSJames Hogan .filter = img_ir_sony_filter,
161e72b21abSJames Hogan };
162