blob: 460e4ba22ffe9f1d4174feaef55ff7badb74dd77 [file] [log] [blame]
Googler25e92cf2023-12-13 10:05:01 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <dm.h>
7#include <errno.h>
8#include <dt-bindings/input/meson_rc.h>
9#include "ir.h"
10
11struct meson_ir_reg_map {
12 unsigned int reg;
13 unsigned int val;
14};
15
16struct meson_ir_reg_proto {
17 int protocol;
18 int reg_map_size;
19 const char *name;
20 const struct meson_ir_reg_map *reg_map;
21 int (*get_framecode)(struct meson_ir_chip *chip);
22};
23
24static const struct meson_ir_reg_map regs_legacy_nec[] = {
25 {REG_LDR_ACTIVE, (500 << 16) | (400 << 0)},
26 {REG_LDR_IDLE, (300 << 16) | (200 << 0)},
27 {REG_LDR_REPEAT, (150 << 16) | (80 << 0)},
28 {REG_BIT_0, (72 << 16) | (40 << 0) },
29 {REG_REG0, (7 << 28) | (0xFA0 << 12) | 0x13},
30 {REG_STATUS, (134 << 20) | (90 << 10)},
31 {REG_REG1, 0xbe00}
32};
33
34static const struct meson_ir_reg_map regs_default_nec[] = {
35 {REG_LDR_ACTIVE, (500 << 16) | (400 << 0)},
36 {REG_LDR_IDLE, (300 << 16) | (200 << 0)},
37 {REG_LDR_REPEAT, (150 << 16) | (80 << 0)},
38 {REG_BIT_0, (72 << 16) | (40 << 0)},
39 {REG_REG0, (7 << 28) | (0xFA0 << 12) | 0x13},
40 {REG_STATUS, (134 << 20) | (90 << 10) | (1 << 30)},
41 {REG_REG1, 0x9f00},
42 {REG_REG2, 0x00},
43 {REG_DURATN2, 0x00},
44 {REG_DURATN3, 0x00},
45 {REG_IRQ_CTL, 0xCFA10BB8}
46};
47
48static const struct meson_ir_reg_map regs_default_duokan[] = {
49 {REG_LDR_ACTIVE, ((70 << 16) | (30 << 0))},
50 {REG_LDR_IDLE, ((50 << 16) | (15 << 0))},
51 {REG_LDR_REPEAT, ((30 << 16) | (26 << 0))},
52 {REG_BIT_0, ((66 << 16) | (40 << 0))},
53 {REG_REG0, ((3 << 28) | (0x4e2 << 12) | (0x13))},
54 {REG_STATUS, ((80 << 20) | (66 << 10))},
55 {REG_REG1, 0x9300},
56 {REG_REG2, 0xb90b},
57 {REG_DURATN2, ((97 << 16) | (80 << 0))},
58 {REG_DURATN3, ((120 << 16) | (97 << 0))},
59 {REG_REG3, 5000 << 0}
60};
61
62static const struct meson_ir_reg_map regs_default_xmp_1[] = {
63 {REG_LDR_ACTIVE, 0},
64 {REG_LDR_IDLE, 0},
65 {REG_LDR_REPEAT, 0},
66 {REG_BIT_0, (52 << 16) | (45 << 0)},
67 {REG_REG0, ((7 << 28) | (0x5DC << 12) | (0x13))},
68 {REG_STATUS, (87 << 20) | (80 << 10)},
69 {REG_REG1, 0x9f00},
70 {REG_REG2, 0xa90e},
71 /*n=10,758+137*10=2128us,2128/20= 106*/
72 {REG_DURATN2, (121 << 16) | (114 << 0)},
73 {REG_DURATN3, (7 << 16) | (7 << 0)},
74 {REG_REG3, 0}
75};
76
77static const struct meson_ir_reg_map regs_default_rc5[] = {
78 {REG_LDR_ACTIVE, 0},
79 {REG_LDR_IDLE, 0},
80 {REG_LDR_REPEAT, 0},
81 {REG_BIT_0, 0},
82 {REG_REG0, ((3 << 28) | (0x1644 << 12) | 0x13)},
83 {REG_STATUS, (1 << 30)},
84 {REG_REG1, ((1 << 15) | (13 << 8))},
85 /*bit[0-3]: RC5; bit[8]: MSB first mode; bit[11]: compare frame method*/
86 {REG_REG2, ((1 << 13) | (1 << 11) | (1 << 8) | 0x7)},
87 /*Half bit for RC5 format: 888.89us*/
88 {REG_DURATN2, ((49 << 16) | (40 << 0))},
89 /*RC5 typically 1777.78us for whole bit*/
90 {REG_DURATN3, ((94 << 16) | (83 << 0))},
91 {REG_REG3, 0}
92};
93
94static const struct meson_ir_reg_map regs_default_rc6[] = {
95 {REG_LDR_ACTIVE, (210 << 16) | (125 << 0)},
96 /*rc6 leader 4000us,200* timebase*/
97 {REG_LDR_IDLE, (50 << 16) | (38 << 0)}, /* leader idle 400*/
98 {REG_LDR_REPEAT, (145 << 16) | (125 << 0)}, /* leader repeat*/
99 /* logic '0' or '00' 1500us*/
100 {REG_BIT_0, (51 << 16) | (38 << 0) },
101 {REG_REG0, (7 << 28) | (0xFA0 << 12) | 0x13},
102 /* sys clock boby time.base time = 20 body frame*/
103 {REG_STATUS, (94 << 20) | (82 << 10)},
104 /*20bit:9440 32bit:9f40 36bit:a340 37bit:a440*/
105 {REG_REG1, 0xa440},
106 /*it may get the wrong customer value and key value from register if
107 *the value is set to 0x4,so the register value must set to 0x104
108 */
109 {REG_REG2, 0x2909},
110 {REG_DURATN2, ((28 << 16) | (16 << 0))},
111 {REG_DURATN3, ((51 << 16) | (38 << 0))}
112};
113
114static const struct meson_ir_reg_map regs_default_toshiba[] = {
115 {REG_LDR_ACTIVE, (280 << 16) | (180 << 0)},
116 {REG_LDR_IDLE, (280 << 16) | (180 << 0)},
117 {REG_LDR_REPEAT, (150 << 16) | (60 << 0)},
118 {REG_BIT_0, (72 << 16) | (40 << 0)},
119 {REG_REG0, (7 << 28) | (0xFA0 << 12) | 0x13},
120 {REG_STATUS, (134 << 20) | (90 << 10)},
121 {REG_REG1, 0x9f00},
122 {REG_REG2, 0x05 | (1 << 24) | (23 << 11)},
123 {REG_DURATN2, 0x00},
124 {REG_DURATN3, 0x00,},
125 {REG_REPEAT_DET, (1 << 31) | (0xFA0 << 16) | (10 << 0)},
126 {REG_REG3, 0x2AF8}
127};
128
129static struct meson_ir_reg_map regs_default_rca[] = {
130 {REG_LDR_ACTIVE, (250 << 16) | (160 << 0)},
131 {REG_LDR_IDLE, (250 << 16) | (160 << 0)},
132 {REG_LDR_REPEAT, (250 << 16) | (160 << 0)},
133 {REG_BIT_0, (100 << 16) | (48 << 0)},
134 {REG_REG0, (7 << 28) | (0xFA0 << 12) | 0x13},
135 {REG_STATUS, (150 << 20) | (110 << 10)},
136 {REG_REG1, 0x9700},
137 {REG_REG2, 0x104 | (1 << 24) | (23 << 11)},
138 {REG_DURATN2, 0x00},
139 {REG_REPEAT_DET, (1 << 31) | (0xFA0 << 16) | (10 << 0)},
140 {REG_REG3, 0x1A00},
141 {REG_DURATN3, 0x00}
142};
143
144static int meson_ir_get_framecode(struct meson_ir_chip *chip, unsigned char id)
145{
146 int status;
147
148 status = readl(chip->ir_contr[id].base + REG_STATUS);
149 if (status & FRAME_STATUS_VALID) {
150 if (status & FRAME_STATUS_REPEAT) {
151 readl(chip->ir_contr[id].base + REG_FRAME);
152 return 0;
153 }
154
155 return readl(chip->ir_contr[id].base + REG_FRAME);
156 }
157
158 return 0;
159}
160
161static int meson_legacy_ir_get_framecode_default(struct meson_ir_chip *chip)
162{
163 return meson_ir_get_framecode(chip, LEGACY_IR_ID);
164}
165
166static int meson_multi_ir_get_framecode_default(struct meson_ir_chip *chip)
167{
168 return meson_ir_get_framecode(chip, MULTI_IR_ID);
169}
170
171static const struct meson_ir_reg_proto reg_legacy_nec ={
172 .protocol = REMOTE_TYPE_LEGACY_NEC,
173 .name = "LEGACY_NEC",
174 .reg_map = regs_legacy_nec,
175 .reg_map_size = ARRAY_SIZE(regs_legacy_nec),
176 .get_framecode = meson_legacy_ir_get_framecode_default,
177};
178
179static const struct meson_ir_reg_proto reg_nec ={
180 .protocol = REMOTE_TYPE_NEC,
181 .name = "NEC",
182 .reg_map = regs_default_nec,
183 .reg_map_size = ARRAY_SIZE(regs_default_nec),
184 .get_framecode = meson_multi_ir_get_framecode_default,
185};
186
187static const struct meson_ir_reg_proto reg_duokan ={
188 .protocol = REMOTE_TYPE_DUOKAN,
189 .name = "DUOKAN",
190 .reg_map = regs_default_duokan,
191 .reg_map_size = ARRAY_SIZE(regs_default_duokan),
192 .get_framecode = meson_multi_ir_get_framecode_default,
193};
194
195static const struct meson_ir_reg_proto reg_xmp_1 ={
196 .protocol = REMOTE_TYPE_XMP_1,
197 .name = "XMP_1",
198 .reg_map = regs_default_xmp_1,
199 .reg_map_size = ARRAY_SIZE(regs_default_xmp_1),
200 .get_framecode = meson_multi_ir_get_framecode_default,
201};
202
203static const struct meson_ir_reg_proto reg_rc5 ={
204 .protocol = REMOTE_TYPE_RC5,
205 .name = "RC5",
206 .reg_map = regs_default_rc5,
207 .reg_map_size = ARRAY_SIZE(regs_default_rc5),
208 .get_framecode = meson_multi_ir_get_framecode_default,
209};
210
211static const struct meson_ir_reg_proto reg_rc6 ={
212 .protocol = REMOTE_TYPE_RC6,
213 .name = "RC6",
214 .reg_map = regs_default_rc6,
215 .reg_map_size = ARRAY_SIZE(regs_default_rc6),
216};
217
218static const struct meson_ir_reg_proto reg_toshiba ={
219 .protocol = REMOTE_TYPE_TOSHIBA,
220 .name = "toshiba",
221 .reg_map = regs_default_toshiba,
222 .reg_map_size = ARRAY_SIZE(regs_default_toshiba),
223 .get_framecode = meson_multi_ir_get_framecode_default,
224};
225
226static const struct meson_ir_reg_proto reg_rca ={
227 .protocol = REMOTE_TYPE_RCA,
228 .name = "RCA",
229 .reg_map = regs_default_rca,
230 .reg_map_size = ARRAY_SIZE(regs_default_rca),
231 .get_framecode = meson_multi_ir_get_framecode_default,
232};
233
234static const struct meson_ir_reg_proto *meson_ir_regs_proto[] = {
235 &reg_nec,
236 &reg_duokan,
237 &reg_rc5,
238 &reg_rc6,
239 &reg_toshiba,
240 &reg_rca,
241 &reg_xmp_1,
242 &reg_legacy_nec,
243 NULL
244};
245
246static int meson_ir_contr_init(struct meson_ir_chip *chip, int type, unsigned char id)
247{
248 const struct meson_ir_reg_proto **reg_proto = meson_ir_regs_proto;
249 const struct meson_ir_reg_map *regmap;
250 int size;
251
252 for (; (*reg_proto) != NULL ; ) {
253 if ((*reg_proto)->protocol == type)
254 break;
255 reg_proto++;
256 }
257
258 if (!(*reg_proto)) {
259 printf("%s: invalid protocol type: %d\n", __func__, type);
260 return -EINVAL;
261 }
262
263 readl(chip->ir_contr[id].base + REG_STATUS);
264 readl(chip->ir_contr[id].base + REG_FRAME);
265
266 /*
267 * reset ir decoder and disable the state machine
268 * of IR decoder.
269 * [15] = 0 ,disable the machine of IR decoder
270 * [0] = 0x01,set to 1 to reset the IR decoder
271 */
272 regmap = (*reg_proto)->reg_map;
273 size = (*reg_proto)->reg_map_size;
274
275 for ( ; size > 0; ) {
276 writel(regmap->val, chip->ir_contr[id].base + regmap->reg);
277 size--;
278 regmap++;
279 }
280
281 /*
282 * when we reinstall remote controller register,
283 * we need reset IR decoder, set 1 to REG_REG1 bit0,
284 * after IR decoder reset, we need to clear the bit0
285 */
286 writel(readl(chip->ir_contr[id].base + REG_REG1) | BIT(0),
287 chip->ir_contr[id].base + REG_REG1);
288 writel(readl(chip->ir_contr[id].base + REG_REG1) & (~BIT(0)),
289 chip->ir_contr[id].base + REG_REG1);
290
291 chip->ir_contr[id].get_framecode = (*reg_proto)->get_framecode;
292
293 return 0;
294}
295
296int meson_ir_register_default_config(struct meson_ir_chip *chip, int type)
297{
298 if (ENABLE_LEGACY_IR(type)) {
299 /*initialize registers for legacy IR controller*/
300 meson_ir_contr_init(chip, LEGACY_IR_TYPE_MASK(type),
301 LEGACY_IR_ID);
302 } else {
303 /*disable legacy IR controller: REG_REG1[15]*/
304 writel(0x0, chip->ir_contr[LEGACY_IR_ID].base + REG_REG1);
305 }
306 /*initialize registers for Multi-format IR controller*/
307 meson_ir_contr_init(chip, MULTI_IR_TYPE_MASK(type), MULTI_IR_ID);
308
309 return 0;
310}