174 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ImgTec IR Decoder setup for NEC protocol.4 *5 * Copyright 2010-2014 Imagination Technologies Ltd.6 */7 8#include "img-ir-hw.h"9#include <linux/bitrev.h>10#include <linux/log2.h>11 12/* Convert NEC data to a scancode */13static int img_ir_nec_scancode(int len, u64 raw, u64 enabled_protocols,14 struct img_ir_scancode_req *request)15{16 unsigned int addr, addr_inv, data, data_inv;17 /* a repeat code has no data */18 if (!len)19 return IMG_IR_REPEATCODE;20 if (len != 32)21 return -EINVAL;22 /* raw encoding: ddDDaaAA */23 addr = (raw >> 0) & 0xff;24 addr_inv = (raw >> 8) & 0xff;25 data = (raw >> 16) & 0xff;26 data_inv = (raw >> 24) & 0xff;27 if ((data_inv ^ data) != 0xff) {28 /* 32-bit NEC (used by Apple and TiVo remotes) */29 /* scan encoding: as transmitted, MSBit = first received bit */30 request->scancode = bitrev8(addr) << 24 |31 bitrev8(addr_inv) << 16 |32 bitrev8(data) << 8 |33 bitrev8(data_inv);34 request->protocol = RC_PROTO_NEC32;35 } else if ((addr_inv ^ addr) != 0xff) {36 /* Extended NEC */37 /* scan encoding: AAaaDD */38 request->scancode = addr << 16 |39 addr_inv << 8 |40 data;41 request->protocol = RC_PROTO_NECX;42 } else {43 /* Normal NEC */44 /* scan encoding: AADD */45 request->scancode = addr << 8 |46 data;47 request->protocol = RC_PROTO_NEC;48 }49 return IMG_IR_SCANCODE;50}51 52/* Convert NEC scancode to NEC data filter */53static int img_ir_nec_filter(const struct rc_scancode_filter *in,54 struct img_ir_filter *out, u64 protocols)55{56 unsigned int addr, addr_inv, data, data_inv;57 unsigned int addr_m, addr_inv_m, data_m, data_inv_m;58 59 data = in->data & 0xff;60 data_m = in->mask & 0xff;61 62 protocols &= RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32;63 64 /*65 * If only one bit is set, we were requested to do an exact66 * protocol. This should be the case for wakeup filters; for67 * normal filters, guess the protocol from the scancode.68 */69 if (!is_power_of_2(protocols)) {70 if ((in->data | in->mask) & 0xff000000)71 protocols = RC_PROTO_BIT_NEC32;72 else if ((in->data | in->mask) & 0x00ff0000)73 protocols = RC_PROTO_BIT_NECX;74 else75 protocols = RC_PROTO_BIT_NEC;76 }77 78 if (protocols == RC_PROTO_BIT_NEC32) {79 /* 32-bit NEC (used by Apple and TiVo remotes) */80 /* scan encoding: as transmitted, MSBit = first received bit */81 addr = bitrev8(in->data >> 24);82 addr_m = bitrev8(in->mask >> 24);83 addr_inv = bitrev8(in->data >> 16);84 addr_inv_m = bitrev8(in->mask >> 16);85 data = bitrev8(in->data >> 8);86 data_m = bitrev8(in->mask >> 8);87 data_inv = bitrev8(in->data >> 0);88 data_inv_m = bitrev8(in->mask >> 0);89 } else if (protocols == RC_PROTO_BIT_NECX) {90 /* Extended NEC */91 /* scan encoding AAaaDD */92 addr = (in->data >> 16) & 0xff;93 addr_m = (in->mask >> 16) & 0xff;94 addr_inv = (in->data >> 8) & 0xff;95 addr_inv_m = (in->mask >> 8) & 0xff;96 data_inv = data ^ 0xff;97 data_inv_m = data_m;98 } else {99 /* Normal NEC */100 /* scan encoding: AADD */101 addr = (in->data >> 8) & 0xff;102 addr_m = (in->mask >> 8) & 0xff;103 addr_inv = addr ^ 0xff;104 addr_inv_m = addr_m;105 data_inv = data ^ 0xff;106 data_inv_m = data_m;107 }108 109 /* raw encoding: ddDDaaAA */110 out->data = data_inv << 24 |111 data << 16 |112 addr_inv << 8 |113 addr;114 out->mask = data_inv_m << 24 |115 data_m << 16 |116 addr_inv_m << 8 |117 addr_m;118 return 0;119}120 121/*122 * NEC decoder123 * See also http://www.sbprojects.com/knowledge/ir/nec.php124 * http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol125 */126struct img_ir_decoder img_ir_nec = {127 .type = RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32,128 .control = {129 .decoden = 1,130 .code_type = IMG_IR_CODETYPE_PULSEDIST,131 },132 /* main timings */133 .unit = 562500, /* 562.5 us */134 .timings = {135 /* leader symbol */136 .ldr = {137 .pulse = { 16 /* 9ms */ },138 .space = { 8 /* 4.5ms */ },139 },140 /* 0 symbol */141 .s00 = {142 .pulse = { 1 /* 562.5 us */ },143 .space = { 1 /* 562.5 us */ },144 },145 /* 1 symbol */146 .s01 = {147 .pulse = { 1 /* 562.5 us */ },148 .space = { 3 /* 1687.5 us */ },149 },150 /* free time */151 .ft = {152 .minlen = 32,153 .maxlen = 32,154 .ft_min = 10, /* 5.625 ms */155 },156 },157 /* repeat codes */158 .repeat = 108, /* 108 ms */159 .rtimings = {160 /* leader symbol */161 .ldr = {162 .space = { 4 /* 2.25 ms */ },163 },164 /* free time */165 .ft = {166 .minlen = 0, /* repeat code has no data */167 .maxlen = 0,168 },169 },170 /* scancode logic */171 .scancode = img_ir_nec_scancode,172 .filter = img_ir_nec_filter,173};174