18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SPCA500 chip based cameras initialization data 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define MODULE_NAME "spca500" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "gspca.h" 138c2ecf20Sopenharmony_ci#include "jpeg.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 168c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver"); 178c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define QUALITY 85 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* specific webcam descriptor */ 228c2ecf20Sopenharmony_cistruct sd { 238c2ecf20Sopenharmony_ci struct gspca_dev gspca_dev; /* !! must be the first item */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci char subtype; 268c2ecf20Sopenharmony_ci#define AgfaCl20 0 278c2ecf20Sopenharmony_ci#define AiptekPocketDV 1 288c2ecf20Sopenharmony_ci#define BenqDC1016 2 298c2ecf20Sopenharmony_ci#define CreativePCCam300 3 308c2ecf20Sopenharmony_ci#define DLinkDSC350 4 318c2ecf20Sopenharmony_ci#define Gsmartmini 5 328c2ecf20Sopenharmony_ci#define IntelPocketPCCamera 6 338c2ecf20Sopenharmony_ci#define KodakEZ200 7 348c2ecf20Sopenharmony_ci#define LogitechClickSmart310 8 358c2ecf20Sopenharmony_ci#define LogitechClickSmart510 9 368c2ecf20Sopenharmony_ci#define LogitechTraveler 10 378c2ecf20Sopenharmony_ci#define MustekGsmart300 11 388c2ecf20Sopenharmony_ci#define Optimedia 12 398c2ecf20Sopenharmony_ci#define PalmPixDC85 13 408c2ecf20Sopenharmony_ci#define ToptroIndus 14 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci u8 jpeg_hdr[JPEG_HDR_SZ]; 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = { 468c2ecf20Sopenharmony_ci {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 478c2ecf20Sopenharmony_ci .bytesperline = 320, 488c2ecf20Sopenharmony_ci .sizeimage = 320 * 240 * 3 / 8 + 590, 498c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 508c2ecf20Sopenharmony_ci .priv = 1}, 518c2ecf20Sopenharmony_ci {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 528c2ecf20Sopenharmony_ci .bytesperline = 640, 538c2ecf20Sopenharmony_ci .sizeimage = 640 * 480 * 3 / 8 + 590, 548c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 558c2ecf20Sopenharmony_ci .priv = 0}, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format sif_mode[] = { 598c2ecf20Sopenharmony_ci {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 608c2ecf20Sopenharmony_ci .bytesperline = 176, 618c2ecf20Sopenharmony_ci .sizeimage = 176 * 144 * 3 / 8 + 590, 628c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 638c2ecf20Sopenharmony_ci .priv = 1}, 648c2ecf20Sopenharmony_ci {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 658c2ecf20Sopenharmony_ci .bytesperline = 352, 668c2ecf20Sopenharmony_ci .sizeimage = 352 * 288 * 3 / 8 + 590, 678c2ecf20Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG, 688c2ecf20Sopenharmony_ci .priv = 0}, 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* Frame packet header offsets for the spca500 */ 728c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_PADDINGLB 2 738c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_PADDINGHB 3 748c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_MODE 4 758c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_IMGWIDTH 5 768c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_IMGHEIGHT 6 778c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_IMGMODE 7 788c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_QTBLINDEX 8 798c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_FRAMSEQ 9 808c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_CDSPINFO 10 818c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_GPIO 11 828c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_AUGPIO 12 838c2ecf20Sopenharmony_ci#define SPCA500_OFFSET_DATA 16 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic const __u16 spca500_visual_defaults[][3] = { 878c2ecf20Sopenharmony_ci {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync, 888c2ecf20Sopenharmony_ci * hue (H byte) = 0, 898c2ecf20Sopenharmony_ci * saturation/hue enable, 908c2ecf20Sopenharmony_ci * brightness/contrast enable. 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_ci {0x00, 0x0000, 0x8167}, /* brightness = 0 */ 938c2ecf20Sopenharmony_ci {0x00, 0x0020, 0x8168}, /* contrast = 0 */ 948c2ecf20Sopenharmony_ci {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync, 958c2ecf20Sopenharmony_ci * hue (H byte) = 0, saturation/hue enable, 968c2ecf20Sopenharmony_ci * brightness/contrast enable. 978c2ecf20Sopenharmony_ci * was 0x0003, now 0x0000. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */ 1008c2ecf20Sopenharmony_ci {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */ 1018c2ecf20Sopenharmony_ci {0x00, 0x0050, 0x8157}, /* edge gain high threshold */ 1028c2ecf20Sopenharmony_ci {0x00, 0x0030, 0x8158}, /* edge gain low threshold */ 1038c2ecf20Sopenharmony_ci {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */ 1048c2ecf20Sopenharmony_ci {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */ 1058c2ecf20Sopenharmony_ci {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */ 1068c2ecf20Sopenharmony_ci {0x0c, 0x0004, 0x0000}, 1078c2ecf20Sopenharmony_ci /* set interface */ 1088c2ecf20Sopenharmony_ci {} 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_cistatic const __u16 Clicksmart510_defaults[][3] = { 1118c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8211}, 1128c2ecf20Sopenharmony_ci {0x00, 0x01, 0x82c0}, 1138c2ecf20Sopenharmony_ci {0x00, 0x10, 0x82cb}, 1148c2ecf20Sopenharmony_ci {0x00, 0x0f, 0x800d}, 1158c2ecf20Sopenharmony_ci {0x00, 0x82, 0x8225}, 1168c2ecf20Sopenharmony_ci {0x00, 0x21, 0x8228}, 1178c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8203}, 1188c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8204}, 1198c2ecf20Sopenharmony_ci {0x00, 0x08, 0x8205}, 1208c2ecf20Sopenharmony_ci {0x00, 0xf8, 0x8206}, 1218c2ecf20Sopenharmony_ci {0x00, 0x28, 0x8207}, 1228c2ecf20Sopenharmony_ci {0x00, 0xa0, 0x8208}, 1238c2ecf20Sopenharmony_ci {0x00, 0x08, 0x824a}, 1248c2ecf20Sopenharmony_ci {0x00, 0x08, 0x8214}, 1258c2ecf20Sopenharmony_ci {0x00, 0x80, 0x82c1}, 1268c2ecf20Sopenharmony_ci {0x00, 0x00, 0x82c2}, 1278c2ecf20Sopenharmony_ci {0x00, 0x00, 0x82ca}, 1288c2ecf20Sopenharmony_ci {0x00, 0x80, 0x82c1}, 1298c2ecf20Sopenharmony_ci {0x00, 0x04, 0x82c2}, 1308c2ecf20Sopenharmony_ci {0x00, 0x00, 0x82ca}, 1318c2ecf20Sopenharmony_ci {0x00, 0xfc, 0x8100}, 1328c2ecf20Sopenharmony_ci {0x00, 0xfc, 0x8105}, 1338c2ecf20Sopenharmony_ci {0x00, 0x30, 0x8101}, 1348c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8102}, 1358c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8103}, 1368c2ecf20Sopenharmony_ci {0x00, 0x66, 0x8107}, 1378c2ecf20Sopenharmony_ci {0x00, 0x00, 0x816b}, 1388c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8155}, 1398c2ecf20Sopenharmony_ci {0x00, 0x01, 0x8156}, 1408c2ecf20Sopenharmony_ci {0x00, 0x60, 0x8157}, 1418c2ecf20Sopenharmony_ci {0x00, 0x40, 0x8158}, 1428c2ecf20Sopenharmony_ci {0x00, 0x0a, 0x8159}, 1438c2ecf20Sopenharmony_ci {0x00, 0x06, 0x815a}, 1448c2ecf20Sopenharmony_ci {0x00, 0x00, 0x813f}, 1458c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8200}, 1468c2ecf20Sopenharmony_ci {0x00, 0x19, 0x8201}, 1478c2ecf20Sopenharmony_ci {0x00, 0x00, 0x82c1}, 1488c2ecf20Sopenharmony_ci {0x00, 0xa0, 0x82c2}, 1498c2ecf20Sopenharmony_ci {0x00, 0x00, 0x82ca}, 1508c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8117}, 1518c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8118}, 1528c2ecf20Sopenharmony_ci {0x00, 0x65, 0x8119}, 1538c2ecf20Sopenharmony_ci {0x00, 0x00, 0x811a}, 1548c2ecf20Sopenharmony_ci {0x00, 0x00, 0x811b}, 1558c2ecf20Sopenharmony_ci {0x00, 0x55, 0x811c}, 1568c2ecf20Sopenharmony_ci {0x00, 0x65, 0x811d}, 1578c2ecf20Sopenharmony_ci {0x00, 0x55, 0x811e}, 1588c2ecf20Sopenharmony_ci {0x00, 0x16, 0x811f}, 1598c2ecf20Sopenharmony_ci {0x00, 0x19, 0x8120}, 1608c2ecf20Sopenharmony_ci {0x00, 0x80, 0x8103}, 1618c2ecf20Sopenharmony_ci {0x00, 0x83, 0x816b}, 1628c2ecf20Sopenharmony_ci {0x00, 0x25, 0x8168}, 1638c2ecf20Sopenharmony_ci {0x00, 0x01, 0x820f}, 1648c2ecf20Sopenharmony_ci {0x00, 0xff, 0x8115}, 1658c2ecf20Sopenharmony_ci {0x00, 0x48, 0x8116}, 1668c2ecf20Sopenharmony_ci {0x00, 0x50, 0x8151}, 1678c2ecf20Sopenharmony_ci {0x00, 0x40, 0x8152}, 1688c2ecf20Sopenharmony_ci {0x00, 0x78, 0x8153}, 1698c2ecf20Sopenharmony_ci {0x00, 0x40, 0x8154}, 1708c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8167}, 1718c2ecf20Sopenharmony_ci {0x00, 0x20, 0x8168}, 1728c2ecf20Sopenharmony_ci {0x00, 0x00, 0x816a}, 1738c2ecf20Sopenharmony_ci {0x00, 0x03, 0x816b}, 1748c2ecf20Sopenharmony_ci {0x00, 0x20, 0x8169}, 1758c2ecf20Sopenharmony_ci {0x00, 0x60, 0x8157}, 1768c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8190}, 1778c2ecf20Sopenharmony_ci {0x00, 0x00, 0x81a1}, 1788c2ecf20Sopenharmony_ci {0x00, 0x00, 0x81b2}, 1798c2ecf20Sopenharmony_ci {0x00, 0x27, 0x8191}, 1808c2ecf20Sopenharmony_ci {0x00, 0x27, 0x81a2}, 1818c2ecf20Sopenharmony_ci {0x00, 0x27, 0x81b3}, 1828c2ecf20Sopenharmony_ci {0x00, 0x4b, 0x8192}, 1838c2ecf20Sopenharmony_ci {0x00, 0x4b, 0x81a3}, 1848c2ecf20Sopenharmony_ci {0x00, 0x4b, 0x81b4}, 1858c2ecf20Sopenharmony_ci {0x00, 0x66, 0x8193}, 1868c2ecf20Sopenharmony_ci {0x00, 0x66, 0x81a4}, 1878c2ecf20Sopenharmony_ci {0x00, 0x66, 0x81b5}, 1888c2ecf20Sopenharmony_ci {0x00, 0x79, 0x8194}, 1898c2ecf20Sopenharmony_ci {0x00, 0x79, 0x81a5}, 1908c2ecf20Sopenharmony_ci {0x00, 0x79, 0x81b6}, 1918c2ecf20Sopenharmony_ci {0x00, 0x8a, 0x8195}, 1928c2ecf20Sopenharmony_ci {0x00, 0x8a, 0x81a6}, 1938c2ecf20Sopenharmony_ci {0x00, 0x8a, 0x81b7}, 1948c2ecf20Sopenharmony_ci {0x00, 0x9b, 0x8196}, 1958c2ecf20Sopenharmony_ci {0x00, 0x9b, 0x81a7}, 1968c2ecf20Sopenharmony_ci {0x00, 0x9b, 0x81b8}, 1978c2ecf20Sopenharmony_ci {0x00, 0xa6, 0x8197}, 1988c2ecf20Sopenharmony_ci {0x00, 0xa6, 0x81a8}, 1998c2ecf20Sopenharmony_ci {0x00, 0xa6, 0x81b9}, 2008c2ecf20Sopenharmony_ci {0x00, 0xb2, 0x8198}, 2018c2ecf20Sopenharmony_ci {0x00, 0xb2, 0x81a9}, 2028c2ecf20Sopenharmony_ci {0x00, 0xb2, 0x81ba}, 2038c2ecf20Sopenharmony_ci {0x00, 0xbe, 0x8199}, 2048c2ecf20Sopenharmony_ci {0x00, 0xbe, 0x81aa}, 2058c2ecf20Sopenharmony_ci {0x00, 0xbe, 0x81bb}, 2068c2ecf20Sopenharmony_ci {0x00, 0xc8, 0x819a}, 2078c2ecf20Sopenharmony_ci {0x00, 0xc8, 0x81ab}, 2088c2ecf20Sopenharmony_ci {0x00, 0xc8, 0x81bc}, 2098c2ecf20Sopenharmony_ci {0x00, 0xd2, 0x819b}, 2108c2ecf20Sopenharmony_ci {0x00, 0xd2, 0x81ac}, 2118c2ecf20Sopenharmony_ci {0x00, 0xd2, 0x81bd}, 2128c2ecf20Sopenharmony_ci {0x00, 0xdb, 0x819c}, 2138c2ecf20Sopenharmony_ci {0x00, 0xdb, 0x81ad}, 2148c2ecf20Sopenharmony_ci {0x00, 0xdb, 0x81be}, 2158c2ecf20Sopenharmony_ci {0x00, 0xe4, 0x819d}, 2168c2ecf20Sopenharmony_ci {0x00, 0xe4, 0x81ae}, 2178c2ecf20Sopenharmony_ci {0x00, 0xe4, 0x81bf}, 2188c2ecf20Sopenharmony_ci {0x00, 0xed, 0x819e}, 2198c2ecf20Sopenharmony_ci {0x00, 0xed, 0x81af}, 2208c2ecf20Sopenharmony_ci {0x00, 0xed, 0x81c0}, 2218c2ecf20Sopenharmony_ci {0x00, 0xf7, 0x819f}, 2228c2ecf20Sopenharmony_ci {0x00, 0xf7, 0x81b0}, 2238c2ecf20Sopenharmony_ci {0x00, 0xf7, 0x81c1}, 2248c2ecf20Sopenharmony_ci {0x00, 0xff, 0x81a0}, 2258c2ecf20Sopenharmony_ci {0x00, 0xff, 0x81b1}, 2268c2ecf20Sopenharmony_ci {0x00, 0xff, 0x81c2}, 2278c2ecf20Sopenharmony_ci {0x00, 0x03, 0x8156}, 2288c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8211}, 2298c2ecf20Sopenharmony_ci {0x00, 0x20, 0x8168}, 2308c2ecf20Sopenharmony_ci {0x00, 0x01, 0x8202}, 2318c2ecf20Sopenharmony_ci {0x00, 0x30, 0x8101}, 2328c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8111}, 2338c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8112}, 2348c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8113}, 2358c2ecf20Sopenharmony_ci {0x00, 0x00, 0x8114}, 2368c2ecf20Sopenharmony_ci {} 2378c2ecf20Sopenharmony_ci}; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistatic const __u8 qtable_creative_pccam[2][64] = { 2408c2ecf20Sopenharmony_ci { /* Q-table Y-components */ 2418c2ecf20Sopenharmony_ci 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 2428c2ecf20Sopenharmony_ci 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, 2438c2ecf20Sopenharmony_ci 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11, 2448c2ecf20Sopenharmony_ci 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13, 2458c2ecf20Sopenharmony_ci 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17, 2468c2ecf20Sopenharmony_ci 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c, 2478c2ecf20Sopenharmony_ci 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e, 2488c2ecf20Sopenharmony_ci 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e}, 2498c2ecf20Sopenharmony_ci { /* Q-table C-components */ 2508c2ecf20Sopenharmony_ci 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, 2518c2ecf20Sopenharmony_ci 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 2528c2ecf20Sopenharmony_ci 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 2538c2ecf20Sopenharmony_ci 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 2548c2ecf20Sopenharmony_ci 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 2558c2ecf20Sopenharmony_ci 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 2568c2ecf20Sopenharmony_ci 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 2578c2ecf20Sopenharmony_ci 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} 2588c2ecf20Sopenharmony_ci}; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic const __u8 qtable_kodak_ez200[2][64] = { 2618c2ecf20Sopenharmony_ci { /* Q-table Y-components */ 2628c2ecf20Sopenharmony_ci 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06, 2638c2ecf20Sopenharmony_ci 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06, 2648c2ecf20Sopenharmony_ci 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06, 2658c2ecf20Sopenharmony_ci 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06, 2668c2ecf20Sopenharmony_ci 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08, 2678c2ecf20Sopenharmony_ci 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09, 2688c2ecf20Sopenharmony_ci 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a, 2698c2ecf20Sopenharmony_ci 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a}, 2708c2ecf20Sopenharmony_ci { /* Q-table C-components */ 2718c2ecf20Sopenharmony_ci 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 2728c2ecf20Sopenharmony_ci 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 2738c2ecf20Sopenharmony_ci 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 2748c2ecf20Sopenharmony_ci 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 2758c2ecf20Sopenharmony_ci 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 2768c2ecf20Sopenharmony_ci 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 2778c2ecf20Sopenharmony_ci 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 2788c2ecf20Sopenharmony_ci 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a} 2798c2ecf20Sopenharmony_ci}; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistatic const __u8 qtable_pocketdv[2][64] = { 2828c2ecf20Sopenharmony_ci { /* Q-table Y-components start registers 0x8800 */ 2838c2ecf20Sopenharmony_ci 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18, 2848c2ecf20Sopenharmony_ci 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16, 2858c2ecf20Sopenharmony_ci 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16, 2868c2ecf20Sopenharmony_ci 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19, 2878c2ecf20Sopenharmony_ci 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f, 2888c2ecf20Sopenharmony_ci 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25, 2898c2ecf20Sopenharmony_ci 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28, 2908c2ecf20Sopenharmony_ci 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28, 2918c2ecf20Sopenharmony_ci }, 2928c2ecf20Sopenharmony_ci { /* Q-table C-components start registers 0x8840 */ 2938c2ecf20Sopenharmony_ci 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28, 2948c2ecf20Sopenharmony_ci 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28, 2958c2ecf20Sopenharmony_ci 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28, 2968c2ecf20Sopenharmony_ci 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 2978c2ecf20Sopenharmony_ci 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 2988c2ecf20Sopenharmony_ci 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 2998c2ecf20Sopenharmony_ci 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 3008c2ecf20Sopenharmony_ci 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28} 3018c2ecf20Sopenharmony_ci}; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci/* read 'len' bytes to gspca_dev->usb_buf */ 3048c2ecf20Sopenharmony_cistatic void reg_r(struct gspca_dev *gspca_dev, 3058c2ecf20Sopenharmony_ci __u16 index, 3068c2ecf20Sopenharmony_ci __u16 length) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci usb_control_msg(gspca_dev->dev, 3098c2ecf20Sopenharmony_ci usb_rcvctrlpipe(gspca_dev->dev, 0), 3108c2ecf20Sopenharmony_ci 0, 3118c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 3128c2ecf20Sopenharmony_ci 0, /* value */ 3138c2ecf20Sopenharmony_ci index, gspca_dev->usb_buf, length, 500); 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic int reg_w(struct gspca_dev *gspca_dev, 3178c2ecf20Sopenharmony_ci __u16 req, __u16 index, __u16 value) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci int ret; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "reg write: [0x%02x] = 0x%02x\n", 3228c2ecf20Sopenharmony_ci index, value); 3238c2ecf20Sopenharmony_ci ret = usb_control_msg(gspca_dev->dev, 3248c2ecf20Sopenharmony_ci usb_sndctrlpipe(gspca_dev->dev, 0), 3258c2ecf20Sopenharmony_ci req, 3268c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 3278c2ecf20Sopenharmony_ci value, index, NULL, 0, 500); 3288c2ecf20Sopenharmony_ci if (ret < 0) 3298c2ecf20Sopenharmony_ci pr_err("reg write: error %d\n", ret); 3308c2ecf20Sopenharmony_ci return ret; 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci/* returns: negative is error, pos or zero is data */ 3348c2ecf20Sopenharmony_cistatic int reg_r_12(struct gspca_dev *gspca_dev, 3358c2ecf20Sopenharmony_ci __u16 req, /* bRequest */ 3368c2ecf20Sopenharmony_ci __u16 index, /* wIndex */ 3378c2ecf20Sopenharmony_ci __u16 length) /* wLength (1 or 2 only) */ 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci int ret; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci gspca_dev->usb_buf[1] = 0; 3428c2ecf20Sopenharmony_ci ret = usb_control_msg(gspca_dev->dev, 3438c2ecf20Sopenharmony_ci usb_rcvctrlpipe(gspca_dev->dev, 0), 3448c2ecf20Sopenharmony_ci req, 3458c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 3468c2ecf20Sopenharmony_ci 0, /* value */ 3478c2ecf20Sopenharmony_ci index, 3488c2ecf20Sopenharmony_ci gspca_dev->usb_buf, length, 3498c2ecf20Sopenharmony_ci 500); /* timeout */ 3508c2ecf20Sopenharmony_ci if (ret < 0) { 3518c2ecf20Sopenharmony_ci pr_err("reg_r_12 err %d\n", ret); 3528c2ecf20Sopenharmony_ci return ret; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci/* 3588c2ecf20Sopenharmony_ci * Simple function to wait for a given 8-bit value to be returned from 3598c2ecf20Sopenharmony_ci * a reg_read call. 3608c2ecf20Sopenharmony_ci * Returns: negative is error or timeout, zero is success. 3618c2ecf20Sopenharmony_ci */ 3628c2ecf20Sopenharmony_cistatic int reg_r_wait(struct gspca_dev *gspca_dev, 3638c2ecf20Sopenharmony_ci __u16 reg, __u16 index, __u16 value) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci int ret, cnt = 20; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci while (--cnt > 0) { 3688c2ecf20Sopenharmony_ci ret = reg_r_12(gspca_dev, reg, index, 1); 3698c2ecf20Sopenharmony_ci if (ret == value) 3708c2ecf20Sopenharmony_ci return 0; 3718c2ecf20Sopenharmony_ci msleep(50); 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci return -EIO; 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic int write_vector(struct gspca_dev *gspca_dev, 3778c2ecf20Sopenharmony_ci const __u16 data[][3]) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci int ret, i = 0; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) { 3828c2ecf20Sopenharmony_ci ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]); 3838c2ecf20Sopenharmony_ci if (ret < 0) 3848c2ecf20Sopenharmony_ci return ret; 3858c2ecf20Sopenharmony_ci i++; 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci return 0; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic int spca50x_setup_qtable(struct gspca_dev *gspca_dev, 3918c2ecf20Sopenharmony_ci unsigned int request, 3928c2ecf20Sopenharmony_ci unsigned int ybase, 3938c2ecf20Sopenharmony_ci unsigned int cbase, 3948c2ecf20Sopenharmony_ci const __u8 qtable[2][64]) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci int i, err; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* loop over y components */ 3998c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) { 4008c2ecf20Sopenharmony_ci err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]); 4018c2ecf20Sopenharmony_ci if (err < 0) 4028c2ecf20Sopenharmony_ci return err; 4038c2ecf20Sopenharmony_ci } 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci /* loop over c components */ 4068c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) { 4078c2ecf20Sopenharmony_ci err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]); 4088c2ecf20Sopenharmony_ci if (err < 0) 4098c2ecf20Sopenharmony_ci return err; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci return 0; 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic void spca500_ping310(struct gspca_dev *gspca_dev) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x0d04, 2); 4178c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x\n", 4188c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic void spca500_clksmart310_init(struct gspca_dev *gspca_dev) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x0d05, 2); 4248c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x\n", 4258c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); 4268c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8167, 0x5a); 4278c2ecf20Sopenharmony_ci spca500_ping310(gspca_dev); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8168, 0x22); 4308c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816a, 0xc0); 4318c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816b, 0x0b); 4328c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8169, 0x25); 4338c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8157, 0x5b); 4348c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8158, 0x5b); 4358c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x813f, 0x03); 4368c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8151, 0x4a); 4378c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8153, 0x78); 4388c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x0d01, 0x04); 4398c2ecf20Sopenharmony_ci /* 00 for adjust shutter */ 4408c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x0d02, 0x01); 4418c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8169, 0x25); 4428c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x0d01, 0x02); 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistatic void spca500_setmode(struct gspca_dev *gspca_dev, 4468c2ecf20Sopenharmony_ci __u8 xmult, __u8 ymult) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci int mode; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci /* set x multiplier */ 4518c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0, 0x8001, xmult); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* set y multiplier */ 4548c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0, 0x8002, ymult); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci /* use compressed mode, VGA, with mode specific subsample */ 4578c2ecf20Sopenharmony_ci mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; 4588c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0, 0x8003, mode << 4); 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic int spca500_full_reset(struct gspca_dev *gspca_dev) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci int err; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci /* send the reset command */ 4668c2ecf20Sopenharmony_ci err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000); 4678c2ecf20Sopenharmony_ci if (err < 0) 4688c2ecf20Sopenharmony_ci return err; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci /* wait for the reset to complete */ 4718c2ecf20Sopenharmony_ci err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000); 4728c2ecf20Sopenharmony_ci if (err < 0) 4738c2ecf20Sopenharmony_ci return err; 4748c2ecf20Sopenharmony_ci err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000); 4758c2ecf20Sopenharmony_ci if (err < 0) 4768c2ecf20Sopenharmony_ci return err; 4778c2ecf20Sopenharmony_ci err = reg_r_wait(gspca_dev, 0x06, 0, 0); 4788c2ecf20Sopenharmony_ci if (err < 0) { 4798c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_r_wait() failed\n"); 4808c2ecf20Sopenharmony_ci return err; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci /* all ok */ 4838c2ecf20Sopenharmony_ci return 0; 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci/* Synchro the Bridge with sensor */ 4878c2ecf20Sopenharmony_ci/* Maybe that will work on all spca500 chip */ 4888c2ecf20Sopenharmony_ci/* because i only own a clicksmart310 try for that chip */ 4898c2ecf20Sopenharmony_ci/* using spca50x_set_packet_size() cause an Ooops here */ 4908c2ecf20Sopenharmony_ci/* usb_set_interface from kernel 2.6.x clear all the urb stuff */ 4918c2ecf20Sopenharmony_ci/* up-port the same feature as in 2.4.x kernel */ 4928c2ecf20Sopenharmony_cistatic int spca500_synch310(struct gspca_dev *gspca_dev) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) { 4958c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Set packet size: set interface error\n"); 4968c2ecf20Sopenharmony_ci goto error; 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci spca500_ping310(gspca_dev); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x0d00, 1); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci /* need alt setting here */ 5038c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_PACK, "ClickSmart310 sync alt: %d\n", 5048c2ecf20Sopenharmony_ci gspca_dev->alt); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci /* Windoze use pipe with altsetting 6 why 7 here */ 5078c2ecf20Sopenharmony_ci if (usb_set_interface(gspca_dev->dev, 5088c2ecf20Sopenharmony_ci gspca_dev->iface, 5098c2ecf20Sopenharmony_ci gspca_dev->alt) < 0) { 5108c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "Set packet size: set interface error\n"); 5118c2ecf20Sopenharmony_ci goto error; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci return 0; 5148c2ecf20Sopenharmony_cierror: 5158c2ecf20Sopenharmony_ci return -EBUSY; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic void spca500_reinit(struct gspca_dev *gspca_dev) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci int err; 5218c2ecf20Sopenharmony_ci __u8 Data; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci /* some unknown command from Aiptek pocket dv and family300 */ 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x0d01, 0x01); 5268c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x0d03, 0x00); 5278c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x0d02, 0x01); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci /* enable drop packet */ 5308c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x850a, 0x0001); 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840, 5338c2ecf20Sopenharmony_ci qtable_pocketdv); 5348c2ecf20Sopenharmony_ci if (err < 0) 5358c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca50x_setup_qtable failed on init\n"); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* set qtable index */ 5388c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8880, 2); 5398c2ecf20Sopenharmony_ci /* family cam Quicksmart stuff */ 5408c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x800a, 0x00); 5418c2ecf20Sopenharmony_ci /* Set agc transfer: synced between frames */ 5428c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x820f, 0x01); 5438c2ecf20Sopenharmony_ci /* Init SDRAM - needed for SDRAM access */ 5448c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x870a, 0x04); 5458c2ecf20Sopenharmony_ci /*Start init sequence or stream */ 5468c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0, 0x8003, 0x00); 5478c2ecf20Sopenharmony_ci /* switch to video camera mode */ 5488c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8000, 0x0004); 5498c2ecf20Sopenharmony_ci msleep(2000); 5508c2ecf20Sopenharmony_ci if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) { 5518c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x816b, 1); 5528c2ecf20Sopenharmony_ci Data = gspca_dev->usb_buf[0]; 5538c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816b, Data); 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci/* this function is called at probe time */ 5588c2ecf20Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev, 5598c2ecf20Sopenharmony_ci const struct usb_device_id *id) 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5628c2ecf20Sopenharmony_ci struct cam *cam; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci cam = &gspca_dev->cam; 5658c2ecf20Sopenharmony_ci sd->subtype = id->driver_info; 5668c2ecf20Sopenharmony_ci if (sd->subtype != LogitechClickSmart310) { 5678c2ecf20Sopenharmony_ci cam->cam_mode = vga_mode; 5688c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(vga_mode); 5698c2ecf20Sopenharmony_ci } else { 5708c2ecf20Sopenharmony_ci cam->cam_mode = sif_mode; 5718c2ecf20Sopenharmony_ci cam->nmodes = ARRAY_SIZE(sif_mode); 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci return 0; 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci/* this function is called at probe and resume time */ 5778c2ecf20Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci /* initialisation of spca500 based cameras is deferred */ 5828c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "SPCA500 init\n"); 5838c2ecf20Sopenharmony_ci if (sd->subtype == LogitechClickSmart310) 5848c2ecf20Sopenharmony_ci spca500_clksmart310_init(gspca_dev); 5858c2ecf20Sopenharmony_ci/* else 5868c2ecf20Sopenharmony_ci spca500_initialise(gspca_dev); */ 5878c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "SPCA500 init done\n"); 5888c2ecf20Sopenharmony_ci return 0; 5898c2ecf20Sopenharmony_ci} 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 5948c2ecf20Sopenharmony_ci int err; 5958c2ecf20Sopenharmony_ci __u8 Data; 5968c2ecf20Sopenharmony_ci __u8 xmult, ymult; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci /* create the JPEG header */ 5998c2ecf20Sopenharmony_ci jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height, 6008c2ecf20Sopenharmony_ci gspca_dev->pixfmt.width, 6018c2ecf20Sopenharmony_ci 0x22); /* JPEG 411 */ 6028c2ecf20Sopenharmony_ci jpeg_set_qual(sd->jpeg_hdr, QUALITY); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci if (sd->subtype == LogitechClickSmart310) { 6058c2ecf20Sopenharmony_ci xmult = 0x16; 6068c2ecf20Sopenharmony_ci ymult = 0x12; 6078c2ecf20Sopenharmony_ci } else { 6088c2ecf20Sopenharmony_ci xmult = 0x28; 6098c2ecf20Sopenharmony_ci ymult = 0x1e; 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* is there a sensor here ? */ 6138c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x8a04, 1); 6148c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Spca500 Sensor Address 0x%02x\n", 6158c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0]); 6168c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x", 6178c2ecf20Sopenharmony_ci gspca_dev->curr_mode, xmult, ymult); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci /* setup qtable */ 6208c2ecf20Sopenharmony_ci switch (sd->subtype) { 6218c2ecf20Sopenharmony_ci case LogitechClickSmart310: 6228c2ecf20Sopenharmony_ci spca500_setmode(gspca_dev, xmult, ymult); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci /* enable drop packet */ 6258c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x850a, 0x0001); 6268c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8880, 3); 6278c2ecf20Sopenharmony_ci err = spca50x_setup_qtable(gspca_dev, 6288c2ecf20Sopenharmony_ci 0x00, 0x8800, 0x8840, 6298c2ecf20Sopenharmony_ci qtable_creative_pccam); 6308c2ecf20Sopenharmony_ci if (err < 0) 6318c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca50x_setup_qtable failed\n"); 6328c2ecf20Sopenharmony_ci /* Init SDRAM - needed for SDRAM access */ 6338c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x870a, 0x04); 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* switch to video camera mode */ 6368c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8000, 0x0004); 6378c2ecf20Sopenharmony_ci msleep(500); 6388c2ecf20Sopenharmony_ci if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) 6398c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_r_wait() failed\n"); 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x816b, 1); 6428c2ecf20Sopenharmony_ci Data = gspca_dev->usb_buf[0]; 6438c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816b, Data); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci spca500_synch310(gspca_dev); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci write_vector(gspca_dev, spca500_visual_defaults); 6488c2ecf20Sopenharmony_ci spca500_setmode(gspca_dev, xmult, ymult); 6498c2ecf20Sopenharmony_ci /* enable drop packet */ 6508c2ecf20Sopenharmony_ci err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001); 6518c2ecf20Sopenharmony_ci if (err < 0) 6528c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "failed to enable drop packet\n"); 6538c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8880, 3); 6548c2ecf20Sopenharmony_ci err = spca50x_setup_qtable(gspca_dev, 6558c2ecf20Sopenharmony_ci 0x00, 0x8800, 0x8840, 6568c2ecf20Sopenharmony_ci qtable_creative_pccam); 6578c2ecf20Sopenharmony_ci if (err < 0) 6588c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca50x_setup_qtable failed\n"); 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci /* Init SDRAM - needed for SDRAM access */ 6618c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x870a, 0x04); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci /* switch to video camera mode */ 6648c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8000, 0x0004); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) 6678c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_r_wait() failed\n"); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x816b, 1); 6708c2ecf20Sopenharmony_ci Data = gspca_dev->usb_buf[0]; 6718c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816b, Data); 6728c2ecf20Sopenharmony_ci break; 6738c2ecf20Sopenharmony_ci case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */ 6748c2ecf20Sopenharmony_ci case IntelPocketPCCamera: /* FIXME: Temporary fix for 6758c2ecf20Sopenharmony_ci * Intel Pocket PC Camera 6768c2ecf20Sopenharmony_ci * - NWG (Sat 29th March 2003) */ 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci /* do a full reset */ 6798c2ecf20Sopenharmony_ci err = spca500_full_reset(gspca_dev); 6808c2ecf20Sopenharmony_ci if (err < 0) 6818c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca500_full_reset failed\n"); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci /* enable drop packet */ 6848c2ecf20Sopenharmony_ci err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001); 6858c2ecf20Sopenharmony_ci if (err < 0) 6868c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "failed to enable drop packet\n"); 6878c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8880, 3); 6888c2ecf20Sopenharmony_ci err = spca50x_setup_qtable(gspca_dev, 6898c2ecf20Sopenharmony_ci 0x00, 0x8800, 0x8840, 6908c2ecf20Sopenharmony_ci qtable_creative_pccam); 6918c2ecf20Sopenharmony_ci if (err < 0) 6928c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca50x_setup_qtable failed\n"); 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci spca500_setmode(gspca_dev, xmult, ymult); 6958c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x20, 0x0001, 0x0004); 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci /* switch to video camera mode */ 6988c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8000, 0x0004); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) 7018c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_r_wait() failed\n"); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x816b, 1); 7048c2ecf20Sopenharmony_ci Data = gspca_dev->usb_buf[0]; 7058c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816b, Data); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci/* write_vector(gspca_dev, spca500_visual_defaults); */ 7088c2ecf20Sopenharmony_ci break; 7098c2ecf20Sopenharmony_ci case KodakEZ200: /* Kodak EZ200 */ 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci /* do a full reset */ 7128c2ecf20Sopenharmony_ci err = spca500_full_reset(gspca_dev); 7138c2ecf20Sopenharmony_ci if (err < 0) 7148c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca500_full_reset failed\n"); 7158c2ecf20Sopenharmony_ci /* enable drop packet */ 7168c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x850a, 0x0001); 7178c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8880, 0); 7188c2ecf20Sopenharmony_ci err = spca50x_setup_qtable(gspca_dev, 7198c2ecf20Sopenharmony_ci 0x00, 0x8800, 0x8840, 7208c2ecf20Sopenharmony_ci qtable_kodak_ez200); 7218c2ecf20Sopenharmony_ci if (err < 0) 7228c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca50x_setup_qtable failed\n"); 7238c2ecf20Sopenharmony_ci spca500_setmode(gspca_dev, xmult, ymult); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x20, 0x0001, 0x0004); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci /* switch to video camera mode */ 7288c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8000, 0x0004); 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) 7318c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "reg_r_wait() failed\n"); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x816b, 1); 7348c2ecf20Sopenharmony_ci Data = gspca_dev->usb_buf[0]; 7358c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816b, Data); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci/* write_vector(gspca_dev, spca500_visual_defaults); */ 7388c2ecf20Sopenharmony_ci break; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci case BenqDC1016: 7418c2ecf20Sopenharmony_ci case DLinkDSC350: /* FamilyCam 300 */ 7428c2ecf20Sopenharmony_ci case AiptekPocketDV: /* Aiptek PocketDV */ 7438c2ecf20Sopenharmony_ci case Gsmartmini: /*Mustek Gsmart Mini */ 7448c2ecf20Sopenharmony_ci case MustekGsmart300: /* Mustek Gsmart 300 */ 7458c2ecf20Sopenharmony_ci case PalmPixDC85: 7468c2ecf20Sopenharmony_ci case Optimedia: 7478c2ecf20Sopenharmony_ci case ToptroIndus: 7488c2ecf20Sopenharmony_ci case AgfaCl20: 7498c2ecf20Sopenharmony_ci spca500_reinit(gspca_dev); 7508c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x0d01, 0x01); 7518c2ecf20Sopenharmony_ci /* enable drop packet */ 7528c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x850a, 0x0001); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci err = spca50x_setup_qtable(gspca_dev, 7558c2ecf20Sopenharmony_ci 0x00, 0x8800, 0x8840, qtable_pocketdv); 7568c2ecf20Sopenharmony_ci if (err < 0) 7578c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca50x_setup_qtable failed\n"); 7588c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8880, 2); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci /* familycam Quicksmart pocketDV stuff */ 7618c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x800a, 0x00); 7628c2ecf20Sopenharmony_ci /* Set agc transfer: synced between frames */ 7638c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x820f, 0x01); 7648c2ecf20Sopenharmony_ci /* Init SDRAM - needed for SDRAM access */ 7658c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x870a, 0x04); 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci spca500_setmode(gspca_dev, xmult, ymult); 7688c2ecf20Sopenharmony_ci /* switch to video camera mode */ 7698c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8000, 0x0004); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci reg_r_wait(gspca_dev, 0, 0x8000, 0x44); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x816b, 1); 7748c2ecf20Sopenharmony_ci Data = gspca_dev->usb_buf[0]; 7758c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816b, Data); 7768c2ecf20Sopenharmony_ci break; 7778c2ecf20Sopenharmony_ci case LogitechTraveler: 7788c2ecf20Sopenharmony_ci case LogitechClickSmart510: 7798c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x02, 0x00, 0x00); 7808c2ecf20Sopenharmony_ci /* enable drop packet */ 7818c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x850a, 0x0001); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci err = spca50x_setup_qtable(gspca_dev, 7848c2ecf20Sopenharmony_ci 0x00, 0x8800, 7858c2ecf20Sopenharmony_ci 0x8840, qtable_creative_pccam); 7868c2ecf20Sopenharmony_ci if (err < 0) 7878c2ecf20Sopenharmony_ci gspca_err(gspca_dev, "spca50x_setup_qtable failed\n"); 7888c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8880, 3); 7898c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x800a, 0x00); 7908c2ecf20Sopenharmony_ci /* Init SDRAM - needed for SDRAM access */ 7918c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x870a, 0x04); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci spca500_setmode(gspca_dev, xmult, ymult); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* switch to video camera mode */ 7968c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8000, 0x0004); 7978c2ecf20Sopenharmony_ci reg_r_wait(gspca_dev, 0, 0x8000, 0x44); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x816b, 1); 8008c2ecf20Sopenharmony_ci Data = gspca_dev->usb_buf[0]; 8018c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x816b, Data); 8028c2ecf20Sopenharmony_ci write_vector(gspca_dev, Clicksmart510_defaults); 8038c2ecf20Sopenharmony_ci break; 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci return 0; 8068c2ecf20Sopenharmony_ci} 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev) 8098c2ecf20Sopenharmony_ci{ 8108c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0, 0x8003, 0x00); 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci /* switch to video camera mode */ 8138c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8000, 0x0004); 8148c2ecf20Sopenharmony_ci reg_r(gspca_dev, 0x8000, 1); 8158c2ecf20Sopenharmony_ci gspca_dbg(gspca_dev, D_STREAM, "stop SPCA500 done reg8000: 0x%2x\n", 8168c2ecf20Sopenharmony_ci gspca_dev->usb_buf[0]); 8178c2ecf20Sopenharmony_ci} 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev, 8208c2ecf20Sopenharmony_ci u8 *data, /* isoc packet */ 8218c2ecf20Sopenharmony_ci int len) /* iso packet length */ 8228c2ecf20Sopenharmony_ci{ 8238c2ecf20Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 8248c2ecf20Sopenharmony_ci int i; 8258c2ecf20Sopenharmony_ci static __u8 ffd9[] = {0xff, 0xd9}; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci/* frames are jpeg 4.1.1 without 0xff escape */ 8288c2ecf20Sopenharmony_ci if (data[0] == 0xff) { 8298c2ecf20Sopenharmony_ci if (data[1] != 0x01) { /* drop packet */ 8308c2ecf20Sopenharmony_ci/* gspca_dev->last_packet_type = DISCARD_PACKET; */ 8318c2ecf20Sopenharmony_ci return; 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, 8348c2ecf20Sopenharmony_ci ffd9, 2); 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci /* put the JPEG header in the new frame */ 8378c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, 8388c2ecf20Sopenharmony_ci sd->jpeg_hdr, JPEG_HDR_SZ); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci data += SPCA500_OFFSET_DATA; 8418c2ecf20Sopenharmony_ci len -= SPCA500_OFFSET_DATA; 8428c2ecf20Sopenharmony_ci } else { 8438c2ecf20Sopenharmony_ci data += 1; 8448c2ecf20Sopenharmony_ci len -= 1; 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci /* add 0x00 after 0xff */ 8488c2ecf20Sopenharmony_ci i = 0; 8498c2ecf20Sopenharmony_ci do { 8508c2ecf20Sopenharmony_ci if (data[i] == 0xff) { 8518c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, 8528c2ecf20Sopenharmony_ci data, i + 1); 8538c2ecf20Sopenharmony_ci len -= i; 8548c2ecf20Sopenharmony_ci data += i; 8558c2ecf20Sopenharmony_ci *data = 0x00; 8568c2ecf20Sopenharmony_ci i = 0; 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci i++; 8598c2ecf20Sopenharmony_ci } while (i < len); 8608c2ecf20Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 8618c2ecf20Sopenharmony_ci} 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev, s32 val) 8648c2ecf20Sopenharmony_ci{ 8658c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8167, 8668c2ecf20Sopenharmony_ci (__u8) (val - 128)); 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev, s32 val) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8168, val); 8728c2ecf20Sopenharmony_ci} 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_cistatic void setcolors(struct gspca_dev *gspca_dev, s32 val) 8758c2ecf20Sopenharmony_ci{ 8768c2ecf20Sopenharmony_ci reg_w(gspca_dev, 0x00, 0x8169, val); 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci struct gspca_dev *gspca_dev = 8828c2ecf20Sopenharmony_ci container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci gspca_dev->usb_err = 0; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci if (!gspca_dev->streaming) 8878c2ecf20Sopenharmony_ci return 0; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci switch (ctrl->id) { 8908c2ecf20Sopenharmony_ci case V4L2_CID_BRIGHTNESS: 8918c2ecf20Sopenharmony_ci setbrightness(gspca_dev, ctrl->val); 8928c2ecf20Sopenharmony_ci break; 8938c2ecf20Sopenharmony_ci case V4L2_CID_CONTRAST: 8948c2ecf20Sopenharmony_ci setcontrast(gspca_dev, ctrl->val); 8958c2ecf20Sopenharmony_ci break; 8968c2ecf20Sopenharmony_ci case V4L2_CID_SATURATION: 8978c2ecf20Sopenharmony_ci setcolors(gspca_dev, ctrl->val); 8988c2ecf20Sopenharmony_ci break; 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci return gspca_dev->usb_err; 9018c2ecf20Sopenharmony_ci} 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = { 9048c2ecf20Sopenharmony_ci .s_ctrl = sd_s_ctrl, 9058c2ecf20Sopenharmony_ci}; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci gspca_dev->vdev.ctrl_handler = hdl; 9128c2ecf20Sopenharmony_ci v4l2_ctrl_handler_init(hdl, 3); 9138c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9148c2ecf20Sopenharmony_ci V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); 9158c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9168c2ecf20Sopenharmony_ci V4L2_CID_CONTRAST, 0, 63, 1, 31); 9178c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9188c2ecf20Sopenharmony_ci V4L2_CID_SATURATION, 0, 63, 1, 31); 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci if (hdl->error) { 9218c2ecf20Sopenharmony_ci pr_err("Could not initialize controls\n"); 9228c2ecf20Sopenharmony_ci return hdl->error; 9238c2ecf20Sopenharmony_ci } 9248c2ecf20Sopenharmony_ci return 0; 9258c2ecf20Sopenharmony_ci} 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci/* sub-driver description */ 9288c2ecf20Sopenharmony_cistatic const struct sd_desc sd_desc = { 9298c2ecf20Sopenharmony_ci .name = MODULE_NAME, 9308c2ecf20Sopenharmony_ci .config = sd_config, 9318c2ecf20Sopenharmony_ci .init = sd_init, 9328c2ecf20Sopenharmony_ci .init_controls = sd_init_controls, 9338c2ecf20Sopenharmony_ci .start = sd_start, 9348c2ecf20Sopenharmony_ci .stopN = sd_stopN, 9358c2ecf20Sopenharmony_ci .pkt_scan = sd_pkt_scan, 9368c2ecf20Sopenharmony_ci}; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci/* -- module initialisation -- */ 9398c2ecf20Sopenharmony_cistatic const struct usb_device_id device_table[] = { 9408c2ecf20Sopenharmony_ci {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200}, 9418c2ecf20Sopenharmony_ci {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300}, 9428c2ecf20Sopenharmony_ci {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler}, 9438c2ecf20Sopenharmony_ci {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310}, 9448c2ecf20Sopenharmony_ci {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510}, 9458c2ecf20Sopenharmony_ci {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016}, 9468c2ecf20Sopenharmony_ci {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85}, 9478c2ecf20Sopenharmony_ci {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300}, 9488c2ecf20Sopenharmony_ci {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini}, 9498c2ecf20Sopenharmony_ci {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20}, 9508c2ecf20Sopenharmony_ci {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia}, 9518c2ecf20Sopenharmony_ci {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350}, 9528c2ecf20Sopenharmony_ci {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV}, 9538c2ecf20Sopenharmony_ci {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus}, 9548c2ecf20Sopenharmony_ci {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera}, 9558c2ecf20Sopenharmony_ci {} 9568c2ecf20Sopenharmony_ci}; 9578c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci/* -- device connect -- */ 9608c2ecf20Sopenharmony_cistatic int sd_probe(struct usb_interface *intf, 9618c2ecf20Sopenharmony_ci const struct usb_device_id *id) 9628c2ecf20Sopenharmony_ci{ 9638c2ecf20Sopenharmony_ci return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 9648c2ecf20Sopenharmony_ci THIS_MODULE); 9658c2ecf20Sopenharmony_ci} 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_cistatic struct usb_driver sd_driver = { 9688c2ecf20Sopenharmony_ci .name = MODULE_NAME, 9698c2ecf20Sopenharmony_ci .id_table = device_table, 9708c2ecf20Sopenharmony_ci .probe = sd_probe, 9718c2ecf20Sopenharmony_ci .disconnect = gspca_disconnect, 9728c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 9738c2ecf20Sopenharmony_ci .suspend = gspca_suspend, 9748c2ecf20Sopenharmony_ci .resume = gspca_resume, 9758c2ecf20Sopenharmony_ci .reset_resume = gspca_resume, 9768c2ecf20Sopenharmony_ci#endif 9778c2ecf20Sopenharmony_ci}; 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_cimodule_usb_driver(sd_driver); 980