From patchwork Mon Apr 16 02:51:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akinobu Mita X-Patchwork-Id: 10342077 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D3368601C2 for ; Mon, 16 Apr 2018 02:52:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C5EA2201CB for ; Mon, 16 Apr 2018 02:52:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BAAD32228E; Mon, 16 Apr 2018 02:52:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 13CD4201CB for ; Mon, 16 Apr 2018 02:52:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752938AbeDPCwn (ORCPT ); Sun, 15 Apr 2018 22:52:43 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:33553 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752915AbeDPCwl (ORCPT ); Sun, 15 Apr 2018 22:52:41 -0400 Received: by mail-pf0-f195.google.com with SMTP id f15so9839896pfn.0; Sun, 15 Apr 2018 19:52:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/M1sJDBeZpHStgQYxgShAlmRD2HyF7hiD9qpcJVZaiw=; b=jrNHKze9CNWkBbsCX3tMr107KUsjq5uZ4ZIYA1b1G29B9DX7Djtc8guxVDbJRIjK0G JS6urWlM9fuicLbOURH/1KS9rv6QSJb78g7sZ2Advv4kY5+5NuEpT5ZlyhaB4ZobRKMz 1wyqAIV7OXBPkLeZF5F/Oyiq8Wbqyq7j03uLCs6NJ4r0O7Bgzh8PYQpm9TpAWjjdMLYJ tYoCZxmhKTPDuFQ7cqoradxQOCRj77+aRcgA4JfkEKQxqrzQ3IkUTkl3ZzT35fXk5Sd0 cqt1Q6swfWniI8tDxnH5iaMJ1x+G1f6nmp+w/sFPfrr9hfTLHGPzIy7UqiqFc74vRUaN HABA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/M1sJDBeZpHStgQYxgShAlmRD2HyF7hiD9qpcJVZaiw=; b=QI8BewbqkHKyzSxkH3Gcu8+g8ibbnYywdeUjcopgqfCprvSi7TyWAooI55xnLC3A7K A8MzU9D9Y1gs8AnhSarpbDwlB+8dKk/AtspijL32j58MMmP6fKiskf20s0DO9wnHbp7n A9sXiJQZtvcjAXU9U579eWs6rvisKSwJb/hNZwNlDK2t3HBwC+KcbUjnHhtDkmcgmVj5 VU/fj2SYNYuaPHP8uI6tiO4Xz5DSSpgwJqyzO8KkZ7PBJ1WkHygH8VXgrq4v2NHhzXGo 3dNai8sEJzY3Frk1YbekZMvc9cAAqw0keeu8/S0k+V9/qrHYKNJRLRmyxUZ4peCXLk9C dovQ== X-Gm-Message-State: ALQs6tCSq64EYatGoP9CdHzghEdjc26ZlOjUwhKtLnQu6KKLAbJlRPMP y5AhHlKQef1HchssMLlnDbc6zA== X-Google-Smtp-Source: AIpwx49CxbvB+adOKcAXkDmKILnafgRuUyx93P35eetG+nq9Pm77VNFOPjxFPgJr5jFCtNTnNfKWCw== X-Received: by 10.98.11.144 with SMTP id 16mr19993115pfl.228.1523847160834; Sun, 15 Apr 2018 19:52:40 -0700 (PDT) Received: from localhost.localdomain ([240f:4:c2bc:1:3df1:9c88:51ad:c027]) by smtp.gmail.com with ESMTPSA id e1sm3694274pgt.49.2018.04.15.19.52.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 15 Apr 2018 19:52:40 -0700 (PDT) From: Akinobu Mita To: linux-media@vger.kernel.org, devicetree@vger.kernel.org Cc: Akinobu Mita , Jacopo Mondi , Laurent Pinchart , Hans Verkuil , Sakari Ailus , Mauro Carvalho Chehab Subject: [PATCH v2 10/10] media: ov772x: avoid accessing registers under power saving mode Date: Mon, 16 Apr 2018 11:51:51 +0900 Message-Id: <1523847111-12986-11-git-send-email-akinobu.mita@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1523847111-12986-1-git-send-email-akinobu.mita@gmail.com> References: <1523847111-12986-1-git-send-email-akinobu.mita@gmail.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The set_fmt() in subdev pad ops, the s_ctrl() for subdev control handler, and the s_frame_interval() in subdev video ops could be called when the device is under power saving mode. These callbacks for ov772x driver cause updating H/W registers that will fail under power saving mode. This avoids it by not apply any changes to H/W if the device is not powered up. Instead the changes will be restored right after power-up. Cc: Jacopo Mondi Cc: Laurent Pinchart Cc: Hans Verkuil Cc: Sakari Ailus Cc: Mauro Carvalho Chehab Signed-off-by: Akinobu Mita --- * v2 - New patch drivers/media/i2c/ov772x.c | 77 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c index 1297a21..c44728f 100644 --- a/drivers/media/i2c/ov772x.c +++ b/drivers/media/i2c/ov772x.c @@ -741,19 +741,29 @@ static int ov772x_s_frame_interval(struct v4l2_subdev *sd, struct ov772x_priv *priv = to_ov772x(sd); struct v4l2_fract *tpf = &ival->interval; unsigned int fps; - int ret; + int ret = 0; fps = ov772x_select_fps(priv, tpf); - ret = ov772x_set_frame_rate(priv, fps, priv->cfmt, priv->win); - if (ret) - return ret; + mutex_lock(&priv->power_lock); + /* + * If the device is not powered up by the host driver do + * not apply any changes to H/W at this time. Instead + * the frame rate will be restored right after power-up. + */ + if (priv->power_count > 0) { + ret = ov772x_set_frame_rate(priv, fps, priv->cfmt, priv->win); + if (ret) + goto error; + } tpf->numerator = 1; tpf->denominator = fps; priv->fps = fps; +error: + mutex_unlock(&priv->power_lock); - return 0; + return ret; } static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) @@ -765,6 +775,16 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) int ret = 0; u8 val; + /* v4l2_ctrl_lock() locks our own mutex */ + + /* + * If the device is not powered up by the host driver do + * not apply any controls to H/W at this time. Instead + * the controls will be restored right after power-up. + */ + if (priv->power_count == 0) + return 0; + switch (ctrl->id) { case V4L2_CID_VFLIP: val = ctrl->val ? VFLIP_IMG : 0x00; @@ -888,6 +908,10 @@ static int ov772x_power_off(struct ov772x_priv *priv) return 0; } +static int ov772x_set_params(struct ov772x_priv *priv, + const struct ov772x_color_format *cfmt, + const struct ov772x_win_size *win); + static int ov772x_s_power(struct v4l2_subdev *sd, int on) { struct ov772x_priv *priv = to_ov772x(sd); @@ -898,8 +922,20 @@ static int ov772x_s_power(struct v4l2_subdev *sd, int on) /* If the power count is modified from 0 to != 0 or from != 0 to 0, * update the power state. */ - if (priv->power_count == !on) - ret = on ? ov772x_power_on(priv) : ov772x_power_off(priv); + if (priv->power_count == !on) { + if (on) { + ret = ov772x_power_on(priv); + /* Restore the controls */ + if (!ret) + ret = ov772x_set_params(priv, priv->cfmt, + priv->win); + /* Restore the format and the frame rate */ + if (!ret) + ret = __v4l2_ctrl_handler_setup(&priv->hdl); + } else { + ret = ov772x_power_off(priv); + } + } if (!ret) { /* Update the power count. */ @@ -1163,7 +1199,7 @@ static int ov772x_set_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf = &format->format; const struct ov772x_color_format *cfmt; const struct ov772x_win_size *win; - int ret; + int ret = 0; if (format->pad) return -EINVAL; @@ -1184,14 +1220,23 @@ static int ov772x_set_fmt(struct v4l2_subdev *sd, return 0; } - ret = ov772x_set_params(priv, cfmt, win); - if (ret < 0) - return ret; - + mutex_lock(&priv->power_lock); + /* + * If the device is not powered up by the host driver do + * not apply any changes to H/W at this time. Instead + * the format will be restored right after power-up. + */ + if (priv->power_count > 0) { + ret = ov772x_set_params(priv, cfmt, win); + if (ret < 0) + goto error; + } priv->win = win; priv->cfmt = cfmt; +error: + mutex_unlock(&priv->power_lock); - return 0; + return ret; } static int ov772x_video_probe(struct ov772x_priv *priv) @@ -1201,7 +1246,7 @@ static int ov772x_video_probe(struct ov772x_priv *priv) const char *devname; int ret; - ret = ov772x_s_power(&priv->subdev, 1); + ret = ov772x_power_on(priv); if (ret < 0) return ret; @@ -1241,7 +1286,7 @@ static int ov772x_video_probe(struct ov772x_priv *priv) ret = v4l2_ctrl_handler_setup(&priv->hdl); done: - ov772x_s_power(&priv->subdev, 0); + ov772x_power_off(priv); return ret; } @@ -1341,6 +1386,8 @@ static int ov772x_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; v4l2_ctrl_handler_init(&priv->hdl, 3); + /* Use our mutex for the controls */ + priv->hdl.lock = &priv->power_lock; v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,