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[JPEG_HDR_SZ]; 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 const 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 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 204 0x21); /* JPEG 422 */ 205 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 206 207 data = gspca_dev->usb_buf; 208 209 data[0] = 0x01; /* address */ 210 data[1] = 0x01; 211 err_code = reg_w(gspca_dev, 2); 212 if (err_code < 0) 213 return err_code; 214 215 /* 216 Initialize the MR97113 chip register 217 */ 218 data[0] = 0x00; /* address */ 219 data[1] = 0x0c | 0x01; /* reg 0 */ 220 data[2] = 0x01; /* reg 1 */ 221 data[3] = gspca_dev->width / 8; /* h_size , reg 2 */ 222 data[4] = gspca_dev->height / 8; /* v_size , reg 3 */ 223 data[5] = 0x30; /* reg 4, MI, PAS5101 : 224 * 0x30 for 24mhz , 0x28 for 12mhz */ 225 data[6] = 0x02; /* reg 5, H start - was 0x04 */ 226 data[7] = sd->gamma * 0x40; /* reg 0x06: gamma */ 227 data[8] = 0x01; /* reg 7, V start - was 0x03 */ 228/* if (h_size == 320 ) */ 229/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */ 230/* else */ 231 data[9] = 0x52; /* reg 8, 24MHz, no scale down */ 232/*jfm: from win trace*/ 233 data[10] = 0x18; 234 235 err_code = reg_w(gspca_dev, 11); 236 if (err_code < 0) 237 return err_code; 238 239 data[0] = 0x23; /* address */ 240 data[1] = 0x09; /* reg 35, append frame header */ 241 242 err_code = reg_w(gspca_dev, 2); 243 if (err_code < 0) 244 return err_code; 245 246 data[0] = 0x3c; /* address */ 247/* if (gspca_dev->width == 1280) */ 248/* data[1] = 200; * reg 60, pc-cam frame size 249 * (unit: 4KB) 800KB */ 250/* else */ 251 data[1] = 50; /* 50 reg 60, pc-cam frame size 252 * (unit: 4KB) 200KB */ 253 err_code = reg_w(gspca_dev, 2); 254 if (err_code < 0) 255 return err_code; 256 257 /* auto dark-gain */ 258 data[0] = 0x5e; /* address */ 259 data[1] = 0; /* reg 94, Y Gain (auto) */ 260/*jfm: from win trace*/ 261 /* reg 0x5f/0x60 (LE) = saturation */ 262 data[2] = sd->colors << 3; 263 data[3] = ((sd->colors >> 2) & 0xf8) | 0x04; 264 data[4] = sd->brightness; /* reg 0x61 = brightness */ 265 data[5] = 0x00; 266 267 err_code = reg_w(gspca_dev, 6); 268 if (err_code < 0) 269 return err_code; 270 271 data[0] = 0x67; 272/*jfm: from win trace*/ 273 data[1] = sd->sharpness * 4 + 3; 274 data[2] = 0x14; 275 err_code = reg_w(gspca_dev, 3); 276 if (err_code < 0) 277 return err_code; 278 279 data[0] = 0x69; 280 data[1] = 0x2f; 281 data[2] = 0x28; 282 data[3] = 0x42; 283 err_code = reg_w(gspca_dev, 4); 284 if (err_code < 0) 285 return err_code; 286 287 data[0] = 0x63; 288 data[1] = 0x07; 289 err_code = reg_w(gspca_dev, 2); 290/*jfm: win trace - many writes here to reg 0x64*/ 291 if (err_code < 0) 292 return err_code; 293 294 /* initialize the MI sensor */ 295 for (i = 0; i < sizeof mi_data; i++) 296 mi_w(gspca_dev, i + 1, mi_data[i]); 297 298 data[0] = 0x00; 299 data[1] = 0x4d; /* ISOC transfering enable... */ 300 reg_w(gspca_dev, 2); 301 return 0; 302} 303 304static void sd_stopN(struct gspca_dev *gspca_dev) 305{ 306 int result; 307 308 gspca_dev->usb_buf[0] = 1; 309 gspca_dev->usb_buf[1] = 0; 310 result = reg_w(gspca_dev, 2); 311 if (result < 0) 312 PDEBUG(D_ERR, "Camera Stop failed"); 313} 314 315static void sd_pkt_scan(struct gspca_dev *gspca_dev, 316 u8 *data, /* isoc packet */ 317 int len) /* iso packet length */ 318{ 319 struct sd *sd = (struct sd *) gspca_dev; 320 int p; 321 322 if (len < 6) { 323/* gspca_dev->last_packet_type = DISCARD_PACKET; */ 324 return; 325 } 326 for (p = 0; p < len - 6; p++) { 327 if (data[0 + p] == 0xff 328 && data[1 + p] == 0xff 329 && data[2 + p] == 0x00 330 && data[3 + p] == 0xff 331 && data[4 + p] == 0x96) { 332 if (data[5 + p] == 0x64 333 || data[5 + p] == 0x65 334 || data[5 + p] == 0x66 335 || data[5 + p] == 0x67) { 336 PDEBUG(D_PACK, "sof offset: %d len: %d", 337 p, len); 338 gspca_frame_add(gspca_dev, LAST_PACKET, 339 data, p); 340 341 /* put the JPEG header */ 342 gspca_frame_add(gspca_dev, FIRST_PACKET, 343 sd->jpeg_hdr, JPEG_HDR_SZ); 344 data += p + 16; 345 len -= p + 16; 346 break; 347 } 348 } 349 } 350 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 351} 352 353static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 354{ 355 struct sd *sd = (struct sd *) gspca_dev; 356 357 sd->brightness = val; 358 if (gspca_dev->streaming) { 359 gspca_dev->usb_buf[0] = 0x61; 360 gspca_dev->usb_buf[1] = val; 361 reg_w(gspca_dev, 2); 362 } 363 return 0; 364} 365 366static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 367{ 368 struct sd *sd = (struct sd *) gspca_dev; 369 370 *val = sd->brightness; 371 return 0; 372} 373 374static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 375{ 376 struct sd *sd = (struct sd *) gspca_dev; 377 378 sd->colors = val; 379 if (gspca_dev->streaming) { 380 381 /* see sd_start */ 382 gspca_dev->usb_buf[0] = 0x5f; 383 gspca_dev->usb_buf[1] = sd->colors << 3; 384 gspca_dev->usb_buf[2] = ((sd->colors >> 2) & 0xf8) | 0x04; 385 reg_w(gspca_dev, 3); 386 } 387 return 0; 388} 389 390static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) 391{ 392 struct sd *sd = (struct sd *) gspca_dev; 393 394 *val = sd->colors; 395 return 0; 396} 397 398static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) 399{ 400 struct sd *sd = (struct sd *) gspca_dev; 401 402 sd->gamma = val; 403 if (gspca_dev->streaming) { 404 gspca_dev->usb_buf[0] = 0x06; 405 gspca_dev->usb_buf[1] = val * 0x40; 406 reg_w(gspca_dev, 2); 407 } 408 return 0; 409} 410 411static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) 412{ 413 struct sd *sd = (struct sd *) gspca_dev; 414 415 *val = sd->gamma; 416 return 0; 417} 418 419static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) 420{ 421 struct sd *sd = (struct sd *) gspca_dev; 422 423 sd->sharpness = val; 424 if (gspca_dev->streaming) { 425 gspca_dev->usb_buf[0] = 0x67; 426 gspca_dev->usb_buf[1] = val * 4 + 3; 427 reg_w(gspca_dev, 2); 428 } 429 return 0; 430} 431 432static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) 433{ 434 struct sd *sd = (struct sd *) gspca_dev; 435 436 *val = sd->sharpness; 437 return 0; 438} 439 440static int sd_set_jcomp(struct gspca_dev *gspca_dev, 441 struct v4l2_jpegcompression *jcomp) 442{ 443 struct sd *sd = (struct sd *) gspca_dev; 444 445 if (jcomp->quality < QUALITY_MIN) 446 sd->quality = QUALITY_MIN; 447 else if (jcomp->quality > QUALITY_MAX) 448 sd->quality = QUALITY_MAX; 449 else 450 sd->quality = jcomp->quality; 451 if (gspca_dev->streaming) 452 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 453 return 0; 454} 455 456static int sd_get_jcomp(struct gspca_dev *gspca_dev, 457 struct v4l2_jpegcompression *jcomp) 458{ 459 struct sd *sd = (struct sd *) gspca_dev; 460 461 memset(jcomp, 0, sizeof *jcomp); 462 jcomp->quality = sd->quality; 463 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT 464 | V4L2_JPEG_MARKER_DQT; 465 return 0; 466} 467 468/* sub-driver description */ 469static const struct sd_desc sd_desc = { 470 .name = MODULE_NAME, 471 .ctrls = sd_ctrls, 472 .nctrls = ARRAY_SIZE(sd_ctrls), 473 .config = sd_config, 474 .init = sd_init, 475 .start = sd_start, 476 .stopN = sd_stopN, 477 .pkt_scan = sd_pkt_scan, 478 .get_jcomp = sd_get_jcomp, 479 .set_jcomp = sd_set_jcomp, 480}; 481 482/* -- module initialisation -- */ 483static const __devinitdata struct usb_device_id device_table[] = { 484 {USB_DEVICE(0x093a, 0x050f)}, 485 {} 486}; 487MODULE_DEVICE_TABLE(usb, device_table); 488 489/* -- device connect -- */ 490static int sd_probe(struct usb_interface *intf, 491 const struct usb_device_id *id) 492{ 493 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 494 THIS_MODULE); 495} 496 497static struct usb_driver sd_driver = { 498 .name = MODULE_NAME, 499 .id_table = device_table, 500 .probe = sd_probe, 501 .disconnect = gspca_disconnect, 502#ifdef CONFIG_PM 503 .suspend = gspca_suspend, 504 .resume = gspca_resume, 505#endif 506}; 507 508/* -- module insert / remove -- */ 509static int __init sd_mod_init(void) 510{ 511 int ret; 512 513 ret = usb_register(&sd_driver); 514 if (ret < 0) 515 return ret; 516 PDEBUG(D_PROBE, "registered"); 517 return 0; 518} 519static void __exit sd_mod_exit(void) 520{ 521 usb_deregister(&sd_driver); 522 PDEBUG(D_PROBE, "deregistered"); 523} 524 525module_init(sd_mod_init); 526module_exit(sd_mod_exit); 527