1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#ifdef __KERNEL__
42#include <asm/uaccess.h>
43#endif
44#include <asm/errno.h>
45
46#include "pwc.h"
47#include "pwc-kiara.h"
48#include "pwc-timon.h"
49#include "pwc-dec1.h"
50#include "pwc-dec23.h"
51
52
53#define GET_STATUS_B00 0x0B00
54#define SENSOR_TYPE_FORMATTER1 0x0C00
55#define GET_STATUS_3000 0x3000
56#define READ_RAW_Y_MEAN_FORMATTER 0x3100
57#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
58#define MIRROR_IMAGE_FORMATTER 0x3300
59#define LED_FORMATTER 0x3400
60#define LOWLIGHT 0x3500
61#define GET_STATUS_3600 0x3600
62#define SENSOR_TYPE_FORMATTER2 0x3700
63#define GET_STATUS_3800 0x3800
64#define GET_STATUS_4000 0x4000
65#define GET_STATUS_4100 0x4100
66#define CTL_STATUS_4200 0x4200
67
68
69#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
70
71static const char *size2name[PSZ_MAX] =
72{
73 "subQCIF",
74 "QSIF",
75 "QCIF",
76 "SIF",
77 "CIF",
78 "VGA",
79};
80
81
82
83
84
85
86
87
88
89#define PWC_FPS_MAX_NALA 8
90
91struct Nala_table_entry {
92 char alternate;
93 int compressed;
94
95 unsigned char mode[3];
96};
97
98static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
99
100static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
101{
102#include "pwc-nala.h"
103};
104
105
106
107static int recv_control_msg(struct pwc_device *pdev,
108 u8 request, u16 value, int recv_count)
109{
110 int rc;
111
112 rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
113 request,
114 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
115 value, pdev->vcinterface,
116 pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
117 if (rc < 0)
118 PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
119 rc, request, value);
120 return rc;
121}
122
123static inline int send_video_command(struct pwc_device *pdev,
124 int index, const unsigned char *buf, int buflen)
125{
126 int rc;
127
128 memcpy(pdev->ctrl_buf, buf, buflen);
129
130 rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
131 SET_EP_STREAM_CTL,
132 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
133 VIDEO_OUTPUT_CONTROL_FORMATTER, index,
134 pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
135 if (rc >= 0)
136 memcpy(pdev->cmd_buf, buf, buflen);
137 else
138 PWC_ERROR("send_video_command error %d\n", rc);
139
140 return rc;
141}
142
143int send_control_msg(struct pwc_device *pdev,
144 u8 request, u16 value, void *buf, int buflen)
145{
146 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
147 request,
148 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
149 value, pdev->vcinterface,
150 buf, buflen, USB_CTRL_SET_TIMEOUT);
151}
152
153static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
154 int frames, int *compression, int send_to_cam)
155{
156 int fps, ret = 0;
157 struct Nala_table_entry *pEntry;
158 int frames2frames[31] =
159 {
160 0, 0, 0, 0, 4,
161 5, 5, 7, 7, 10,
162 10, 10, 12, 12, 15,
163 15, 15, 15, 20, 20,
164 20, 20, 20, 24, 24,
165 24, 24, 24, 24, 24,
166 24
167 };
168 int frames2table[31] =
169 { 0, 0, 0, 0, 0,
170 1, 1, 1, 2, 2,
171 3, 3, 4, 4, 4,
172 5, 5, 5, 5, 5,
173 6, 6, 6, 6, 7,
174 7, 7, 7, 7, 7,
175 7
176 };
177
178 if (size < 0 || size > PSZ_CIF)
179 return -EINVAL;
180 if (frames < 4)
181 frames = 4;
182 else if (size > PSZ_QCIF && frames > 15)
183 frames = 15;
184 else if (frames > 25)
185 frames = 25;
186 frames = frames2frames[frames];
187 fps = frames2table[frames];
188 pEntry = &Nala_table[size][fps];
189 if (pEntry->alternate == 0)
190 return -EINVAL;
191
192 if (send_to_cam)
193 ret = send_video_command(pdev, pdev->vendpoint,
194 pEntry->mode, 3);
195 if (ret < 0)
196 return ret;
197
198 if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
199 pwc_dec1_init(pdev, pEntry->mode);
200
201
202 pdev->pixfmt = pixfmt;
203 pdev->vframes = frames;
204 pdev->valternate = pEntry->alternate;
205 pdev->width = pwc_image_sizes[size][0];
206 pdev->height = pwc_image_sizes[size][1];
207 pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
208 if (pEntry->compressed) {
209 if (pdev->release < 5) {
210 pdev->vbandlength = 528;
211 pdev->frame_size /= 4;
212 }
213 else {
214 pdev->vbandlength = 704;
215 pdev->frame_size /= 3;
216 }
217 }
218 else
219 pdev->vbandlength = 0;
220
221
222 *compression = 3;
223
224 return 0;
225}
226
227
228static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
229 int frames, int *compression, int send_to_cam)
230{
231 const struct Timon_table_entry *pChoose;
232 int fps, ret = 0;
233
234 if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
235 return -EINVAL;
236 if (frames < 5)
237 frames = 5;
238 else if (size == PSZ_VGA && frames > 15)
239 frames = 15;
240 else if (frames > 30)
241 frames = 30;
242 fps = (frames / 5) - 1;
243
244
245 pChoose = NULL;
246 while (*compression <= 3) {
247 pChoose = &Timon_table[size][fps][*compression];
248 if (pChoose->alternate != 0)
249 break;
250 (*compression)++;
251 }
252 if (pChoose == NULL || pChoose->alternate == 0)
253 return -ENOENT;
254
255 if (send_to_cam)
256 ret = send_video_command(pdev, pdev->vendpoint,
257 pChoose->mode, 13);
258 if (ret < 0)
259 return ret;
260
261 if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
262 pwc_dec23_init(pdev, pChoose->mode);
263
264
265 pdev->pixfmt = pixfmt;
266 pdev->vframes = (fps + 1) * 5;
267 pdev->valternate = pChoose->alternate;
268 pdev->width = pwc_image_sizes[size][0];
269 pdev->height = pwc_image_sizes[size][1];
270 pdev->vbandlength = pChoose->bandlength;
271 if (pChoose->bandlength > 0)
272 pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
273 else
274 pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
275 return 0;
276}
277
278
279static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
280 int frames, int *compression, int send_to_cam)
281{
282 const struct Kiara_table_entry *pChoose = NULL;
283 int fps, ret = 0;
284
285 if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
286 return -EINVAL;
287 if (frames < 5)
288 frames = 5;
289 else if (size == PSZ_VGA && frames > 15)
290 frames = 15;
291 else if (frames > 30)
292 frames = 30;
293 fps = (frames / 5) - 1;
294
295
296 while (*compression <= 3) {
297 pChoose = &Kiara_table[size][fps][*compression];
298 if (pChoose->alternate != 0)
299 break;
300 (*compression)++;
301 }
302 if (pChoose == NULL || pChoose->alternate == 0)
303 return -ENOENT;
304
305
306 if (send_to_cam)
307 ret = send_video_command(pdev, 4, pChoose->mode, 12);
308 if (ret < 0)
309 return ret;
310
311 if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
312 pwc_dec23_init(pdev, pChoose->mode);
313
314
315 pdev->pixfmt = pixfmt;
316 pdev->vframes = (fps + 1) * 5;
317 pdev->valternate = pChoose->alternate;
318 pdev->width = pwc_image_sizes[size][0];
319 pdev->height = pwc_image_sizes[size][1];
320 pdev->vbandlength = pChoose->bandlength;
321 if (pdev->vbandlength > 0)
322 pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
323 else
324 pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
325 PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
326 pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
327 return 0;
328}
329
330int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
331 int pixfmt, int frames, int *compression, int send_to_cam)
332{
333 int ret, size;
334
335 PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
336 width, height, frames, pixfmt);
337 size = pwc_get_size(pdev, width, height);
338 PWC_TRACE("decode_size = %d.\n", size);
339
340 if (DEVICE_USE_CODEC1(pdev->type)) {
341 ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
342 compression, send_to_cam);
343 } else if (DEVICE_USE_CODEC3(pdev->type)) {
344 ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
345 compression, send_to_cam);
346 } else {
347 ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
348 compression, send_to_cam);
349 }
350 if (ret < 0) {
351 PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
352 return ret;
353 }
354 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
355 PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
356 return 0;
357}
358
359static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
360{
361 unsigned int i;
362
363 for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
364 if (Nala_table[size][i].alternate) {
365 if (index--==0) return Nala_fps_vector[i];
366 }
367 }
368 return 0;
369}
370
371static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
372{
373 unsigned int i;
374
375 for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
376 if (Kiara_table[size][i][3].alternate) {
377 if (index--==0) return Kiara_fps_vector[i];
378 }
379 }
380 return 0;
381}
382
383static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
384{
385 unsigned int i;
386
387 for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
388 if (Timon_table[size][i][3].alternate) {
389 if (index--==0) return Timon_fps_vector[i];
390 }
391 }
392 return 0;
393}
394
395unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
396{
397 unsigned int ret;
398
399 if (DEVICE_USE_CODEC1(pdev->type)) {
400 ret = pwc_get_fps_Nala(pdev, index, size);
401
402 } else if (DEVICE_USE_CODEC3(pdev->type)) {
403 ret = pwc_get_fps_Kiara(pdev, index, size);
404
405 } else {
406 ret = pwc_get_fps_Timon(pdev, index, size);
407 }
408
409 return ret;
410}
411
412int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
413{
414 int ret;
415
416 ret = recv_control_msg(pdev, request, value, 1);
417 if (ret < 0)
418 return ret;
419
420 *data = pdev->ctrl_buf[0];
421 return 0;
422}
423
424int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
425{
426 int ret;
427
428 pdev->ctrl_buf[0] = data;
429 ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
430 if (ret < 0)
431 return ret;
432
433 return 0;
434}
435
436int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
437{
438 int ret;
439
440 ret = recv_control_msg(pdev, request, value, 1);
441 if (ret < 0)
442 return ret;
443
444 *data = ((s8 *)pdev->ctrl_buf)[0];
445 return 0;
446}
447
448int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
449{
450 int ret;
451
452 ret = recv_control_msg(pdev, request, value, 2);
453 if (ret < 0)
454 return ret;
455
456 *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
457 return 0;
458}
459
460int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
461{
462 int ret;
463
464 pdev->ctrl_buf[0] = data & 0xff;
465 pdev->ctrl_buf[1] = data >> 8;
466 ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
467 if (ret < 0)
468 return ret;
469
470 return 0;
471}
472
473int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
474{
475 int ret;
476
477 ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
478 if (ret < 0)
479 return ret;
480
481 return 0;
482}
483
484
485void pwc_camera_power(struct pwc_device *pdev, int power)
486{
487 int r;
488
489 if (!pdev->power_save)
490 return;
491
492 if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
493 return;
494
495 if (power)
496 pdev->ctrl_buf[0] = 0x00;
497 else
498 pdev->ctrl_buf[0] = 0xFF;
499 r = send_control_msg(pdev, SET_STATUS_CTL,
500 SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
501 if (r < 0)
502 PWC_ERROR("Failed to power %s camera (%d)\n",
503 power ? "on" : "off", r);
504}
505
506int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
507{
508 int r;
509
510 if (pdev->type < 730)
511 return 0;
512 on_value /= 100;
513 off_value /= 100;
514 if (on_value < 0)
515 on_value = 0;
516 if (on_value > 0xff)
517 on_value = 0xff;
518 if (off_value < 0)
519 off_value = 0;
520 if (off_value > 0xff)
521 off_value = 0xff;
522
523 pdev->ctrl_buf[0] = on_value;
524 pdev->ctrl_buf[1] = off_value;
525
526 r = send_control_msg(pdev,
527 SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
528 if (r < 0)
529 PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
530
531 return r;
532}
533
534#ifdef CONFIG_USB_PWC_DEBUG
535int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
536{
537 int ret = -1, request;
538
539 if (pdev->type < 675)
540 request = SENSOR_TYPE_FORMATTER1;
541 else if (pdev->type < 730)
542 return -1;
543 else
544 request = SENSOR_TYPE_FORMATTER2;
545
546 ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
547 if (ret < 0)
548 return ret;
549 if (pdev->type < 675)
550 *sensor = pdev->ctrl_buf[0] | 0x100;
551 else
552 *sensor = pdev->ctrl_buf[0];
553 return 0;
554}
555#endif
556