Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] pwc: Properly fill all fields on try_fmt

Before this patch the resulting values from a try_fmt were different then
those from a s_fmt with the same parameters. try_fmt simply did not
touch / fill some values like bytesperline at all.

This patch also corrects bytesperline to the proper value for a planar
format such as the YUV420P format the pwc driver produces, which is
the bytesperline value for the biggest plane, rather then those
of all planes added together.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Hans de Goede and committed by
Mauro Carvalho Chehab
31e582e9 5bbe18d7

+17 -25
+17 -25
drivers/media/video/pwc/pwc-v4l.c
··· 395 395 return hdl->error; 396 396 } 397 397 398 - static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f) 398 + static void pwc_vidioc_fill_fmt(struct v4l2_format *f, 399 + int width, int height, u32 pixfmt) 399 400 { 400 401 memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); 401 - f->fmt.pix.width = pdev->width; 402 - f->fmt.pix.height = pdev->height; 402 + f->fmt.pix.width = width; 403 + f->fmt.pix.height = height; 403 404 f->fmt.pix.field = V4L2_FIELD_NONE; 404 - if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) { 405 - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; 406 - f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2; 407 - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; 408 - } else { 409 - /* vbandlength contains 4 lines ... */ 410 - f->fmt.pix.bytesperline = pdev->vbandlength/4; 411 - f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame); 412 - if (DEVICE_USE_CODEC1(pdev->type)) 413 - f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC1; 414 - else 415 - f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC2; 416 - } 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; 417 408 PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() " 418 409 "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", 419 410 f->fmt.pix.width, ··· 449 458 } 450 459 451 460 size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height); 452 - f->fmt.pix.width = pwc_image_sizes[size][0]; 453 - f->fmt.pix.height = pwc_image_sizes[size][1]; 461 + pwc_vidioc_fill_fmt(f, 462 + pwc_image_sizes[size][0], 463 + pwc_image_sizes[size][1], 464 + f->fmt.pix.pixelformat); 454 465 455 466 return 0; 456 467 } ··· 472 479 return ret; 473 480 474 481 pixelformat = f->fmt.pix.pixelformat; 475 - 476 - if (pixelformat != V4L2_PIX_FMT_YUV420 && 477 - pixelformat != V4L2_PIX_FMT_PWC1 && 478 - pixelformat != V4L2_PIX_FMT_PWC2) 479 - return -EINVAL; 480 482 481 483 mutex_lock(&pdev->udevlock); 482 484 if (!pdev->udev) { ··· 499 511 500 512 if (ret == 0) { 501 513 pdev->pixfmt = pixelformat; 502 - pwc_vidioc_fill_fmt(pdev, f); 514 + pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, 515 + pdev->pixfmt); 503 516 } 504 517 505 518 leave: ··· 951 962 { 952 963 struct pwc_device *pdev = video_drvdata(file); 953 964 965 + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 966 + return -EINVAL; 967 + 954 968 mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */ 955 969 PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", 956 970 pdev->width, pdev->height); 957 - pwc_vidioc_fill_fmt(pdev, f); 971 + pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); 958 972 mutex_unlock(&pdev->udevlock); 959 973 return 0; 960 974 }