123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /*
- * ImgTec IR Decoder setup for Sony (SIRC) protocol.
- *
- * Copyright 2012-2014 Imagination Technologies Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
- #include "img-ir-hw.h"
- /* Convert Sony data to a scancode */
- static int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols,
- struct img_ir_scancode_req *request)
- {
- unsigned int dev, subdev, func;
- switch (len) {
- case 12:
- if (!(enabled_protocols & RC_BIT_SONY12))
- return -EINVAL;
- func = raw & 0x7f; /* first 7 bits */
- raw >>= 7;
- dev = raw & 0x1f; /* next 5 bits */
- subdev = 0;
- request->protocol = RC_TYPE_SONY12;
- break;
- case 15:
- if (!(enabled_protocols & RC_BIT_SONY15))
- return -EINVAL;
- func = raw & 0x7f; /* first 7 bits */
- raw >>= 7;
- dev = raw & 0xff; /* next 8 bits */
- subdev = 0;
- request->protocol = RC_TYPE_SONY15;
- break;
- case 20:
- if (!(enabled_protocols & RC_BIT_SONY20))
- return -EINVAL;
- func = raw & 0x7f; /* first 7 bits */
- raw >>= 7;
- dev = raw & 0x1f; /* next 5 bits */
- raw >>= 5;
- subdev = raw & 0xff; /* next 8 bits */
- request->protocol = RC_TYPE_SONY20;
- break;
- default:
- return -EINVAL;
- }
- request->scancode = dev << 16 | subdev << 8 | func;
- return IMG_IR_SCANCODE;
- }
- /* Convert NEC scancode to NEC data filter */
- static int img_ir_sony_filter(const struct rc_scancode_filter *in,
- struct img_ir_filter *out, u64 protocols)
- {
- unsigned int dev, subdev, func;
- unsigned int dev_m, subdev_m, func_m;
- unsigned int len = 0;
- dev = (in->data >> 16) & 0xff;
- dev_m = (in->mask >> 16) & 0xff;
- subdev = (in->data >> 8) & 0xff;
- subdev_m = (in->mask >> 8) & 0xff;
- func = (in->data >> 0) & 0x7f;
- func_m = (in->mask >> 0) & 0x7f;
- if (subdev & subdev_m) {
- /* can't encode subdev and higher device bits */
- if (dev & dev_m & 0xe0)
- return -EINVAL;
- /* subdevice (extended) bits only in 20 bit encoding */
- if (!(protocols & RC_BIT_SONY20))
- return -EINVAL;
- len = 20;
- dev_m &= 0x1f;
- } else if (dev & dev_m & 0xe0) {
- /* upper device bits only in 15 bit encoding */
- if (!(protocols & RC_BIT_SONY15))
- return -EINVAL;
- len = 15;
- subdev_m = 0;
- } else {
- /*
- * The hardware mask cannot distinguish high device bits and low
- * extended bits, so logically AND those bits of the masks
- * together.
- */
- subdev_m &= (dev_m >> 5) | 0xf8;
- dev_m &= 0x1f;
- }
- /* ensure there aren't any bits straying between fields */
- dev &= dev_m;
- subdev &= subdev_m;
- /* write the hardware filter */
- out->data = func |
- dev << 7 |
- subdev << 15;
- out->mask = func_m |
- dev_m << 7 |
- subdev_m << 15;
- if (len) {
- out->minlen = len;
- out->maxlen = len;
- }
- return 0;
- }
- /*
- * Sony SIRC decoder
- * See also http://www.sbprojects.com/knowledge/ir/sirc.php
- * http://picprojects.org.uk/projects/sirc/sonysirc.pdf
- */
- struct img_ir_decoder img_ir_sony = {
- .type = RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20,
- .control = {
- .decoden = 1,
- .code_type = IMG_IR_CODETYPE_PULSELEN,
- },
- /* main timings */
- .unit = 600000, /* 600 us */
- .timings = {
- /* leader symbol */
- .ldr = {
- .pulse = { 4 /* 2.4 ms */ },
- .space = { 1 /* 600 us */ },
- },
- /* 0 symbol */
- .s00 = {
- .pulse = { 1 /* 600 us */ },
- .space = { 1 /* 600 us */ },
- },
- /* 1 symbol */
- .s01 = {
- .pulse = { 2 /* 1.2 ms */ },
- .space = { 1 /* 600 us */ },
- },
- /* free time */
- .ft = {
- .minlen = 12,
- .maxlen = 20,
- .ft_min = 10, /* 6 ms */
- },
- },
- /* scancode logic */
- .scancode = img_ir_sony_scancode,
- .filter = img_ir_sony_filter,
- };
|