From patchwork Wed Mar 12 18:08:31 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Manley X-Patchwork-Id: 23029 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1WNnaj-0003se-92; Wed, 12 Mar 2014 19:09:21 +0100 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.72/mailfrontend-6) with esmtp id 1WNnah-0005Zv-3r; Wed, 12 Mar 2014 19:09:21 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756660AbaCLSJO (ORCPT + 1 other); Wed, 12 Mar 2014 14:09:14 -0400 Received: from out3-smtp.messagingengine.com ([66.111.4.27]:51085 "EHLO out3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756033AbaCLSJM (ORCPT ); Wed, 12 Mar 2014 14:09:12 -0400 Received: from compute3.internal (compute3.nyi.mail.srv.osa [10.202.2.43]) by gateway1.nyi.mail.srv.osa (Postfix) with ESMTP id 84AB020D56 for ; Wed, 12 Mar 2014 14:09:11 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute3.internal (MEProxy); Wed, 12 Mar 2014 14:09:11 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=williammanley.net; h=from:to:cc:subject:date:message-id; s=mesmtp; bh=W8YzvImn7zUt NDriMiyjkqKVlv8=; b=YRuZiA//VmAQ2rRqODyIDHOsvJj2bfekB0R/1UaA529y 9quNj9eL1nobxcq5UcsTPmksaTVO3tjqi8DAvOSfCAeydOVJIWRURqTQ3bLRewZP FbqbWU/FfQuD3QDwiXKsso5mCumjD+slWd/oEl7EG0jRs9+3DGjbQ4RcAY3Po74= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=from:to:cc:subject:date:message-id; s= smtpout; bh=W8YzvImn7zUtNDriMiyjkqKVlv8=; b=JUxEg+1YBMe/hN7ZKfxt XZc/BeDQxQMbsvlUfbroiBf1QatbpPfUATe9szcV1dVixjJKBjsz4s+N19O08N/+ Bq1u0h9QKHhZ+A8gA7IknlvSSuAtrK+sMa7LgZblkLdNXQ513EjDL3GyNANLvaA/ t3KArABDNCywvTQEFP45Oco= X-Sasl-enc: uBYz6/vX8lLR2Bp2IrIkUgmuSbj615bMjPLxSRJtzPxM 1394647751 Received: from localhost.localdomain (unknown [86.26.230.106]) by mail.messagingengine.com (Postfix) with ESMTPA id D9084C007AB; Wed, 12 Mar 2014 14:09:10 -0400 (EDT) From: William Manley To: linux-media@vger.kernel.org Cc: William Manley Subject: [PATCH] uvcvideo: Work around buggy Logitech C920 firmware Date: Wed, 12 Mar 2014 18:08:31 +0000 Message-Id: <1394647711-25291-1-git-send-email-will@williammanley.net> X-Mailer: git-send-email 1.9.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2014.3.12.180014 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' HTML_00_01 0.05, HTML_00_10 0.05, BODY_SIZE_3000_3999 0, BODY_SIZE_5000_LESS 0, BODY_SIZE_7000_LESS 0, DKIM_SIGNATURE 0, URI_ENDS_IN_HTML 0, __ANY_URI 0, __CP_MEDIA_BODY 0, __CP_URI_IN_BODY 0, __HAS_FROM 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __MIME_TEXT_ONLY 0, __SANE_MSGID 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_NO_WWW 0, __URI_NS ' The uvcvideo webcam driver exposes the v4l2 control "Exposure (Absolute)" which allows the user to control the exposure time of the webcam, essentially controlling the brightness of the received image. By default the webcam automatically adjusts the exposure time automatically but the if you set the control "Exposure, Auto"="Manual Mode" the user can fix the exposure time. Unfortunately it seems that the Logitech C920 has a firmware bug where it will forget that it's in manual mode temporarily during initialisation. This means that the camera doesn't respect the exposure time that the user requested if they request it before starting to stream video. They end up with a video stream which is either too bright or too dark and must reset the controls after video starts streaming. This patch works around this camera bug by re-uploading the cached controls to the camera immediately after initialising the camera. Signed-off-by: William Manley --- drivers/media/usb/uvc/uvc_ctrl.c | 2 +- drivers/media/usb/uvc/uvc_driver.c | 2 +- drivers/media/usb/uvc/uvc_video.c | 5 +++++ drivers/media/usb/uvc/uvcvideo.h | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index a2f4501..f72d7eb 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -1795,7 +1795,7 @@ done: * - Handle restore order (Auto-Exposure Mode should be restored before * Exposure Time). */ -int uvc_ctrl_resume_device(struct uvc_device *dev) +int uvc_ctrl_restore_values(struct uvc_device *dev) { struct uvc_control *ctrl; struct uvc_entity *entity; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index c3bb250..9f8a87e 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1981,7 +1981,7 @@ static int __uvc_resume(struct usb_interface *intf, int reset) int ret = 0; if (reset) { - ret = uvc_ctrl_resume_device(dev); + ret = uvc_ctrl_restore_values(dev); if (ret < 0) return ret; } diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 3394c34..87cd57b 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -1660,6 +1660,11 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) } } + /* The Logitech C920 temporarily forgets that it should not be + adjusting Exposure Absolute during init so restore controls to + stored values. */ + uvc_ctrl_restore_values(stream->dev); + return 0; } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 9e35982..3b365a3 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -676,7 +676,7 @@ extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, const struct uvc_control_mapping *mapping); extern int uvc_ctrl_init_device(struct uvc_device *dev); extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); -extern int uvc_ctrl_resume_device(struct uvc_device *dev); +extern int uvc_ctrl_restore_values(struct uvc_device *dev); extern int uvc_ctrl_begin(struct uvc_video_chain *chain); extern int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,