mars.c revision 3eb0237d445c23e9f46b11a07bce986eca450640
1/* 2 * Mars-Semi MR97311A library 3 * Copyright (C) 2005 <bradlch@hotmail.com> 4 * 5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22#define MODULE_NAME "mars" 23 24#include "gspca.h" 25#include "jpeg.h" 26 27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 28MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver"); 29MODULE_LICENSE("GPL"); 30 31/* specific webcam descriptor */ 32struct sd { 33 struct gspca_dev gspca_dev; /* !! must be the first item */ 34 35 u8 brightness; 36 u8 colors; 37 u8 gamma; 38 u8 sharpness; 39 u8 quality; 40#define QUALITY_MIN 40 41#define QUALITY_MAX 70 42#define QUALITY_DEF 50 43 44 u8 *jpeg_hdr; 45}; 46 47/* V4L2 controls supported by the driver */ 48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 50static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); 51static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); 52static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val); 53static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); 54static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); 55static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); 56 57static struct ctrl sd_ctrls[] = { 58 { 59 { 60 .id = V4L2_CID_BRIGHTNESS, 61 .type = V4L2_CTRL_TYPE_INTEGER, 62 .name = "Brightness", 63 .minimum = 0, 64 .maximum = 30, 65 .step = 1, 66#define BRIGHTNESS_DEF 15 67 .default_value = BRIGHTNESS_DEF, 68 }, 69 .set = sd_setbrightness, 70 .get = sd_getbrightness, 71 }, 72 { 73 { 74 .id = V4L2_CID_SATURATION, 75 .type = V4L2_CTRL_TYPE_INTEGER, 76 .name = "Color", 77 .minimum = 1, 78 .maximum = 255, 79 .step = 1, 80#define COLOR_DEF 200 81 .default_value = COLOR_DEF, 82 }, 83 .set = sd_setcolors, 84 .get = sd_getcolors, 85 }, 86 { 87 { 88 .id = V4L2_CID_GAMMA, 89 .type = V4L2_CTRL_TYPE_INTEGER, 90 .name = "Gamma", 91 .minimum = 0, 92 .maximum = 3, 93 .step = 1, 94#define GAMMA_DEF 1 95 .default_value = GAMMA_DEF, 96 }, 97 .set = sd_setgamma, 98 .get = sd_getgamma, 99 }, 100 { 101 { 102 .id = V4L2_CID_SHARPNESS, 103 .type = V4L2_CTRL_TYPE_INTEGER, 104 .name = "Sharpness", 105 .minimum = 0, 106 .maximum = 2, 107 .step = 1, 108#define SHARPNESS_DEF 1 109 .default_value = SHARPNESS_DEF, 110 }, 111 .set = sd_setsharpness, 112 .get = sd_getsharpness, 113 }, 114}; 115 116static const struct v4l2_pix_format vga_mode[] = { 117 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 118 .bytesperline = 320, 119 .sizeimage = 320 * 240 * 3 / 8 + 590, 120 .colorspace = V4L2_COLORSPACE_JPEG, 121 .priv = 2}, 122 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 123 .bytesperline = 640, 124 .sizeimage = 640 * 480 * 3 / 8 + 590, 125 .colorspace = V4L2_COLORSPACE_JPEG, 126 .priv = 1}, 127}; 128 129static const __u8 mi_data[0x20] = { 130/* 01 02 03 04 05 06 07 08 */ 131 0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00, 132/* 09 0a 0b 0c 0d 0e 0f 10 */ 133 0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, 134/* 11 12 13 14 15 16 17 18 */ 135 0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02, 136/* 19 1a 1b 1c 1d 1e 1f 20 */ 137 0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00 138}; 139 140/* write <len> bytes from gspca_dev->usb_buf */ 141static int reg_w(struct gspca_dev *gspca_dev, 142 int len) 143{ 144 int alen, ret; 145 146 ret = usb_bulk_msg(gspca_dev->dev, 147 usb_sndbulkpipe(gspca_dev->dev, 4), 148 gspca_dev->usb_buf, 149 len, 150 &alen, 151 500); /* timeout in milliseconds */ 152 if (ret < 0) 153 PDEBUG(D_ERR, "reg write [%02x] error %d", 154 gspca_dev->usb_buf[0], ret); 155 return ret; 156} 157 158static void mi_w(struct gspca_dev *gspca_dev, 159 u8 addr, 160 u8 value) 161{ 162 gspca_dev->usb_buf[0] = 0x1f; 163 gspca_dev->usb_buf[1] = 0; /* control byte */ 164 gspca_dev->usb_buf[2] = addr; 165 gspca_dev->usb_buf[3] = value; 166 167 reg_w(gspca_dev, 4); 168} 169 170/* this function is called at probe time */ 171static int sd_config(struct gspca_dev *gspca_dev, 172 const struct usb_device_id *id) 173{ 174 struct sd *sd = (struct sd *) gspca_dev; 175 struct cam *cam; 176 177 cam = &gspca_dev->cam; 178 cam->cam_mode = vga_mode; 179 cam->nmodes = ARRAY_SIZE(vga_mode); 180 sd->brightness = BRIGHTNESS_DEF; 181 sd->colors = COLOR_DEF; 182 sd->gamma = GAMMA_DEF; 183 sd->sharpness = SHARPNESS_DEF; 184 sd->quality = QUALITY_DEF; 185 gspca_dev->nbalt = 9; /* use the altsetting 08 */ 186 return 0; 187} 188 189/* this function is called at probe and resume time */ 190static int sd_init(struct gspca_dev *gspca_dev) 191{ 192 return 0; 193} 194 195static int sd_start(struct gspca_dev *gspca_dev) 196{ 197 struct sd *sd = (struct sd *) gspca_dev; 198 int err_code; 199 u8 *data; 200 int i; 201 202 /* create the JPEG header */ 203 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); 204 if (!sd->jpeg_hdr) 205 return -ENOMEM; 206 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 207 0x21); /* JPEG 422 */ 208 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 209 210 data = gspca_dev->usb_buf; 211 212 data[0] = 0x01; /* address */ 213 data[1] = 0x01; 214 err_code = reg_w(gspca_dev, 2); 215 if (err_code < 0) 216 return err_code; 217 218 /* 219 Initialize the MR97113 chip register 220 */ 221 data[0] = 0x00; /* address */ 222 data[1] = 0x0c | 0x01; /* reg 0 */ 223 data[2] = 0x01; /* reg 1 */ 224 data[3] = gspca_dev->width / 8; /* h_size , reg 2 */ 225 data[4] = gspca_dev->height / 8; /* v_size , reg 3 */ 226 data[5] = 0x30; /* reg 4, MI, PAS5101 : 227 * 0x30 for 24mhz , 0x28 for 12mhz */ 228 data[6] = 0x02; /* reg 5, H start - was 0x04 */ 229 data[7] = sd->gamma * 0x40; /* reg 0x06: gamma */ 230 data[8] = 0x01; /* reg 7, V start - was 0x03 */ 231/* if (h_size == 320 ) */ 232/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */ 233/* else */ 234 data[9] = 0x52; /* reg 8, 24MHz, no scale down */ 235/*jfm: from win trace*/ 236 data[10] = 0x18; 237 238 err_code = reg_w(gspca_dev, 11); 239 if (err_code < 0) 240 return err_code; 241 242 data[0] = 0x23; /* address */ 243 data[1] = 0x09; /* reg 35, append frame header */ 244 245 err_code = reg_w(gspca_dev, 2); 246 if (err_code < 0) 247 return err_code; 248 249 data[0] = 0x3c; /* address */ 250/* if (gspca_dev->width == 1280) */ 251/* data[1] = 200; * reg 60, pc-cam frame size 252 * (unit: 4KB) 800KB */ 253/* else */ 254 data[1] = 50; /* 50 reg 60, pc-cam frame size 255 * (unit: 4KB) 200KB */ 256 err_code = reg_w(gspca_dev, 2); 257 if (err_code < 0) 258 return err_code; 259 260 /* auto dark-gain */ 261 data[0] = 0x5e; /* address */ 262 data[1] = 0; /* reg 94, Y Gain (auto) */ 263/*jfm: from win trace*/ 264 /* reg 0x5f/0x60 (LE) = saturation */ 265 /* h (60): xxxx x100 266 * l (5f): xxxx x000 */ 267 data[2] = sd->colors << 3; 268 data[3] = ((sd->colors >> 2) & 0xf8) | 0x04; 269 data[4] = sd->brightness; /* reg 0x61 = brightness */ 270 data[5] = 0x00; 271 272 err_code = reg_w(gspca_dev, 6); 273 if (err_code < 0) 274 return err_code; 275 276 data[0] = 0x67; 277/*jfm: from win trace*/ 278 data[1] = sd->sharpness * 4 + 3; 279 data[2] = 0x14; 280 err_code = reg_w(gspca_dev, 3); 281 if (err_code < 0) 282 return err_code; 283 284 data[0] = 0x69; 285 data[1] = 0x2f; 286 data[2] = 0x28; 287 data[3] = 0x42; 288 err_code = reg_w(gspca_dev, 4); 289 if (err_code < 0) 290 return err_code; 291 292 data[0] = 0x63; 293 data[1] = 0x07; 294 err_code = reg_w(gspca_dev, 2); 295/*jfm: win trace - many writes here to reg 0x64*/ 296 if (err_code < 0) 297 return err_code; 298 299 /* initialize the MI sensor */ 300 for (i = 0; i < sizeof mi_data; i++) 301 mi_w(gspca_dev, i + 1, mi_data[i]); 302 303 data[0] = 0x00; 304 data[1] = 0x4d; /* ISOC transfering enable... */ 305 reg_w(gspca_dev, 2); 306 return 0; 307} 308 309static void sd_stopN(struct gspca_dev *gspca_dev) 310{ 311 int result; 312 313 gspca_dev->usb_buf[0] = 1; 314 gspca_dev->usb_buf[1] = 0; 315 result = reg_w(gspca_dev, 2); 316 if (result < 0) 317 PDEBUG(D_ERR, "Camera Stop failed"); 318} 319 320static void sd_stop0(struct gspca_dev *gspca_dev) 321{ 322 struct sd *sd = (struct sd *) gspca_dev; 323 324 kfree(sd->jpeg_hdr); 325} 326 327static void sd_pkt_scan(struct gspca_dev *gspca_dev, 328 struct gspca_frame *frame, /* target */ 329 __u8 *data, /* isoc packet */ 330 int len) /* iso packet length */ 331{ 332 struct sd *sd = (struct sd *) gspca_dev; 333 int p; 334 335 if (len < 6) { 336/* gspca_dev->last_packet_type = DISCARD_PACKET; */ 337 return; 338 } 339 for (p = 0; p < len - 6; p++) { 340 if (data[0 + p] == 0xff 341 && data[1 + p] == 0xff 342 && data[2 + p] == 0x00 343 && data[3 + p] == 0xff 344 && data[4 + p] == 0x96) { 345 if (data[5 + p] == 0x64 346 || data[5 + p] == 0x65 347 || data[5 + p] == 0x66 348 || data[5 + p] == 0x67) { 349 PDEBUG(D_PACK, "sof offset: %d len: %d", 350 p, len); 351 frame = gspca_frame_add(gspca_dev, LAST_PACKET, 352 frame, data, p); 353 354 /* put the JPEG header */ 355 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, 356 sd->jpeg_hdr, JPEG_HDR_SZ); 357 data += p + 16; 358 len -= p + 16; 359 break; 360 } 361 } 362 } 363 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); 364} 365 366static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 367{ 368 struct sd *sd = (struct sd *) gspca_dev; 369 370 sd->brightness = val; 371 if (gspca_dev->streaming) { 372 gspca_dev->usb_buf[0] = 0x61; 373 gspca_dev->usb_buf[1] = val; 374 reg_w(gspca_dev, 2); 375 } 376 return 0; 377} 378 379static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 380{ 381 struct sd *sd = (struct sd *) gspca_dev; 382 383 *val = sd->brightness; 384 return 0; 385} 386 387static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 388{ 389 struct sd *sd = (struct sd *) gspca_dev; 390 391 sd->colors = val; 392 if (gspca_dev->streaming) { 393 394 /* see sd_start */ 395 gspca_dev->usb_buf[0] = 0x5f; 396 gspca_dev->usb_buf[1] = sd->colors << 3; 397 gspca_dev->usb_buf[2] = ((sd->colors >> 2) & 0xf8) | 0x04; 398 reg_w(gspca_dev, 3); 399 } 400 return 0; 401} 402 403static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) 404{ 405 struct sd *sd = (struct sd *) gspca_dev; 406 407 *val = sd->colors; 408 return 0; 409} 410 411static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) 412{ 413 struct sd *sd = (struct sd *) gspca_dev; 414 415 sd->gamma = val; 416 if (gspca_dev->streaming) { 417 gspca_dev->usb_buf[0] = 0x06; 418 gspca_dev->usb_buf[1] = val * 0x40; 419 reg_w(gspca_dev, 2); 420 } 421 return 0; 422} 423 424static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) 425{ 426 struct sd *sd = (struct sd *) gspca_dev; 427 428 *val = sd->gamma; 429 return 0; 430} 431 432static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) 433{ 434 struct sd *sd = (struct sd *) gspca_dev; 435 436 sd->sharpness = val; 437 if (gspca_dev->streaming) { 438 gspca_dev->usb_buf[0] = 0x67; 439 gspca_dev->usb_buf[1] = val * 4 + 3; 440 reg_w(gspca_dev, 2); 441 } 442 return 0; 443} 444 445static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) 446{ 447 struct sd *sd = (struct sd *) gspca_dev; 448 449 *val = sd->sharpness; 450 return 0; 451} 452 453static int sd_set_jcomp(struct gspca_dev *gspca_dev, 454 struct v4l2_jpegcompression *jcomp) 455{ 456 struct sd *sd = (struct sd *) gspca_dev; 457 458 if (jcomp->quality < QUALITY_MIN) 459 sd->quality = QUALITY_MIN; 460 else if (jcomp->quality > QUALITY_MAX) 461 sd->quality = QUALITY_MAX; 462 else 463 sd->quality = jcomp->quality; 464 if (gspca_dev->streaming) 465 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 466 return 0; 467} 468 469static int sd_get_jcomp(struct gspca_dev *gspca_dev, 470 struct v4l2_jpegcompression *jcomp) 471{ 472 struct sd *sd = (struct sd *) gspca_dev; 473 474 memset(jcomp, 0, sizeof *jcomp); 475 jcomp->quality = sd->quality; 476 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT 477 | V4L2_JPEG_MARKER_DQT; 478 return 0; 479} 480 481/* sub-driver description */ 482static const struct sd_desc sd_desc = { 483 .name = MODULE_NAME, 484 .ctrls = sd_ctrls, 485 .nctrls = ARRAY_SIZE(sd_ctrls), 486 .config = sd_config, 487 .init = sd_init, 488 .start = sd_start, 489 .stopN = sd_stopN, 490 .stop0 = sd_stop0, 491 .pkt_scan = sd_pkt_scan, 492 .get_jcomp = sd_get_jcomp, 493 .set_jcomp = sd_set_jcomp, 494}; 495 496/* -- module initialisation -- */ 497static const __devinitdata struct usb_device_id device_table[] = { 498 {USB_DEVICE(0x093a, 0x050f)}, 499 {} 500}; 501MODULE_DEVICE_TABLE(usb, device_table); 502 503/* -- device connect -- */ 504static int sd_probe(struct usb_interface *intf, 505 const struct usb_device_id *id) 506{ 507 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 508 THIS_MODULE); 509} 510 511static struct usb_driver sd_driver = { 512 .name = MODULE_NAME, 513 .id_table = device_table, 514 .probe = sd_probe, 515 .disconnect = gspca_disconnect, 516#ifdef CONFIG_PM 517 .suspend = gspca_suspend, 518 .resume = gspca_resume, 519#endif 520}; 521 522/* -- module insert / remove -- */ 523static int __init sd_mod_init(void) 524{ 525 int ret; 526 527 ret = usb_register(&sd_driver); 528 if (ret < 0) 529 return ret; 530 PDEBUG(D_PROBE, "registered"); 531 return 0; 532} 533static void __exit sd_mod_exit(void) 534{ 535 usb_deregister(&sd_driver); 536 PDEBUG(D_PROBE, "deregistered"); 537} 538 539module_init(sd_mod_init); 540module_exit(sd_mod_exit); 541