1 /* 2 * ImgTec IR Decoder setup for Sony (SIRC) protocol. 3 * 4 * Copyright 2012-2014 Imagination Technologies Ltd. 5 */ 6 7 #include "img-ir-hw.h" 8 9 /* Convert Sony data to a scancode */ 10 static int img_ir_sony_scancode(int len, u64 raw, int *scancode, u64 protocols) 11 { 12 unsigned int dev, subdev, func; 13 14 switch (len) { 15 case 12: 16 if (!(protocols & RC_BIT_SONY12)) 17 return -EINVAL; 18 func = raw & 0x7f; /* first 7 bits */ 19 raw >>= 7; 20 dev = raw & 0x1f; /* next 5 bits */ 21 subdev = 0; 22 break; 23 case 15: 24 if (!(protocols & RC_BIT_SONY15)) 25 return -EINVAL; 26 func = raw & 0x7f; /* first 7 bits */ 27 raw >>= 7; 28 dev = raw & 0xff; /* next 8 bits */ 29 subdev = 0; 30 break; 31 case 20: 32 if (!(protocols & RC_BIT_SONY20)) 33 return -EINVAL; 34 func = raw & 0x7f; /* first 7 bits */ 35 raw >>= 7; 36 dev = raw & 0x1f; /* next 5 bits */ 37 raw >>= 5; 38 subdev = raw & 0xff; /* next 8 bits */ 39 break; 40 default: 41 return -EINVAL; 42 } 43 *scancode = dev << 16 | subdev << 8 | func; 44 return IMG_IR_SCANCODE; 45 } 46 47 /* Convert NEC scancode to NEC data filter */ 48 static int img_ir_sony_filter(const struct rc_scancode_filter *in, 49 struct img_ir_filter *out, u64 protocols) 50 { 51 unsigned int dev, subdev, func; 52 unsigned int dev_m, subdev_m, func_m; 53 unsigned int len = 0; 54 55 dev = (in->data >> 16) & 0xff; 56 dev_m = (in->mask >> 16) & 0xff; 57 subdev = (in->data >> 8) & 0xff; 58 subdev_m = (in->mask >> 8) & 0xff; 59 func = (in->data >> 0) & 0x7f; 60 func_m = (in->mask >> 0) & 0x7f; 61 62 if (subdev & subdev_m) { 63 /* can't encode subdev and higher device bits */ 64 if (dev & dev_m & 0xe0) 65 return -EINVAL; 66 /* subdevice (extended) bits only in 20 bit encoding */ 67 if (!(protocols & RC_BIT_SONY20)) 68 return -EINVAL; 69 len = 20; 70 dev_m &= 0x1f; 71 } else if (dev & dev_m & 0xe0) { 72 /* upper device bits only in 15 bit encoding */ 73 if (!(protocols & RC_BIT_SONY15)) 74 return -EINVAL; 75 len = 15; 76 subdev_m = 0; 77 } else { 78 /* 79 * The hardware mask cannot distinguish high device bits and low 80 * extended bits, so logically AND those bits of the masks 81 * together. 82 */ 83 subdev_m &= (dev_m >> 5) | 0xf8; 84 dev_m &= 0x1f; 85 } 86 87 /* ensure there aren't any bits straying between fields */ 88 dev &= dev_m; 89 subdev &= subdev_m; 90 91 /* write the hardware filter */ 92 out->data = func | 93 dev << 7 | 94 subdev << 15; 95 out->mask = func_m | 96 dev_m << 7 | 97 subdev_m << 15; 98 99 if (len) { 100 out->minlen = len; 101 out->maxlen = len; 102 } 103 return 0; 104 } 105 106 /* 107 * Sony SIRC decoder 108 * See also http://www.sbprojects.com/knowledge/ir/sirc.php 109 * http://picprojects.org.uk/projects/sirc/sonysirc.pdf 110 */ 111 struct img_ir_decoder img_ir_sony = { 112 .type = RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20, 113 .control = { 114 .decoden = 1, 115 .code_type = IMG_IR_CODETYPE_PULSELEN, 116 }, 117 /* main timings */ 118 .unit = 600000, /* 600 us */ 119 .timings = { 120 /* leader symbol */ 121 .ldr = { 122 .pulse = { 4 /* 2.4 ms */ }, 123 .space = { 1 /* 600 us */ }, 124 }, 125 /* 0 symbol */ 126 .s00 = { 127 .pulse = { 1 /* 600 us */ }, 128 .space = { 1 /* 600 us */ }, 129 }, 130 /* 1 symbol */ 131 .s01 = { 132 .pulse = { 2 /* 1.2 ms */ }, 133 .space = { 1 /* 600 us */ }, 134 }, 135 /* free time */ 136 .ft = { 137 .minlen = 12, 138 .maxlen = 20, 139 .ft_min = 10, /* 6 ms */ 140 }, 141 }, 142 /* scancode logic */ 143 .scancode = img_ir_sony_scancode, 144 .filter = img_ir_sony_filter, 145 }; 146