img-ir-sony.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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_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_TYPE_SONY12;
  26. break;
  27. case 15:
  28. if (!(enabled_protocols & RC_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_TYPE_SONY15;
  35. break;
  36. case 20:
  37. if (!(enabled_protocols & RC_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_TYPE_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. if (subdev & subdev_m) {
  66. /* can't encode subdev and higher device bits */
  67. if (dev & dev_m & 0xe0)
  68. return -EINVAL;
  69. /* subdevice (extended) bits only in 20 bit encoding */
  70. if (!(protocols & RC_BIT_SONY20))
  71. return -EINVAL;
  72. len = 20;
  73. dev_m &= 0x1f;
  74. } else if (dev & dev_m & 0xe0) {
  75. /* upper device bits only in 15 bit encoding */
  76. if (!(protocols & RC_BIT_SONY15))
  77. return -EINVAL;
  78. len = 15;
  79. subdev_m = 0;
  80. } else {
  81. /*
  82. * The hardware mask cannot distinguish high device bits and low
  83. * extended bits, so logically AND those bits of the masks
  84. * together.
  85. */
  86. subdev_m &= (dev_m >> 5) | 0xf8;
  87. dev_m &= 0x1f;
  88. }
  89. /* ensure there aren't any bits straying between fields */
  90. dev &= dev_m;
  91. subdev &= subdev_m;
  92. /* write the hardware filter */
  93. out->data = func |
  94. dev << 7 |
  95. subdev << 15;
  96. out->mask = func_m |
  97. dev_m << 7 |
  98. subdev_m << 15;
  99. if (len) {
  100. out->minlen = len;
  101. out->maxlen = len;
  102. }
  103. return 0;
  104. }
  105. /*
  106. * Sony SIRC decoder
  107. * See also http://www.sbprojects.com/knowledge/ir/sirc.php
  108. * http://picprojects.org.uk/projects/sirc/sonysirc.pdf
  109. */
  110. struct img_ir_decoder img_ir_sony = {
  111. .type = RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20,
  112. .control = {
  113. .decoden = 1,
  114. .code_type = IMG_IR_CODETYPE_PULSELEN,
  115. },
  116. /* main timings */
  117. .unit = 600000, /* 600 us */
  118. .timings = {
  119. /* leader symbol */
  120. .ldr = {
  121. .pulse = { 4 /* 2.4 ms */ },
  122. .space = { 1 /* 600 us */ },
  123. },
  124. /* 0 symbol */
  125. .s00 = {
  126. .pulse = { 1 /* 600 us */ },
  127. .space = { 1 /* 600 us */ },
  128. },
  129. /* 1 symbol */
  130. .s01 = {
  131. .pulse = { 2 /* 1.2 ms */ },
  132. .space = { 1 /* 600 us */ },
  133. },
  134. /* free time */
  135. .ft = {
  136. .minlen = 12,
  137. .maxlen = 20,
  138. .ft_min = 10, /* 6 ms */
  139. },
  140. },
  141. /* scancode logic */
  142. .scancode = img_ir_sony_scancode,
  143. .filter = img_ir_sony_filter,
  144. };