0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #ifdef __KERNEL__
0030 #include <linux/uaccess.h>
0031 #endif
0032 #include <asm/errno.h>
0033
0034 #include "pwc.h"
0035 #include "pwc-kiara.h"
0036 #include "pwc-timon.h"
0037 #include "pwc-dec1.h"
0038 #include "pwc-dec23.h"
0039
0040
0041 #define GET_STATUS_B00 0x0B00
0042 #define SENSOR_TYPE_FORMATTER1 0x0C00
0043 #define GET_STATUS_3000 0x3000
0044 #define READ_RAW_Y_MEAN_FORMATTER 0x3100
0045 #define SET_POWER_SAVE_MODE_FORMATTER 0x3200
0046 #define MIRROR_IMAGE_FORMATTER 0x3300
0047 #define LED_FORMATTER 0x3400
0048 #define LOWLIGHT 0x3500
0049 #define GET_STATUS_3600 0x3600
0050 #define SENSOR_TYPE_FORMATTER2 0x3700
0051 #define GET_STATUS_3800 0x3800
0052 #define GET_STATUS_4000 0x4000
0053 #define GET_STATUS_4100 0x4100
0054 #define CTL_STATUS_4200 0x4200
0055
0056
0057 #define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
0058
0059 static const char *size2name[PSZ_MAX] =
0060 {
0061 "subQCIF",
0062 "QSIF",
0063 "QCIF",
0064 "SIF",
0065 "CIF",
0066 "VGA",
0067 };
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 #define PWC_FPS_MAX_NALA 8
0078
0079 struct Nala_table_entry {
0080 char alternate;
0081 int compressed;
0082
0083 unsigned char mode[3];
0084 };
0085
0086 static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
0087
0088 static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
0089 {
0090 #include "pwc-nala.h"
0091 };
0092
0093
0094
0095 static int recv_control_msg(struct pwc_device *pdev,
0096 u8 request, u16 value, int recv_count)
0097 {
0098 int rc;
0099
0100 rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
0101 request,
0102 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0103 value, pdev->vcinterface,
0104 pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
0105 if (rc < 0)
0106 PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
0107 rc, request, value);
0108 return rc;
0109 }
0110
0111 static inline int send_video_command(struct pwc_device *pdev,
0112 int index, const unsigned char *buf, int buflen)
0113 {
0114 int rc;
0115
0116 memcpy(pdev->ctrl_buf, buf, buflen);
0117
0118 rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
0119 SET_EP_STREAM_CTL,
0120 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0121 VIDEO_OUTPUT_CONTROL_FORMATTER, index,
0122 pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
0123 if (rc >= 0)
0124 memcpy(pdev->cmd_buf, buf, buflen);
0125 else
0126 PWC_ERROR("send_video_command error %d\n", rc);
0127
0128 return rc;
0129 }
0130
0131 int send_control_msg(struct pwc_device *pdev,
0132 u8 request, u16 value, void *buf, int buflen)
0133 {
0134 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
0135 request,
0136 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0137 value, pdev->vcinterface,
0138 buf, buflen, USB_CTRL_SET_TIMEOUT);
0139 }
0140
0141 static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
0142 int frames, int *compression, int send_to_cam)
0143 {
0144 int fps, ret = 0;
0145 struct Nala_table_entry *pEntry;
0146 int frames2frames[31] =
0147 {
0148 0, 0, 0, 0, 4,
0149 5, 5, 7, 7, 10,
0150 10, 10, 12, 12, 15,
0151 15, 15, 15, 20, 20,
0152 20, 20, 20, 24, 24,
0153 24, 24, 24, 24, 24,
0154 24
0155 };
0156 int frames2table[31] =
0157 { 0, 0, 0, 0, 0,
0158 1, 1, 1, 2, 2,
0159 3, 3, 4, 4, 4,
0160 5, 5, 5, 5, 5,
0161 6, 6, 6, 6, 7,
0162 7, 7, 7, 7, 7,
0163 7
0164 };
0165
0166 if (size < 0 || size > PSZ_CIF)
0167 return -EINVAL;
0168 if (frames < 4)
0169 frames = 4;
0170 else if (size > PSZ_QCIF && frames > 15)
0171 frames = 15;
0172 else if (frames > 25)
0173 frames = 25;
0174 frames = frames2frames[frames];
0175 fps = frames2table[frames];
0176 pEntry = &Nala_table[size][fps];
0177 if (pEntry->alternate == 0)
0178 return -EINVAL;
0179
0180 if (send_to_cam)
0181 ret = send_video_command(pdev, pdev->vendpoint,
0182 pEntry->mode, 3);
0183 if (ret < 0)
0184 return ret;
0185
0186 if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
0187 pwc_dec1_init(pdev, pEntry->mode);
0188
0189
0190 pdev->pixfmt = pixfmt;
0191 pdev->vframes = frames;
0192 pdev->valternate = pEntry->alternate;
0193 pdev->width = pwc_image_sizes[size][0];
0194 pdev->height = pwc_image_sizes[size][1];
0195 pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
0196 if (pEntry->compressed) {
0197 if (pdev->release < 5) {
0198 pdev->vbandlength = 528;
0199 pdev->frame_size /= 4;
0200 }
0201 else {
0202 pdev->vbandlength = 704;
0203 pdev->frame_size /= 3;
0204 }
0205 }
0206 else
0207 pdev->vbandlength = 0;
0208
0209
0210 *compression = 3;
0211
0212 return 0;
0213 }
0214
0215
0216 static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
0217 int frames, int *compression, int send_to_cam)
0218 {
0219 const struct Timon_table_entry *pChoose;
0220 int fps, ret = 0;
0221
0222 if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
0223 return -EINVAL;
0224 if (frames < 5)
0225 frames = 5;
0226 else if (size == PSZ_VGA && frames > 15)
0227 frames = 15;
0228 else if (frames > 30)
0229 frames = 30;
0230 fps = (frames / 5) - 1;
0231
0232
0233 do {
0234 pChoose = &Timon_table[size][fps][*compression];
0235 if (pChoose->alternate != 0)
0236 break;
0237 (*compression)++;
0238 } while (*compression <= 3);
0239
0240 if (pChoose->alternate == 0)
0241 return -ENOENT;
0242
0243 if (send_to_cam)
0244 ret = send_video_command(pdev, pdev->vendpoint,
0245 pChoose->mode, 13);
0246 if (ret < 0)
0247 return ret;
0248
0249 if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
0250 pwc_dec23_init(pdev, pChoose->mode);
0251
0252
0253 pdev->pixfmt = pixfmt;
0254 pdev->vframes = (fps + 1) * 5;
0255 pdev->valternate = pChoose->alternate;
0256 pdev->width = pwc_image_sizes[size][0];
0257 pdev->height = pwc_image_sizes[size][1];
0258 pdev->vbandlength = pChoose->bandlength;
0259 if (pChoose->bandlength > 0)
0260 pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
0261 else
0262 pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
0263 return 0;
0264 }
0265
0266
0267 static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
0268 int frames, int *compression, int send_to_cam)
0269 {
0270 const struct Kiara_table_entry *pChoose;
0271 int fps, ret = 0;
0272
0273 if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
0274 return -EINVAL;
0275 if (frames < 5)
0276 frames = 5;
0277 else if (size == PSZ_VGA && frames > 15)
0278 frames = 15;
0279 else if (frames > 30)
0280 frames = 30;
0281 fps = (frames / 5) - 1;
0282
0283
0284 do {
0285 pChoose = &Kiara_table[size][fps][*compression];
0286 if (pChoose->alternate != 0)
0287 break;
0288 (*compression)++;
0289 } while (*compression <= 3);
0290
0291 if (pChoose->alternate == 0)
0292 return -ENOENT;
0293
0294
0295 if (send_to_cam)
0296 ret = send_video_command(pdev, 4, pChoose->mode, 12);
0297 if (ret < 0)
0298 return ret;
0299
0300 if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
0301 pwc_dec23_init(pdev, pChoose->mode);
0302
0303
0304 pdev->pixfmt = pixfmt;
0305 pdev->vframes = (fps + 1) * 5;
0306 pdev->valternate = pChoose->alternate;
0307 pdev->width = pwc_image_sizes[size][0];
0308 pdev->height = pwc_image_sizes[size][1];
0309 pdev->vbandlength = pChoose->bandlength;
0310 if (pdev->vbandlength > 0)
0311 pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
0312 else
0313 pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
0314 PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
0315 pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
0316 return 0;
0317 }
0318
0319 int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
0320 int pixfmt, int frames, int *compression, int send_to_cam)
0321 {
0322 int ret, size;
0323
0324 PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
0325 width, height, frames, pixfmt);
0326 size = pwc_get_size(pdev, width, height);
0327 PWC_TRACE("decode_size = %d.\n", size);
0328
0329 if (DEVICE_USE_CODEC1(pdev->type)) {
0330 ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
0331 compression, send_to_cam);
0332 } else if (DEVICE_USE_CODEC3(pdev->type)) {
0333 ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
0334 compression, send_to_cam);
0335 } else {
0336 ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
0337 compression, send_to_cam);
0338 }
0339 if (ret < 0) {
0340 PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
0341 return ret;
0342 }
0343 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
0344 PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
0345 return 0;
0346 }
0347
0348 static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
0349 {
0350 unsigned int i;
0351
0352 for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
0353 if (Nala_table[size][i].alternate) {
0354 if (index--==0) return Nala_fps_vector[i];
0355 }
0356 }
0357 return 0;
0358 }
0359
0360 static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
0361 {
0362 unsigned int i;
0363
0364 for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
0365 if (Kiara_table[size][i][3].alternate) {
0366 if (index--==0) return Kiara_fps_vector[i];
0367 }
0368 }
0369 return 0;
0370 }
0371
0372 static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
0373 {
0374 unsigned int i;
0375
0376 for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
0377 if (Timon_table[size][i][3].alternate) {
0378 if (index--==0) return Timon_fps_vector[i];
0379 }
0380 }
0381 return 0;
0382 }
0383
0384 unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
0385 {
0386 unsigned int ret;
0387
0388 if (DEVICE_USE_CODEC1(pdev->type)) {
0389 ret = pwc_get_fps_Nala(pdev, index, size);
0390
0391 } else if (DEVICE_USE_CODEC3(pdev->type)) {
0392 ret = pwc_get_fps_Kiara(pdev, index, size);
0393
0394 } else {
0395 ret = pwc_get_fps_Timon(pdev, index, size);
0396 }
0397
0398 return ret;
0399 }
0400
0401 int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
0402 {
0403 int ret;
0404
0405 ret = recv_control_msg(pdev, request, value, 1);
0406 if (ret < 0)
0407 return ret;
0408
0409 *data = pdev->ctrl_buf[0];
0410 return 0;
0411 }
0412
0413 int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
0414 {
0415 int ret;
0416
0417 pdev->ctrl_buf[0] = data;
0418 ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
0419 if (ret < 0)
0420 return ret;
0421
0422 return 0;
0423 }
0424
0425 int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
0426 {
0427 int ret;
0428
0429 ret = recv_control_msg(pdev, request, value, 1);
0430 if (ret < 0)
0431 return ret;
0432
0433 *data = ((s8 *)pdev->ctrl_buf)[0];
0434 return 0;
0435 }
0436
0437 int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
0438 {
0439 int ret;
0440
0441 ret = recv_control_msg(pdev, request, value, 2);
0442 if (ret < 0)
0443 return ret;
0444
0445 *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
0446 return 0;
0447 }
0448
0449 int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
0450 {
0451 int ret;
0452
0453 pdev->ctrl_buf[0] = data & 0xff;
0454 pdev->ctrl_buf[1] = data >> 8;
0455 ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
0456 if (ret < 0)
0457 return ret;
0458
0459 return 0;
0460 }
0461
0462 int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
0463 {
0464 int ret;
0465
0466 ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
0467 if (ret < 0)
0468 return ret;
0469
0470 return 0;
0471 }
0472
0473
0474 void pwc_camera_power(struct pwc_device *pdev, int power)
0475 {
0476 int r;
0477
0478 if (!pdev->power_save)
0479 return;
0480
0481 if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
0482 return;
0483
0484 if (power)
0485 pdev->ctrl_buf[0] = 0x00;
0486 else
0487 pdev->ctrl_buf[0] = 0xFF;
0488 r = send_control_msg(pdev, SET_STATUS_CTL,
0489 SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
0490 if (r < 0)
0491 PWC_ERROR("Failed to power %s camera (%d)\n",
0492 power ? "on" : "off", r);
0493 }
0494
0495 int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
0496 {
0497 int r;
0498
0499 if (pdev->type < 730)
0500 return 0;
0501 on_value /= 100;
0502 off_value /= 100;
0503 if (on_value < 0)
0504 on_value = 0;
0505 if (on_value > 0xff)
0506 on_value = 0xff;
0507 if (off_value < 0)
0508 off_value = 0;
0509 if (off_value > 0xff)
0510 off_value = 0xff;
0511
0512 pdev->ctrl_buf[0] = on_value;
0513 pdev->ctrl_buf[1] = off_value;
0514
0515 r = send_control_msg(pdev,
0516 SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
0517 if (r < 0)
0518 PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
0519
0520 return r;
0521 }
0522
0523 #ifdef CONFIG_USB_PWC_DEBUG
0524 int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
0525 {
0526 int ret, request;
0527
0528 if (pdev->type < 675)
0529 request = SENSOR_TYPE_FORMATTER1;
0530 else if (pdev->type < 730)
0531 return -1;
0532 else
0533 request = SENSOR_TYPE_FORMATTER2;
0534
0535 ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
0536 if (ret < 0)
0537 return ret;
0538 if (pdev->type < 675)
0539 *sensor = pdev->ctrl_buf[0] | 0x100;
0540 else
0541 *sensor = pdev->ctrl_buf[0];
0542 return 0;
0543 }
0544 #endif