Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /* Driver for Philips webcam
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)    Functions that send various control messages to the webcam, including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)    video modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)    (C) 1999-2003 Nemosoft Unv.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)    (C) 2004-2006 Luc Saillard (luc@saillard.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)    (C) 2011 Hans de Goede <hdegoede@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)    driver and thus may have bugs that are not present in the original version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)    Please send bug reports and support requests to <luc@saillard.org>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)    driver and thus may have bugs that are not present in the original version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)    Please send bug reports and support requests to <luc@saillard.org>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)    The decompression routines have been implemented by reverse-engineering the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)    Nemosoft binary pwcx module. Caveat emptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)    Changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)    2001/08/03  Alvarado   Added methods for changing white balance and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 			  red/green gains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) /* Control functions for the cam; brightness, contrast, video mode, etc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #ifdef __KERNEL__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include <asm/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include "pwc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include "pwc-kiara.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include "pwc-timon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include "pwc-dec1.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include "pwc-dec23.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /* Selectors for status controls used only in this file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define GET_STATUS_B00				0x0B00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define SENSOR_TYPE_FORMATTER1			0x0C00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define GET_STATUS_3000				0x3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define READ_RAW_Y_MEAN_FORMATTER		0x3100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define SET_POWER_SAVE_MODE_FORMATTER		0x3200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define MIRROR_IMAGE_FORMATTER			0x3300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define LED_FORMATTER				0x3400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define LOWLIGHT				0x3500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define GET_STATUS_3600				0x3600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define SENSOR_TYPE_FORMATTER2			0x3700
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define GET_STATUS_3800				0x3800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define GET_STATUS_4000				0x4000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) #define GET_STATUS_4100				0x4100	/* Get */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define CTL_STATUS_4200				0x4200	/* [GS] 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static const char *size2name[PSZ_MAX] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	"subQCIF",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	"QSIF",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	"QCIF",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	"SIF",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	"CIF",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	"VGA",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) /********/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) /* Entries for the Nala (645/646) camera; the Nala doesn't have compression
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)    preferences, so you either get compressed or non-compressed streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)    An alternate value of 0 means this mode is not available at all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) #define PWC_FPS_MAX_NALA 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) struct Nala_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	char alternate;			/* USB alternate setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	int compressed;			/* Compressed yes/no */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	unsigned char mode[3];		/* precomputed mode table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) #include "pwc-nala.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static int recv_control_msg(struct pwc_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	u8 request, u16 value, int recv_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		value, pdev->vcinterface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			  rc, request, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static inline int send_video_command(struct pwc_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	int index, const unsigned char *buf, int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	memcpy(pdev->ctrl_buf, buf, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			SET_EP_STREAM_CTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			VIDEO_OUTPUT_CONTROL_FORMATTER, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 			pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (rc >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		memcpy(pdev->cmd_buf, buf, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		PWC_ERROR("send_video_command error %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int send_control_msg(struct pwc_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	u8 request, u16 value, void *buf, int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			value, pdev->vcinterface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 			buf, buflen, USB_CTRL_SET_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			       int frames, int *compression, int send_to_cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	int fps, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	struct Nala_table_entry *pEntry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	int frames2frames[31] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	{ /* closest match of framerate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	   0,  0,  0,  0,  4,  /*  0-4  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	   5,  5,  7,  7, 10,  /*  5-9  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	  10, 10, 12, 12, 15,  /* 10-14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	  15, 15, 15, 20, 20,  /* 15-19 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	  20, 20, 20, 24, 24,  /* 20-24 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	  24, 24, 24, 24, 24,  /* 25-29 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	  24                   /* 30    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	int frames2table[31] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	{ 0, 0, 0, 0, 0, /*  0-4  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	  1, 1, 1, 2, 2, /*  5-9  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	  3, 3, 4, 4, 4, /* 10-14 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	  5, 5, 5, 5, 5, /* 15-19 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	  6, 6, 6, 6, 7, /* 20-24 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	  7, 7, 7, 7, 7, /* 25-29 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	  7              /* 30    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	if (size < 0 || size > PSZ_CIF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	if (frames < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		frames = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	else if (size > PSZ_QCIF && frames > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		frames = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	else if (frames > 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		frames = 25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	frames = frames2frames[frames];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	fps = frames2table[frames];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	pEntry = &Nala_table[size][fps];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	if (pEntry->alternate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (send_to_cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		ret = send_video_command(pdev, pdev->vendpoint,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 					 pEntry->mode, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		pwc_dec1_init(pdev, pEntry->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	/* Set various parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	pdev->pixfmt = pixfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	pdev->vframes = frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	pdev->valternate = pEntry->alternate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	pdev->width  = pwc_image_sizes[size][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	pdev->height = pwc_image_sizes[size][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	if (pEntry->compressed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		if (pdev->release < 5) { /* 4 fold compression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			pdev->vbandlength = 528;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			pdev->frame_size /= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			pdev->vbandlength = 704;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			pdev->frame_size /= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		pdev->vbandlength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	/* Let pwc-if.c:isoc_init know we don't support higher compression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	*compression = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 				int frames, int *compression, int send_to_cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	const struct Timon_table_entry *pChoose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	int fps, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	if (frames < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		frames = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	else if (size == PSZ_VGA && frames > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		frames = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	else if (frames > 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		frames = 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	fps = (frames / 5) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	/* Find a supported framerate with progressively higher compression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		pChoose = &Timon_table[size][fps][*compression];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		if (pChoose->alternate != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		(*compression)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	} while (*compression <= 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	if (pChoose->alternate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		return -ENOENT; /* Not supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (send_to_cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		ret = send_video_command(pdev, pdev->vendpoint,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 					 pChoose->mode, 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		pwc_dec23_init(pdev, pChoose->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	/* Set various parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	pdev->pixfmt = pixfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	pdev->vframes = (fps + 1) * 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	pdev->valternate = pChoose->alternate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	pdev->width  = pwc_image_sizes[size][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	pdev->height = pwc_image_sizes[size][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	pdev->vbandlength = pChoose->bandlength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	if (pChoose->bandlength > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 				int frames, int *compression, int send_to_cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	const struct Kiara_table_entry *pChoose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	int fps, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (frames < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		frames = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	else if (size == PSZ_VGA && frames > 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		frames = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	else if (frames > 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		frames = 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	fps = (frames / 5) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	/* Find a supported framerate with progressively higher compression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		pChoose = &Kiara_table[size][fps][*compression];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		if (pChoose->alternate != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		(*compression)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	} while (*compression <= 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	if (pChoose->alternate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		return -ENOENT; /* Not supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	if (send_to_cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		ret = send_video_command(pdev, 4, pChoose->mode, 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		pwc_dec23_init(pdev, pChoose->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	/* All set and go */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	pdev->pixfmt = pixfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	pdev->vframes = (fps + 1) * 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	pdev->valternate = pChoose->alternate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	pdev->width  = pwc_image_sizes[size][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	pdev->height = pwc_image_sizes[size][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	pdev->vbandlength = pChoose->bandlength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	if (pdev->vbandlength > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	    pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	int pixfmt, int frames, int *compression, int send_to_cam)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	int ret, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		       width, height, frames, pixfmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	size = pwc_get_size(pdev, width, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	PWC_TRACE("decode_size = %d.\n", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	if (DEVICE_USE_CODEC1(pdev->type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 					  compression, send_to_cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	} else if (DEVICE_USE_CODEC3(pdev->type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 					   compression, send_to_cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 					   compression, send_to_cam);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		if (Nala_table[size][i].alternate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			if (index--==0) return Nala_fps_vector[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		if (Kiara_table[size][i][3].alternate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			if (index--==0) return Kiara_fps_vector[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		if (Timon_table[size][i][3].alternate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 			if (index--==0) return Timon_fps_vector[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	unsigned int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (DEVICE_USE_CODEC1(pdev->type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		ret = pwc_get_fps_Nala(pdev, index, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	} else if (DEVICE_USE_CODEC3(pdev->type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		ret = pwc_get_fps_Kiara(pdev, index, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		ret = pwc_get_fps_Timon(pdev, index, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	ret = recv_control_msg(pdev, request, value, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	*data = pdev->ctrl_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	pdev->ctrl_buf[0] = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	ret = recv_control_msg(pdev, request, value, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	*data = ((s8 *)pdev->ctrl_buf)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	ret = recv_control_msg(pdev, request, value, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	*data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	pdev->ctrl_buf[0] = data & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	pdev->ctrl_buf[1] = data >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* POWER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) void pwc_camera_power(struct pwc_device *pdev, int power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	if (!pdev->power_save)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		return;	/* Not supported by Nala or Timon < release 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	if (power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		pdev->ctrl_buf[0] = 0x00; /* active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		pdev->ctrl_buf[0] = 0xFF; /* power save */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	r = send_control_msg(pdev, SET_STATUS_CTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		PWC_ERROR("Failed to power %s camera (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 			  power ? "on" : "off", r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	if (pdev->type < 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	on_value /= 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	off_value /= 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	if (on_value < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		on_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	if (on_value > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 		on_value = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	if (off_value < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		off_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	if (off_value > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		off_value = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	pdev->ctrl_buf[0] = on_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	pdev->ctrl_buf[1] = off_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	r = send_control_msg(pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) #ifdef CONFIG_USB_PWC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	int ret, request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	if (pdev->type < 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		request = SENSOR_TYPE_FORMATTER1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	else if (pdev->type < 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		return -1; /* The Vesta series doesn't have this call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		request = SENSOR_TYPE_FORMATTER2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	if (pdev->type < 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		*sensor = pdev->ctrl_buf[0] | 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		*sensor = pdev->ctrl_buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) #endif