120835280SMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0 220835280SMauro Carvalho Chehab // ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol 320835280SMauro Carvalho Chehab // 420835280SMauro Carvalho Chehab // Copyright (C) 2011 by Mauro Carvalho Chehab 520835280SMauro Carvalho Chehab // 620835280SMauro Carvalho Chehab // This protocol uses the NEC protocol timings. However, data is formatted as: 720835280SMauro Carvalho Chehab // 13 bits Custom Code 820835280SMauro Carvalho Chehab // 13 bits NOT(Custom Code) 920835280SMauro Carvalho Chehab // 8 bits Key data 1020835280SMauro Carvalho Chehab // 8 bits NOT(Key data) 1120835280SMauro Carvalho Chehab // 1220835280SMauro Carvalho Chehab // According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon 1320835280SMauro Carvalho Chehab // Information for this protocol is available at the Sanyo LC7461 datasheet. 14b32e7243SMauro Carvalho Chehab 152e962f4eSHans Verkuil #include <linux/module.h> 16b32e7243SMauro Carvalho Chehab #include <linux/bitrev.h> 17b32e7243SMauro Carvalho Chehab #include "rc-core-priv.h" 18b32e7243SMauro Carvalho Chehab 19b32e7243SMauro Carvalho Chehab #define SANYO_NBITS (13+13+8+8) 20b32e7243SMauro Carvalho Chehab #define SANYO_UNIT 562500 /* ns */ 21b32e7243SMauro Carvalho Chehab #define SANYO_HEADER_PULSE (16 * SANYO_UNIT) 22b32e7243SMauro Carvalho Chehab #define SANYO_HEADER_SPACE (8 * SANYO_UNIT) 23b32e7243SMauro Carvalho Chehab #define SANYO_BIT_PULSE (1 * SANYO_UNIT) 24b32e7243SMauro Carvalho Chehab #define SANYO_BIT_0_SPACE (1 * SANYO_UNIT) 25b32e7243SMauro Carvalho Chehab #define SANYO_BIT_1_SPACE (3 * SANYO_UNIT) 26b32e7243SMauro Carvalho Chehab #define SANYO_REPEAT_SPACE (150 * SANYO_UNIT) 27b32e7243SMauro Carvalho Chehab #define SANYO_TRAILER_PULSE (1 * SANYO_UNIT) 28b32e7243SMauro Carvalho Chehab #define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */ 29b32e7243SMauro Carvalho Chehab 30b32e7243SMauro Carvalho Chehab enum sanyo_state { 31b32e7243SMauro Carvalho Chehab STATE_INACTIVE, 32b32e7243SMauro Carvalho Chehab STATE_HEADER_SPACE, 33b32e7243SMauro Carvalho Chehab STATE_BIT_PULSE, 34b32e7243SMauro Carvalho Chehab STATE_BIT_SPACE, 35b32e7243SMauro Carvalho Chehab STATE_TRAILER_PULSE, 36b32e7243SMauro Carvalho Chehab STATE_TRAILER_SPACE, 37b32e7243SMauro Carvalho Chehab }; 38b32e7243SMauro Carvalho Chehab 39b32e7243SMauro Carvalho Chehab /** 40b32e7243SMauro Carvalho Chehab * ir_sanyo_decode() - Decode one SANYO pulse or space 41b32e7243SMauro Carvalho Chehab * @dev: the struct rc_dev descriptor of the device 421855e988SMauro Carvalho Chehab * @ev: the struct ir_raw_event descriptor of the pulse/space 43b32e7243SMauro Carvalho Chehab * 44b32e7243SMauro Carvalho Chehab * This function returns -EINVAL if the pulse violates the state machine 45b32e7243SMauro Carvalho Chehab */ 46b32e7243SMauro Carvalho Chehab static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev) 47b32e7243SMauro Carvalho Chehab { 48b32e7243SMauro Carvalho Chehab struct sanyo_dec *data = &dev->raw->sanyo; 49b32e7243SMauro Carvalho Chehab u32 scancode; 502bfc04d6SSean Young u16 address; 512bfc04d6SSean Young u8 command, not_command; 52b32e7243SMauro Carvalho Chehab 53b32e7243SMauro Carvalho Chehab if (!is_timing_event(ev)) { 54b32e7243SMauro Carvalho Chehab if (ev.reset) { 5550078a90SSean Young dev_dbg(&dev->dev, "SANYO event reset received. reset to state 0\n"); 56b32e7243SMauro Carvalho Chehab data->state = STATE_INACTIVE; 57b32e7243SMauro Carvalho Chehab } 58b32e7243SMauro Carvalho Chehab return 0; 59b32e7243SMauro Carvalho Chehab } 60b32e7243SMauro Carvalho Chehab 6150078a90SSean Young dev_dbg(&dev->dev, "SANYO decode started at state %d (%uus %s)\n", 62b32e7243SMauro Carvalho Chehab data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 63b32e7243SMauro Carvalho Chehab 64b32e7243SMauro Carvalho Chehab switch (data->state) { 65b32e7243SMauro Carvalho Chehab 66b32e7243SMauro Carvalho Chehab case STATE_INACTIVE: 67b32e7243SMauro Carvalho Chehab if (!ev.pulse) 68b32e7243SMauro Carvalho Chehab break; 69b32e7243SMauro Carvalho Chehab 70b32e7243SMauro Carvalho Chehab if (eq_margin(ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) { 71b32e7243SMauro Carvalho Chehab data->count = 0; 72b32e7243SMauro Carvalho Chehab data->state = STATE_HEADER_SPACE; 73b32e7243SMauro Carvalho Chehab return 0; 74b32e7243SMauro Carvalho Chehab } 75b32e7243SMauro Carvalho Chehab break; 76b32e7243SMauro Carvalho Chehab 77b32e7243SMauro Carvalho Chehab 78b32e7243SMauro Carvalho Chehab case STATE_HEADER_SPACE: 79b32e7243SMauro Carvalho Chehab if (ev.pulse) 80b32e7243SMauro Carvalho Chehab break; 81b32e7243SMauro Carvalho Chehab 82b32e7243SMauro Carvalho Chehab if (eq_margin(ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) { 83b32e7243SMauro Carvalho Chehab data->state = STATE_BIT_PULSE; 84b32e7243SMauro Carvalho Chehab return 0; 85b32e7243SMauro Carvalho Chehab } 86b32e7243SMauro Carvalho Chehab 87b32e7243SMauro Carvalho Chehab break; 88b32e7243SMauro Carvalho Chehab 89b32e7243SMauro Carvalho Chehab case STATE_BIT_PULSE: 90b32e7243SMauro Carvalho Chehab if (!ev.pulse) 91b32e7243SMauro Carvalho Chehab break; 92b32e7243SMauro Carvalho Chehab 93b32e7243SMauro Carvalho Chehab if (!eq_margin(ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2)) 94b32e7243SMauro Carvalho Chehab break; 95b32e7243SMauro Carvalho Chehab 96b32e7243SMauro Carvalho Chehab data->state = STATE_BIT_SPACE; 97b32e7243SMauro Carvalho Chehab return 0; 98b32e7243SMauro Carvalho Chehab 99b32e7243SMauro Carvalho Chehab case STATE_BIT_SPACE: 100b32e7243SMauro Carvalho Chehab if (ev.pulse) 101b32e7243SMauro Carvalho Chehab break; 102b32e7243SMauro Carvalho Chehab 103b32e7243SMauro Carvalho Chehab if (!data->count && geq_margin(ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) { 104b32e7243SMauro Carvalho Chehab rc_repeat(dev); 10550078a90SSean Young dev_dbg(&dev->dev, "SANYO repeat last key\n"); 106b32e7243SMauro Carvalho Chehab data->state = STATE_INACTIVE; 107b32e7243SMauro Carvalho Chehab return 0; 108b32e7243SMauro Carvalho Chehab } 109b32e7243SMauro Carvalho Chehab 110b32e7243SMauro Carvalho Chehab data->bits <<= 1; 111b32e7243SMauro Carvalho Chehab if (eq_margin(ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2)) 112b32e7243SMauro Carvalho Chehab data->bits |= 1; 113b32e7243SMauro Carvalho Chehab else if (!eq_margin(ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2)) 114b32e7243SMauro Carvalho Chehab break; 115b32e7243SMauro Carvalho Chehab data->count++; 116b32e7243SMauro Carvalho Chehab 117b32e7243SMauro Carvalho Chehab if (data->count == SANYO_NBITS) 118b32e7243SMauro Carvalho Chehab data->state = STATE_TRAILER_PULSE; 119b32e7243SMauro Carvalho Chehab else 120b32e7243SMauro Carvalho Chehab data->state = STATE_BIT_PULSE; 121b32e7243SMauro Carvalho Chehab 122b32e7243SMauro Carvalho Chehab return 0; 123b32e7243SMauro Carvalho Chehab 124b32e7243SMauro Carvalho Chehab case STATE_TRAILER_PULSE: 125b32e7243SMauro Carvalho Chehab if (!ev.pulse) 126b32e7243SMauro Carvalho Chehab break; 127b32e7243SMauro Carvalho Chehab 128b32e7243SMauro Carvalho Chehab if (!eq_margin(ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2)) 129b32e7243SMauro Carvalho Chehab break; 130b32e7243SMauro Carvalho Chehab 131b32e7243SMauro Carvalho Chehab data->state = STATE_TRAILER_SPACE; 132b32e7243SMauro Carvalho Chehab return 0; 133b32e7243SMauro Carvalho Chehab 134b32e7243SMauro Carvalho Chehab case STATE_TRAILER_SPACE: 135b32e7243SMauro Carvalho Chehab if (ev.pulse) 136b32e7243SMauro Carvalho Chehab break; 137b32e7243SMauro Carvalho Chehab 138b32e7243SMauro Carvalho Chehab if (!geq_margin(ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2)) 139b32e7243SMauro Carvalho Chehab break; 140b32e7243SMauro Carvalho Chehab 141b32e7243SMauro Carvalho Chehab address = bitrev16((data->bits >> 29) & 0x1fff) >> 3; 1425becbc58SHans Verkuil /* not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3; */ 143b32e7243SMauro Carvalho Chehab command = bitrev8((data->bits >> 8) & 0xff); 144b32e7243SMauro Carvalho Chehab not_command = bitrev8((data->bits >> 0) & 0xff); 145b32e7243SMauro Carvalho Chehab 146b32e7243SMauro Carvalho Chehab if ((command ^ not_command) != 0xff) { 14750078a90SSean Young dev_dbg(&dev->dev, "SANYO checksum error: received 0x%08llx\n", 148b32e7243SMauro Carvalho Chehab data->bits); 149b32e7243SMauro Carvalho Chehab data->state = STATE_INACTIVE; 150b32e7243SMauro Carvalho Chehab return 0; 151b32e7243SMauro Carvalho Chehab } 152b32e7243SMauro Carvalho Chehab 153b32e7243SMauro Carvalho Chehab scancode = address << 8 | command; 15450078a90SSean Young dev_dbg(&dev->dev, "SANYO scancode: 0x%06x\n", scancode); 1556d741bfeSSean Young rc_keydown(dev, RC_PROTO_SANYO, scancode, 0); 156b32e7243SMauro Carvalho Chehab data->state = STATE_INACTIVE; 157b32e7243SMauro Carvalho Chehab return 0; 158b32e7243SMauro Carvalho Chehab } 159b32e7243SMauro Carvalho Chehab 16050078a90SSean Young dev_dbg(&dev->dev, "SANYO decode failed at count %d state %d (%uus %s)\n", 161b32e7243SMauro Carvalho Chehab data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 162b32e7243SMauro Carvalho Chehab data->state = STATE_INACTIVE; 163b32e7243SMauro Carvalho Chehab return -EINVAL; 164b32e7243SMauro Carvalho Chehab } 165b32e7243SMauro Carvalho Chehab 166cb981257SSean Young static const struct ir_raw_timings_pd ir_sanyo_timings = { 167cb981257SSean Young .header_pulse = SANYO_HEADER_PULSE, 168cb981257SSean Young .header_space = SANYO_HEADER_SPACE, 169cb981257SSean Young .bit_pulse = SANYO_BIT_PULSE, 170cb981257SSean Young .bit_space[0] = SANYO_BIT_0_SPACE, 171cb981257SSean Young .bit_space[1] = SANYO_BIT_1_SPACE, 172cb981257SSean Young .trailer_pulse = SANYO_TRAILER_PULSE, 173cb981257SSean Young .trailer_space = SANYO_TRAILER_SPACE, 174cb981257SSean Young .msb_first = 1, 175cb981257SSean Young }; 176cb981257SSean Young 177cb981257SSean Young /** 178cb981257SSean Young * ir_sanyo_encode() - Encode a scancode as a stream of raw events 179cb981257SSean Young * 180cb981257SSean Young * @protocol: protocol to encode 181cb981257SSean Young * @scancode: scancode to encode 182cb981257SSean Young * @events: array of raw ir events to write into 183cb981257SSean Young * @max: maximum size of @events 184cb981257SSean Young * 185cb981257SSean Young * Returns: The number of events written. 186cb981257SSean Young * -ENOBUFS if there isn't enough space in the array to fit the 187cb981257SSean Young * encoding. In this case all @max events will have been written. 188cb981257SSean Young */ 1896d741bfeSSean Young static int ir_sanyo_encode(enum rc_proto protocol, u32 scancode, 190cb981257SSean Young struct ir_raw_event *events, unsigned int max) 191cb981257SSean Young { 192cb981257SSean Young struct ir_raw_event *e = events; 193cb981257SSean Young int ret; 194cb981257SSean Young u64 raw; 195cb981257SSean Young 196cb981257SSean Young raw = ((u64)(bitrev16(scancode >> 8) & 0xfff8) << (8 + 8 + 13 - 3)) | 197cb981257SSean Young ((u64)(bitrev16(~scancode >> 8) & 0xfff8) << (8 + 8 + 0 - 3)) | 198cb981257SSean Young ((bitrev8(scancode) & 0xff) << 8) | 199cb981257SSean Young (bitrev8(~scancode) & 0xff); 200cb981257SSean Young 201cb981257SSean Young ret = ir_raw_gen_pd(&e, max, &ir_sanyo_timings, SANYO_NBITS, raw); 202cb981257SSean Young if (ret < 0) 203cb981257SSean Young return ret; 204cb981257SSean Young 205cb981257SSean Young return e - events; 206cb981257SSean Young } 207cb981257SSean Young 208b32e7243SMauro Carvalho Chehab static struct ir_raw_handler sanyo_handler = { 2096d741bfeSSean Young .protocols = RC_PROTO_BIT_SANYO, 210b32e7243SMauro Carvalho Chehab .decode = ir_sanyo_decode, 211cb981257SSean Young .encode = ir_sanyo_encode, 212cdfaa01cSSean Young .carrier = 38000, 213b32e7243SMauro Carvalho Chehab }; 214b32e7243SMauro Carvalho Chehab 215b32e7243SMauro Carvalho Chehab static int __init ir_sanyo_decode_init(void) 216b32e7243SMauro Carvalho Chehab { 217b32e7243SMauro Carvalho Chehab ir_raw_handler_register(&sanyo_handler); 218b32e7243SMauro Carvalho Chehab 219b32e7243SMauro Carvalho Chehab printk(KERN_INFO "IR SANYO protocol handler initialized\n"); 220b32e7243SMauro Carvalho Chehab return 0; 221b32e7243SMauro Carvalho Chehab } 222b32e7243SMauro Carvalho Chehab 223b32e7243SMauro Carvalho Chehab static void __exit ir_sanyo_decode_exit(void) 224b32e7243SMauro Carvalho Chehab { 225b32e7243SMauro Carvalho Chehab ir_raw_handler_unregister(&sanyo_handler); 226b32e7243SMauro Carvalho Chehab } 227b32e7243SMauro Carvalho Chehab 228b32e7243SMauro Carvalho Chehab module_init(ir_sanyo_decode_init); 229b32e7243SMauro Carvalho Chehab module_exit(ir_sanyo_decode_exit); 230b32e7243SMauro Carvalho Chehab 23120835280SMauro Carvalho Chehab MODULE_LICENSE("GPL v2"); 23237e59f87SMauro Carvalho Chehab MODULE_AUTHOR("Mauro Carvalho Chehab"); 233b32e7243SMauro Carvalho Chehab MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); 234b32e7243SMauro Carvalho Chehab MODULE_DESCRIPTION("SANYO IR protocol decoder"); 235