Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * ImgTec IR Decoder setup for Sony (SIRC) protocol.
0004  *
0005  * Copyright 2012-2014 Imagination Technologies Ltd.
0006  */
0007 
0008 #include "img-ir-hw.h"
0009 
0010 /* Convert Sony data to a scancode */
0011 static int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols,
0012                 struct img_ir_scancode_req *request)
0013 {
0014     unsigned int dev, subdev, func;
0015 
0016     switch (len) {
0017     case 12:
0018         if (!(enabled_protocols & RC_PROTO_BIT_SONY12))
0019             return -EINVAL;
0020         func   = raw & 0x7f;    /* first 7 bits */
0021         raw    >>= 7;
0022         dev    = raw & 0x1f;    /* next 5 bits */
0023         subdev = 0;
0024         request->protocol = RC_PROTO_SONY12;
0025         break;
0026     case 15:
0027         if (!(enabled_protocols & RC_PROTO_BIT_SONY15))
0028             return -EINVAL;
0029         func   = raw & 0x7f;    /* first 7 bits */
0030         raw    >>= 7;
0031         dev    = raw & 0xff;    /* next 8 bits */
0032         subdev = 0;
0033         request->protocol = RC_PROTO_SONY15;
0034         break;
0035     case 20:
0036         if (!(enabled_protocols & RC_PROTO_BIT_SONY20))
0037             return -EINVAL;
0038         func   = raw & 0x7f;    /* first 7 bits */
0039         raw    >>= 7;
0040         dev    = raw & 0x1f;    /* next 5 bits */
0041         raw    >>= 5;
0042         subdev = raw & 0xff;    /* next 8 bits */
0043         request->protocol = RC_PROTO_SONY20;
0044         break;
0045     default:
0046         return -EINVAL;
0047     }
0048     request->scancode = dev << 16 | subdev << 8 | func;
0049     return IMG_IR_SCANCODE;
0050 }
0051 
0052 /* Convert NEC scancode to NEC data filter */
0053 static int img_ir_sony_filter(const struct rc_scancode_filter *in,
0054                   struct img_ir_filter *out, u64 protocols)
0055 {
0056     unsigned int dev, subdev, func;
0057     unsigned int dev_m, subdev_m, func_m;
0058     unsigned int len = 0;
0059 
0060     dev      = (in->data >> 16) & 0xff;
0061     dev_m    = (in->mask >> 16) & 0xff;
0062     subdev   = (in->data >> 8)  & 0xff;
0063     subdev_m = (in->mask >> 8)  & 0xff;
0064     func     = (in->data >> 0)  & 0x7f;
0065     func_m   = (in->mask >> 0)  & 0x7f;
0066 
0067     protocols &= RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 |
0068                             RC_PROTO_BIT_SONY20;
0069 
0070     /*
0071      * If only one bit is set, we were requested to do an exact
0072      * protocol. This should be the case for wakeup filters; for
0073      * normal filters, guess the protocol from the scancode.
0074      */
0075     if (!is_power_of_2(protocols)) {
0076         if (subdev & subdev_m)
0077             protocols = RC_PROTO_BIT_SONY20;
0078         else if (dev & dev_m & 0xe0)
0079             protocols = RC_PROTO_BIT_SONY15;
0080         else
0081             protocols = RC_PROTO_BIT_SONY12;
0082     }
0083 
0084     if (protocols == RC_PROTO_BIT_SONY20) {
0085         /* can't encode subdev and higher device bits */
0086         if (dev & dev_m & 0xe0)
0087             return -EINVAL;
0088         len = 20;
0089         dev_m &= 0x1f;
0090     } else if (protocols == RC_PROTO_BIT_SONY15) {
0091         len = 15;
0092         subdev_m = 0;
0093     } else {
0094         /*
0095          * The hardware mask cannot distinguish high device bits and low
0096          * extended bits, so logically AND those bits of the masks
0097          * together.
0098          */
0099         subdev_m &= (dev_m >> 5) | 0xf8;
0100         dev_m &= 0x1f;
0101     }
0102 
0103     /* ensure there aren't any bits straying between fields */
0104     dev &= dev_m;
0105     subdev &= subdev_m;
0106 
0107     /* write the hardware filter */
0108     out->data = func          |
0109             dev      << 7 |
0110             subdev   << 15;
0111     out->mask = func_m        |
0112             dev_m    << 7 |
0113             subdev_m << 15;
0114 
0115     if (len) {
0116         out->minlen = len;
0117         out->maxlen = len;
0118     }
0119     return 0;
0120 }
0121 
0122 /*
0123  * Sony SIRC decoder
0124  * See also http://www.sbprojects.com/knowledge/ir/sirc.php
0125  *          http://picprojects.org.uk/projects/sirc/sonysirc.pdf
0126  */
0127 struct img_ir_decoder img_ir_sony = {
0128     .type = RC_PROTO_BIT_SONY12 | RC_PROTO_BIT_SONY15 | RC_PROTO_BIT_SONY20,
0129     .control = {
0130         .decoden = 1,
0131         .code_type = IMG_IR_CODETYPE_PULSELEN,
0132     },
0133     /* main timings */
0134     .unit = 600000, /* 600 us */
0135     .timings = {
0136         /* leader symbol */
0137         .ldr = {
0138             .pulse = { 4    /* 2.4 ms */ },
0139             .space = { 1    /* 600 us */ },
0140         },
0141         /* 0 symbol */
0142         .s00 = {
0143             .pulse = { 1    /* 600 us */ },
0144             .space = { 1    /* 600 us */ },
0145         },
0146         /* 1 symbol */
0147         .s01 = {
0148             .pulse = { 2    /* 1.2 ms */ },
0149             .space = { 1    /* 600 us */ },
0150         },
0151         /* free time */
0152         .ft = {
0153             .minlen = 12,
0154             .maxlen = 20,
0155             .ft_min = 10,   /* 6 ms */
0156         },
0157     },
0158     /* scancode logic */
0159     .scancode = img_ir_sony_scancode,
0160     .filter = img_ir_sony_filter,
0161 };