| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* Driver for Philips webcam
 | 
					
						
							|  |  |  |    Functions that send various control messages to the webcam, including | 
					
						
							|  |  |  |    video modes. | 
					
						
							|  |  |  |    (C) 1999-2003 Nemosoft Unv. | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  |    (C) 2004-2006 Luc Saillard (luc@saillard.org) | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  |    (C) 2011 Hans de Goede <hdegoede@redhat.com> | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 
					
						
							|  |  |  |    driver and thus may have bugs that are not present in the original version. | 
					
						
							|  |  |  |    Please send bug reports and support requests to <luc@saillard.org>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx | 
					
						
							|  |  |  |    driver and thus may have bugs that are not present in the original version. | 
					
						
							|  |  |  |    Please send bug reports and support requests to <luc@saillard.org>. | 
					
						
							|  |  |  |    The decompression routines have been implemented by reverse-engineering the | 
					
						
							|  |  |  |    Nemosoft binary pwcx module. Caveat emptor. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    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 | 
					
						
							|  |  |  |    (at your option) 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 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |    Changes | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  |    2001/08/03  Alvarado   Added methods for changing white balance and | 
					
						
							|  |  |  | 			  red/green gains | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Control functions for the cam; brightness, contrast, video mode, etc. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __KERNEL__
 | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | #include <asm/uaccess.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #include <asm/errno.h>
 | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "pwc.h"
 | 
					
						
							|  |  |  | #include "pwc-kiara.h"
 | 
					
						
							|  |  |  | #include "pwc-timon.h"
 | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | #include "pwc-dec1.h"
 | 
					
						
							|  |  |  | #include "pwc-dec23.h"
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | /* Selectors for status controls used only in this file */ | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | #define GET_STATUS_B00				0x0B00
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define SENSOR_TYPE_FORMATTER1			0x0C00
 | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | #define GET_STATUS_3000				0x3000
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define READ_RAW_Y_MEAN_FORMATTER		0x3100
 | 
					
						
							|  |  |  | #define SET_POWER_SAVE_MODE_FORMATTER		0x3200
 | 
					
						
							|  |  |  | #define MIRROR_IMAGE_FORMATTER			0x3300
 | 
					
						
							|  |  |  | #define LED_FORMATTER				0x3400
 | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | #define LOWLIGHT				0x3500
 | 
					
						
							|  |  |  | #define GET_STATUS_3600				0x3600
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define SENSOR_TYPE_FORMATTER2			0x3700
 | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | #define GET_STATUS_3800				0x3800
 | 
					
						
							|  |  |  | #define GET_STATUS_4000				0x4000
 | 
					
						
							|  |  |  | #define GET_STATUS_4100				0x4100	/* Get */
 | 
					
						
							|  |  |  | #define CTL_STATUS_4200				0x4200	/* [GS] 1 */
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ | 
					
						
							|  |  |  | #define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-29 09:43:42 +01:00
										 |  |  | static const char *size2name[PSZ_MAX] = | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	"subQCIF", | 
					
						
							|  |  |  | 	"QSIF", | 
					
						
							|  |  |  | 	"QCIF", | 
					
						
							|  |  |  | 	"SIF", | 
					
						
							|  |  |  | 	"CIF", | 
					
						
							|  |  |  | 	"VGA", | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /********/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | /* Entries for the Nala (645/646) camera; the Nala doesn't have compression
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |    preferences, so you either get compressed or non-compressed streams. | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |    An alternate value of 0 means this mode is not available at all. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-22 23:54:36 -03:00
										 |  |  | #define PWC_FPS_MAX_NALA 8
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | struct Nala_table_entry { | 
					
						
							|  |  |  | 	char alternate;			/* USB alternate setting */ | 
					
						
							|  |  |  | 	int compressed;			/* Compressed yes/no */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned char mode[3];		/* precomputed mode table */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-22 23:54:36 -03:00
										 |  |  | static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] = | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | #include "pwc-nala.h"
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /****************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-21 21:48:09 +02:00
										 |  |  | static int recv_control_msg(struct pwc_device *pdev, | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	u8 request, u16 value, int recv_count) | 
					
						
							| 
									
										
										
										
											2009-04-21 21:48:09 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), | 
					
						
							|  |  |  | 		request, | 
					
						
							|  |  |  | 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		value, pdev->vcinterface, | 
					
						
							|  |  |  | 		pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT); | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | 	if (rc < 0) | 
					
						
							|  |  |  | 		PWC_ERROR("recv_control_msg error %d req %02x val %04x\n", | 
					
						
							|  |  |  | 			  rc, request, value); | 
					
						
							| 
									
										
										
										
											2009-04-21 21:48:09 +02:00
										 |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-21 21:48:09 +02:00
										 |  |  | static inline int send_video_command(struct pwc_device *pdev, | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	int index, const unsigned char *buf, int buflen) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy(pdev->ctrl_buf, buf, buflen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), | 
					
						
							|  |  |  | 			SET_EP_STREAM_CTL, | 
					
						
							|  |  |  | 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
					
						
							|  |  |  | 			VIDEO_OUTPUT_CONTROL_FORMATTER, index, | 
					
						
							|  |  |  | 			pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT); | 
					
						
							|  |  |  | 	if (rc >= 0) | 
					
						
							|  |  |  | 		memcpy(pdev->cmd_buf, buf, buflen); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		PWC_ERROR("send_video_command error %d\n", rc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rc; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-03 12:23:24 -03:00
										 |  |  | int send_control_msg(struct pwc_device *pdev, | 
					
						
							| 
									
										
										
										
											2009-04-21 21:48:09 +02:00
										 |  |  | 	u8 request, u16 value, void *buf, int buflen) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), | 
					
						
							|  |  |  | 			request, | 
					
						
							|  |  |  | 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
					
						
							|  |  |  | 			value, pdev->vcinterface, | 
					
						
							|  |  |  | 			buf, buflen, USB_CTRL_SET_TIMEOUT); | 
					
						
							| 
									
										
										
										
											2009-04-21 21:48:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt, | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 			       int frames, int *compression, int send_to_cam) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 	int fps, ret = 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	struct Nala_table_entry *pEntry; | 
					
						
							|  |  |  | 	int frames2frames[31] = | 
					
						
							|  |  |  | 	{ /* closest match of framerate */ | 
					
						
							|  |  |  | 	   0,  0,  0,  0,  4,  /*  0-4  */ | 
					
						
							|  |  |  | 	   5,  5,  7,  7, 10,  /*  5-9  */ | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 	  10, 10, 12, 12, 15,  /* 10-14 */ | 
					
						
							|  |  |  | 	  15, 15, 15, 20, 20,  /* 15-19 */ | 
					
						
							|  |  |  | 	  20, 20, 20, 24, 24,  /* 20-24 */ | 
					
						
							|  |  |  | 	  24, 24, 24, 24, 24,  /* 25-29 */ | 
					
						
							|  |  |  | 	  24                   /* 30    */ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 	int frames2table[31] = | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	{ 0, 0, 0, 0, 0, /*  0-4  */ | 
					
						
							|  |  |  | 	  1, 1, 1, 2, 2, /*  5-9  */ | 
					
						
							|  |  |  | 	  3, 3, 4, 4, 4, /* 10-14 */ | 
					
						
							|  |  |  | 	  5, 5, 5, 5, 5, /* 15-19 */ | 
					
						
							|  |  |  | 	  6, 6, 6, 6, 7, /* 20-24 */ | 
					
						
							|  |  |  | 	  7, 7, 7, 7, 7, /* 25-29 */ | 
					
						
							|  |  |  | 	  7              /* 30    */ | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	if (size < 0 || size > PSZ_CIF) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return -EINVAL; | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	if (frames < 4) | 
					
						
							|  |  |  | 		frames = 4; | 
					
						
							| 
									
										
										
										
											2012-10-08 06:05:24 -03:00
										 |  |  | 	else if (size > PSZ_QCIF && frames > 15) | 
					
						
							|  |  |  | 		frames = 15; | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	else if (frames > 25) | 
					
						
							|  |  |  | 		frames = 25; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	frames = frames2frames[frames]; | 
					
						
							|  |  |  | 	fps = frames2table[frames]; | 
					
						
							|  |  |  | 	pEntry = &Nala_table[size][fps]; | 
					
						
							|  |  |  | 	if (pEntry->alternate == 0) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 	if (send_to_cam) | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		ret = send_video_command(pdev, pdev->vendpoint, | 
					
						
							|  |  |  | 					 pEntry->mode, 3); | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return ret; | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420) | 
					
						
							|  |  |  | 		pwc_dec1_init(pdev, pEntry->mode); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Set various parameters */ | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 	pdev->pixfmt = pixfmt; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	pdev->vframes = frames; | 
					
						
							|  |  |  | 	pdev->valternate = pEntry->alternate; | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 	pdev->width  = pwc_image_sizes[size][0]; | 
					
						
							|  |  |  | 	pdev->height = pwc_image_sizes[size][1]; | 
					
						
							|  |  |  | 	pdev->frame_size = (pdev->width * pdev->height * 3) / 2; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (pEntry->compressed) { | 
					
						
							|  |  |  | 		if (pdev->release < 5) { /* 4 fold compression */ | 
					
						
							|  |  |  | 			pdev->vbandlength = 528; | 
					
						
							|  |  |  | 			pdev->frame_size /= 4; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			pdev->vbandlength = 704; | 
					
						
							|  |  |  | 			pdev->frame_size /= 3; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		pdev->vbandlength = 0; | 
					
						
							| 
									
										
										
										
											2012-01-04 18:48:05 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Let pwc-if.c:isoc_init know we don't support higher compression */ | 
					
						
							|  |  |  | 	*compression = 3; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt, | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 				int frames, int *compression, int send_to_cam) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	const struct Timon_table_entry *pChoose; | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 	int fps, ret = 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	if (size >= PSZ_MAX || *compression < 0 || *compression > 3) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return -EINVAL; | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	if (frames < 5) | 
					
						
							|  |  |  | 		frames = 5; | 
					
						
							|  |  |  | 	else if (size == PSZ_VGA && frames > 15) | 
					
						
							|  |  |  | 		frames = 15; | 
					
						
							|  |  |  | 	else if (frames > 30) | 
					
						
							|  |  |  | 		frames = 30; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	fps = (frames / 5) - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-04 18:48:05 -03:00
										 |  |  | 	/* Find a supported framerate with progressively higher compression */ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	pChoose = NULL; | 
					
						
							| 
									
										
										
										
											2012-01-04 18:48:05 -03:00
										 |  |  | 	while (*compression <= 3) { | 
					
						
							|  |  |  | 		pChoose = &Timon_table[size][fps][*compression]; | 
					
						
							|  |  |  | 		if (pChoose->alternate != 0) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		(*compression)++; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (pChoose == NULL || pChoose->alternate == 0) | 
					
						
							|  |  |  | 		return -ENOENT; /* Not supported. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 	if (send_to_cam) | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		ret = send_video_command(pdev, pdev->vendpoint, | 
					
						
							|  |  |  | 					 pChoose->mode, 13); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 	if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420) | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		pwc_dec23_init(pdev, pChoose->mode); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Set various parameters */ | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 	pdev->pixfmt = pixfmt; | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	pdev->vframes = (fps + 1) * 5; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	pdev->valternate = pChoose->alternate; | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 	pdev->width  = pwc_image_sizes[size][0]; | 
					
						
							|  |  |  | 	pdev->height = pwc_image_sizes[size][1]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	pdev->vbandlength = pChoose->bandlength; | 
					
						
							|  |  |  | 	if (pChoose->bandlength > 0) | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 		pdev->frame_size = (pChoose->bandlength * pdev->height) / 4; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 		pdev->frame_size = (pdev->width * pdev->height * 12) / 8; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt, | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 				int frames, int *compression, int send_to_cam) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	const struct Kiara_table_entry *pChoose = NULL; | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 	int fps, ret = 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	if (size >= PSZ_MAX || *compression < 0 || *compression > 3) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return -EINVAL; | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	if (frames < 5) | 
					
						
							|  |  |  | 		frames = 5; | 
					
						
							|  |  |  | 	else if (size == PSZ_VGA && frames > 15) | 
					
						
							|  |  |  | 		frames = 15; | 
					
						
							|  |  |  | 	else if (frames > 30) | 
					
						
							|  |  |  | 		frames = 30; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	fps = (frames / 5) - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-04 18:48:05 -03:00
										 |  |  | 	/* Find a supported framerate with progressively higher compression */ | 
					
						
							|  |  |  | 	while (*compression <= 3) { | 
					
						
							|  |  |  | 		pChoose = &Kiara_table[size][fps][*compression]; | 
					
						
							| 
									
										
										
										
											2011-12-31 10:52:02 -03:00
										 |  |  | 		if (pChoose->alternate != 0) | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2012-01-04 18:48:05 -03:00
										 |  |  | 		(*compression)++; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (pChoose == NULL || pChoose->alternate == 0) | 
					
						
							|  |  |  | 		return -ENOENT; /* Not supported. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 	if (send_to_cam) | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		ret = send_video_command(pdev, 4, pChoose->mode, 12); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 	if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420) | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		pwc_dec23_init(pdev, pChoose->mode); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* All set and go */ | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 	pdev->pixfmt = pixfmt; | 
					
						
							| 
									
										
										
										
											2012-01-08 07:19:29 -03:00
										 |  |  | 	pdev->vframes = (fps + 1) * 5; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	pdev->valternate = pChoose->alternate; | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 	pdev->width  = pwc_image_sizes[size][0]; | 
					
						
							|  |  |  | 	pdev->height = pwc_image_sizes[size][1]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	pdev->vbandlength = pChoose->bandlength; | 
					
						
							|  |  |  | 	if (pdev->vbandlength > 0) | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 		pdev->frame_size = (pdev->vbandlength * pdev->height) / 4; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 		pdev->frame_size = (pdev->width * pdev->height * 12) / 8; | 
					
						
							| 
									
										
										
										
											2011-12-31 10:52:02 -03:00
										 |  |  | 	PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n", | 
					
						
							|  |  |  | 	    pdev->frame_size, pdev->vframes, size, pdev->vbandlength); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-31 10:52:02 -03:00
										 |  |  | int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 	int pixfmt, int frames, int *compression, int send_to_cam) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 	int ret, size; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-08 11:29:19 -03:00
										 |  |  | 	PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 		       width, height, frames, pixfmt); | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 	size = pwc_get_size(pdev, width, height); | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 	PWC_TRACE("decode_size = %d.\n", size); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 	if (DEVICE_USE_CODEC1(pdev->type)) { | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 		ret = set_video_mode_Nala(pdev, size, pixfmt, frames, | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 					  compression, send_to_cam); | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 	} else if (DEVICE_USE_CODEC3(pdev->type)) { | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 		ret = set_video_mode_Kiara(pdev, size, pixfmt, frames, | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 					   compression, send_to_cam); | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2012-01-10 13:01:41 -03:00
										 |  |  | 		ret = set_video_mode_Timon(pdev, size, pixfmt, frames, | 
					
						
							| 
									
										
										
										
											2012-01-10 13:14:46 -03:00
										 |  |  | 					   compression, send_to_cam); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (ret < 0) { | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 		PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; | 
					
						
							| 
									
										
										
										
											2012-01-04 16:58:44 -03:00
										 |  |  | 	PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-22 23:54:36 -03:00
										 |  |  | static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < PWC_FPS_MAX_NALA; i++) { | 
					
						
							|  |  |  | 		if (Nala_table[size][i].alternate) { | 
					
						
							|  |  |  | 			if (index--==0) return Nala_fps_vector[i]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < PWC_FPS_MAX_KIARA; i++) { | 
					
						
							|  |  |  | 		if (Kiara_table[size][i][3].alternate) { | 
					
						
							|  |  |  | 			if (index--==0) return Kiara_fps_vector[i]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i=0; i < PWC_FPS_MAX_TIMON; i++) { | 
					
						
							|  |  |  | 		if (Timon_table[size][i][3].alternate) { | 
					
						
							|  |  |  | 			if (index--==0) return Timon_fps_vector[i]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (DEVICE_USE_CODEC1(pdev->type)) { | 
					
						
							|  |  |  | 		ret = pwc_get_fps_Nala(pdev, index, size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else if (DEVICE_USE_CODEC3(pdev->type)) { | 
					
						
							|  |  |  | 		ret = pwc_get_fps_Kiara(pdev, index, size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ret = pwc_get_fps_Timon(pdev, index, size); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	ret = recv_control_msg(pdev, request, value, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	*data = pdev->ctrl_buf[0]; | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	pdev->ctrl_buf[0] = data; | 
					
						
							|  |  |  | 	ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int ret; | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	ret = recv_control_msg(pdev, request, value, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	*data = ((s8 *)pdev->ctrl_buf)[0]; | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int ret; | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	ret = recv_control_msg(pdev, request, value, 2); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	*data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int ret; | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	pdev->ctrl_buf[0] = data & 0xff; | 
					
						
							|  |  |  | 	pdev->ctrl_buf[1] = data >> 8; | 
					
						
							|  |  |  | 	ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | int pwc_button_ctrl(struct pwc_device *pdev, u16 value) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | 	ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0); | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							| 
									
										
										
										
											2011-06-26 12:52:01 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-24 10:29:46 -03:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* POWER */ | 
					
						
							| 
									
										
										
										
											2011-06-26 03:51:19 -03:00
										 |  |  | void pwc_camera_power(struct pwc_device *pdev, int power) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-26 03:51:19 -03:00
										 |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!pdev->power_save) | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6)) | 
					
						
							| 
									
										
										
										
											2011-06-26 03:51:19 -03:00
										 |  |  | 		return;	/* Not supported by Nala or Timon < release 6 */ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (power) | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		pdev->ctrl_buf[0] = 0x00; /* active */ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		pdev->ctrl_buf[0] = 0xFF; /* power save */ | 
					
						
							|  |  |  | 	r = send_control_msg(pdev, SET_STATUS_CTL, | 
					
						
							|  |  |  | 		SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1); | 
					
						
							| 
									
										
										
										
											2011-06-26 03:51:19 -03:00
										 |  |  | 	if (r < 0) | 
					
						
							|  |  |  | 		PWC_ERROR("Failed to power %s camera (%d)\n", | 
					
						
							|  |  |  | 			  power ? "on" : "off", r); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-26 03:51:19 -03:00
										 |  |  | 	int r; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (pdev->type < 730) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	on_value /= 100; | 
					
						
							|  |  |  | 	off_value /= 100; | 
					
						
							|  |  |  | 	if (on_value < 0) | 
					
						
							|  |  |  | 		on_value = 0; | 
					
						
							|  |  |  | 	if (on_value > 0xff) | 
					
						
							|  |  |  | 		on_value = 0xff; | 
					
						
							|  |  |  | 	if (off_value < 0) | 
					
						
							|  |  |  | 		off_value = 0; | 
					
						
							|  |  |  | 	if (off_value > 0xff) | 
					
						
							|  |  |  | 		off_value = 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	pdev->ctrl_buf[0] = on_value; | 
					
						
							|  |  |  | 	pdev->ctrl_buf[1] = off_value; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 03:51:19 -03:00
										 |  |  | 	r = send_control_msg(pdev, | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2); | 
					
						
							| 
									
										
										
										
											2011-06-26 03:51:19 -03:00
										 |  |  | 	if (r < 0) | 
					
						
							|  |  |  | 		PWC_ERROR("Failed to set LED on/off time (%d)\n", r); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-26 06:49:59 -03:00
										 |  |  | #ifdef CONFIG_USB_PWC_DEBUG
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int ret = -1, request; | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (pdev->type < 675) | 
					
						
							|  |  |  | 		request = SENSOR_TYPE_FORMATTER1; | 
					
						
							|  |  |  | 	else if (pdev->type < 730) | 
					
						
							|  |  |  | 		return -1; /* The Vesta series doesn't have this call */ | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		request = SENSOR_TYPE_FORMATTER2; | 
					
						
							| 
									
										
										
										
											2006-03-25 09:19:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 	ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 	if (pdev->type < 675) | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		*sensor = pdev->ctrl_buf[0] | 0x100; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2012-01-10 17:02:04 -03:00
										 |  |  | 		*sensor = pdev->ctrl_buf[0]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-06-26 06:49:59 -03:00
										 |  |  | #endif
 |