^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