diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 12:35:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 12:35:11 -0400 |
commit | 0851668fdd97e526b2a41f794b785c204dd3d3e0 (patch) | |
tree | 4ef7c20a8be8393006c6fe9627eb29dd30877d61 /drivers/media/IR/ir-lirc-codec.c | |
parent | 00ebb6382b8d9c7c15b5f8ad230670d8161d38dd (diff) | |
parent | 7655e594945289b418af39f6669fea4666a7b520 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (505 commits)
[media] af9015: Fix max I2C message size when used with tda18271
[media] IR: initialize ir_raw_event in few more drivers
[media] Guard a divide in v4l1 compat layer
[media] imon: fix nomouse modprobe option
[media] imon: remove redundant change_protocol call
[media] imon: fix my egregious brown paper bag w/rdev/idev split
[media] cafe_ccic: Configure ov7670 correctly
[media] ov7670: allow configuration of image size, clock speed, and I/O method
[media] af9015: support for DigitalNow TinyTwin v3 [1f4d:9016]
[media] af9015: map DigitalNow TinyTwin v2 remote
[media] DigitalNow TinyTwin remote controller
[media] af9015: RC fixes and improvements
videodev2.h.xml: Update to reflect the latest changes at videodev2.h
[media] v4l: document new Bayer and monochrome pixel formats
[media] DocBook/v4l: Add missing formats used on gspca cpia1 and sn9c2028
[media] firedtv: add parameter to fake ca_system_ids in CA_INFO
[media] tm6000: fix a macro coding style issue
tm6000: Remove some ugly debug code
[media] Nova-S-Plus audio line input
[media] [RFC,1/1] V4L2: Use new CAP bits in existing RDS capable drivers
...
Diffstat (limited to 'drivers/media/IR/ir-lirc-codec.c')
-rw-r--r-- | drivers/media/IR/ir-lirc-codec.c | 135 |
1 files changed, 95 insertions, 40 deletions
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c index 1983cd3f3994..9fc0db9d344d 100644 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c | |||
@@ -32,6 +32,7 @@ | |||
32 | static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | 32 | static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) |
33 | { | 33 | { |
34 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | 34 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
35 | struct lirc_codec *lirc = &ir_dev->raw->lirc; | ||
35 | int sample; | 36 | int sample; |
36 | 37 | ||
37 | if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) | 38 | if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) |
@@ -40,21 +41,57 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
40 | if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) | 41 | if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) |
41 | return -EINVAL; | 42 | return -EINVAL; |
42 | 43 | ||
43 | if (IS_RESET(ev)) | 44 | /* Packet start */ |
45 | if (ev.reset) | ||
44 | return 0; | 46 | return 0; |
45 | 47 | ||
46 | IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", | 48 | /* Carrier reports */ |
47 | TO_US(ev.duration), TO_STR(ev.pulse)); | 49 | if (ev.carrier_report) { |
50 | sample = LIRC_FREQUENCY(ev.carrier); | ||
51 | |||
52 | /* Packet end */ | ||
53 | } else if (ev.timeout) { | ||
54 | |||
55 | if (lirc->gap) | ||
56 | return 0; | ||
57 | |||
58 | lirc->gap_start = ktime_get(); | ||
59 | lirc->gap = true; | ||
60 | lirc->gap_duration = ev.duration; | ||
61 | |||
62 | if (!lirc->send_timeout_reports) | ||
63 | return 0; | ||
64 | |||
65 | sample = LIRC_TIMEOUT(ev.duration / 1000); | ||
48 | 66 | ||
49 | sample = ev.duration / 1000; | 67 | /* Normal sample */ |
50 | if (ev.pulse) | 68 | } else { |
51 | sample |= PULSE_BIT; | 69 | |
70 | if (lirc->gap) { | ||
71 | int gap_sample; | ||
72 | |||
73 | lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(), | ||
74 | lirc->gap_start)); | ||
75 | |||
76 | /* Convert to ms and cap by LIRC_VALUE_MASK */ | ||
77 | do_div(lirc->gap_duration, 1000); | ||
78 | lirc->gap_duration = min(lirc->gap_duration, | ||
79 | (u64)LIRC_VALUE_MASK); | ||
80 | |||
81 | gap_sample = LIRC_SPACE(lirc->gap_duration); | ||
82 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, | ||
83 | (unsigned char *) &gap_sample); | ||
84 | lirc->gap = false; | ||
85 | } | ||
86 | |||
87 | sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : | ||
88 | LIRC_SPACE(ev.duration / 1000); | ||
89 | } | ||
52 | 90 | ||
53 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, | 91 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, |
54 | (unsigned char *) &sample); | 92 | (unsigned char *) &sample); |
55 | wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); | 93 | wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); |
56 | 94 | ||
57 | |||
58 | return 0; | 95 | return 0; |
59 | } | 96 | } |
60 | 97 | ||
@@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
102 | struct ir_input_dev *ir_dev; | 139 | struct ir_input_dev *ir_dev; |
103 | int ret = 0; | 140 | int ret = 0; |
104 | void *drv_data; | 141 | void *drv_data; |
105 | unsigned long val = 0; | 142 | __u32 val = 0, tmp; |
106 | 143 | ||
107 | lirc = lirc_get_pdata(filep); | 144 | lirc = lirc_get_pdata(filep); |
108 | if (!lirc) | 145 | if (!lirc) |
@@ -115,7 +152,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
115 | drv_data = ir_dev->props->priv; | 152 | drv_data = ir_dev->props->priv; |
116 | 153 | ||
117 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | 154 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
118 | ret = get_user(val, (unsigned long *)arg); | 155 | ret = get_user(val, (__u32 *)arg); |
119 | if (ret) | 156 | if (ret) |
120 | return ret; | 157 | return ret; |
121 | } | 158 | } |
@@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
130 | case LIRC_SET_SEND_MODE: | 167 | case LIRC_SET_SEND_MODE: |
131 | if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) | 168 | if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) |
132 | return -EINVAL; | 169 | return -EINVAL; |
133 | break; | 170 | return 0; |
134 | 171 | ||
135 | /* TX settings */ | 172 | /* TX settings */ |
136 | case LIRC_SET_TRANSMITTER_MASK: | 173 | case LIRC_SET_TRANSMITTER_MASK: |
137 | if (ir_dev->props->s_tx_mask) | 174 | if (!ir_dev->props->s_tx_mask) |
138 | ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); | ||
139 | else | ||
140 | return -EINVAL; | 175 | return -EINVAL; |
141 | break; | 176 | |
177 | return ir_dev->props->s_tx_mask(drv_data, val); | ||
142 | 178 | ||
143 | case LIRC_SET_SEND_CARRIER: | 179 | case LIRC_SET_SEND_CARRIER: |
144 | if (ir_dev->props->s_tx_carrier) | 180 | if (!ir_dev->props->s_tx_carrier) |
145 | ir_dev->props->s_tx_carrier(drv_data, (u32)val); | ||
146 | else | ||
147 | return -EINVAL; | 181 | return -EINVAL; |
148 | break; | 182 | |
183 | return ir_dev->props->s_tx_carrier(drv_data, val); | ||
149 | 184 | ||
150 | case LIRC_SET_SEND_DUTY_CYCLE: | 185 | case LIRC_SET_SEND_DUTY_CYCLE: |
151 | if (!ir_dev->props->s_tx_duty_cycle) | 186 | if (!ir_dev->props->s_tx_duty_cycle) |
@@ -154,39 +189,42 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
154 | if (val <= 0 || val >= 100) | 189 | if (val <= 0 || val >= 100) |
155 | return -EINVAL; | 190 | return -EINVAL; |
156 | 191 | ||
157 | ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val); | 192 | return ir_dev->props->s_tx_duty_cycle(drv_data, val); |
158 | break; | ||
159 | 193 | ||
160 | /* RX settings */ | 194 | /* RX settings */ |
161 | case LIRC_SET_REC_CARRIER: | 195 | case LIRC_SET_REC_CARRIER: |
162 | if (ir_dev->props->s_rx_carrier_range) | 196 | if (!ir_dev->props->s_rx_carrier_range) |
163 | ret = ir_dev->props->s_rx_carrier_range( | ||
164 | ir_dev->props->priv, | ||
165 | ir_dev->raw->lirc.carrier_low, val); | ||
166 | else | ||
167 | return -ENOSYS; | 197 | return -ENOSYS; |
168 | 198 | ||
169 | if (!ret) | 199 | if (val <= 0) |
170 | ir_dev->raw->lirc.carrier_low = 0; | 200 | return -EINVAL; |
171 | break; | 201 | |
202 | return ir_dev->props->s_rx_carrier_range(drv_data, | ||
203 | ir_dev->raw->lirc.carrier_low, val); | ||
172 | 204 | ||
173 | case LIRC_SET_REC_CARRIER_RANGE: | 205 | case LIRC_SET_REC_CARRIER_RANGE: |
174 | if (val >= 0) | 206 | if (val <= 0) |
175 | ir_dev->raw->lirc.carrier_low = val; | 207 | return -EINVAL; |
176 | break; | ||
177 | 208 | ||
209 | ir_dev->raw->lirc.carrier_low = val; | ||
210 | return 0; | ||
178 | 211 | ||
179 | case LIRC_GET_REC_RESOLUTION: | 212 | case LIRC_GET_REC_RESOLUTION: |
180 | val = ir_dev->props->rx_resolution; | 213 | val = ir_dev->props->rx_resolution; |
181 | break; | 214 | break; |
182 | 215 | ||
183 | case LIRC_SET_WIDEBAND_RECEIVER: | 216 | case LIRC_SET_WIDEBAND_RECEIVER: |
184 | if (ir_dev->props->s_learning_mode) | 217 | if (!ir_dev->props->s_learning_mode) |
185 | return ir_dev->props->s_learning_mode( | ||
186 | ir_dev->props->priv, !!val); | ||
187 | else | ||
188 | return -ENOSYS; | 218 | return -ENOSYS; |
189 | 219 | ||
220 | return ir_dev->props->s_learning_mode(drv_data, !!val); | ||
221 | |||
222 | case LIRC_SET_MEASURE_CARRIER_MODE: | ||
223 | if (!ir_dev->props->s_carrier_report) | ||
224 | return -ENOSYS; | ||
225 | |||
226 | return ir_dev->props->s_carrier_report(drv_data, !!val); | ||
227 | |||
190 | /* Generic timeout support */ | 228 | /* Generic timeout support */ |
191 | case LIRC_GET_MIN_TIMEOUT: | 229 | case LIRC_GET_MIN_TIMEOUT: |
192 | if (!ir_dev->props->max_timeout) | 230 | if (!ir_dev->props->max_timeout) |
@@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
201 | break; | 239 | break; |
202 | 240 | ||
203 | case LIRC_SET_REC_TIMEOUT: | 241 | case LIRC_SET_REC_TIMEOUT: |
204 | if (val < ir_dev->props->min_timeout || | 242 | if (!ir_dev->props->max_timeout) |
205 | val > ir_dev->props->max_timeout) | 243 | return -ENOSYS; |
206 | return -EINVAL; | 244 | |
207 | ir_dev->props->timeout = val * 1000; | 245 | tmp = val * 1000; |
246 | |||
247 | if (tmp < ir_dev->props->min_timeout || | ||
248 | tmp > ir_dev->props->max_timeout) | ||
249 | return -EINVAL; | ||
250 | |||
251 | ir_dev->props->timeout = tmp; | ||
252 | break; | ||
253 | |||
254 | case LIRC_SET_REC_TIMEOUT_REPORTS: | ||
255 | lirc->send_timeout_reports = !!val; | ||
208 | break; | 256 | break; |
209 | 257 | ||
210 | default: | 258 | default: |
@@ -212,7 +260,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
212 | } | 260 | } |
213 | 261 | ||
214 | if (_IOC_DIR(cmd) & _IOC_READ) | 262 | if (_IOC_DIR(cmd) & _IOC_READ) |
215 | ret = put_user(val, (unsigned long *)arg); | 263 | ret = put_user(val, (__u32 *)arg); |
216 | 264 | ||
217 | return ret; | 265 | return ret; |
218 | } | 266 | } |
@@ -231,6 +279,9 @@ static struct file_operations lirc_fops = { | |||
231 | .owner = THIS_MODULE, | 279 | .owner = THIS_MODULE, |
232 | .write = ir_lirc_transmit_ir, | 280 | .write = ir_lirc_transmit_ir, |
233 | .unlocked_ioctl = ir_lirc_ioctl, | 281 | .unlocked_ioctl = ir_lirc_ioctl, |
282 | #ifdef CONFIG_COMPAT | ||
283 | .compat_ioctl = ir_lirc_ioctl, | ||
284 | #endif | ||
234 | .read = lirc_dev_fop_read, | 285 | .read = lirc_dev_fop_read, |
235 | .poll = lirc_dev_fop_poll, | 286 | .poll = lirc_dev_fop_poll, |
236 | .open = lirc_dev_fop_open, | 287 | .open = lirc_dev_fop_open, |
@@ -278,6 +329,10 @@ static int ir_lirc_register(struct input_dev *input_dev) | |||
278 | if (ir_dev->props->s_learning_mode) | 329 | if (ir_dev->props->s_learning_mode) |
279 | features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; | 330 | features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; |
280 | 331 | ||
332 | if (ir_dev->props->s_carrier_report) | ||
333 | features |= LIRC_CAN_MEASURE_CARRIER; | ||
334 | |||
335 | |||
281 | if (ir_dev->props->max_timeout) | 336 | if (ir_dev->props->max_timeout) |
282 | features |= LIRC_CAN_SET_REC_TIMEOUT; | 337 | features |= LIRC_CAN_SET_REC_TIMEOUT; |
283 | 338 | ||