11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Driver for Philips webcam 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Functions that send various control messages to the webcam, including 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds video modes. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (C) 1999-2003 Nemosoft Unv. 52b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard (C) 2004-2006 Luc Saillard (luc@saillard.org) 66c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede (C) 2011 Hans de Goede <hdegoede@redhat.com> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver and thus may have bugs that are not present in the original version. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Please send bug reports and support requests to <luc@saillard.org>. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver and thus may have bugs that are not present in the original version. 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Please send bug reports and support requests to <luc@saillard.org>. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The decompression routines have been implemented by reverse-engineering the 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Nemosoft binary pwcx module. Caveat emptor. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License as published by 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the Free Software Foundation; either version 2 of the License, or 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (at your option) any later version. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is distributed in the hope that it will be useful, 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GNU General Public License for more details. 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds You should have received a copy of the GNU General Public License 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds along with this program; if not, write to the Free Software 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Changes 35d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 2001/08/03 Alvarado Added methods for changing white balance and 36d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab red/green gains 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Control functions for the cam; brightness, contrast, video mode, etc. */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __KERNEL__ 42d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab#include <asm/uaccess.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/errno.h> 45d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pwc.h" 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pwc-kiara.h" 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pwc-timon.h" 492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#include "pwc-dec1.h" 502b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#include "pwc-dec23.h" 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 526c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede/* Selectors for status controls used only in this file */ 532b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define GET_STATUS_B00 0x0B00 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SENSOR_TYPE_FORMATTER1 0x0C00 552b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define GET_STATUS_3000 0x3000 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_RAW_Y_MEAN_FORMATTER 0x3100 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SET_POWER_SAVE_MODE_FORMATTER 0x3200 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MIRROR_IMAGE_FORMATTER 0x3300 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LED_FORMATTER 0x3400 602b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define LOWLIGHT 0x3500 612b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define GET_STATUS_3600 0x3600 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SENSOR_TYPE_FORMATTER2 0x3700 632b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define GET_STATUS_3800 0x3800 642b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define GET_STATUS_4000 0x4000 652b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define GET_STATUS_4100 0x4100 /* Get */ 662b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard#define CTL_STATUS_4200 0x4200 /* [GS] 1 */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 714c4c9432a6c916729c7296c47fe93b053a73e20cArjan van de Venstatic const char *size2name[PSZ_MAX] = 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "subQCIF", 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "QSIF", 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "QCIF", 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "SIF", 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CIF", 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "VGA", 79d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab}; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********/ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 83d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab/* Entries for the Nala (645/646) camera; the Nala doesn't have compression 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds preferences, so you either get compressed or non-compressed streams. 85d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds An alternate value of 0 means this mode is not available at all. 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 899ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard#define PWC_FPS_MAX_NALA 8 909ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct Nala_table_entry { 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char alternate; /* USB alternate setting */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int compressed; /* Compressed yes/no */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char mode[3]; /* precomputed mode table */ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 989ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillardstatic unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 }; 999ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 1009ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillardstatic struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] = 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pwc-nala.h" 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1076b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzeystatic int recv_control_msg(struct pwc_device *pdev, 10824be689bfbbcd6c047d7918784ff810e97648006Hans de Goede u8 request, u16 value, int recv_count) 1096b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey{ 1106b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey int rc; 1116b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey 1126b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 1136b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey request, 1146b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 11524be689bfbbcd6c047d7918784ff810e97648006Hans de Goede value, pdev->vcinterface, 11624be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT); 1176c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede if (rc < 0) 1186c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede PWC_ERROR("recv_control_msg error %d req %02x val %04x\n", 1196c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede rc, request, value); 1206b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey return rc; 1216b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey} 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1236b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzeystatic inline int send_video_command(struct pwc_device *pdev, 12424be689bfbbcd6c047d7918784ff810e97648006Hans de Goede int index, const unsigned char *buf, int buflen) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12624be689bfbbcd6c047d7918784ff810e97648006Hans de Goede int rc; 12724be689bfbbcd6c047d7918784ff810e97648006Hans de Goede 12824be689bfbbcd6c047d7918784ff810e97648006Hans de Goede memcpy(pdev->ctrl_buf, buf, buflen); 12924be689bfbbcd6c047d7918784ff810e97648006Hans de Goede 13024be689bfbbcd6c047d7918784ff810e97648006Hans de Goede rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 13124be689bfbbcd6c047d7918784ff810e97648006Hans de Goede SET_EP_STREAM_CTL, 13224be689bfbbcd6c047d7918784ff810e97648006Hans de Goede USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 13324be689bfbbcd6c047d7918784ff810e97648006Hans de Goede VIDEO_OUTPUT_CONTROL_FORMATTER, index, 13424be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT); 13524be689bfbbcd6c047d7918784ff810e97648006Hans de Goede if (rc >= 0) 13624be689bfbbcd6c047d7918784ff810e97648006Hans de Goede memcpy(pdev->cmd_buf, buf, buflen); 13724be689bfbbcd6c047d7918784ff810e97648006Hans de Goede else 13824be689bfbbcd6c047d7918784ff810e97648006Hans de Goede PWC_ERROR("send_video_command error %d\n", rc); 13924be689bfbbcd6c047d7918784ff810e97648006Hans de Goede 14024be689bfbbcd6c047d7918784ff810e97648006Hans de Goede return rc; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 143294e289602d7827f1389b081535fda3b7553a651Hans de Goedeint send_control_msg(struct pwc_device *pdev, 1446b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey u8 request, u16 value, void *buf, int buflen) 1456b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey{ 14624be689bfbbcd6c047d7918784ff810e97648006Hans de Goede return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 14724be689bfbbcd6c047d7918784ff810e97648006Hans de Goede request, 14824be689bfbbcd6c047d7918784ff810e97648006Hans de Goede USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 14924be689bfbbcd6c047d7918784ff810e97648006Hans de Goede value, pdev->vcinterface, 15024be689bfbbcd6c047d7918784ff810e97648006Hans de Goede buf, buflen, USB_CTRL_SET_TIMEOUT); 1516b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey} 1526b35ca0d3d586b8ecb8396821af21186e20afaf0Martin Fuzzey 153d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goedestatic int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt, 154938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede int frames, int *compression, int send_to_cam) 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 156938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede int fps, ret = 0; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Nala_table_entry *pEntry; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int frames2frames[31] = 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { /* closest match of framerate */ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, 0, 0, 0, 4, /* 0-4 */ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5, 5, 7, 7, 10, /* 5-9 */ 162d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 10, 10, 12, 12, 15, /* 10-14 */ 163d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 15, 15, 15, 20, 20, /* 15-19 */ 164d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 20, 20, 20, 24, 24, /* 20-24 */ 165d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 24, 24, 24, 24, 24, /* 25-29 */ 166d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 24 /* 30 */ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 168d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab int frames2table[31] = 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, 0, 0, 0, 0, /* 0-4 */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1, 1, 1, 2, 2, /* 5-9 */ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3, 3, 4, 4, 4, /* 10-14 */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5, 5, 5, 5, 5, /* 15-19 */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6, 6, 6, 6, 7, /* 20-24 */ 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7, 7, 7, 7, 7, /* 25-29 */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7 /* 30 */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 177d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 17854d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede if (size < 0 || size > PSZ_CIF) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 18054d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede if (frames < 4) 18154d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede frames = 4; 18254d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede else if (frames > 25) 18354d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede frames = 25; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frames = frames2frames[frames]; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fps = frames2table[frames]; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pEntry = &Nala_table[size][fps]; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pEntry->alternate == 0) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 190938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede if (send_to_cam) 19124be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = send_video_command(pdev, pdev->vendpoint, 19224be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pEntry->mode, 3); 19324be689bfbbcd6c047d7918784ff810e97648006Hans de Goede if (ret < 0) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 195d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 19624be689bfbbcd6c047d7918784ff810e97648006Hans de Goede if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420) 19724be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pwc_dec1_init(pdev, pEntry->mode); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set various parameters */ 200d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede pdev->pixfmt = pixfmt; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->vframes = frames; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->valternate = pEntry->alternate; 203795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->width = pwc_image_sizes[size][0]; 204795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->height = pwc_image_sizes[size][1]; 205795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->frame_size = (pdev->width * pdev->height * 3) / 2; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pEntry->compressed) { 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->release < 5) { /* 4 fold compression */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->vbandlength = 528; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->frame_size /= 4; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->vbandlength = 704; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->frame_size /= 3; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->vbandlength = 0; 2185bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede 2195bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede /* Let pwc-if.c:isoc_init know we don't support higher compression */ 2205bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede *compression = 3; 2215bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 226d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goedestatic int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt, 227938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede int frames, int *compression, int send_to_cam) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct Timon_table_entry *pChoose; 230938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede int fps, ret = 0; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23254d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede if (size >= PSZ_MAX || *compression < 0 || *compression > 3) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 23454d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede if (frames < 5) 23554d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede frames = 5; 23654d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede else if (size == PSZ_VGA && frames > 15) 23754d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede frames = 15; 23854d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede else if (frames > 30) 23954d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede frames = 30; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fps = (frames / 5) - 1; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2425bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede /* Find a supported framerate with progressively higher compression */ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pChoose = NULL; 2445bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede while (*compression <= 3) { 2455bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede pChoose = &Timon_table[size][fps][*compression]; 2465bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede if (pChoose->alternate != 0) 2475bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede break; 2485bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede (*compression)++; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pChoose == NULL || pChoose->alternate == 0) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOENT; /* Not supported. */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 253938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede if (send_to_cam) 25424be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = send_video_command(pdev, pdev->vendpoint, 25524be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pChoose->mode, 13); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 259d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420) 26024be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pwc_dec23_init(pdev, pChoose->mode); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set various parameters */ 263d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede pdev->pixfmt = pixfmt; 26454d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede pdev->vframes = (fps + 1) * 5; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->valternate = pChoose->alternate; 266795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->width = pwc_image_sizes[size][0]; 267795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->height = pwc_image_sizes[size][1]; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->vbandlength = pChoose->bandlength; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pChoose->bandlength > 0) 270795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->frame_size = (pChoose->bandlength * pdev->height) / 4; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 272795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->frame_size = (pdev->width * pdev->height * 12) / 8; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 277d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goedestatic int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt, 278938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede int frames, int *compression, int send_to_cam) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct Kiara_table_entry *pChoose = NULL; 281938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede int fps, ret = 0; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28354d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede if (size >= PSZ_MAX || *compression < 0 || *compression > 3) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 28554d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede if (frames < 5) 28654d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede frames = 5; 28754d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede else if (size == PSZ_VGA && frames > 15) 28854d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede frames = 15; 28954d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede else if (frames > 30) 29054d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede frames = 30; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fps = (frames / 5) - 1; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2935bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede /* Find a supported framerate with progressively higher compression */ 2945bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede while (*compression <= 3) { 2955bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede pChoose = &Kiara_table[size][fps][*compression]; 296dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede if (pChoose->alternate != 0) 297dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede break; 2985bbe18d74f0c163090cd16bd25e252e8806a6c75Hans de Goede (*compression)++; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pChoose == NULL || pChoose->alternate == 0) 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOENT; /* Not supported. */ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ 304938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede if (send_to_cam) 30524be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = send_video_command(pdev, 4, pChoose->mode, 12); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 309d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420) 31024be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pwc_dec23_init(pdev, pChoose->mode); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* All set and go */ 313d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede pdev->pixfmt = pixfmt; 31454d3fb3b11a7c38b112585e54b7af7cb3faa5c91Hans de Goede pdev->vframes = (fps + 1) * 5; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->valternate = pChoose->alternate; 316795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->width = pwc_image_sizes[size][0]; 317795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->height = pwc_image_sizes[size][1]; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->vbandlength = pChoose->bandlength; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->vbandlength > 0) 320795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->frame_size = (pdev->vbandlength * pdev->height) / 4; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 322795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede pdev->frame_size = (pdev->width * pdev->height * 12) / 8; 323dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n", 324dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goede pdev->frame_size, pdev->vframes, size, pdev->vbandlength); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 328dc8a7e83aaf8bb1bcf7163bda8926a6dd29c409bHans de Goedeint pwc_set_video_mode(struct pwc_device *pdev, int width, int height, 329938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede int pixfmt, int frames, int *compression, int send_to_cam) 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 331d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab int ret, size; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33356ae24aad8f9e25dfef995c3e898e5f394cf0bebHans de Goede PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", 334d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede width, height, frames, pixfmt); 335795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede size = pwc_get_size(pdev, width, height); 3362b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard PWC_TRACE("decode_size = %d.\n", size); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3382b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard if (DEVICE_USE_CODEC1(pdev->type)) { 339d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede ret = set_video_mode_Nala(pdev, size, pixfmt, frames, 340938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede compression, send_to_cam); 3412b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard } else if (DEVICE_USE_CODEC3(pdev->type)) { 342d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede ret = set_video_mode_Kiara(pdev, size, pixfmt, frames, 343938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede compression, send_to_cam); 3442b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard } else { 345d167a85c5fb45b1ecdacdb9b7733833a9af78da8Hans de Goede ret = set_video_mode_Timon(pdev, size, pixfmt, frames, 346938d5b9e7c2e20a7e609ad5874c6e7d8d391e6e9Hans de Goede compression, send_to_cam); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) { 3492b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; 353795e6eb3262d3b7247ce450835eea6df6571d103Hans de Goede PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3579ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillardstatic unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size) 3589ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard{ 3599ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard unsigned int i; 3609ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 3619ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard for (i = 0; i < PWC_FPS_MAX_NALA; i++) { 3629ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard if (Nala_table[size][i].alternate) { 3639ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard if (index--==0) return Nala_fps_vector[i]; 3649ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } 3659ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } 3669ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard return 0; 3679ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard} 3689ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 3699ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillardstatic unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size) 3709ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard{ 3719ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard unsigned int i; 3729ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 3739ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard for (i = 0; i < PWC_FPS_MAX_KIARA; i++) { 3749ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard if (Kiara_table[size][i][3].alternate) { 3759ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard if (index--==0) return Kiara_fps_vector[i]; 3769ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } 3779ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } 3789ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard return 0; 3799ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard} 3809ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 3819ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillardstatic unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size) 3829ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard{ 3839ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard unsigned int i; 3849ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 3859ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard for (i=0; i < PWC_FPS_MAX_TIMON; i++) { 3869ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard if (Timon_table[size][i][3].alternate) { 3879ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard if (index--==0) return Timon_fps_vector[i]; 3889ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } 3899ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } 3909ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard return 0; 3919ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard} 3929ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 3939ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillardunsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size) 3949ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard{ 3959ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard unsigned int ret; 3969ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 3979ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard if (DEVICE_USE_CODEC1(pdev->type)) { 3989ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard ret = pwc_get_fps_Nala(pdev, index, size); 3999ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 4009ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } else if (DEVICE_USE_CODEC3(pdev->type)) { 4019ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard ret = pwc_get_fps_Kiara(pdev, index, size); 4029ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 4039ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } else { 4049ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard ret = pwc_get_fps_Timon(pdev, index, size); 4059ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard } 4069ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 4079ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard return ret; 4089ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard} 4099ee6d78cd4112c0f5a257a01383c64dadbf66da9Luc Saillard 4106c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goedeint pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41424be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = recv_control_msg(pdev, request, value, 1); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41824be689bfbbcd6c047d7918784ff810e97648006Hans de Goede *data = pdev->ctrl_buf[0]; 4196c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede return 0; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4226c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goedeint pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data) 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42624be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf[0] = data; 42724be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1); 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4316c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede return 0; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4346c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goedeint pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 437d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 43824be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = recv_control_msg(pdev, request, value, 1); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44224be689bfbbcd6c047d7918784ff810e97648006Hans de Goede *data = ((s8 *)pdev->ctrl_buf)[0]; 4432b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard return 0; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4466c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goedeint pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 449d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 45024be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = recv_control_msg(pdev, request, value, 2); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4536c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede 45424be689bfbbcd6c047d7918784ff810e97648006Hans de Goede *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0]; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4586c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goedeint pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 461d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 46224be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf[0] = data & 0xff; 46324be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf[1] = data >> 8; 46424be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4716c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goedeint pwc_button_ctrl(struct pwc_device *pdev, u16 value) 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4732b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard int ret; 4742b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard 4756c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0); 4762b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard if (ret < 0) 4772b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard return ret; 4786c9cac89c009c049a9ad29cdf0f51892410fe751Hans de Goede 4792b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard return 0; 4802b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard} 4812b455db6d456ef2d44808a8377fd3bc832e08317Luc Saillard 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* POWER */ 4833b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goedevoid pwc_camera_power(struct pwc_device *pdev, int power) 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4853b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede int r; 4863b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede 4873b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede if (!pdev->power_save) 4883b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede return; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6)) 4913b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede return; /* Not supported by Nala or Timon < release 6 */ 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (power) 49424be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf[0] = 0x00; /* active */ 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 49624be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf[0] = 0xFF; /* power save */ 49724be689bfbbcd6c047d7918784ff810e97648006Hans de Goede r = send_control_msg(pdev, SET_STATUS_CTL, 49824be689bfbbcd6c047d7918784ff810e97648006Hans de Goede SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1); 4993b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede if (r < 0) 5003b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede PWC_ERROR("Failed to power %s camera (%d)\n", 5013b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede power ? "on" : "off", r); 5023b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede} 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5063b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede int r; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->type < 730) 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds on_value /= 100; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds off_value /= 100; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (on_value < 0) 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds on_value = 0; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (on_value > 0xff) 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds on_value = 0xff; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (off_value < 0) 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds off_value = 0; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (off_value > 0xff) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds off_value = 0xff; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52124be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf[0] = on_value; 52224be689bfbbcd6c047d7918784ff810e97648006Hans de Goede pdev->ctrl_buf[1] = off_value; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5243b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede r = send_control_msg(pdev, 52524be689bfbbcd6c047d7918784ff810e97648006Hans de Goede SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2); 5263b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede if (r < 0) 5273b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede PWC_ERROR("Failed to set LED on/off time (%d)\n", r); 5283b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede 5293b4d0ec79113e77b3fe90749ae00bfa015c73048Hans de Goede return r; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5326eba93573d2dda3f627006101c0652faeeaffde6Hans de Goede#ifdef CONFIG_USB_PWC_DEBUG 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -1, request; 536d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->type < 675) 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request = SENSOR_TYPE_FORMATTER1; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (pdev->type < 730) 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; /* The Vesta series doesn't have this call */ 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request = SENSOR_TYPE_FORMATTER2; 543d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab 54424be689bfbbcd6c047d7918784ff810e97648006Hans de Goede ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->type < 675) 54824be689bfbbcd6c047d7918784ff810e97648006Hans de Goede *sensor = pdev->ctrl_buf[0] | 0x100; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 55024be689bfbbcd6c047d7918784ff810e97648006Hans de Goede *sensor = pdev->ctrl_buf[0]; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5536eba93573d2dda3f627006101c0652faeeaffde6Hans de Goede#endif 554