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