1 // SPDX-License-Identifier: GPL-2.0+
2 // handle au0828 IR remotes via linux kernel input layer.
4 // Copyright (c) 2014 Mauro Carvalho Chehab <mchehab@samsung.com>
5 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
7 // Based on em28xx-input.c.
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/interrupt.h>
15 #include <linux/usb.h>
16 #include <linux/slab.h>
17 #include <media/rc-core.h>
19 static int disable_ir
;
20 module_param(disable_ir
, int, 0444);
21 MODULE_PARM_DESC(disable_ir
, "disable infrared remote support");
24 struct au0828_dev
*dev
;
31 struct delayed_work work
;
33 /* i2c slave address of external device (if used) */
36 int (*get_key_i2c
)(struct au0828_rc
*ir
);
40 * AU8522 has a builtin IR receiver. Add functions to get IR from it
43 static int au8522_rc_write(struct au0828_rc
*ir
, u16 reg
, u8 data
)
46 char buf
[] = { (reg
>> 8) | 0x80, reg
& 0xff, data
};
47 struct i2c_msg msg
= { .addr
= ir
->i2c_dev_addr
, .flags
= 0,
48 .buf
= buf
, .len
= sizeof(buf
) };
50 rc
= i2c_transfer(ir
->dev
->i2c_client
.adapter
, &msg
, 1);
55 return (rc
== 1) ? 0 : -EIO
;
58 static int au8522_rc_read(struct au0828_rc
*ir
, u16 reg
, int val
,
63 struct i2c_msg msg
[2] = { { .addr
= ir
->i2c_dev_addr
, .flags
= 0,
64 .buf
= obuf
, .len
= 2 },
65 { .addr
= ir
->i2c_dev_addr
, .flags
= I2C_M_RD
,
66 .buf
= buf
, .len
= size
} };
68 obuf
[0] = 0x40 | reg
>> 8;
75 rc
= i2c_transfer(ir
->dev
->i2c_client
.adapter
, msg
, 2);
80 return (rc
== 2) ? 0 : -EIO
;
83 static int au8522_rc_andor(struct au0828_rc
*ir
, u16 reg
, u8 mask
, u8 value
)
88 rc
= au8522_rc_read(ir
, reg
, -1, &buf
, 1);
93 buf
= (buf
& ~mask
) | (value
& mask
);
95 /* Nothing to do, just return */
99 return au8522_rc_write(ir
, reg
, buf
);
102 #define au8522_rc_set(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), (bit))
103 #define au8522_rc_clear(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), 0)
105 /* Remote Controller time units */
107 #define AU8522_UNIT 200000 /* ns */
108 #define NEC_START_SPACE (4500000 / AU8522_UNIT)
109 #define NEC_START_PULSE (562500 * 16)
110 #define RC5_START_SPACE (4 * AU8522_UNIT)
111 #define RC5_START_PULSE 888888
113 static int au0828_get_key_au8522(struct au0828_rc
*ir
)
115 unsigned char buf
[40];
116 DEFINE_IR_RAW_EVENT(rawir
);
118 int prv_bit
, bit
, width
;
121 /* do nothing if device is disconnected */
122 if (test_bit(DEV_DISCONNECTED
, &ir
->dev
->dev_state
))
126 rc
= au8522_rc_read(ir
, 0xe1, -1, buf
, 1);
127 if (rc
< 0 || !(buf
[0] & (1 << 4))) {
128 /* Be sure that IR is enabled */
129 au8522_rc_set(ir
, 0xe0, 1 << 4);
133 /* Something arrived. Get the data */
134 rc
= au8522_rc_read(ir
, 0xe3, 0x11, buf
, sizeof(buf
));
141 au8522_rc_clear(ir
, 0xe0, 1 << 4);
144 au8522_rc_set(ir
, 0xe0, 1 << 4);
146 dprintk(16, "RC data received: %*ph\n", 40, buf
);
148 prv_bit
= (buf
[0] >> 7) & 0x01;
150 for (i
= 0; i
< sizeof(buf
); i
++) {
151 for (j
= 7; j
>= 0; j
--) {
152 bit
= (buf
[i
] >> j
) & 0x01;
153 if (bit
== prv_bit
) {
159 * Fix an au8522 bug: the first pulse event
160 * is lost. So, we need to fake it, based on the
161 * protocol. That means that not all raw decoders
162 * will work, as we need to add a hack for each
163 * protocol, based on the first space.
164 * So, we only support RC5 and NEC.
170 init_ir_raw_event(&rawir
);
172 if (width
> NEC_START_SPACE
- 2 &&
173 width
< NEC_START_SPACE
+ 2) {
175 rawir
.duration
= NEC_START_PULSE
;
176 dprintk(16, "Storing NEC start %s with duration %d",
177 rawir
.pulse
? "pulse" : "space",
181 rawir
.duration
= RC5_START_PULSE
;
182 dprintk(16, "Storing RC5 start %s with duration %d",
183 rawir
.pulse
? "pulse" : "space",
186 ir_raw_event_store(ir
->rc
, &rawir
);
189 init_ir_raw_event(&rawir
);
190 rawir
.pulse
= prv_bit
? false : true;
191 rawir
.duration
= AU8522_UNIT
* width
;
192 dprintk(16, "Storing %s with duration %d",
193 rawir
.pulse
? "pulse" : "space",
195 ir_raw_event_store(ir
->rc
, &rawir
);
202 init_ir_raw_event(&rawir
);
203 rawir
.pulse
= prv_bit
? false : true;
204 rawir
.duration
= AU8522_UNIT
* width
;
205 dprintk(16, "Storing end %s with duration %d",
206 rawir
.pulse
? "pulse" : "space",
208 ir_raw_event_store(ir
->rc
, &rawir
);
210 ir_raw_event_handle(ir
->rc
);
219 static void au0828_rc_work(struct work_struct
*work
)
221 struct au0828_rc
*ir
= container_of(work
, struct au0828_rc
, work
.work
);
224 rc
= ir
->get_key_i2c(ir
);
226 pr_info("Error while getting RC scancode\n");
228 schedule_delayed_work(&ir
->work
, msecs_to_jiffies(ir
->polling
));
231 static int au0828_rc_start(struct rc_dev
*rc
)
233 struct au0828_rc
*ir
= rc
->priv
;
235 INIT_DELAYED_WORK(&ir
->work
, au0828_rc_work
);
238 au8522_rc_set(ir
, 0xe0, 1 << 4);
240 schedule_delayed_work(&ir
->work
, msecs_to_jiffies(ir
->polling
));
245 static void au0828_rc_stop(struct rc_dev
*rc
)
247 struct au0828_rc
*ir
= rc
->priv
;
249 cancel_delayed_work_sync(&ir
->work
);
251 /* do nothing if device is disconnected */
252 if (!test_bit(DEV_DISCONNECTED
, &ir
->dev
->dev_state
)) {
254 au8522_rc_clear(ir
, 0xe0, 1 << 4);
258 static int au0828_probe_i2c_ir(struct au0828_dev
*dev
)
261 static const unsigned short addr_list
[] = {
265 while (addr_list
[i
] != I2C_CLIENT_END
) {
266 if (i2c_probe_func_quick_read(dev
->i2c_client
.adapter
,
275 int au0828_rc_register(struct au0828_dev
*dev
)
277 struct au0828_rc
*ir
;
280 u16 i2c_rc_dev_addr
= 0;
282 if (!dev
->board
.has_ir_i2c
|| disable_ir
)
285 i2c_rc_dev_addr
= au0828_probe_i2c_ir(dev
);
286 if (!i2c_rc_dev_addr
)
289 ir
= kzalloc(sizeof(*ir
), GFP_KERNEL
);
290 rc
= rc_allocate_device(RC_DRIVER_IR_RAW
);
294 /* record handles to ourself */
300 rc
->open
= au0828_rc_start
;
301 rc
->close
= au0828_rc_stop
;
303 if (dev
->board
.has_ir_i2c
) { /* external i2c device */
304 switch (dev
->boardnr
) {
305 case AU0828_BOARD_HAUPPAUGE_HVR950Q
:
306 rc
->map_name
= RC_MAP_HAUPPAUGE
;
307 ir
->get_key_i2c
= au0828_get_key_au8522
;
314 ir
->i2c_dev_addr
= i2c_rc_dev_addr
;
317 /* This is how often we ask the chip for IR information */
318 ir
->polling
= 100; /* ms */
320 /* init input device */
321 snprintf(ir
->name
, sizeof(ir
->name
), "au0828 IR (%s)",
324 usb_make_path(dev
->usbdev
, ir
->phys
, sizeof(ir
->phys
));
325 strlcat(ir
->phys
, "/input0", sizeof(ir
->phys
));
327 rc
->device_name
= ir
->name
;
328 rc
->input_phys
= ir
->phys
;
329 rc
->input_id
.bustype
= BUS_USB
;
330 rc
->input_id
.version
= 1;
331 rc
->input_id
.vendor
= le16_to_cpu(dev
->usbdev
->descriptor
.idVendor
);
332 rc
->input_id
.product
= le16_to_cpu(dev
->usbdev
->descriptor
.idProduct
);
333 rc
->dev
.parent
= &dev
->usbdev
->dev
;
334 rc
->driver_name
= "au0828-input";
335 rc
->allowed_protocols
= RC_PROTO_BIT_NEC
| RC_PROTO_BIT_NECX
|
336 RC_PROTO_BIT_NEC32
| RC_PROTO_BIT_RC5
;
339 err
= rc_register_device(rc
);
343 pr_info("Remote controller %s initialized\n", ir
->name
);
354 void au0828_rc_unregister(struct au0828_dev
*dev
)
356 struct au0828_rc
*ir
= dev
->ir
;
358 /* skip detach on non attached boards */
362 rc_unregister_device(ir
->rc
);
369 int au0828_rc_suspend(struct au0828_dev
*dev
)
371 struct au0828_rc
*ir
= dev
->ir
;
376 pr_info("Stopping RC\n");
378 cancel_delayed_work_sync(&ir
->work
);
381 au8522_rc_clear(ir
, 0xe0, 1 << 4);
386 int au0828_rc_resume(struct au0828_dev
*dev
)
388 struct au0828_rc
*ir
= dev
->ir
;
393 pr_info("Restarting RC\n");
396 au8522_rc_set(ir
, 0xe0, 1 << 4);
398 schedule_delayed_work(&ir
->work
, msecs_to_jiffies(ir
->polling
));