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 struct 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.
171 if (width
> NEC_START_SPACE
- 2 &&
172 width
< NEC_START_SPACE
+ 2) {
174 rawir
.duration
= NEC_START_PULSE
;
175 dprintk(16, "Storing NEC start %s with duration %d",
176 rawir
.pulse
? "pulse" : "space",
180 rawir
.duration
= RC5_START_PULSE
;
181 dprintk(16, "Storing RC5 start %s with duration %d",
182 rawir
.pulse
? "pulse" : "space",
185 ir_raw_event_store(ir
->rc
, &rawir
);
188 rawir
.pulse
= prv_bit
? false : true;
189 rawir
.duration
= AU8522_UNIT
* width
;
190 dprintk(16, "Storing %s with duration %d",
191 rawir
.pulse
? "pulse" : "space",
193 ir_raw_event_store(ir
->rc
, &rawir
);
200 rawir
.pulse
= prv_bit
? false : true;
201 rawir
.duration
= AU8522_UNIT
* width
;
202 dprintk(16, "Storing end %s with duration %d",
203 rawir
.pulse
? "pulse" : "space",
205 ir_raw_event_store(ir
->rc
, &rawir
);
207 ir_raw_event_handle(ir
->rc
);
216 static void au0828_rc_work(struct work_struct
*work
)
218 struct au0828_rc
*ir
= container_of(work
, struct au0828_rc
, work
.work
);
221 rc
= ir
->get_key_i2c(ir
);
223 pr_info("Error while getting RC scancode\n");
225 schedule_delayed_work(&ir
->work
, msecs_to_jiffies(ir
->polling
));
228 static int au0828_rc_start(struct rc_dev
*rc
)
230 struct au0828_rc
*ir
= rc
->priv
;
232 INIT_DELAYED_WORK(&ir
->work
, au0828_rc_work
);
235 au8522_rc_set(ir
, 0xe0, 1 << 4);
237 schedule_delayed_work(&ir
->work
, msecs_to_jiffies(ir
->polling
));
242 static void au0828_rc_stop(struct rc_dev
*rc
)
244 struct au0828_rc
*ir
= rc
->priv
;
246 cancel_delayed_work_sync(&ir
->work
);
248 /* do nothing if device is disconnected */
249 if (!test_bit(DEV_DISCONNECTED
, &ir
->dev
->dev_state
)) {
251 au8522_rc_clear(ir
, 0xe0, 1 << 4);
255 static int au0828_probe_i2c_ir(struct au0828_dev
*dev
)
258 static const unsigned short addr_list
[] = {
262 while (addr_list
[i
] != I2C_CLIENT_END
) {
263 if (i2c_probe_func_quick_read(dev
->i2c_client
.adapter
,
272 int au0828_rc_register(struct au0828_dev
*dev
)
274 struct au0828_rc
*ir
;
277 u16 i2c_rc_dev_addr
= 0;
279 if (!dev
->board
.has_ir_i2c
|| disable_ir
)
282 i2c_rc_dev_addr
= au0828_probe_i2c_ir(dev
);
283 if (!i2c_rc_dev_addr
)
286 ir
= kzalloc(sizeof(*ir
), GFP_KERNEL
);
287 rc
= rc_allocate_device(RC_DRIVER_IR_RAW
);
291 /* record handles to ourself */
297 rc
->open
= au0828_rc_start
;
298 rc
->close
= au0828_rc_stop
;
300 if (dev
->board
.has_ir_i2c
) { /* external i2c device */
301 switch (dev
->boardnr
) {
302 case AU0828_BOARD_HAUPPAUGE_HVR950Q
:
303 rc
->map_name
= RC_MAP_HAUPPAUGE
;
304 ir
->get_key_i2c
= au0828_get_key_au8522
;
311 ir
->i2c_dev_addr
= i2c_rc_dev_addr
;
314 /* This is how often we ask the chip for IR information */
315 ir
->polling
= 100; /* ms */
317 /* init input device */
318 snprintf(ir
->name
, sizeof(ir
->name
), "au0828 IR (%s)",
321 usb_make_path(dev
->usbdev
, ir
->phys
, sizeof(ir
->phys
));
322 strlcat(ir
->phys
, "/input0", sizeof(ir
->phys
));
324 rc
->device_name
= ir
->name
;
325 rc
->input_phys
= ir
->phys
;
326 rc
->input_id
.bustype
= BUS_USB
;
327 rc
->input_id
.version
= 1;
328 rc
->input_id
.vendor
= le16_to_cpu(dev
->usbdev
->descriptor
.idVendor
);
329 rc
->input_id
.product
= le16_to_cpu(dev
->usbdev
->descriptor
.idProduct
);
330 rc
->dev
.parent
= &dev
->usbdev
->dev
;
331 rc
->driver_name
= "au0828-input";
332 rc
->allowed_protocols
= RC_PROTO_BIT_NEC
| RC_PROTO_BIT_NECX
|
333 RC_PROTO_BIT_NEC32
| RC_PROTO_BIT_RC5
;
336 err
= rc_register_device(rc
);
340 pr_info("Remote controller %s initialized\n", ir
->name
);
351 void au0828_rc_unregister(struct au0828_dev
*dev
)
353 struct au0828_rc
*ir
= dev
->ir
;
355 /* skip detach on non attached boards */
359 rc_unregister_device(ir
->rc
);
366 int au0828_rc_suspend(struct au0828_dev
*dev
)
368 struct au0828_rc
*ir
= dev
->ir
;
373 pr_info("Stopping RC\n");
375 cancel_delayed_work_sync(&ir
->work
);
378 au8522_rc_clear(ir
, 0xe0, 1 << 4);
383 int au0828_rc_resume(struct au0828_dev
*dev
)
385 struct au0828_rc
*ir
= dev
->ir
;
390 pr_info("Restarting RC\n");
393 au8522_rc_set(ir
, 0xe0, 1 << 4);
395 schedule_delayed_work(&ir
->work
, msecs_to_jiffies(ir
->polling
));