^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 Sony (SIRC) protocol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2012-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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /* Convert Sony data to a scancode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) static int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) struct img_ir_scancode_req *request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) unsigned int dev, subdev, func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) switch (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) case 12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) if (!(enabled_protocols & RC_PROTO_BIT_SONY12))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) func = raw & 0x7f; /* first 7 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) raw >>= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) dev = raw & 0x1f; /* next 5 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) subdev = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) request->protocol = RC_PROTO_SONY12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) case 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (!(enabled_protocols & RC_PROTO_BIT_SONY15))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) func = raw & 0x7f; /* first 7 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) raw >>= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) dev = raw & 0xff; /* next 8 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) subdev = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) request->protocol = RC_PROTO_SONY15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) case 20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (!(enabled_protocols & RC_PROTO_BIT_SONY20))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) func = raw & 0x7f; /* first 7 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) raw >>= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) dev = raw & 0x1f; /* next 5 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) raw >>= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) subdev = raw & 0xff; /* next 8 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) request->protocol = RC_PROTO_SONY20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) request->scancode = dev << 16 | subdev << 8 | func;
^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_sony_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 dev, subdev, func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned int dev_m, subdev_m, func_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) dev = (in->data >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) dev_m = (in->mask >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) subdev = (in->data >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) subdev_m = (in->mask >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) func = (in->data >> 0) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) func_m = (in->mask >> 0) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) protocols &= RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) RC_PROTO_BIT_SONY20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * If only one bit is set, we were requested to do an exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * protocol. This should be the case for wakeup filters; for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * normal filters, guess the protocol from the scancode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!is_power_of_2(protocols)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (subdev & subdev_m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) protocols = RC_PROTO_BIT_SONY20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) else if (dev & dev_m & 0xe0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) protocols = RC_PROTO_BIT_SONY15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) protocols = RC_PROTO_BIT_SONY12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (protocols == RC_PROTO_BIT_SONY20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* can't encode subdev and higher device bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (dev & dev_m & 0xe0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) len = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) dev_m &= 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) } else if (protocols == RC_PROTO_BIT_SONY15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) len = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) subdev_m = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * The hardware mask cannot distinguish high device bits and low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * extended bits, so logically AND those bits of the masks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * together.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) subdev_m &= (dev_m >> 5) | 0xf8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) dev_m &= 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* ensure there aren't any bits straying between fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) dev &= dev_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) subdev &= subdev_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* write the hardware filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) out->data = func |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) dev << 7 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) subdev << 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) out->mask = func_m |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dev_m << 7 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) subdev_m << 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) out->minlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) out->maxlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return 0;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Sony SIRC decoder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * See also http://www.sbprojects.com/knowledge/ir/sirc.php
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * http://picprojects.org.uk/projects/sirc/sonysirc.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct img_ir_decoder img_ir_sony = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .type = RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 | RC_PROTO_BIT_SONY20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .control = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .decoden = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .code_type = IMG_IR_CODETYPE_PULSELEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* main timings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .unit = 600000, /* 600 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .timings = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* leader symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .ldr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .pulse = { 4 /* 2.4 ms */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .space = { 1 /* 600 us */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* 0 symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .s00 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .pulse = { 1 /* 600 us */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .space = { 1 /* 600 us */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* 1 symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .s01 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .pulse = { 2 /* 1.2 ms */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .space = { 1 /* 600 us */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* free time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .ft = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .minlen = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .maxlen = 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .ft_min = 10, /* 6 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* scancode logic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .scancode = img_ir_sony_scancode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .filter = img_ir_sony_filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };