img-ir-sony.c 4.0 KB

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