1e72b21abSJames Hogan /* 2e72b21abSJames Hogan * ImgTec IR Decoder setup for Sony (SIRC) protocol. 3e72b21abSJames Hogan * 4e72b21abSJames Hogan * Copyright 2012-2014 Imagination Technologies Ltd. 52ac6f630SJames Hogan * 62ac6f630SJames Hogan * This program is free software; you can redistribute it and/or modify 72ac6f630SJames Hogan * it under the terms of the GNU General Public License as published by the 82ac6f630SJames Hogan * Free Software Foundation; either version 2 of the License, or (at your 92ac6f630SJames Hogan * option) any later version. 10e72b21abSJames Hogan */ 11e72b21abSJames Hogan 12e72b21abSJames Hogan #include "img-ir-hw.h" 13e72b21abSJames Hogan 14e72b21abSJames Hogan /* Convert Sony data to a scancode */ 15ab93ce06SSifan Naeem static int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols, 16ab93ce06SSifan Naeem struct img_ir_scancode_req *request) 17e72b21abSJames Hogan { 18e72b21abSJames Hogan unsigned int dev, subdev, func; 19e72b21abSJames Hogan 20e72b21abSJames Hogan switch (len) { 21e72b21abSJames Hogan case 12: 226d741bfeSSean Young if (!(enabled_protocols & RC_PROTO_BIT_SONY12)) 23e72b21abSJames Hogan return -EINVAL; 24e72b21abSJames Hogan func = raw & 0x7f; /* first 7 bits */ 25e72b21abSJames Hogan raw >>= 7; 26e72b21abSJames Hogan dev = raw & 0x1f; /* next 5 bits */ 27e72b21abSJames Hogan subdev = 0; 286d741bfeSSean Young request->protocol = RC_PROTO_SONY12; 29e72b21abSJames Hogan break; 30e72b21abSJames Hogan case 15: 316d741bfeSSean Young if (!(enabled_protocols & RC_PROTO_BIT_SONY15)) 32e72b21abSJames Hogan return -EINVAL; 33e72b21abSJames Hogan func = raw & 0x7f; /* first 7 bits */ 34e72b21abSJames Hogan raw >>= 7; 35e72b21abSJames Hogan dev = raw & 0xff; /* next 8 bits */ 36e72b21abSJames Hogan subdev = 0; 376d741bfeSSean Young request->protocol = RC_PROTO_SONY15; 38e72b21abSJames Hogan break; 39e72b21abSJames Hogan case 20: 406d741bfeSSean Young if (!(enabled_protocols & RC_PROTO_BIT_SONY20)) 41e72b21abSJames Hogan return -EINVAL; 42e72b21abSJames Hogan func = raw & 0x7f; /* first 7 bits */ 43e72b21abSJames Hogan raw >>= 7; 44e72b21abSJames Hogan dev = raw & 0x1f; /* next 5 bits */ 45e72b21abSJames Hogan raw >>= 5; 46e72b21abSJames Hogan subdev = raw & 0xff; /* next 8 bits */ 476d741bfeSSean Young request->protocol = RC_PROTO_SONY20; 48e72b21abSJames Hogan break; 49e72b21abSJames Hogan default: 50e72b21abSJames Hogan return -EINVAL; 51e72b21abSJames Hogan } 52ab93ce06SSifan Naeem request->scancode = dev << 16 | subdev << 8 | func; 53e72b21abSJames Hogan return IMG_IR_SCANCODE; 54e72b21abSJames Hogan } 55e72b21abSJames Hogan 56e72b21abSJames Hogan /* Convert NEC scancode to NEC data filter */ 57e72b21abSJames Hogan static int img_ir_sony_filter(const struct rc_scancode_filter *in, 58e72b21abSJames Hogan struct img_ir_filter *out, u64 protocols) 59e72b21abSJames Hogan { 60e72b21abSJames Hogan unsigned int dev, subdev, func; 61e72b21abSJames Hogan unsigned int dev_m, subdev_m, func_m; 62e72b21abSJames Hogan unsigned int len = 0; 63e72b21abSJames Hogan 64e72b21abSJames Hogan dev = (in->data >> 16) & 0xff; 65e72b21abSJames Hogan dev_m = (in->mask >> 16) & 0xff; 66e72b21abSJames Hogan subdev = (in->data >> 8) & 0xff; 67e72b21abSJames Hogan subdev_m = (in->mask >> 8) & 0xff; 68e72b21abSJames Hogan func = (in->data >> 0) & 0x7f; 69e72b21abSJames Hogan func_m = (in->mask >> 0) & 0x7f; 70e72b21abSJames Hogan 716d741bfeSSean Young protocols &= RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 | 726d741bfeSSean Young RC_PROTO_BIT_SONY20; 730751d33cSSean Young 740751d33cSSean Young /* 750751d33cSSean Young * If only one bit is set, we were requested to do an exact 760751d33cSSean Young * protocol. This should be the case for wakeup filters; for 770751d33cSSean Young * normal filters, guess the protocol from the scancode. 780751d33cSSean Young */ 790751d33cSSean Young if (!is_power_of_2(protocols)) { 800751d33cSSean Young if (subdev & subdev_m) 816d741bfeSSean Young protocols = RC_PROTO_BIT_SONY20; 820751d33cSSean Young else if (dev & dev_m & 0xe0) 836d741bfeSSean Young protocols = RC_PROTO_BIT_SONY15; 840751d33cSSean Young else 856d741bfeSSean Young protocols = RC_PROTO_BIT_SONY12; 860751d33cSSean Young } 870751d33cSSean Young 886d741bfeSSean Young if (protocols == RC_PROTO_BIT_SONY20) { 89e72b21abSJames Hogan /* can't encode subdev and higher device bits */ 90e72b21abSJames Hogan if (dev & dev_m & 0xe0) 91e72b21abSJames Hogan return -EINVAL; 92e72b21abSJames Hogan len = 20; 93e72b21abSJames Hogan dev_m &= 0x1f; 946d741bfeSSean Young } else if (protocols == RC_PROTO_BIT_SONY15) { 95e72b21abSJames Hogan len = 15; 96e72b21abSJames Hogan subdev_m = 0; 97e72b21abSJames Hogan } else { 98e72b21abSJames Hogan /* 99e72b21abSJames Hogan * The hardware mask cannot distinguish high device bits and low 100e72b21abSJames Hogan * extended bits, so logically AND those bits of the masks 101e72b21abSJames Hogan * together. 102e72b21abSJames Hogan */ 103e72b21abSJames Hogan subdev_m &= (dev_m >> 5) | 0xf8; 104e72b21abSJames Hogan dev_m &= 0x1f; 105e72b21abSJames Hogan } 106e72b21abSJames Hogan 107e72b21abSJames Hogan /* ensure there aren't any bits straying between fields */ 108e72b21abSJames Hogan dev &= dev_m; 109e72b21abSJames Hogan subdev &= subdev_m; 110e72b21abSJames Hogan 111e72b21abSJames Hogan /* write the hardware filter */ 112e72b21abSJames Hogan out->data = func | 113e72b21abSJames Hogan dev << 7 | 114e72b21abSJames Hogan subdev << 15; 115e72b21abSJames Hogan out->mask = func_m | 116e72b21abSJames Hogan dev_m << 7 | 117e72b21abSJames Hogan subdev_m << 15; 118e72b21abSJames Hogan 119e72b21abSJames Hogan if (len) { 120e72b21abSJames Hogan out->minlen = len; 121e72b21abSJames Hogan out->maxlen = len; 122e72b21abSJames Hogan } 123e72b21abSJames Hogan return 0; 124e72b21abSJames Hogan } 125e72b21abSJames Hogan 126e72b21abSJames Hogan /* 127e72b21abSJames Hogan * Sony SIRC decoder 128e72b21abSJames Hogan * See also http://www.sbprojects.com/knowledge/ir/sirc.php 129e72b21abSJames Hogan * http://picprojects.org.uk/projects/sirc/sonysirc.pdf 130e72b21abSJames Hogan */ 131e72b21abSJames Hogan struct img_ir_decoder img_ir_sony = { 1326d741bfeSSean Young .type = RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 | RC_PROTO_BIT_SONY20, 133e72b21abSJames Hogan .control = { 134e72b21abSJames Hogan .decoden = 1, 135e72b21abSJames Hogan .code_type = IMG_IR_CODETYPE_PULSELEN, 136e72b21abSJames Hogan }, 137e72b21abSJames Hogan /* main timings */ 138e72b21abSJames Hogan .unit = 600000, /* 600 us */ 139e72b21abSJames Hogan .timings = { 140e72b21abSJames Hogan /* leader symbol */ 141e72b21abSJames Hogan .ldr = { 142e72b21abSJames Hogan .pulse = { 4 /* 2.4 ms */ }, 143e72b21abSJames Hogan .space = { 1 /* 600 us */ }, 144e72b21abSJames Hogan }, 145e72b21abSJames Hogan /* 0 symbol */ 146e72b21abSJames Hogan .s00 = { 147e72b21abSJames Hogan .pulse = { 1 /* 600 us */ }, 148e72b21abSJames Hogan .space = { 1 /* 600 us */ }, 149e72b21abSJames Hogan }, 150e72b21abSJames Hogan /* 1 symbol */ 151e72b21abSJames Hogan .s01 = { 152e72b21abSJames Hogan .pulse = { 2 /* 1.2 ms */ }, 153e72b21abSJames Hogan .space = { 1 /* 600 us */ }, 154e72b21abSJames Hogan }, 155e72b21abSJames Hogan /* free time */ 156e72b21abSJames Hogan .ft = { 157e72b21abSJames Hogan .minlen = 12, 158e72b21abSJames Hogan .maxlen = 20, 159e72b21abSJames Hogan .ft_min = 10, /* 6 ms */ 160e72b21abSJames Hogan }, 161e72b21abSJames Hogan }, 162e72b21abSJames Hogan /* scancode logic */ 163e72b21abSJames Hogan .scancode = img_ir_sony_scancode, 164e72b21abSJames Hogan .filter = img_ir_sony_filter, 165e72b21abSJames Hogan }; 166