diff options
-rw-r--r-- | drivers/media/rc/img-ir/Kconfig | 7 | ||||
-rw-r--r-- | drivers/media/rc/img-ir/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/rc/img-ir/img-ir-hw.c | 4 | ||||
-rw-r--r-- | drivers/media/rc/img-ir/img-ir-sony.c | 145 |
4 files changed, 157 insertions, 0 deletions
diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index 96006fbfb0d6..ab365778b5d2 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig | |||
@@ -38,3 +38,10 @@ config IR_IMG_JVC | |||
38 | help | 38 | help |
39 | Say Y here to enable support for the JVC protocol in the ImgTec | 39 | Say Y here to enable support for the JVC protocol in the ImgTec |
40 | infrared decoder block. | 40 | infrared decoder block. |
41 | |||
42 | config IR_IMG_SONY | ||
43 | bool "Sony protocol support" | ||
44 | depends on IR_IMG_HW | ||
45 | help | ||
46 | Say Y here to enable support for the Sony protocol in the ImgTec | ||
47 | infrared decoder block. | ||
diff --git a/drivers/media/rc/img-ir/Makefile b/drivers/media/rc/img-ir/Makefile index c5f8f06c89eb..978c0c6713ab 100644 --- a/drivers/media/rc/img-ir/Makefile +++ b/drivers/media/rc/img-ir/Makefile | |||
@@ -3,6 +3,7 @@ img-ir-$(CONFIG_IR_IMG_RAW) += img-ir-raw.o | |||
3 | img-ir-$(CONFIG_IR_IMG_HW) += img-ir-hw.o | 3 | img-ir-$(CONFIG_IR_IMG_HW) += img-ir-hw.o |
4 | img-ir-$(CONFIG_IR_IMG_NEC) += img-ir-nec.o | 4 | img-ir-$(CONFIG_IR_IMG_NEC) += img-ir-nec.o |
5 | img-ir-$(CONFIG_IR_IMG_JVC) += img-ir-jvc.o | 5 | img-ir-$(CONFIG_IR_IMG_JVC) += img-ir-jvc.o |
6 | img-ir-$(CONFIG_IR_IMG_SONY) += img-ir-sony.o | ||
6 | img-ir-objs := $(img-ir-y) | 7 | img-ir-objs := $(img-ir-y) |
7 | 8 | ||
8 | obj-$(CONFIG_IR_IMG) += img-ir.o | 9 | obj-$(CONFIG_IR_IMG) += img-ir.o |
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 81c50e3f88d9..0d4f9211f9f2 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c | |||
@@ -22,6 +22,7 @@ static DEFINE_SPINLOCK(img_ir_decoders_lock); | |||
22 | 22 | ||
23 | extern struct img_ir_decoder img_ir_nec; | 23 | extern struct img_ir_decoder img_ir_nec; |
24 | extern struct img_ir_decoder img_ir_jvc; | 24 | extern struct img_ir_decoder img_ir_jvc; |
25 | extern struct img_ir_decoder img_ir_sony; | ||
25 | 26 | ||
26 | static bool img_ir_decoders_preprocessed; | 27 | static bool img_ir_decoders_preprocessed; |
27 | static struct img_ir_decoder *img_ir_decoders[] = { | 28 | static struct img_ir_decoder *img_ir_decoders[] = { |
@@ -31,6 +32,9 @@ static struct img_ir_decoder *img_ir_decoders[] = { | |||
31 | #ifdef CONFIG_IR_IMG_JVC | 32 | #ifdef CONFIG_IR_IMG_JVC |
32 | &img_ir_jvc, | 33 | &img_ir_jvc, |
33 | #endif | 34 | #endif |
35 | #ifdef CONFIG_IR_IMG_SONY | ||
36 | &img_ir_sony, | ||
37 | #endif | ||
34 | NULL | 38 | NULL |
35 | }; | 39 | }; |
36 | 40 | ||
diff --git a/drivers/media/rc/img-ir/img-ir-sony.c b/drivers/media/rc/img-ir/img-ir-sony.c new file mode 100644 index 000000000000..993409a51a71 --- /dev/null +++ b/drivers/media/rc/img-ir/img-ir-sony.c | |||
@@ -0,0 +1,145 @@ | |||
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 | }; | ||