162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ImgTec IR Decoder setup for Sony (SIRC) protocol. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2012-2014 Imagination Technologies Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "img-ir-hw.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* Convert Sony data to a scancode */ 1162306a36Sopenharmony_cistatic int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols, 1262306a36Sopenharmony_ci struct img_ir_scancode_req *request) 1362306a36Sopenharmony_ci{ 1462306a36Sopenharmony_ci unsigned int dev, subdev, func; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci switch (len) { 1762306a36Sopenharmony_ci case 12: 1862306a36Sopenharmony_ci if (!(enabled_protocols & RC_PROTO_BIT_SONY12)) 1962306a36Sopenharmony_ci return -EINVAL; 2062306a36Sopenharmony_ci func = raw & 0x7f; /* first 7 bits */ 2162306a36Sopenharmony_ci raw >>= 7; 2262306a36Sopenharmony_ci dev = raw & 0x1f; /* next 5 bits */ 2362306a36Sopenharmony_ci subdev = 0; 2462306a36Sopenharmony_ci request->protocol = RC_PROTO_SONY12; 2562306a36Sopenharmony_ci break; 2662306a36Sopenharmony_ci case 15: 2762306a36Sopenharmony_ci if (!(enabled_protocols & RC_PROTO_BIT_SONY15)) 2862306a36Sopenharmony_ci return -EINVAL; 2962306a36Sopenharmony_ci func = raw & 0x7f; /* first 7 bits */ 3062306a36Sopenharmony_ci raw >>= 7; 3162306a36Sopenharmony_ci dev = raw & 0xff; /* next 8 bits */ 3262306a36Sopenharmony_ci subdev = 0; 3362306a36Sopenharmony_ci request->protocol = RC_PROTO_SONY15; 3462306a36Sopenharmony_ci break; 3562306a36Sopenharmony_ci case 20: 3662306a36Sopenharmony_ci if (!(enabled_protocols & RC_PROTO_BIT_SONY20)) 3762306a36Sopenharmony_ci return -EINVAL; 3862306a36Sopenharmony_ci func = raw & 0x7f; /* first 7 bits */ 3962306a36Sopenharmony_ci raw >>= 7; 4062306a36Sopenharmony_ci dev = raw & 0x1f; /* next 5 bits */ 4162306a36Sopenharmony_ci raw >>= 5; 4262306a36Sopenharmony_ci subdev = raw & 0xff; /* next 8 bits */ 4362306a36Sopenharmony_ci request->protocol = RC_PROTO_SONY20; 4462306a36Sopenharmony_ci break; 4562306a36Sopenharmony_ci default: 4662306a36Sopenharmony_ci return -EINVAL; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci request->scancode = dev << 16 | subdev << 8 | func; 4962306a36Sopenharmony_ci return IMG_IR_SCANCODE; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* Convert NEC scancode to NEC data filter */ 5362306a36Sopenharmony_cistatic int img_ir_sony_filter(const struct rc_scancode_filter *in, 5462306a36Sopenharmony_ci struct img_ir_filter *out, u64 protocols) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci unsigned int dev, subdev, func; 5762306a36Sopenharmony_ci unsigned int dev_m, subdev_m, func_m; 5862306a36Sopenharmony_ci unsigned int len = 0; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci dev = (in->data >> 16) & 0xff; 6162306a36Sopenharmony_ci dev_m = (in->mask >> 16) & 0xff; 6262306a36Sopenharmony_ci subdev = (in->data >> 8) & 0xff; 6362306a36Sopenharmony_ci subdev_m = (in->mask >> 8) & 0xff; 6462306a36Sopenharmony_ci func = (in->data >> 0) & 0x7f; 6562306a36Sopenharmony_ci func_m = (in->mask >> 0) & 0x7f; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci protocols &= RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 | 6862306a36Sopenharmony_ci RC_PROTO_BIT_SONY20; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* 7162306a36Sopenharmony_ci * If only one bit is set, we were requested to do an exact 7262306a36Sopenharmony_ci * protocol. This should be the case for wakeup filters; for 7362306a36Sopenharmony_ci * normal filters, guess the protocol from the scancode. 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci if (!is_power_of_2(protocols)) { 7662306a36Sopenharmony_ci if (subdev & subdev_m) 7762306a36Sopenharmony_ci protocols = RC_PROTO_BIT_SONY20; 7862306a36Sopenharmony_ci else if (dev & dev_m & 0xe0) 7962306a36Sopenharmony_ci protocols = RC_PROTO_BIT_SONY15; 8062306a36Sopenharmony_ci else 8162306a36Sopenharmony_ci protocols = RC_PROTO_BIT_SONY12; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci if (protocols == RC_PROTO_BIT_SONY20) { 8562306a36Sopenharmony_ci /* can't encode subdev and higher device bits */ 8662306a36Sopenharmony_ci if (dev & dev_m & 0xe0) 8762306a36Sopenharmony_ci return -EINVAL; 8862306a36Sopenharmony_ci len = 20; 8962306a36Sopenharmony_ci dev_m &= 0x1f; 9062306a36Sopenharmony_ci } else if (protocols == RC_PROTO_BIT_SONY15) { 9162306a36Sopenharmony_ci len = 15; 9262306a36Sopenharmony_ci subdev_m = 0; 9362306a36Sopenharmony_ci } else { 9462306a36Sopenharmony_ci /* 9562306a36Sopenharmony_ci * The hardware mask cannot distinguish high device bits and low 9662306a36Sopenharmony_ci * extended bits, so logically AND those bits of the masks 9762306a36Sopenharmony_ci * together. 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ci subdev_m &= (dev_m >> 5) | 0xf8; 10062306a36Sopenharmony_ci dev_m &= 0x1f; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* ensure there aren't any bits straying between fields */ 10462306a36Sopenharmony_ci dev &= dev_m; 10562306a36Sopenharmony_ci subdev &= subdev_m; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* write the hardware filter */ 10862306a36Sopenharmony_ci out->data = func | 10962306a36Sopenharmony_ci dev << 7 | 11062306a36Sopenharmony_ci subdev << 15; 11162306a36Sopenharmony_ci out->mask = func_m | 11262306a36Sopenharmony_ci dev_m << 7 | 11362306a36Sopenharmony_ci subdev_m << 15; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (len) { 11662306a36Sopenharmony_ci out->minlen = len; 11762306a36Sopenharmony_ci out->maxlen = len; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* 12362306a36Sopenharmony_ci * Sony SIRC decoder 12462306a36Sopenharmony_ci * See also http://www.sbprojects.com/knowledge/ir/sirc.php 12562306a36Sopenharmony_ci * http://picprojects.org.uk/projects/sirc/sonysirc.pdf 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_cistruct img_ir_decoder img_ir_sony = { 12862306a36Sopenharmony_ci .type = RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 | RC_PROTO_BIT_SONY20, 12962306a36Sopenharmony_ci .control = { 13062306a36Sopenharmony_ci .decoden = 1, 13162306a36Sopenharmony_ci .code_type = IMG_IR_CODETYPE_PULSELEN, 13262306a36Sopenharmony_ci }, 13362306a36Sopenharmony_ci /* main timings */ 13462306a36Sopenharmony_ci .unit = 600000, /* 600 us */ 13562306a36Sopenharmony_ci .timings = { 13662306a36Sopenharmony_ci /* leader symbol */ 13762306a36Sopenharmony_ci .ldr = { 13862306a36Sopenharmony_ci .pulse = { 4 /* 2.4 ms */ }, 13962306a36Sopenharmony_ci .space = { 1 /* 600 us */ }, 14062306a36Sopenharmony_ci }, 14162306a36Sopenharmony_ci /* 0 symbol */ 14262306a36Sopenharmony_ci .s00 = { 14362306a36Sopenharmony_ci .pulse = { 1 /* 600 us */ }, 14462306a36Sopenharmony_ci .space = { 1 /* 600 us */ }, 14562306a36Sopenharmony_ci }, 14662306a36Sopenharmony_ci /* 1 symbol */ 14762306a36Sopenharmony_ci .s01 = { 14862306a36Sopenharmony_ci .pulse = { 2 /* 1.2 ms */ }, 14962306a36Sopenharmony_ci .space = { 1 /* 600 us */ }, 15062306a36Sopenharmony_ci }, 15162306a36Sopenharmony_ci /* free time */ 15262306a36Sopenharmony_ci .ft = { 15362306a36Sopenharmony_ci .minlen = 12, 15462306a36Sopenharmony_ci .maxlen = 20, 15562306a36Sopenharmony_ci .ft_min = 10, /* 6 ms */ 15662306a36Sopenharmony_ci }, 15762306a36Sopenharmony_ci }, 15862306a36Sopenharmony_ci /* scancode logic */ 15962306a36Sopenharmony_ci .scancode = img_ir_sony_scancode, 16062306a36Sopenharmony_ci .filter = img_ir_sony_filter, 16162306a36Sopenharmony_ci}; 162