pwc-ctrl.c 14 KB

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