| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *		Mars-Semi MR97311A library | 
					
						
							|  |  |  |  *		Copyright (C) 2005 <bradlch@hotmail.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |  * the Free Software Foundation; either version 2 of the License, or | 
					
						
							|  |  |  |  * any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-21 19:56:57 -03:00
										 |  |  | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | #define MODULE_NAME "mars"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gspca.h"
 | 
					
						
							|  |  |  | #include "jpeg.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 
					
						
							|  |  |  | MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver"); | 
					
						
							|  |  |  | MODULE_LICENSE("GPL"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-27 16:48:33 -03:00
										 |  |  | #define QUALITY 50
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | /* specific webcam descriptor */ | 
					
						
							|  |  |  | struct sd { | 
					
						
							|  |  |  | 	struct gspca_dev gspca_dev;	/* !! must be the first item */ | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	struct v4l2_ctrl *brightness; | 
					
						
							|  |  |  | 	struct v4l2_ctrl *saturation; | 
					
						
							|  |  |  | 	struct v4l2_ctrl *sharpness; | 
					
						
							|  |  |  | 	struct v4l2_ctrl *gamma; | 
					
						
							|  |  |  | 	struct { /* illuminator control cluster */ | 
					
						
							|  |  |  | 		struct v4l2_ctrl *illum_top; | 
					
						
							|  |  |  | 		struct v4l2_ctrl *illum_bottom; | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2010-06-04 05:26:42 -03:00
										 |  |  | 	u8 jpeg_hdr[JPEG_HDR_SZ]; | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* V4L2 controls supported by the driver */ | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | static void setbrightness(struct gspca_dev *gspca_dev, s32 val); | 
					
						
							|  |  |  | static void setcolors(struct gspca_dev *gspca_dev, s32 val); | 
					
						
							|  |  |  | static void setgamma(struct gspca_dev *gspca_dev, s32 val); | 
					
						
							|  |  |  | static void setsharpness(struct gspca_dev *gspca_dev, s32 val); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-29 07:49:41 -03:00
										 |  |  | static const struct v4l2_pix_format vga_mode[] = { | 
					
						
							| 
									
										
										
										
											2008-07-05 11:49:20 -03:00
										 |  |  | 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 
					
						
							|  |  |  | 		.bytesperline = 320, | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 		.sizeimage = 320 * 240 * 3 / 8 + 590, | 
					
						
							| 
									
										
										
										
											2008-07-05 11:49:20 -03:00
										 |  |  | 		.colorspace = V4L2_COLORSPACE_JPEG, | 
					
						
							|  |  |  | 		.priv = 2}, | 
					
						
							|  |  |  | 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 
					
						
							|  |  |  | 		.bytesperline = 640, | 
					
						
							|  |  |  | 		.sizeimage = 640 * 480 * 3 / 8 + 590, | 
					
						
							|  |  |  | 		.colorspace = V4L2_COLORSPACE_JPEG, | 
					
						
							|  |  |  | 		.priv = 1}, | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | static const __u8 mi_data[0x20] = { | 
					
						
							|  |  |  | /*	 01    02   03     04    05    06    07    08 */ | 
					
						
							|  |  |  | 	0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00, | 
					
						
							|  |  |  | /*	 09    0a   0b     0c    0d    0e    0f    10 */ | 
					
						
							|  |  |  | 	0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, | 
					
						
							|  |  |  | /*	 11    12   13     14    15    16    17    18 */ | 
					
						
							|  |  |  | 	0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02, | 
					
						
							|  |  |  | /*	 19    1a   1b     1c    1d    1e    1f    20 */ | 
					
						
							|  |  |  | 	0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00 | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | /* write <len> bytes from gspca_dev->usb_buf */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | static void reg_w(struct gspca_dev *gspca_dev, | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 		 int len) | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	int alen, ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	if (gspca_dev->usb_err < 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	ret = usb_bulk_msg(gspca_dev->dev, | 
					
						
							|  |  |  | 			usb_sndbulkpipe(gspca_dev->dev, 4), | 
					
						
							|  |  |  | 			gspca_dev->usb_buf, | 
					
						
							|  |  |  | 			len, | 
					
						
							|  |  |  | 			&alen, | 
					
						
							|  |  |  | 			500);	/* timeout in milliseconds */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	if (ret < 0) { | 
					
						
							| 
									
										
										
										
											2011-08-21 19:56:57 -03:00
										 |  |  | 		pr_err("reg write [%02x] error %d\n", | 
					
						
							|  |  |  | 		       gspca_dev->usb_buf[0], ret); | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 		gspca_dev->usb_err = ret; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | static void mi_w(struct gspca_dev *gspca_dev, | 
					
						
							|  |  |  | 		 u8 addr, | 
					
						
							|  |  |  | 		 u8 value) | 
					
						
							| 
									
										
										
										
											2008-07-14 09:38:29 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[0] = 0x1f; | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[1] = 0;			/* control byte */ | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	gspca_dev->usb_buf[2] = addr; | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[3] = value; | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	reg_w(gspca_dev, 4); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | static void setbrightness(struct gspca_dev *gspca_dev, s32 val) | 
					
						
							| 
									
										
										
										
											2010-10-16 14:07:06 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[0] = 0x61; | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	gspca_dev->usb_buf[1] = val; | 
					
						
							| 
									
										
										
										
											2010-10-16 14:07:06 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | static void setcolors(struct gspca_dev *gspca_dev, s32 val) | 
					
						
							| 
									
										
										
										
											2010-10-16 14:07:06 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[0] = 0x5f; | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[1] = val << 3; | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04; | 
					
						
							|  |  |  | 	reg_w(gspca_dev, 3); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | static void setgamma(struct gspca_dev *gspca_dev, s32 val) | 
					
						
							| 
									
										
										
										
											2010-10-16 14:07:06 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[0] = 0x06; | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	gspca_dev->usb_buf[1] = val * 0x40; | 
					
						
							| 
									
										
										
										
											2010-10-16 14:07:06 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | static void setsharpness(struct gspca_dev *gspca_dev, s32 val) | 
					
						
							| 
									
										
										
										
											2010-10-16 14:07:06 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[0] = 0x67; | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	gspca_dev->usb_buf[1] = val * 4 + 3; | 
					
						
							| 
									
										
										
										
											2010-10-16 14:07:06 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom) | 
					
						
							| 
									
										
										
										
											2010-10-16 14:12:53 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	/* both are off if not streaming */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:12:53 -03:00
										 |  |  | 	gspca_dev->usb_buf[0] = 0x22; | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	if (top) | 
					
						
							| 
									
										
										
										
											2010-10-16 14:12:53 -03:00
										 |  |  | 		gspca_dev->usb_buf[1] = 0x76; | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	else if (bottom) | 
					
						
							| 
									
										
										
										
											2010-10-16 14:12:53 -03:00
										 |  |  | 		gspca_dev->usb_buf[1] = 0x7a; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		gspca_dev->usb_buf[1] = 0x7e; | 
					
						
							|  |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | static int mars_s_ctrl(struct v4l2_ctrl *ctrl) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-09 11:19:00 -03:00
										 |  |  | 	struct gspca_dev *gspca_dev = | 
					
						
							|  |  |  | 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler); | 
					
						
							|  |  |  | 	struct sd *sd = (struct sd *)gspca_dev; | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	gspca_dev->usb_err = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ctrl->id == V4L2_CID_ILLUMINATORS_1) { | 
					
						
							|  |  |  | 		/* only one can be on at a time */ | 
					
						
							|  |  |  | 		if (ctrl->is_new && ctrl->val) | 
					
						
							|  |  |  | 			sd->illum_bottom->val = 0; | 
					
						
							|  |  |  | 		if (sd->illum_bottom->is_new && sd->illum_bottom->val) | 
					
						
							|  |  |  | 			sd->illum_top->val = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!gspca_dev->streaming) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (ctrl->id) { | 
					
						
							|  |  |  | 	case V4L2_CID_BRIGHTNESS: | 
					
						
							| 
									
										
										
										
											2012-05-09 11:19:00 -03:00
										 |  |  | 		setbrightness(gspca_dev, ctrl->val); | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case V4L2_CID_SATURATION: | 
					
						
							| 
									
										
										
										
											2012-05-09 11:19:00 -03:00
										 |  |  | 		setcolors(gspca_dev, ctrl->val); | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case V4L2_CID_GAMMA: | 
					
						
							| 
									
										
										
										
											2012-05-09 11:19:00 -03:00
										 |  |  | 		setgamma(gspca_dev, ctrl->val); | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case V4L2_CID_ILLUMINATORS_1: | 
					
						
							| 
									
										
										
										
											2012-05-09 11:19:00 -03:00
										 |  |  | 		setilluminators(gspca_dev, sd->illum_top->val, | 
					
						
							|  |  |  | 					   sd->illum_bottom->val); | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case V4L2_CID_SHARPNESS: | 
					
						
							| 
									
										
										
										
											2012-05-09 11:19:00 -03:00
										 |  |  | 		setsharpness(gspca_dev, ctrl->val); | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return gspca_dev->usb_err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct v4l2_ctrl_ops mars_ctrl_ops = { | 
					
						
							|  |  |  | 	.s_ctrl = mars_s_ctrl, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* this function is called at probe time */ | 
					
						
							|  |  |  | static int sd_init_controls(struct gspca_dev *gspca_dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sd *sd = (struct sd *) gspca_dev; | 
					
						
							| 
									
										
										
										
											2012-05-09 11:19:00 -03:00
										 |  |  | 	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	gspca_dev->vdev.ctrl_handler = hdl; | 
					
						
							| 
									
										
										
										
											2012-06-27 16:48:33 -03:00
										 |  |  | 	v4l2_ctrl_handler_init(hdl, 6); | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, | 
					
						
							|  |  |  | 			V4L2_CID_BRIGHTNESS, 0, 30, 1, 15); | 
					
						
							|  |  |  | 	sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, | 
					
						
							|  |  |  | 			V4L2_CID_SATURATION, 0, 255, 1, 200); | 
					
						
							|  |  |  | 	sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, | 
					
						
							|  |  |  | 			V4L2_CID_GAMMA, 0, 3, 1, 1); | 
					
						
							|  |  |  | 	sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, | 
					
						
							|  |  |  | 			V4L2_CID_SHARPNESS, 0, 2, 1, 1); | 
					
						
							|  |  |  | 	sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, | 
					
						
							|  |  |  | 			V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0); | 
					
						
							|  |  |  | 	sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE; | 
					
						
							|  |  |  | 	sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, | 
					
						
							|  |  |  | 			V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0); | 
					
						
							|  |  |  | 	sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE; | 
					
						
							|  |  |  | 	if (hdl->error) { | 
					
						
							|  |  |  | 		pr_err("Could not initialize controls\n"); | 
					
						
							|  |  |  | 		return hdl->error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v4l2_ctrl_cluster(2, &sd->illum_top); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | /* this function is called at probe time */ | 
					
						
							|  |  |  | static int sd_config(struct gspca_dev *gspca_dev, | 
					
						
							|  |  |  | 			const struct usb_device_id *id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct cam *cam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cam = &gspca_dev->cam; | 
					
						
							|  |  |  | 	cam->cam_mode = vga_mode; | 
					
						
							| 
									
										
										
										
											2008-11-12 23:18:21 -03:00
										 |  |  | 	cam->nmodes = ARRAY_SIZE(vga_mode); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-03 17:12:16 -03:00
										 |  |  | /* this function is called at probe and resume time */ | 
					
						
							|  |  |  | static int sd_init(struct gspca_dev *gspca_dev) | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-20 06:39:08 -03:00
										 |  |  | static int sd_start(struct gspca_dev *gspca_dev) | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	struct sd *sd = (struct sd *) gspca_dev; | 
					
						
							|  |  |  | 	u8 *data; | 
					
						
							| 
									
										
										
										
											2009-02-28 08:09:24 -03:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 05:33:41 -03:00
										 |  |  | 	/* create the JPEG header */ | 
					
						
							| 
									
										
										
										
											2013-08-30 17:54:23 -03:00
										 |  |  | 	jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height, | 
					
						
							|  |  |  | 			gspca_dev->pixfmt.width, | 
					
						
							| 
									
										
										
										
											2009-03-03 05:33:41 -03:00
										 |  |  | 			0x21);		/* JPEG 422 */ | 
					
						
							| 
									
										
										
										
											2012-06-27 16:48:33 -03:00
										 |  |  | 	jpeg_set_qual(sd->jpeg_hdr, QUALITY); | 
					
						
							| 
									
										
										
										
											2009-03-03 05:33:41 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 09:38:29 -03:00
										 |  |  | 	data = gspca_dev->usb_buf; | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 	data[0] = 0x01;		/* address */ | 
					
						
							|  |  |  | 	data[1] = 0x01; | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	   Initialize the MR97113 chip register | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	data[0] = 0x00;		/* address */ | 
					
						
							|  |  |  | 	data[1] = 0x0c | 0x01;	/* reg 0 */ | 
					
						
							|  |  |  | 	data[2] = 0x01;		/* reg 1 */ | 
					
						
							| 
									
										
										
										
											2013-08-30 17:54:23 -03:00
										 |  |  | 	data[3] = gspca_dev->pixfmt.width / 8;	/* h_size , reg 2 */ | 
					
						
							|  |  |  | 	data[4] = gspca_dev->pixfmt.height / 8;	/* v_size , reg 3 */ | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 	data[5] = 0x30;		/* reg 4, MI, PAS5101 :
 | 
					
						
							|  |  |  | 				 *	0x30 for 24mhz , 0x28 for 12mhz */ | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	data[6] = 0x02;		/* reg 5, H start - was 0x04 */ | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40;	/* reg 0x06: gamma */ | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	data[8] = 0x01;		/* reg 7, V start - was 0x03 */ | 
					
						
							| 
									
										
										
										
											2008-07-14 09:38:29 -03:00
										 |  |  | /*	if (h_size == 320 ) */ | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | /*		data[9]= 0x56;	 * reg 8, 24MHz, 2:1 scale down */ | 
					
						
							|  |  |  | /*	else */ | 
					
						
							|  |  |  | 	data[9] = 0x52;		/* reg 8, 24MHz, no scale down */ | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | /*jfm: from win trace*/ | 
					
						
							|  |  |  | 	data[10] = 0x18; | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 11); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	data[0] = 0x23;		/* address */ | 
					
						
							|  |  |  | 	data[1] = 0x09;		/* reg 35, append frame header */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 09:38:29 -03:00
										 |  |  | 	data[0] = 0x3c;		/* address */ | 
					
						
							|  |  |  | /*	if (gspca_dev->width == 1280) */ | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | /*		data[1] = 200;	 * reg 60, pc-cam frame size
 | 
					
						
							|  |  |  | 				 *	(unit: 4KB) 800KB */ | 
					
						
							|  |  |  | /*	else */ | 
					
						
							|  |  |  | 	data[1] = 50;		/* 50 reg 60, pc-cam frame size
 | 
					
						
							|  |  |  | 				 *	(unit: 4KB) 200KB */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* auto dark-gain */ | 
					
						
							|  |  |  | 	data[0] = 0x5e;		/* address */ | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	data[1] = 0;		/* reg 94, Y Gain (auto) */ | 
					
						
							|  |  |  | /*jfm: from win trace*/ | 
					
						
							| 
									
										
										
										
											2009-02-28 08:09:24 -03:00
										 |  |  | 				/* reg 0x5f/0x60 (LE) = saturation */ | 
					
						
							|  |  |  | 				/* h (60): xxxx x100
 | 
					
						
							|  |  |  | 				 * l (5f): xxxx x000 */ | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3; | 
					
						
							|  |  |  | 	data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04; | 
					
						
							|  |  |  | 	data[4] = v4l2_ctrl_g_ctrl(sd->brightness); /* reg 0x61 = brightness */ | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	data[5] = 0x00; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 6); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	data[0] = 0x67; | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | /*jfm: from win trace*/ | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3; | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	data[2] = 0x14; | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 3); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	data[0] = 0x69; | 
					
						
							|  |  |  | 	data[1] = 0x2f; | 
					
						
							|  |  |  | 	data[2] = 0x28; | 
					
						
							|  |  |  | 	data[3] = 0x42; | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 4); | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	data[0] = 0x63; | 
					
						
							|  |  |  | 	data[1] = 0x07; | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | /*jfm: win trace - many writes here to reg 0x64*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* initialize the MI sensor */ | 
					
						
							|  |  |  | 	for (i = 0; i < sizeof mi_data; i++) | 
					
						
							|  |  |  | 		mi_w(gspca_dev, i + 1, mi_data[i]); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	data[0] = 0x00; | 
					
						
							| 
									
										
										
										
											2011-03-30 22:57:33 -03:00
										 |  |  | 	data[1] = 0x4d;		/* ISOC transferring enable... */ | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top), | 
					
						
							|  |  |  | 				   v4l2_ctrl_g_ctrl(sd->illum_bottom)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	return gspca_dev->usb_err; | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sd_stopN(struct gspca_dev *gspca_dev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-16 14:12:53 -03:00
										 |  |  | 	struct sd *sd = (struct sd *) gspca_dev; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	if (v4l2_ctrl_g_ctrl(sd->illum_top) || | 
					
						
							|  |  |  | 	    v4l2_ctrl_g_ctrl(sd->illum_bottom)) { | 
					
						
							|  |  |  | 		setilluminators(gspca_dev, false, false); | 
					
						
							| 
									
										
										
										
											2010-10-16 14:12:53 -03:00
										 |  |  | 		msleep(20); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 09:38:29 -03:00
										 |  |  | 	gspca_dev->usb_buf[0] = 1; | 
					
						
							|  |  |  | 	gspca_dev->usb_buf[1] = 0; | 
					
						
							| 
									
										
										
										
											2010-10-16 14:10:59 -03:00
										 |  |  | 	reg_w(gspca_dev, 2); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 
					
						
							| 
									
										
										
										
											2009-11-13 09:21:03 -03:00
										 |  |  | 			u8 *data,			/* isoc packet */ | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 			int len)			/* iso packet length */ | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-03 05:33:41 -03:00
										 |  |  | 	struct sd *sd = (struct sd *) gspca_dev; | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 	int p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (len < 6) { | 
					
						
							|  |  |  | /*		gspca_dev->last_packet_type = DISCARD_PACKET; */ | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (p = 0; p < len - 6; p++) { | 
					
						
							|  |  |  | 		if (data[0 + p] == 0xff | 
					
						
							|  |  |  | 		    && data[1 + p] == 0xff | 
					
						
							|  |  |  | 		    && data[2 + p] == 0x00 | 
					
						
							|  |  |  | 		    && data[3 + p] == 0xff | 
					
						
							|  |  |  | 		    && data[4 + p] == 0x96) { | 
					
						
							|  |  |  | 			if (data[5 + p] == 0x64 | 
					
						
							|  |  |  | 			    || data[5 + p] == 0x65 | 
					
						
							|  |  |  | 			    || data[5 + p] == 0x66 | 
					
						
							|  |  |  | 			    || data[5 + p] == 0x67) { | 
					
						
							| 
									
										
										
										
											2009-01-08 16:29:38 -03:00
										 |  |  | 				PDEBUG(D_PACK, "sof offset: %d len: %d", | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 					p, len); | 
					
						
							| 
									
										
										
										
											2009-11-13 09:21:03 -03:00
										 |  |  | 				gspca_frame_add(gspca_dev, LAST_PACKET, | 
					
						
							|  |  |  | 						data, p); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* put the JPEG header */ | 
					
						
							| 
									
										
										
										
											2009-11-13 09:21:03 -03:00
										 |  |  | 				gspca_frame_add(gspca_dev, FIRST_PACKET, | 
					
						
							| 
									
										
										
										
											2009-03-03 05:33:41 -03:00
										 |  |  | 					sd->jpeg_hdr, JPEG_HDR_SZ); | 
					
						
							| 
									
										
										
										
											2009-01-08 16:30:58 -03:00
										 |  |  | 				data += p + 16; | 
					
						
							|  |  |  | 				len -= p + 16; | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-13 09:21:03 -03:00
										 |  |  | 	gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* sub-driver description */ | 
					
						
							| 
									
										
										
										
											2008-07-04 11:16:16 -03:00
										 |  |  | static const struct sd_desc sd_desc = { | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 	.name = MODULE_NAME, | 
					
						
							|  |  |  | 	.config = sd_config, | 
					
						
							| 
									
										
										
										
											2008-09-03 17:12:16 -03:00
										 |  |  | 	.init = sd_init, | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	.init_controls = sd_init_controls, | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 	.start = sd_start, | 
					
						
							|  |  |  | 	.stopN = sd_stopN, | 
					
						
							|  |  |  | 	.pkt_scan = sd_pkt_scan, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -- module initialisation -- */ | 
					
						
							| 
									
										
										
										
											2011-01-13 05:20:29 -03:00
										 |  |  | static const struct usb_device_id device_table[] = { | 
					
						
							| 
									
										
										
										
											2008-07-25 08:53:03 -03:00
										 |  |  | 	{USB_DEVICE(0x093a, 0x050f)}, | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | 	{} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | MODULE_DEVICE_TABLE(usb, device_table); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -- device connect -- */ | 
					
						
							|  |  |  | static int sd_probe(struct usb_interface *intf, | 
					
						
							|  |  |  | 			const struct usb_device_id *id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 
					
						
							|  |  |  | 				THIS_MODULE); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct usb_driver sd_driver = { | 
					
						
							|  |  |  | 	.name = MODULE_NAME, | 
					
						
							|  |  |  | 	.id_table = device_table, | 
					
						
							|  |  |  | 	.probe = sd_probe, | 
					
						
							|  |  |  | 	.disconnect = gspca_disconnect, | 
					
						
							| 
									
										
										
										
											2008-09-03 16:48:10 -03:00
										 |  |  | #ifdef CONFIG_PM
 | 
					
						
							|  |  |  | 	.suspend = gspca_suspend, | 
					
						
							|  |  |  | 	.resume = gspca_resume, | 
					
						
							| 
									
										
										
										
											2012-05-06 09:28:31 -03:00
										 |  |  | 	.reset_resume = gspca_resume, | 
					
						
							| 
									
										
										
										
											2008-09-03 16:48:10 -03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-06-30 15:50:11 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-18 09:46:12 -08:00
										 |  |  | module_usb_driver(sd_driver); |