Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pwc-v4l.c
Go to the documentation of this file.
1 /* Linux driver for Philips webcam
2  USB and Video4Linux interface part.
3  (C) 1999-2004 Nemosoft Unv.
4  (C) 2004-2006 Luc Saillard ([email protected])
5  (C) 2011 Hans de Goede <[email protected]>
6 
7  NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
8  driver and thus may have bugs that are not present in the original version.
9  Please send bug reports and support requests to <[email protected]>.
10  The decompression routines have been implemented by reverse-engineering the
11  Nemosoft binary pwcx module. Caveat emptor.
12 
13  This program is free software; you can redistribute it and/or modify
14  it under the terms of the GNU General Public License as published by
15  the Free Software Foundation; either version 2 of the License, or
16  (at your option) any later version.
17 
18  This program is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with this program; if not, write to the Free Software
25  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 
27 */
28 
29 #include <linux/errno.h>
30 #include <linux/init.h>
31 #include <linux/mm.h>
32 #include <linux/module.h>
33 #include <linux/poll.h>
34 #include <linux/vmalloc.h>
35 #include <linux/jiffies.h>
36 #include <asm/io.h>
37 
38 #include "pwc.h"
39 
40 #define PWC_CID_CUSTOM(ctrl) ((V4L2_CID_USER_BASE | 0xf000) + custom_ ## ctrl)
41 
42 static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
43 static int pwc_s_ctrl(struct v4l2_ctrl *ctrl);
44 
45 static const struct v4l2_ctrl_ops pwc_ctrl_ops = {
46  .g_volatile_ctrl = pwc_g_volatile_ctrl,
47  .s_ctrl = pwc_s_ctrl,
48 };
49 
54 
55 const char * const pwc_auto_whitebal_qmenu[] = {
56  "Indoor (Incandescant Lighting) Mode",
57  "Outdoor (Sunlight) Mode",
58  "Indoor (Fluorescent Lighting) Mode",
59  "Manual Mode",
60  "Auto Mode",
61  NULL
62 };
63 
64 static const struct v4l2_ctrl_config pwc_auto_white_balance_cfg = {
65  .ops = &pwc_ctrl_ops,
67  .type = V4L2_CTRL_TYPE_MENU,
68  .max = awb_auto,
69  .qmenu = pwc_auto_whitebal_qmenu,
70 };
71 
72 static const struct v4l2_ctrl_config pwc_autocontour_cfg = {
73  .ops = &pwc_ctrl_ops,
74  .id = PWC_CID_CUSTOM(autocontour),
75  .type = V4L2_CTRL_TYPE_BOOLEAN,
76  .name = "Auto contour",
77  .min = 0,
78  .max = 1,
79  .step = 1,
80 };
81 
82 static const struct v4l2_ctrl_config pwc_contour_cfg = {
83  .ops = &pwc_ctrl_ops,
84  .id = PWC_CID_CUSTOM(contour),
85  .type = V4L2_CTRL_TYPE_INTEGER,
86  .name = "Contour",
87  .flags = V4L2_CTRL_FLAG_SLIDER,
88  .min = 0,
89  .max = 63,
90  .step = 1,
91 };
92 
93 static const struct v4l2_ctrl_config pwc_backlight_cfg = {
94  .ops = &pwc_ctrl_ops,
96  .type = V4L2_CTRL_TYPE_BOOLEAN,
97  .min = 0,
98  .max = 1,
99  .step = 1,
100 };
101 
102 static const struct v4l2_ctrl_config pwc_flicker_cfg = {
103  .ops = &pwc_ctrl_ops,
105  .type = V4L2_CTRL_TYPE_BOOLEAN,
106  .min = 0,
107  .max = 1,
108  .step = 1,
109 };
110 
111 static const struct v4l2_ctrl_config pwc_noise_reduction_cfg = {
112  .ops = &pwc_ctrl_ops,
113  .id = PWC_CID_CUSTOM(noise_reduction),
114  .type = V4L2_CTRL_TYPE_INTEGER,
115  .name = "Dynamic Noise Reduction",
116  .min = 0,
117  .max = 3,
118  .step = 1,
119 };
120 
121 static const struct v4l2_ctrl_config pwc_save_user_cfg = {
122  .ops = &pwc_ctrl_ops,
123  .id = PWC_CID_CUSTOM(save_user),
124  .type = V4L2_CTRL_TYPE_BUTTON,
125  .name = "Save User Settings",
126 };
127 
128 static const struct v4l2_ctrl_config pwc_restore_user_cfg = {
129  .ops = &pwc_ctrl_ops,
130  .id = PWC_CID_CUSTOM(restore_user),
131  .type = V4L2_CTRL_TYPE_BUTTON,
132  .name = "Restore User Settings",
133 };
134 
135 static const struct v4l2_ctrl_config pwc_restore_factory_cfg = {
136  .ops = &pwc_ctrl_ops,
137  .id = PWC_CID_CUSTOM(restore_factory),
138  .type = V4L2_CTRL_TYPE_BUTTON,
139  .name = "Restore Factory Settings",
140 };
141 
142 static const struct v4l2_ctrl_config pwc_awb_speed_cfg = {
143  .ops = &pwc_ctrl_ops,
144  .id = PWC_CID_CUSTOM(awb_speed),
145  .type = V4L2_CTRL_TYPE_INTEGER,
146  .name = "Auto White Balance Speed",
147  .min = 1,
148  .max = 32,
149  .step = 1,
150 };
151 
152 static const struct v4l2_ctrl_config pwc_awb_delay_cfg = {
153  .ops = &pwc_ctrl_ops,
154  .id = PWC_CID_CUSTOM(awb_delay),
155  .type = V4L2_CTRL_TYPE_INTEGER,
156  .name = "Auto White Balance Delay",
157  .min = 0,
158  .max = 63,
159  .step = 1,
160 };
161 
162 int pwc_init_controls(struct pwc_device *pdev)
163 {
164  struct v4l2_ctrl_handler *hdl;
165  struct v4l2_ctrl_config cfg;
166  int r, def;
167 
168  hdl = &pdev->ctrl_handler;
169  r = v4l2_ctrl_handler_init(hdl, 20);
170  if (r)
171  return r;
172 
173  /* Brightness, contrast, saturation, gamma */
175  if (r || def > 127)
176  def = 63;
177  pdev->brightness = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
178  V4L2_CID_BRIGHTNESS, 0, 127, 1, def);
179 
181  if (r || def > 63)
182  def = 31;
183  pdev->contrast = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
184  V4L2_CID_CONTRAST, 0, 63, 1, def);
185 
186  if (pdev->type >= 675) {
187  if (pdev->type < 730)
189  else
192  &def);
193  if (r || def < -100 || def > 100)
194  def = 0;
195  pdev->saturation = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
196  V4L2_CID_SATURATION, -100, 100, 1, def);
197  }
198 
199  r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, GAMMA_FORMATTER, &def);
200  if (r || def > 31)
201  def = 15;
202  pdev->gamma = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
203  V4L2_CID_GAMMA, 0, 31, 1, def);
204 
205  /* auto white balance, red gain, blue gain */
207  if (r || def > awb_auto)
208  def = awb_auto;
209  cfg = pwc_auto_white_balance_cfg;
210  cfg.name = v4l2_ctrl_get_name(cfg.id);
211  cfg.def = def;
212  pdev->auto_white_balance = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
213  /* check auto controls to avoid NULL deref in v4l2_ctrl_auto_cluster */
214  if (!pdev->auto_white_balance)
215  return hdl->error;
216 
217  r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
219  if (r)
220  def = 127;
221  pdev->red_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
222  V4L2_CID_RED_BALANCE, 0, 255, 1, def);
223 
224  r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
226  if (r)
227  def = 127;
228  pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
229  V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);
230 
232 
233  /* autogain, gain */
235  if (r || (def != 0 && def != 0xff))
236  def = 0;
237  /* Note a register value if 0 means auto gain is on */
238  pdev->autogain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
239  V4L2_CID_AUTOGAIN, 0, 1, 1, def == 0);
240  if (!pdev->autogain)
241  return hdl->error;
242 
244  if (r || def > 63)
245  def = 31;
246  pdev->gain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
247  V4L2_CID_GAIN, 0, 63, 1, def);
248 
249  /* auto exposure, exposure */
250  if (DEVICE_USE_CODEC2(pdev->type)) {
252  &def);
253  if (r || (def != 0 && def != 0xff))
254  def = 0;
255  /*
256  * def = 0 auto, def = ff manual
257  * menu idx 0 = auto, idx 1 = manual
258  */
260  &pwc_ctrl_ops,
262  1, 0, def != 0);
263  if (!pdev->exposure_auto)
264  return hdl->error;
265 
266  /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
268  READ_SHUTTER_FORMATTER, &def);
269  if (r || def > 655)
270  def = 655;
271  pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
272  V4L2_CID_EXPOSURE, 0, 655, 1, def);
273  /* CODEC2: separate auto gain & auto exposure */
274  v4l2_ctrl_auto_cluster(2, &pdev->autogain, 0, true);
276  V4L2_EXPOSURE_MANUAL, true);
277  } else if (DEVICE_USE_CODEC3(pdev->type)) {
278  /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
280  READ_SHUTTER_FORMATTER, &def);
281  if (r || def > 255)
282  def = 255;
283  pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
284  V4L2_CID_EXPOSURE, 0, 255, 1, def);
285  /* CODEC3: both gain and exposure controlled by autogain */
286  pdev->autogain_expo_cluster[0] = pdev->autogain;
287  pdev->autogain_expo_cluster[1] = pdev->gain;
288  pdev->autogain_expo_cluster[2] = pdev->exposure;
290  0, true);
291  }
292 
293  /* color / bw setting */
295  &def);
296  if (r || (def != 0 && def != 0xff))
297  def = 0xff;
298  /* def = 0 bw, def = ff color, menu idx 0 = color, idx 1 = bw */
299  pdev->colorfx = v4l2_ctrl_new_std_menu(hdl, &pwc_ctrl_ops,
300  V4L2_CID_COLORFX, 1, 0, def == 0);
301 
302  /* autocontour, contour */
304  if (r || (def != 0 && def != 0xff))
305  def = 0;
306  cfg = pwc_autocontour_cfg;
307  cfg.def = def == 0;
308  pdev->autocontour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
309  if (!pdev->autocontour)
310  return hdl->error;
311 
313  if (r || def > 63)
314  def = 31;
315  cfg = pwc_contour_cfg;
316  cfg.def = def;
317  pdev->contour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
318 
319  v4l2_ctrl_auto_cluster(2, &pdev->autocontour, 0, false);
320 
321  /* backlight */
322  r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
324  if (r || (def != 0 && def != 0xff))
325  def = 0;
326  cfg = pwc_backlight_cfg;
327  cfg.name = v4l2_ctrl_get_name(cfg.id);
328  cfg.def = def == 0;
329  pdev->backlight = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
330 
331  /* flikker rediction */
332  r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
334  if (r || (def != 0 && def != 0xff))
335  def = 0;
336  cfg = pwc_flicker_cfg;
337  cfg.name = v4l2_ctrl_get_name(cfg.id);
338  cfg.def = def == 0;
339  pdev->flicker = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
340 
341  /* Dynamic noise reduction */
342  r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
344  if (r || def > 3)
345  def = 2;
346  cfg = pwc_noise_reduction_cfg;
347  cfg.def = def;
348  pdev->noise_reduction = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
349 
350  /* Save / Restore User / Factory Settings */
351  pdev->save_user = v4l2_ctrl_new_custom(hdl, &pwc_save_user_cfg, NULL);
352  pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
353  NULL);
354  if (pdev->restore_user)
355  pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE;
357  &pwc_restore_factory_cfg,
358  NULL);
359  if (pdev->restore_factory)
360  pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
361 
362  /* Auto White Balance speed & delay */
363  r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
365  if (r || def < 1 || def > 32)
366  def = 1;
367  cfg = pwc_awb_speed_cfg;
368  cfg.def = def;
369  pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
370 
371  r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
373  if (r || def > 63)
374  def = 0;
375  cfg = pwc_awb_delay_cfg;
376  cfg.def = def;
377  pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
378 
379  if (!(pdev->features & FEATURE_MOTOR_PANTILT))
380  return hdl->error;
381 
382  /* Motor pan / tilt / reset */
383  pdev->motor_pan = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
384  V4L2_CID_PAN_RELATIVE, -4480, 4480, 64, 0);
385  if (!pdev->motor_pan)
386  return hdl->error;
387  pdev->motor_tilt = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
388  V4L2_CID_TILT_RELATIVE, -1920, 1920, 64, 0);
389  pdev->motor_pan_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
390  V4L2_CID_PAN_RESET, 0, 0, 0, 0);
391  pdev->motor_tilt_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
392  V4L2_CID_TILT_RESET, 0, 0, 0, 0);
393  v4l2_ctrl_cluster(4, &pdev->motor_pan);
394 
395  return hdl->error;
396 }
397 
398 static void pwc_vidioc_fill_fmt(struct v4l2_format *f,
399  int width, int height, u32 pixfmt)
400 {
401  memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
402  f->fmt.pix.width = width;
403  f->fmt.pix.height = height;
404  f->fmt.pix.field = V4L2_FIELD_NONE;
405  f->fmt.pix.pixelformat = pixfmt;
406  f->fmt.pix.bytesperline = f->fmt.pix.width;
407  f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.width * 3 / 2;
408  f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
409  PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
410  "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
411  f->fmt.pix.width,
412  f->fmt.pix.height,
413  f->fmt.pix.bytesperline,
414  f->fmt.pix.sizeimage,
415  (f->fmt.pix.pixelformat)&255,
416  (f->fmt.pix.pixelformat>>8)&255,
417  (f->fmt.pix.pixelformat>>16)&255,
418  (f->fmt.pix.pixelformat>>24)&255);
419 }
420 
421 /* ioctl(VIDIOC_TRY_FMT) */
422 static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
423 {
424  int size;
425 
426  if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
427  PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
428  return -EINVAL;
429  }
430 
431  switch (f->fmt.pix.pixelformat) {
432  case V4L2_PIX_FMT_YUV420:
433  break;
434  case V4L2_PIX_FMT_PWC1:
435  if (DEVICE_USE_CODEC23(pdev->type)) {
436  PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
437  return -EINVAL;
438  }
439  break;
440  case V4L2_PIX_FMT_PWC2:
441  if (DEVICE_USE_CODEC1(pdev->type)) {
442  PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
443  return -EINVAL;
444  }
445  break;
446  default:
447  PWC_DEBUG_IOCTL("Unsupported pixel format\n");
448  return -EINVAL;
449 
450  }
451 
452  size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height);
453  pwc_vidioc_fill_fmt(f,
454  pwc_image_sizes[size][0],
455  pwc_image_sizes[size][1],
456  f->fmt.pix.pixelformat);
457 
458  return 0;
459 }
460 
461 /* ioctl(VIDIOC_SET_FMT) */
462 
463 static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
464 {
465  struct pwc_device *pdev = video_drvdata(file);
466  int ret, pixelformat, compression = 0;
467 
468  ret = pwc_vidioc_try_fmt(pdev, f);
469  if (ret < 0)
470  return ret;
471 
472  if (vb2_is_busy(&pdev->vb_queue))
473  return -EBUSY;
474 
475  pixelformat = f->fmt.pix.pixelformat;
476 
477  PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
478  "format=%c%c%c%c\n",
479  f->fmt.pix.width, f->fmt.pix.height, pdev->vframes,
480  (pixelformat)&255,
481  (pixelformat>>8)&255,
482  (pixelformat>>16)&255,
483  (pixelformat>>24)&255);
484 
485  ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
486  pixelformat, 30, &compression, 0);
487 
488  PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
489 
490  pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
491  return ret;
492 }
493 
494 static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
495 {
496  struct pwc_device *pdev = video_drvdata(file);
497 
498  strcpy(cap->driver, PWC_NAME);
499  strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card));
500  usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
504  return 0;
505 }
506 
507 static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
508 {
509  if (i->index) /* Only one INPUT is supported */
510  return -EINVAL;
511 
512  strlcpy(i->name, "Camera", sizeof(i->name));
514  return 0;
515 }
516 
517 static int pwc_g_input(struct file *file, void *fh, unsigned int *i)
518 {
519  *i = 0;
520  return 0;
521 }
522 
523 static int pwc_s_input(struct file *file, void *fh, unsigned int i)
524 {
525  return i ? -EINVAL : 0;
526 }
527 
528 static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
529 {
530  struct pwc_device *pdev =
532  int ret = 0;
533 
534  switch (ctrl->id) {
536  if (pdev->color_bal_valid &&
537  (pdev->auto_white_balance->val != awb_auto ||
538  time_before(jiffies,
539  pdev->last_color_bal_update + HZ / 4))) {
540  pdev->red_balance->val = pdev->last_red_balance;
541  pdev->blue_balance->val = pdev->last_blue_balance;
542  break;
543  }
544  ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
546  &pdev->red_balance->val);
547  if (ret)
548  break;
549  ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
551  &pdev->blue_balance->val);
552  if (ret)
553  break;
554  pdev->last_red_balance = pdev->red_balance->val;
555  pdev->last_blue_balance = pdev->blue_balance->val;
557  pdev->color_bal_valid = true;
558  break;
559  case V4L2_CID_AUTOGAIN:
560  if (pdev->gain_valid && time_before(jiffies,
561  pdev->last_gain_update + HZ / 4)) {
562  pdev->gain->val = pdev->last_gain;
563  break;
564  }
565  ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
566  READ_AGC_FORMATTER, &pdev->gain->val);
567  if (ret)
568  break;
569  pdev->last_gain = pdev->gain->val;
570  pdev->last_gain_update = jiffies;
571  pdev->gain_valid = true;
572  if (!DEVICE_USE_CODEC3(pdev->type))
573  break;
574  /* Fall through for CODEC3 where autogain also controls expo */
576  if (pdev->exposure_valid && time_before(jiffies,
577  pdev->last_exposure_update + HZ / 4)) {
578  pdev->exposure->val = pdev->last_exposure;
579  break;
580  }
581  ret = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
583  &pdev->exposure->val);
584  if (ret)
585  break;
586  pdev->last_exposure = pdev->exposure->val;
588  pdev->exposure_valid = true;
589  break;
590  default:
591  ret = -EINVAL;
592  }
593 
594  if (ret)
595  PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
596 
597  return ret;
598 }
599 
600 static int pwc_set_awb(struct pwc_device *pdev)
601 {
602  int ret;
603 
604  if (pdev->auto_white_balance->is_new) {
605  ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
607  pdev->auto_white_balance->val);
608  if (ret)
609  return ret;
610 
611  if (pdev->auto_white_balance->val != awb_manual)
612  pdev->color_bal_valid = false; /* Force cache update */
613 
614  /*
615  * If this is a preset, update our red / blue balance values
616  * so that events get generated for the new preset values
617  */
618  if (pdev->auto_white_balance->val == awb_indoor ||
619  pdev->auto_white_balance->val == awb_outdoor ||
620  pdev->auto_white_balance->val == awb_fl)
621  pwc_g_volatile_ctrl(pdev->auto_white_balance);
622  }
623  if (pdev->auto_white_balance->val != awb_manual)
624  return 0;
625 
626  if (pdev->red_balance->is_new) {
627  ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
629  pdev->red_balance->val);
630  if (ret)
631  return ret;
632  }
633 
634  if (pdev->blue_balance->is_new) {
635  ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
637  pdev->blue_balance->val);
638  if (ret)
639  return ret;
640  }
641  return 0;
642 }
643 
644 /* For CODEC2 models which have separate autogain and auto exposure */
645 static int pwc_set_autogain(struct pwc_device *pdev)
646 {
647  int ret;
648 
649  if (pdev->autogain->is_new) {
650  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
652  pdev->autogain->val ? 0 : 0xff);
653  if (ret)
654  return ret;
655 
656  if (pdev->autogain->val)
657  pdev->gain_valid = false; /* Force cache update */
658  }
659 
660  if (pdev->autogain->val)
661  return 0;
662 
663  if (pdev->gain->is_new) {
664  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
666  pdev->gain->val);
667  if (ret)
668  return ret;
669  }
670  return 0;
671 }
672 
673 /* For CODEC2 models which have separate autogain and auto exposure */
674 static int pwc_set_exposure_auto(struct pwc_device *pdev)
675 {
676  int ret;
677  int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
678 
679  if (pdev->exposure_auto->is_new) {
680  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
682  is_auto ? 0 : 0xff);
683  if (ret)
684  return ret;
685 
686  if (is_auto)
687  pdev->exposure_valid = false; /* Force cache update */
688  }
689 
690  if (is_auto)
691  return 0;
692 
693  if (pdev->exposure->is_new) {
694  ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
696  pdev->exposure->val);
697  if (ret)
698  return ret;
699  }
700  return 0;
701 }
702 
703 /* For CODEC3 models which have autogain controlling both gain and exposure */
704 static int pwc_set_autogain_expo(struct pwc_device *pdev)
705 {
706  int ret;
707 
708  if (pdev->autogain->is_new) {
709  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
711  pdev->autogain->val ? 0 : 0xff);
712  if (ret)
713  return ret;
714 
715  if (pdev->autogain->val) {
716  pdev->gain_valid = false; /* Force cache update */
717  pdev->exposure_valid = false; /* Force cache update */
718  }
719  }
720 
721  if (pdev->autogain->val)
722  return 0;
723 
724  if (pdev->gain->is_new) {
725  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
727  pdev->gain->val);
728  if (ret)
729  return ret;
730  }
731 
732  if (pdev->exposure->is_new) {
733  ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
735  pdev->exposure->val);
736  if (ret)
737  return ret;
738  }
739  return 0;
740 }
741 
742 static int pwc_set_motor(struct pwc_device *pdev)
743 {
744  int ret;
745 
746  pdev->ctrl_buf[0] = 0;
747  if (pdev->motor_pan_reset->is_new)
748  pdev->ctrl_buf[0] |= 0x01;
749  if (pdev->motor_tilt_reset->is_new)
750  pdev->ctrl_buf[0] |= 0x02;
751  if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
752  ret = send_control_msg(pdev, SET_MPT_CTL,
754  pdev->ctrl_buf, 1);
755  if (ret < 0)
756  return ret;
757  }
758 
759  memset(pdev->ctrl_buf, 0, 4);
760  if (pdev->motor_pan->is_new) {
761  pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF;
762  pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8);
763  }
764  if (pdev->motor_tilt->is_new) {
765  pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF;
766  pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8);
767  }
768  if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
769  ret = send_control_msg(pdev, SET_MPT_CTL,
771  pdev->ctrl_buf, 4);
772  if (ret < 0)
773  return ret;
774  }
775 
776  return 0;
777 }
778 
779 static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
780 {
781  struct pwc_device *pdev =
783  int ret = 0;
784 
785  switch (ctrl->id) {
786  case V4L2_CID_BRIGHTNESS:
787  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
788  BRIGHTNESS_FORMATTER, ctrl->val);
789  break;
790  case V4L2_CID_CONTRAST:
791  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
792  CONTRAST_FORMATTER, ctrl->val);
793  break;
794  case V4L2_CID_SATURATION:
795  ret = pwc_set_s8_ctrl(pdev, SET_CHROM_CTL,
796  pdev->saturation_fmt, ctrl->val);
797  break;
798  case V4L2_CID_GAMMA:
799  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
800  GAMMA_FORMATTER, ctrl->val);
801  break;
803  ret = pwc_set_awb(pdev);
804  break;
805  case V4L2_CID_AUTOGAIN:
806  if (DEVICE_USE_CODEC2(pdev->type))
807  ret = pwc_set_autogain(pdev);
808  else if (DEVICE_USE_CODEC3(pdev->type))
809  ret = pwc_set_autogain_expo(pdev);
810  else
811  ret = -EINVAL;
812  break;
814  if (DEVICE_USE_CODEC2(pdev->type))
815  ret = pwc_set_exposure_auto(pdev);
816  else
817  ret = -EINVAL;
818  break;
819  case V4L2_CID_COLORFX:
820  ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
822  ctrl->val ? 0 : 0xff);
823  break;
825  if (pdev->autocontour->is_new) {
826  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
828  pdev->autocontour->val ? 0 : 0xff);
829  }
830  if (ret == 0 && pdev->contour->is_new) {
831  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
833  pdev->contour->val);
834  }
835  break;
837  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
839  ctrl->val ? 0 : 0xff);
840  break;
842  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
844  ctrl->val ? 0 : 0xff);
845  break;
847  ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
849  ctrl->val);
850  break;
853  break;
856  break;
858  ret = pwc_button_ctrl(pdev,
860  break;
862  ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
864  ctrl->val);
865  break;
867  ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
869  ctrl->val);
870  break;
872  ret = pwc_set_motor(pdev);
873  break;
874  default:
875  ret = -EINVAL;
876  }
877 
878  if (ret)
879  PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret);
880 
881  return ret;
882 }
883 
884 static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
885 {
886  struct pwc_device *pdev = video_drvdata(file);
887 
888  /* We only support two format: the raw format, and YUV */
889  switch (f->index) {
890  case 0:
891  /* RAW format */
892  f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2;
894  strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description));
895  break;
896  case 1:
898  strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description));
899  break;
900  default:
901  return -EINVAL;
902  }
903  return 0;
904 }
905 
906 static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
907 {
908  struct pwc_device *pdev = video_drvdata(file);
909 
911  return -EINVAL;
912 
913  PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
914  pdev->width, pdev->height);
915  pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
916  return 0;
917 }
918 
919 static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
920 {
921  struct pwc_device *pdev = video_drvdata(file);
922 
923  return pwc_vidioc_try_fmt(pdev, f);
924 }
925 
926 static int pwc_enum_framesizes(struct file *file, void *fh,
927  struct v4l2_frmsizeenum *fsize)
928 {
929  struct pwc_device *pdev = video_drvdata(file);
930  unsigned int i = 0, index = fsize->index;
931 
932  if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 ||
933  (fsize->pixel_format == V4L2_PIX_FMT_PWC1 &&
934  DEVICE_USE_CODEC1(pdev->type)) ||
935  (fsize->pixel_format == V4L2_PIX_FMT_PWC2 &&
936  DEVICE_USE_CODEC23(pdev->type))) {
937  for (i = 0; i < PSZ_MAX; i++) {
938  if (!(pdev->image_mask & (1UL << i)))
939  continue;
940  if (!index--) {
942  fsize->discrete.width = pwc_image_sizes[i][0];
943  fsize->discrete.height = pwc_image_sizes[i][1];
944  return 0;
945  }
946  }
947  }
948  return -EINVAL;
949 }
950 
951 static int pwc_enum_frameintervals(struct file *file, void *fh,
952  struct v4l2_frmivalenum *fival)
953 {
954  struct pwc_device *pdev = video_drvdata(file);
955  int size = -1;
956  unsigned int i;
957 
958  for (i = 0; i < PSZ_MAX; i++) {
959  if (pwc_image_sizes[i][0] == fival->width &&
960  pwc_image_sizes[i][1] == fival->height) {
961  size = i;
962  break;
963  }
964  }
965 
966  /* TODO: Support raw format */
967  if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420)
968  return -EINVAL;
969 
970  i = pwc_get_fps(pdev, fival->index, size);
971  if (!i)
972  return -EINVAL;
973 
975  fival->discrete.numerator = 1;
976  fival->discrete.denominator = i;
977 
978  return 0;
979 }
980 
981 static int pwc_g_parm(struct file *file, void *fh,
982  struct v4l2_streamparm *parm)
983 {
984  struct pwc_device *pdev = video_drvdata(file);
985 
986  if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
987  return -EINVAL;
988 
989  memset(parm, 0, sizeof(*parm));
990 
992  parm->parm.capture.readbuffers = MIN_FRAMES;
993  parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
994  parm->parm.capture.timeperframe.denominator = pdev->vframes;
995  parm->parm.capture.timeperframe.numerator = 1;
996 
997  return 0;
998 }
999 
1000 static int pwc_s_parm(struct file *file, void *fh,
1001  struct v4l2_streamparm *parm)
1002 {
1003  struct pwc_device *pdev = video_drvdata(file);
1004  int compression = 0;
1005  int ret, fps;
1006 
1007  if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1008  return -EINVAL;
1009 
1010  /* If timeperframe == 0, then reset the framerate to the nominal value.
1011  We pick a high framerate here, and let pwc_set_video_mode() figure
1012  out the best match. */
1013  if (parm->parm.capture.timeperframe.numerator == 0 ||
1014  parm->parm.capture.timeperframe.denominator == 0)
1015  fps = 30;
1016  else
1017  fps = parm->parm.capture.timeperframe.denominator /
1018  parm->parm.capture.timeperframe.numerator;
1019 
1020  if (vb2_is_busy(&pdev->vb_queue))
1021  return -EBUSY;
1022 
1023  ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
1024  fps, &compression, 0);
1025 
1026  pwc_g_parm(file, fh, parm);
1027 
1028  return ret;
1029 }
1030 
1032  .vidioc_querycap = pwc_querycap,
1033  .vidioc_enum_input = pwc_enum_input,
1034  .vidioc_g_input = pwc_g_input,
1035  .vidioc_s_input = pwc_s_input,
1036  .vidioc_enum_fmt_vid_cap = pwc_enum_fmt_vid_cap,
1037  .vidioc_g_fmt_vid_cap = pwc_g_fmt_vid_cap,
1038  .vidioc_s_fmt_vid_cap = pwc_s_fmt_vid_cap,
1039  .vidioc_try_fmt_vid_cap = pwc_try_fmt_vid_cap,
1040  .vidioc_reqbufs = vb2_ioctl_reqbufs,
1041  .vidioc_querybuf = vb2_ioctl_querybuf,
1042  .vidioc_qbuf = vb2_ioctl_qbuf,
1043  .vidioc_dqbuf = vb2_ioctl_dqbuf,
1044  .vidioc_streamon = vb2_ioctl_streamon,
1045  .vidioc_streamoff = vb2_ioctl_streamoff,
1046  .vidioc_log_status = v4l2_ctrl_log_status,
1047  .vidioc_enum_framesizes = pwc_enum_framesizes,
1048  .vidioc_enum_frameintervals = pwc_enum_frameintervals,
1049  .vidioc_g_parm = pwc_g_parm,
1050  .vidioc_s_parm = pwc_s_parm,
1051  .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1052  .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1053 };