Received: by 2002:a05:6a10:1a4d:0:0:0:0 with SMTP id nk13csp2717390pxb; Thu, 3 Feb 2022 12:38:28 -0800 (PST) X-Google-Smtp-Source: ABdhPJxyhbxIu+sKqP54ea5p4NhR0w/Gz7s0HAQMUXP5/HOCiZ7L2rah4AtJdP4xx9EslzjszIeB X-Received: by 2002:a05:6a00:1693:: with SMTP id k19mr35421530pfc.71.1643920708506; Thu, 03 Feb 2022 12:38:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643920708; cv=none; d=google.com; s=arc-20160816; b=X1tUn5GVrnsvJVzZHXr1/apPshgUUpqXzX6RZDrk00uWXDVBJrTee/a0m9h1gMcXdP k73w8owjn1YyB9oVOkUU7xexaKZyR6noDjT1Sdc4Z0wpnqDi2h0yeIVrqXW3SKagJl1Q Y6LBWELwN9uuuwrCHh5NZSROakIeqprMRZyrT2B7IzhB2/R1HZ0g3Vu2PvJQSMcE6/vd lvkGeYHYfy6PK/wDvns9uG3SQv4V2skAd4RhKhVaWuwfb3nxVnUg0gXQW+P9NnTvOQ6A U8vUE0Hs5iy6ShRKOwKjS12ds16btnY3V2FC8Npt5/XcrY/EjIUmUz8b1Yb+Un8mEPv+ +cMg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=gAYs+ZZHkB07iFJ4CYifZkETlgoxw7ookBwRaGDcqbc=; b=Csbbrh+a0++ro+TKbGsR4gp3zYTFX6oYCqXEM7/UI0W3yUpRlPTiOzTiO6OgJgS1Ju +xM76mipz95mzi2qF4ZRrM5iwl4FtJfwZPLFDnPagYOy/gn5+CJC8rWjE1fNoFdH05LN eG3fYOzkrQa+8/m7WmxCWIzFXNt5anAr7bJhmfnfnJggtxF9gbc6iWOC4A9A8ezh+Y00 eBgmCUVcDtm5oNQsQHHs6AM8TtkaSuukDjHPoOQc4p/oAD70oAJOjgoMISBdyIodi0IV gzp+8GJh4e2i9y+AeNQfjbxaDTZY5o4fwFFk1QgmRutp2YgKZXhynilz7hU/VOJQqlE3 SuGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b="Q/mLOfzR"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a12si25239007pfv.135.2022.02.03.12.38.16; Thu, 03 Feb 2022 12:38:28 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b="Q/mLOfzR"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353357AbiBCRwe (ORCPT + 99 others); Thu, 3 Feb 2022 12:52:34 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:59048 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353232AbiBCRut (ORCPT ); Thu, 3 Feb 2022 12:50:49 -0500 Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:5173:4d3f:4ddc:2012]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 74E711C3A; Thu, 3 Feb 2022 18:50:29 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1643910629; bh=5CetPsMNqlbOx/W3JD3+AaeH0cV+k4nWAztBn5qAQck=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Q/mLOfzR+jZ+7rttlao5ppQH5m4+kd4W0n30dYEz6xj9Zz/HCvMLTnZy14cqUWDQb 6XRS9LKonJRZVb1nP1VnteivWwq+HRpwzM8eXKN15dwLprD1i6PZiNetWvktqOXKk/ MJLrXNDeVASNA8uTE+CIOARsqrWhuJ7UFOzPiyZU= From: Jean-Michel Hautbois To: jeanmichel.hautbois@ideasonboard.com Cc: dave.stevenson@raspberrypi.com, devicetree@vger.kernel.org, kernel-list@raspberrypi.com, laurent.pinchart@ideasonboard.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, lukasz@jany.st, mchehab@kernel.org, naush@raspberrypi.com, robh@kernel.org, tomi.valkeinen@ideasonboard.com, nsaenz@kernel.org, bcm-kernel-feedback-list@broadcom.com Subject: [RFC PATCH v4 11/12] media: imx219: Add support for the V4L2 subdev active state Date: Thu, 3 Feb 2022 18:50:08 +0100 Message-Id: <20220203175009.558868-12-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220203175009.558868-1-jeanmichel.hautbois@ideasonboard.com> References: <20220203175009.558868-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Now that we have multiplexed streams support in the V4L2 API, add support for the subdev active state in the sensor. In order to use state to manage the active configuration, we need to initialize the subdevice state with a call to v4l2_subdev_init_finalize() before registering it. The call to v4l2_subdev_cleanup() is also required to release the resources before unregistering. Accessing the configuration is then done after a call to v4l2_subdev_lock_state() and the set_fmt operation can then call v4l2_state_get_stream_format() directly. The get_fmt operation does not need to be complex, and a simple call to v4l2_subdev_get_fmt will do the trick, as it will grab the configured format based on the state. Signed-off-by: Jean-Michel Hautbois --- drivers/media/i2c/imx219.c | 151 +++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 74 deletions(-) diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index 7c224d007f3e..88212f86ce9b 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -870,78 +870,43 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *fse) { - struct imx219 *imx219 = to_imx219(sd); - u32 code; - - if (fse->index >= ARRAY_SIZE(supported_modes)) - return -EINVAL; - - mutex_lock(&imx219->mutex); - code = imx219_get_format_code(imx219, fse->code); - mutex_unlock(&imx219->mutex); - if (fse->code != code) - return -EINVAL; + unsigned int i; - fse->min_width = supported_modes[fse->index].width; - fse->max_width = fse->min_width; - fse->min_height = supported_modes[fse->index].height; - fse->max_height = fse->min_height; + if (fse->stream == 0) { + for (i = 0; i < ARRAY_SIZE(imx219_mbus_formats); ++i) { + if (imx219_mbus_formats[i] == fse->code) + break; + } - return 0; -} + if (i == ARRAY_SIZE(imx219_mbus_formats)) + return -EINVAL; -static void imx219_reset_colorspace(struct v4l2_mbus_framefmt *fmt) -{ - fmt->colorspace = V4L2_COLORSPACE_SRGB; - fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace); - fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, - fmt->colorspace, - fmt->ycbcr_enc); - fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace); -} + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; -static void imx219_update_pad_format(struct imx219 *imx219, - const struct imx219_mode *mode, - struct v4l2_subdev_format *fmt) -{ - fmt->format.width = mode->width; - fmt->format.height = mode->height; - fmt->format.field = V4L2_FIELD_NONE; - imx219_reset_colorspace(&fmt->format); -} - -static int __imx219_get_pad_format(struct imx219 *imx219, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - struct v4l2_mbus_framefmt *try_fmt = - v4l2_subdev_get_try_format(&imx219->sd, sd_state, - fmt->pad); - /* update the code which could change due to vflip or hflip: */ - try_fmt->code = imx219_get_format_code(imx219, try_fmt->code); - fmt->format = *try_fmt; + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->max_height = supported_modes[fse->index].height; + fse->min_height = fse->max_height; } else { - imx219_update_pad_format(imx219, imx219->mode, fmt); - fmt->format.code = imx219_get_format_code(imx219, - imx219->fmt.code); + if (fse->code != MEDIA_BUS_FMT_METADATA_8) + return -EINVAL; + + fse->min_width = IMX219_EMBEDDED_LINE_WIDTH; + fse->max_width = fse->min_width; + fse->min_height = IMX219_NUM_EMBEDDED_LINES; + fse->max_height = fse->min_height; } return 0; } -static int imx219_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) +static void imx219_update_metadata_pad_format(struct v4l2_subdev_format *fmt) { - struct imx219 *imx219 = to_imx219(sd); - int ret; - - mutex_lock(&imx219->mutex); - ret = __imx219_get_pad_format(imx219, sd_state, fmt); - mutex_unlock(&imx219->mutex); - - return ret; + fmt->format.width = IMX219_EMBEDDED_LINE_WIDTH; + fmt->format.height = IMX219_NUM_EMBEDDED_LINES; + fmt->format.code = MEDIA_BUS_FMT_METADATA_8; + fmt->format.field = V4L2_FIELD_NONE; } static int imx219_set_pad_format(struct v4l2_subdev *sd, @@ -949,32 +914,58 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_format *fmt) { struct imx219 *imx219 = to_imx219(sd); + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); const struct imx219_mode *mode; - struct v4l2_mbus_framefmt *framefmt; + struct v4l2_mbus_framefmt *format; int exposure_max, exposure_def, hblank; unsigned int i; + int ret = 0; mutex_lock(&imx219->mutex); + if (fmt->pad != 0) { + dev_err(&client->dev, "%s Could not get pad %d\n", __func__, + fmt->pad); + ret = -EINVAL; + goto done; + } + + if (fmt->stream == 1) { + /* Only one embedded data mode is supported */ + imx219_update_metadata_pad_format(fmt); + ret = 0; + goto done; + } + for (i = 0; i < ARRAY_SIZE(imx219_mbus_formats); i++) if (imx219_mbus_formats[i] == fmt->format.code) break; if (i >= ARRAY_SIZE(imx219_mbus_formats)) i = 0; - /* Bayer order varies with flips */ - fmt->format.code = imx219_get_format_code(imx219, imx219_mbus_formats[i]); - mode = v4l2_find_nearest_size(supported_modes, ARRAY_SIZE(supported_modes), width, height, fmt->format.width, fmt->format.height); - imx219_update_pad_format(imx219, mode, fmt); - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); - *framefmt = fmt->format; - } else if (imx219->mode != mode || - imx219->fmt.code != fmt->format.code) { + + v4l2_subdev_lock_state(sd_state); + + /* Update the stored format and return it. */ + format = v4l2_state_get_stream_format(sd_state, fmt->pad, fmt->stream); + + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && imx219->streaming) { + ret = -EBUSY; + goto err_state; + } + + /* Bayer order varies with flips */ + format->code = imx219_get_format_code(imx219, imx219_mbus_formats[i]); + format->width = mode->width; + format->height = mode->height; + /* Bayer order varies with flips */ + fmt->format = *format; + + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { imx219->fmt = fmt->format; imx219->mode = mode; /* Update limits and set FPS to default */ @@ -1001,9 +992,12 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd, hblank); } +err_state: + v4l2_subdev_unlock_state(sd_state); +done: mutex_unlock(&imx219->mutex); - return 0; + return ret; } static int imx219_set_framefmt(struct imx219 *imx219) @@ -1305,7 +1299,7 @@ static const struct v4l2_subdev_video_ops imx219_video_ops = { static const struct v4l2_subdev_pad_ops imx219_pad_ops = { .init_cfg = imx219_init_cfg, .enum_mbus_code = imx219_enum_mbus_code, - .get_fmt = imx219_get_pad_format, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = imx219_set_pad_format, .get_selection = imx219_get_selection, .set_routing = imx219_set_routing, @@ -1582,10 +1576,16 @@ static int imx219_probe(struct i2c_client *client) goto error_handler_free; } + ret = v4l2_subdev_init_finalize(sd); + if (ret) { + dev_err(dev, "failed to finalize sensor init: %d\n", ret); + goto error_media_entity; + } + ret = v4l2_async_register_subdev_sensor(sd); if (ret < 0) { dev_err(dev, "failed to register sensor sub-device: %d\n", ret); - goto error_media_entity; + goto error_free_state; } /* Enable runtime PM and turn off the device */ @@ -1595,6 +1595,8 @@ static int imx219_probe(struct i2c_client *client) return 0; +error_free_state: + v4l2_subdev_cleanup(sd); error_media_entity: media_entity_cleanup(&sd->entity); @@ -1613,6 +1615,7 @@ static int imx219_remove(struct i2c_client *client) struct imx219 *imx219 = to_imx219(sd); v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); imx219_free_controls(imx219); -- 2.32.0