From patchwork Fri May 7 12:35:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432331 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF2AFC433B4 for ; Fri, 7 May 2021 12:36:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8CF4C61460 for ; Fri, 7 May 2021 12:36:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236547AbhEGMh5 (ORCPT ); Fri, 7 May 2021 08:37:57 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:59646 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231179AbhEGMhz (ORCPT ); Fri, 7 May 2021 08:37:55 -0400 Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 565C23F2; Fri, 7 May 2021 14:36:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391015; bh=eb7mpxApR5OHhlGD+jZHmLIcDgnPN+JenNNDLJFhBA4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DjQhDelgK5WjqNT01lJ1Tgs5MhK8BKyOvtVEQd/bijciKeMs/Ewoh1NiovcYxp2Cy PCIcbr2eOLEvtjqwPORXfTw+DI9z4j3wqkOfjfdskvuRzz8bvRcQgXQuuG6ufEeAig KWOSVwmc9w0pC+9j4bDta0EAOzjSNsETTL6ke6+o= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 01/11] media: v4l2-subdev: add subdev-wide state struct Date: Fri, 7 May 2021 15:35:48 +0300 Message-Id: <20210507123558.146948-2-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org We have 'struct v4l2_subdev_pad_config' which contains configuration for a single pad used for the TRY functionality, and an array of those structs is passed to various v4l2_subdev_pad_ops. I was working on subdev internal routing between pads, and realized that there's no way to add TRY functionality for routes, which is not pad specific configuration. Adding a separate struct for try-route config wouldn't work either, as e.g. set-fmt needs to know the try-route configuration to propagate the settings. This patch adds a new struct, 'struct v4l2_subdev_state' (which at the moment only contains the v4l2_subdev_pad_config array) and the new struct is used in most of the places where v4l2_subdev_pad_config was used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config are changed to instead take v4l2_subdev_state. Two drivers are changed to work with the above changes (drivers for HW which I have) as an example. I worked on a semantic patch (included below, my first spatch...) to do this change to all drivers, but hit lots of problems with non-trivial uses of v4l2_subdev_pad_config. As it looks like substantial amount of manual work is needed, I'm posting this RFC to get an ack on the changes before continuing that work. @ v4l2_subdev_pad_ops @ identifier pad_ops; identifier func; @@ ( static const struct v4l2_subdev_pad_ops pad_ops = { ..., .enum_mbus_code = func, ..., }; | static const struct v4l2_subdev_pad_ops pad_ops = { ..., .enum_frame_size = func, ..., }; | static const struct v4l2_subdev_pad_ops pad_ops = { ..., .enum_frame_interval = func, ..., }; | static const struct v4l2_subdev_pad_ops pad_ops = { ..., .get_fmt = func, ..., }; | static const struct v4l2_subdev_pad_ops pad_ops = { ..., .set_fmt = func, ..., }; | static const struct v4l2_subdev_pad_ops pad_ops = { ..., .get_selection = func, ..., }; | static const struct v4l2_subdev_pad_ops pad_ops = { ..., .set_selection = func, ..., }; | static const struct v4l2_subdev_pad_ops pad_ops = { ..., .init_cfg = func, ..., }; ) @@ identifier v4l2_subdev_pad_ops.func; identifier sd; identifier cfg; @@ func(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, ... ) { ... } @@ identifier v4l2_subdev_pad_ops.func; identifier sd; identifier cfg; @@ func(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg + struct v4l2_subdev_state *cfg ) { ... } @@ struct v4l2_subdev_fh *fh; @@ - fh->pad + &fh->cfg @@ identifier func; identifier cfg; @@ func(..., - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, ...) { ... } @@ struct v4l2_subdev_state *cfg; @@ { <... ( - cfg->try_fmt + cfg->pad->try_fmt | - cfg->try_crop + cfg->pad->try_crop | - cfg->try_compose + cfg->pad->try_compose ) ...> } @@ identifier pad_cfg; @@ { ... struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev_state cfg = { .pad = &pad_cfg }; <... - &pad_cfg + &cfg ...> } Signed-off-by: Tomi Valkeinen --- drivers/media/v4l2-core/v4l2-subdev.c | 141 +++++++++++++++----------- include/media/v4l2-subdev.h | 72 +++++++------ 2 files changed, 120 insertions(+), 93 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 956dafab43d4..bd996dcace3b 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -26,19 +26,21 @@ #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) { - if (sd->entity.num_pads) { - fh->pad = v4l2_subdev_alloc_pad_config(sd); - if (fh->pad == NULL) - return -ENOMEM; - } + struct v4l2_subdev_state *state; + + state = v4l2_subdev_alloc_state(sd); + if (IS_ERR(state)) + return PTR_ERR(state); + + fh->state = state; return 0; } static void subdev_fh_free(struct v4l2_subdev_fh *fh) { - v4l2_subdev_free_pad_config(fh->pad); - fh->pad = NULL; + v4l2_subdev_free_state(fh->state); + fh->state = NULL; } static int subdev_open(struct file *file) @@ -146,63 +148,63 @@ static inline int check_pad(struct v4l2_subdev *sd, u32 pad) return 0; } -static int check_cfg(u32 which, struct v4l2_subdev_pad_config *cfg) +static int check_cfg(u32 which, struct v4l2_subdev_state *state) { - if (which == V4L2_SUBDEV_FORMAT_TRY && !cfg) + if (which == V4L2_SUBDEV_FORMAT_TRY && !state) return -EINVAL; return 0; } static inline int check_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format) { if (!format) return -EINVAL; return check_which(format->which) ? : check_pad(sd, format->pad) ? : - check_cfg(format->which, cfg); + check_cfg(format->which, state); } static int call_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format) { - return check_format(sd, cfg, format) ? : - sd->ops->pad->get_fmt(sd, cfg, format); + return check_format(sd, state, format) ? : + sd->ops->pad->get_fmt(sd, state, format); } static int call_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format) { - return check_format(sd, cfg, format) ? : - sd->ops->pad->set_fmt(sd, cfg, format); + return check_format(sd, state, format) ? : + sd->ops->pad->set_fmt(sd, state, format); } static int call_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code) { if (!code) return -EINVAL; return check_which(code->which) ? : check_pad(sd, code->pad) ? : - check_cfg(code->which, cfg) ? : - sd->ops->pad->enum_mbus_code(sd, cfg, code); + check_cfg(code->which, state) ? : + sd->ops->pad->enum_mbus_code(sd, state, code); } static int call_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_frame_size_enum *fse) { if (!fse) return -EINVAL; return check_which(fse->which) ? : check_pad(sd, fse->pad) ? : - check_cfg(fse->which, cfg) ? : - sd->ops->pad->enum_frame_size(sd, cfg, fse); + check_cfg(fse->which, state) ? : + sd->ops->pad->enum_frame_size(sd, state, fse); } static inline int check_frame_interval(struct v4l2_subdev *sd, @@ -229,42 +231,42 @@ static int call_s_frame_interval(struct v4l2_subdev *sd, } static int call_enum_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval_enum *fie) { if (!fie) return -EINVAL; return check_which(fie->which) ? : check_pad(sd, fie->pad) ? : - check_cfg(fie->which, cfg) ? : - sd->ops->pad->enum_frame_interval(sd, cfg, fie); + check_cfg(fie->which, state) ? : + sd->ops->pad->enum_frame_interval(sd, state, fie); } static inline int check_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel) { if (!sel) return -EINVAL; return check_which(sel->which) ? : check_pad(sd, sel->pad) ? : - check_cfg(sel->which, cfg); + check_cfg(sel->which, state); } static int call_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel) { - return check_selection(sd, cfg, sel) ? : - sd->ops->pad->get_selection(sd, cfg, sel); + return check_selection(sd, state, sel) ? : + sd->ops->pad->get_selection(sd, state, sel); } static int call_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel) { - return check_selection(sd, cfg, sel) ? : - sd->ops->pad->set_selection(sd, cfg, sel); + return check_selection(sd, state, sel) ? : + sd->ops->pad->set_selection(sd, state, sel); } static inline int check_edid(struct v4l2_subdev *sd, @@ -506,7 +508,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(format->reserved, 0, sizeof(format->reserved)); memset(format->format.reserved, 0, sizeof(format->format.reserved)); - return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh->pad, format); + return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh->state, format); } case VIDIOC_SUBDEV_S_FMT: { @@ -517,7 +519,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(format->reserved, 0, sizeof(format->reserved)); memset(format->format.reserved, 0, sizeof(format->format.reserved)); - return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh->pad, format); + return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh->state, format); } case VIDIOC_SUBDEV_G_CROP: { @@ -531,7 +533,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) sel.target = V4L2_SEL_TGT_CROP; rval = v4l2_subdev_call( - sd, pad, get_selection, subdev_fh->pad, &sel); + sd, pad, get_selection, subdev_fh->state, &sel); crop->rect = sel.r; @@ -553,7 +555,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) sel.r = crop->rect; rval = v4l2_subdev_call( - sd, pad, set_selection, subdev_fh->pad, &sel); + sd, pad, set_selection, subdev_fh->state, &sel); crop->rect = sel.r; @@ -564,7 +566,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_subdev_mbus_code_enum *code = arg; memset(code->reserved, 0, sizeof(code->reserved)); - return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh->pad, + return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh->state, code); } @@ -572,7 +574,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_subdev_frame_size_enum *fse = arg; memset(fse->reserved, 0, sizeof(fse->reserved)); - return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh->pad, + return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh->state, fse); } @@ -597,7 +599,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_subdev_frame_interval_enum *fie = arg; memset(fie->reserved, 0, sizeof(fie->reserved)); - return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh->pad, + return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh->state, fie); } @@ -606,7 +608,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(sel->reserved, 0, sizeof(sel->reserved)); return v4l2_subdev_call( - sd, pad, get_selection, subdev_fh->pad, sel); + sd, pad, get_selection, subdev_fh->state, sel); } case VIDIOC_SUBDEV_S_SELECTION: { @@ -617,7 +619,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(sel->reserved, 0, sizeof(sel->reserved)); return v4l2_subdev_call( - sd, pad, set_selection, subdev_fh->pad, sel); + sd, pad, set_selection, subdev_fh->state, sel); } case VIDIOC_G_EDID: { @@ -892,35 +894,50 @@ int v4l2_subdev_link_validate(struct media_link *link) } EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate); -struct v4l2_subdev_pad_config * -v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd) +struct v4l2_subdev_state *v4l2_subdev_alloc_state(struct v4l2_subdev *sd) { - struct v4l2_subdev_pad_config *cfg; + struct v4l2_subdev_state *state; int ret; - if (!sd->entity.num_pads) - return NULL; - - cfg = kvmalloc_array(sd->entity.num_pads, sizeof(*cfg), - GFP_KERNEL | __GFP_ZERO); - if (!cfg) - return NULL; + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) { + ret = -ENOMEM; + goto err; + } - ret = v4l2_subdev_call(sd, pad, init_cfg, cfg); - if (ret < 0 && ret != -ENOIOCTLCMD) { - kvfree(cfg); - return NULL; + if (sd->entity.num_pads) { + state->pads = kvmalloc_array(sd->entity.num_pads, + sizeof(*state->pads), + GFP_KERNEL | __GFP_ZERO); + if (!state->pads) { + ret = -ENOMEM; + goto err; + } } - return cfg; + ret = v4l2_subdev_call(sd, pad, init_cfg, state); + if (ret < 0 && ret != -ENOIOCTLCMD) + goto err; + + return state; + +err: + if (state && state->pads) + kvfree(state->pads); + + kfree(state); + + return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config); +EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_state); -void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg) +void v4l2_subdev_free_state(struct v4l2_subdev_state *state) { - kvfree(cfg); + kvfree(state->pads); + kvfree(state); } -EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config); +EXPORT_SYMBOL_GPL(v4l2_subdev_free_state); + #endif /* CONFIG_MEDIA_CONTROLLER */ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index ebe0d50f6a73..a9c470605367 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -665,6 +665,19 @@ struct v4l2_subdev_pad_config { struct v4l2_rect try_compose; }; +/** + * struct v4l2_subdev_state - Used for storing subdev information. + * + * @pads: &struct v4l2_subdev_pad_config array + * + * This structure only needs to be passed to the pad op if the 'which' field + * of the main argument is set to %V4L2_SUBDEV_FORMAT_TRY. For + * %V4L2_SUBDEV_FORMAT_ACTIVE it is safe to pass %NULL. + */ +struct v4l2_subdev_state { + struct v4l2_subdev_pad_config *pads; +}; + /** * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations * @@ -729,27 +742,27 @@ struct v4l2_subdev_pad_config { */ struct v4l2_subdev_pad_ops { int (*init_cfg)(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg); + struct v4l2_subdev_state *state); int (*enum_mbus_code)(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code); int (*enum_frame_size)(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_frame_size_enum *fse); int (*enum_frame_interval)(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval_enum *fie); int (*get_fmt)(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format); int (*set_fmt)(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format); int (*get_selection)(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel); int (*set_selection)(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel); int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid); int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid); @@ -960,14 +973,14 @@ struct v4l2_subdev { * struct v4l2_subdev_fh - Used for storing subdev information per file handle * * @vfh: pointer to &struct v4l2_fh - * @pad: pointer to &struct v4l2_subdev_pad_config + * @state: pointer to &struct v4l2_subdev_state * @owner: module pointer to the owner of this file handle */ struct v4l2_subdev_fh { struct v4l2_fh vfh; struct module *owner; #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) - struct v4l2_subdev_pad_config *pad; + struct v4l2_subdev_state *state; #endif }; @@ -987,17 +1000,17 @@ struct v4l2_subdev_fh { * &struct v4l2_subdev_pad_config->try_fmt * * @sd: pointer to &struct v4l2_subdev - * @cfg: pointer to &struct v4l2_subdev_pad_config array. - * @pad: index of the pad in the @cfg array. + * @state: pointer to &struct v4l2_subdev_state. + * @pad: index of the pad in the @state array. */ static inline struct v4l2_mbus_framefmt * v4l2_subdev_get_try_format(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, unsigned int pad) { if (WARN_ON(pad >= sd->entity.num_pads)) pad = 0; - return &cfg[pad].try_fmt; + return &state->pads[pad].try_fmt; } /** @@ -1005,17 +1018,17 @@ v4l2_subdev_get_try_format(struct v4l2_subdev *sd, * &struct v4l2_subdev_pad_config->try_crop * * @sd: pointer to &struct v4l2_subdev - * @cfg: pointer to &struct v4l2_subdev_pad_config array. - * @pad: index of the pad in the @cfg array. + * @state: pointer to &struct v4l2_subdev_state. + * @pad: index of the pad in the @state array. */ static inline struct v4l2_rect * v4l2_subdev_get_try_crop(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, unsigned int pad) { if (WARN_ON(pad >= sd->entity.num_pads)) pad = 0; - return &cfg[pad].try_crop; + return &state->pads[pad].try_crop; } /** @@ -1023,17 +1036,17 @@ v4l2_subdev_get_try_crop(struct v4l2_subdev *sd, * &struct v4l2_subdev_pad_config->try_compose * * @sd: pointer to &struct v4l2_subdev - * @cfg: pointer to &struct v4l2_subdev_pad_config array. - * @pad: index of the pad in the @cfg array. + * @state: pointer to &struct v4l2_subdev_state. + * @pad: index of the pad in the @state array. */ static inline struct v4l2_rect * v4l2_subdev_get_try_compose(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, unsigned int pad) { if (WARN_ON(pad >= sd->entity.num_pads)) pad = 0; - return &cfg[pad].try_compose; + return &state->pads[pad].try_compose; } #endif @@ -1135,20 +1148,17 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, int v4l2_subdev_link_validate(struct media_link *link); /** - * v4l2_subdev_alloc_pad_config - Allocates memory for pad config + * v4l2_subdev_alloc_state - allocate v4l2_subdev_state * - * @sd: pointer to struct v4l2_subdev + * Must call v4l2_subdev_free_state() when state is no longer needed. */ -struct -v4l2_subdev_pad_config *v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd); +struct v4l2_subdev_state *v4l2_subdev_alloc_state(struct v4l2_subdev *sd); /** - * v4l2_subdev_free_pad_config - Frees memory allocated by - * v4l2_subdev_alloc_pad_config(). - * - * @cfg: pointer to &struct v4l2_subdev_pad_config + * v4l2_subdev_free_state - uninitialize v4l2_subdev_state */ -void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg); +void v4l2_subdev_free_state(struct v4l2_subdev_state *state); + #endif /* CONFIG_MEDIA_CONTROLLER */ /** From patchwork Fri May 7 12:35:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432736 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14096C43460 for ; Fri, 7 May 2021 12:37:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C93FF61464 for ; Fri, 7 May 2021 12:37:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236618AbhEGMiB (ORCPT ); Fri, 7 May 2021 08:38:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59834 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231179AbhEGMiA (ORCPT ); Fri, 7 May 2021 08:38:00 -0400 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 466B1C061574 for ; Fri, 7 May 2021 05:37:00 -0700 (PDT) Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5272C8A1; Fri, 7 May 2021 14:36:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391016; bh=Cugm65dp6wMYYpGMe9vCicD0E/d7W+AQc/VCe9eIHQY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rWb2wOZO9GKTIycXwFUgagEY9YLOFaErOENV2Qq3fyhhuKK0EB5y78JYq43rG9Il7 CWET7oZYaISLhMFeTM4MyoE4+ivqgeAa6DcNENGzHFFawlVsgSm+tYD/OwAE7LEfT9 PxCjEeN4r/zFZ2AwwVpjpU6ygjPLXFWdPHTAZBmI= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 02/11] media: v4l2-subdev: driver fixes for subdev-wide state struct Date: Fri, 7 May 2021 15:35:49 +0300 Message-Id: <20210507123558.146948-3-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Change two drivers as an example to use the new struct v4l2_subdev_pad_config. All drivers need to be fixed, and these fixes need to be squashed into the previous commit. Signed-off-by: Tomi Valkeinen --- drivers/media/i2c/ov5640.c | 10 +++++----- drivers/media/platform/ti-vpe/cal-camerarx.c | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index b4f52cee1dff..b29f887cbf84 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -2227,7 +2227,7 @@ static int ov5640_try_frame_interval(struct ov5640_dev *sensor, } static int ov5640_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_format *format) { struct ov5640_dev *sensor = to_ov5640_dev(sd); @@ -2285,7 +2285,7 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd, } static int ov5640_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_format *format) { struct ov5640_dev *sensor = to_ov5640_dev(sd); @@ -2818,7 +2818,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor) } static int ov5640_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_frame_size_enum *fse) { if (fse->pad != 0) @@ -2838,7 +2838,7 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd, static int ov5640_enum_frame_interval( struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_frame_interval_enum *fie) { struct ov5640_dev *sensor = to_ov5640_dev(sd); @@ -2924,7 +2924,7 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd, } static int ov5640_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_mbus_code_enum *code) { if (code->pad != 0) diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c index 36103f5af6e9..5b41ba493599 100644 --- a/drivers/media/platform/ti-vpe/cal-camerarx.c +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c @@ -621,7 +621,7 @@ static inline struct cal_camerarx *to_cal_camerarx(struct v4l2_subdev *sd) static struct v4l2_mbus_framefmt * cal_camerarx_get_pad_format(struct cal_camerarx *phy, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, unsigned int pad, u32 which) { switch (which) { @@ -652,7 +652,7 @@ static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable) } static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_mbus_code_enum *code) { struct cal_camerarx *phy = to_cal_camerarx(sd); @@ -689,7 +689,7 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd, } static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_frame_size_enum *fse) { struct cal_camerarx *phy = to_cal_camerarx(sd); @@ -739,7 +739,7 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd, } static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_format *format) { struct cal_camerarx *phy = to_cal_camerarx(sd); @@ -756,7 +756,7 @@ static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd, } static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *cfg, struct v4l2_subdev_format *format) { struct cal_camerarx *phy = to_cal_camerarx(sd); @@ -806,7 +806,7 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd, } static int cal_camerarx_sd_init_cfg(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg) + struct v4l2_subdev_state *cfg) { struct v4l2_subdev_format format = { .which = cfg ? V4L2_SUBDEV_FORMAT_TRY From patchwork Fri May 7 12:35:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432737 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0715CC433ED for ; Fri, 7 May 2021 12:37:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C6FA061448 for ; Fri, 7 May 2021 12:37:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236576AbhEGMh7 (ORCPT ); Fri, 7 May 2021 08:37:59 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:59674 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231179AbhEGMh6 (ORCPT ); Fri, 7 May 2021 08:37:58 -0400 Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 76396ACF; Fri, 7 May 2021 14:36:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391017; bh=gPqOehCOXtQl0eZutBhG4bcicx/yMEw/Ao33NCZDPDU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PINeq0kmDUz3yORG13DqAzSgxtceLDnA8AzzQ/lrJC/6+IPHDZw7FjJPNNd4rPuT/ LmUsowAt+yNHQn108TQ+UAuHUt9qYSzNVYVWBSZP+gJmU4Zgd+wwyCxCdWVbwOkr1Q gSwsJ6/qwQ8o3i5kpvk3pIwO20eL4sS0iOPPq6xc= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham , Michal Simek Subject: [RFC 03/11] v4l: subdev: Add [GS]_ROUTING subdev ioctls and operations Date: Fri, 7 May 2021 15:35:50 +0300 Message-Id: <20210507123558.146948-4-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Laurent Pinchart Add support for subdev internal routing. A route is defined as a single stream from a sink pad to a source pad. The userspace can configure the routing via two new ioctls, VIDIOC_SUBDEV_G_ROUTING and VIDIOC_SUBDEV_S_ROUTING, and subdevs can implement the functionality with v4l2_subdev_pad_ops.get_routing() and v4l2_subdev_pad_ops.set_routing(). Signed-off-by: Laurent Pinchart Signed-off-by: Michal Simek - Add sink and source streams for multiplexed links - Copy the argument back in case of an error. This is needed to let the caller know the number of routes. Signed-off-by: Sakari Ailus Reviewed-by: Niklas Söderlund - Expand and refine documentation. - Make the 'routes' pointer a __u64 __user pointer so that a compat32 version of the ioctl is not required. - Add struct v4l2_subdev_krouting to be used for subdevice operations. Signed-off-by: Jacopo Mondi - Fix typecasing warnings - Check sink & source pad types - Add 'which' field Signed-off-by: Tomi Valkeinen --- drivers/media/v4l2-core/v4l2-ioctl.c | 25 +++++++++++++- drivers/media/v4l2-core/v4l2-subdev.c | 46 +++++++++++++++++++++++++ include/media/v4l2-subdev.h | 26 +++++++++++++++ include/uapi/linux/v4l2-subdev.h | 48 +++++++++++++++++++++++++++ 4 files changed, 144 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 6ed218f10522..9fb2812799ec 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -3110,6 +3111,21 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, ret = 1; break; } + + case VIDIOC_SUBDEV_G_ROUTING: + case VIDIOC_SUBDEV_S_ROUTING: { + struct v4l2_subdev_routing *routing = parg; + + if (routing->num_routes > 256) + return -EINVAL; + + *user_ptr = u64_to_user_ptr(routing->routes); + *kernel_ptr = (void **)&routing->routes; + *array_size = sizeof(struct v4l2_subdev_route) + * routing->num_routes; + ret = 1; + break; + } } return ret; @@ -3371,8 +3387,15 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg, /* * Some ioctls can return an error, but still have valid * results that must be returned. + * + * FIXME: subdev IOCTLS are partially handled here and partially in + * v4l2-subdev.c and the 'always_copy' flag can only be set for IOCTLS + * defined here as part of the 'v4l2_ioctls' array. As + * VIDIOC_SUBDEV_G_ROUTING needs to return results to applications even + * in case of failure, but it is not defined here as part of the + * 'v4l2_ioctls' array, insert an ad-hoc check to address that. */ - if (err < 0 && !always_copy) + if (err < 0 && !always_copy && cmd != VIDIOC_SUBDEV_G_ROUTING) goto out; out_array_args: diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index bd996dcace3b..28e84453fe28 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -683,6 +683,52 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_SUBDEV_QUERYSTD: return v4l2_subdev_call(sd, video, querystd, arg); + case VIDIOC_SUBDEV_G_ROUTING: { + struct v4l2_subdev_routing *routing = arg; + struct v4l2_subdev_krouting krouting = { + .which = routing->which, + .num_routes = routing->num_routes, + .routes = (struct v4l2_subdev_route *)(uintptr_t) + routing->routes, + }; + int ret; + + ret = v4l2_subdev_call(sd, pad, get_routing, subdev_fh->state, &krouting); + + routing->num_routes = krouting.num_routes; + + return ret; + } + + case VIDIOC_SUBDEV_S_ROUTING: { + struct v4l2_subdev_routing *routing = arg; + struct v4l2_subdev_route *routes = + (struct v4l2_subdev_route *)(uintptr_t)routing->routes; + struct v4l2_subdev_krouting krouting = {}; + unsigned int i; + + if (routing->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev) + return -EPERM; + + for (i = 0; i < routing->num_routes; ++i) { + if (routes[i].sink_pad >= sd->entity.num_pads || + routes[i].source_pad >= sd->entity.num_pads) + return -EINVAL; + + if (!(sd->entity.pads[routes[i].sink_pad].flags & + MEDIA_PAD_FL_SINK) || + !(sd->entity.pads[routes[i].source_pad].flags & + MEDIA_PAD_FL_SOURCE)) + return -EINVAL; + } + + krouting.which = routing->which; + krouting.num_routes = routing->num_routes; + krouting.routes = routes; + + return v4l2_subdev_call(sd, pad, set_routing, subdev_fh->state, &krouting); + } + default: return v4l2_subdev_call(sd, core, ioctl, cmd, arg); } diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index a9c470605367..4cd1a3818c68 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -665,6 +665,22 @@ struct v4l2_subdev_pad_config { struct v4l2_rect try_compose; }; +/** + * struct v4l2_subdev_krouting - subdev routing table + * + * @which: format type (from enum v4l2_subdev_format_whence) + * @routes: &struct v4l2_subdev_route + * @num_routes: number of routes + * + * This structure is used to translate arguments received from + * VIDIOC_SUBDEV_G/S_ROUTING() ioctl to subdev device drivers operations. + */ +struct v4l2_subdev_krouting { + u32 which; + struct v4l2_subdev_route *routes; + unsigned int num_routes; +}; + /** * struct v4l2_subdev_state - Used for storing subdev information. * @@ -739,6 +755,10 @@ struct v4l2_subdev_state { * applied to the hardware. The operation shall fail if the * pad index it has been called on is not valid or in case of * unrecoverable failures. + * + * @get_routing: get the subdevice routing table. + * @set_routing: enable or disable data connection routes described in the + * subdevice routing table. */ struct v4l2_subdev_pad_ops { int (*init_cfg)(struct v4l2_subdev *sd, @@ -783,6 +803,12 @@ struct v4l2_subdev_pad_ops { struct v4l2_mbus_config *config); int (*set_mbus_config)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_config *config); + int (*get_routing)(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *route); + int (*set_routing)(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *route); }; /** diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h index 658106f5b5dc..45c01799e2cd 100644 --- a/include/uapi/linux/v4l2-subdev.h +++ b/include/uapi/linux/v4l2-subdev.h @@ -188,6 +188,52 @@ struct v4l2_subdev_capability { /* The v4l2 sub-device video device node is registered in read-only mode. */ #define V4L2_SUBDEV_CAP_RO_SUBDEV 0x00000001 +/** + * Is the route active? An active route will start when streaming is enabled + * on a video node. + */ +#define V4L2_SUBDEV_ROUTE_FL_ACTIVE BIT(0) + +/** + * Is the route immutable, i.e. can it be activated and inactivated? + * Set by the driver. + */ +#define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE BIT(1) + +/** + * struct v4l2_subdev_route - A route inside a subdev + * + * @sink_pad: the sink pad index + * @sink_stream: the sink stream identifier + * @source_pad: the source pad index + * @source_stream: the source stream identifier + * @flags: route flags V4L2_SUBDEV_ROUTE_FL_* + * @reserved: drivers and applications must zero this array + */ +struct v4l2_subdev_route { + __u32 sink_pad; + __u32 sink_stream; + __u32 source_pad; + __u32 source_stream; + __u32 flags; + __u32 reserved[5]; +}; + +/** + * struct v4l2_subdev_routing - Subdev routing information + * + * @which: configuration type (from enum v4l2_subdev_format_whence) + * @routes: pointer to the routes array + * @num_routes: the total number of routes in the routes array + * @reserved: drivers and applications must zero this array + */ +struct v4l2_subdev_routing { + __u32 which; + __u64 routes; + __u32 num_routes; + __u32 reserved[5]; +}; + /* Backwards compatibility define --- to be removed */ #define v4l2_subdev_edid v4l2_edid @@ -203,6 +249,8 @@ struct v4l2_subdev_capability { #define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop) #define VIDIOC_SUBDEV_G_SELECTION _IOWR('V', 61, struct v4l2_subdev_selection) #define VIDIOC_SUBDEV_S_SELECTION _IOWR('V', 62, struct v4l2_subdev_selection) +#define VIDIOC_SUBDEV_G_ROUTING _IOWR('V', 38, struct v4l2_subdev_routing) +#define VIDIOC_SUBDEV_S_ROUTING _IOWR('V', 39, struct v4l2_subdev_routing) /* The following ioctls are identical to the ioctls in videodev2.h */ #define VIDIOC_SUBDEV_G_STD _IOR('V', 23, v4l2_std_id) #define VIDIOC_SUBDEV_S_STD _IOW('V', 24, v4l2_std_id) From patchwork Fri May 7 12:35:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432330 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01F4EC433B4 for ; Fri, 7 May 2021 12:37:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BE3C76145E for ; Fri, 7 May 2021 12:37:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236615AbhEGMiA (ORCPT ); Fri, 7 May 2021 08:38:00 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:59674 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236569AbhEGMh7 (ORCPT ); Fri, 7 May 2021 08:37:59 -0400 Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4F7E3D4A; Fri, 7 May 2021 14:36:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391019; bh=8DPrS2WWZL/fgOJvorYFzGjmuL7BwEspF28Yv1QzZvs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qJ0w96AbO/IzmbOtBiCjTkDcErXaMJmsiNfVVgasXMhCF6Ai8P5rhaC6Me4tYKXAV mDVwPq5ZXJyBpDkK3jC8fW7CjcTjKPt7Sc7/uKA9O4hpC5ldEsVKiMA+Rsh7uRhWMB 46T26r5XuLsctudD8bmrgcXY6kZM9Kw1kcWzOisI= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 04/11] v4l: subdev: routing kernel helper functions Date: Fri, 7 May 2021 15:35:51 +0300 Message-Id: <20210507123558.146948-5-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add helper functions for routing. These helpers make it easier for the drivers to use struct v4l2_subdev_krouting. TODO: add docs TODO: fix according to comments Signed-off-by: Tomi Valkeinen --- drivers/media/v4l2-core/v4l2-subdev.c | 89 +++++++++++++++++++++++++++ include/media/v4l2-subdev.h | 15 +++++ 2 files changed, 104 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 28e84453fe28..7b40bf34f8a3 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -912,6 +912,95 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad, return -EINVAL; } +int v4l2_subdev_get_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *routing) +{ + int ret; + + routing->which = state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + routing->routes = NULL; + routing->num_routes = 0; + + ret = v4l2_subdev_call(sd, pad, get_routing, state, routing); + if (ret == 0) + return 0; + if (ret != -ENOSPC) + return ret; + + routing->routes = kvmalloc_array(routing->num_routes, + sizeof(*routing->routes), GFP_KERNEL); + if (!routing->routes) + return -ENOMEM; + + ret = v4l2_subdev_call(sd, pad, get_routing, state, routing); + if (ret) { + kvfree(routing->routes); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_get_routing); + +void v4l2_subdev_free_routing(struct v4l2_subdev_krouting *routing) +{ + kvfree(routing->routes); + routing->routes = NULL; + routing->num_routes = 0; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_free_routing); + +void v4l2_subdev_cpy_routing(struct v4l2_subdev_krouting *dst, + const struct v4l2_subdev_krouting *src) +{ + memcpy(dst->routes, src->routes, + src->num_routes * sizeof(*src->routes)); + dst->num_routes = src->num_routes; + dst->which = src->which; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_cpy_routing); + +int v4l2_subdev_dup_routing(struct v4l2_subdev_krouting *dst, + const struct v4l2_subdev_krouting *src) +{ + v4l2_subdev_free_routing(dst); + + if (src->num_routes == 0) { + dst->which = src->which; + return 0; + } + + dst->routes = kvmalloc_array(src->num_routes, sizeof(*src->routes), + GFP_KERNEL); + if (!dst->routes) + return -ENOMEM; + + v4l2_subdev_cpy_routing(dst, src); + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_dup_routing); + +bool v4l2_subdev_has_route(struct v4l2_subdev_krouting *routing, + unsigned int pad0, unsigned int pad1) +{ + unsigned int i; + + for (i = 0; i < routing->num_routes; ++i) { + struct v4l2_subdev_route *route = &routing->routes[i]; + + if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + if (route->sink_pad == pad0 && route->source_pad == pad1) + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_has_route); + int v4l2_subdev_link_validate(struct media_link *link) { struct v4l2_subdev *sink; diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 4cd1a3818c68..63a36eead7dc 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1252,4 +1252,19 @@ extern const struct v4l2_subdev_ops v4l2_subdev_call_wrappers; void v4l2_subdev_notify_event(struct v4l2_subdev *sd, const struct v4l2_event *ev); +int v4l2_subdev_get_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *routing); + +void v4l2_subdev_free_routing(struct v4l2_subdev_krouting *routing); + +int v4l2_subdev_dup_routing(struct v4l2_subdev_krouting *dst, + const struct v4l2_subdev_krouting *src); + +void v4l2_subdev_cpy_routing(struct v4l2_subdev_krouting *dst, + const struct v4l2_subdev_krouting *src); + +bool v4l2_subdev_has_route(struct v4l2_subdev_krouting *routing, + unsigned int pad0, unsigned int pad1); + #endif From patchwork Fri May 7 12:35:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432329 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8CD63C433ED for ; Fri, 7 May 2021 12:37:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5775661474 for ; Fri, 7 May 2021 12:37:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236662AbhEGMiC (ORCPT ); Fri, 7 May 2021 08:38:02 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:59674 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236599AbhEGMiA (ORCPT ); Fri, 7 May 2021 08:38:00 -0400 Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 465DDF88; Fri, 7 May 2021 14:36:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391020; bh=uiGYlaKwLktgOFCENKD/bNHb25wlUxxvwQNikmhc/gc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oaDZRtOoLA4BLJsDjU3YiHneE9whU+rR/eI+B8U2bLzVAFtip8+jZAXrwcF/FCG8J oIcwNtvxfQp8LV9vOud5uMG6zA1wxcvQo+ovOVfHhbJwoWw2TH8KC+PgMba9yNuJQp AAyAO5xtGcsWTBHzvTlESPLoXQea1l5pUZZhKsx4= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 05/11] v4l: subdev: add V4L2_SUBDEV_ROUTE_FL_SOURCE Date: Fri, 7 May 2021 15:35:52 +0300 Message-Id: <20210507123558.146948-6-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add route flag to indicate that the route is a source route. This means that the route does not lead anywhere, and the sink_pad and sink_stream should not be used. A sensor which provides multiple streams should implement get_routing and use the flag to mark the routes as sources. Signed-off-by: Tomi Valkeinen --- include/uapi/linux/v4l2-subdev.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h index 45c01799e2cd..f20491e1f53f 100644 --- a/include/uapi/linux/v4l2-subdev.h +++ b/include/uapi/linux/v4l2-subdev.h @@ -200,6 +200,13 @@ struct v4l2_subdev_capability { */ #define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE BIT(1) +/** + * Is the route a source endpoint? A source endpoint route doesn't come + * from "anywhere", and the sink_pad and sink_stream fields are unused. + * Set by the driver. + */ +#define V4L2_SUBDEV_ROUTE_FL_SOURCE BIT(2) + /** * struct v4l2_subdev_route - A route inside a subdev * From patchwork Fri May 7 12:35:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432735 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A36ECC433B4 for ; Fri, 7 May 2021 12:37:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6DEE061464 for ; Fri, 7 May 2021 12:37:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236744AbhEGMiD (ORCPT ); Fri, 7 May 2021 08:38:03 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:59722 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236640AbhEGMiC (ORCPT ); Fri, 7 May 2021 08:38:02 -0400 Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id F368C2CF; Fri, 7 May 2021 14:37:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391021; bh=7EwTlNzHzd6IbTJ/jUGYEiISglWx8pZJX5Ik1idrwGk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z1FjGqJsgwyAESgeBhxFNIq+ly5PlFXlbp0O5qKYMUFYzUZycoyXWMtwP23NThRzr rgcoo7SHGJoaR4mzVo0hATqSChCD2kjnf02DjNhkPTUWGnnLzcWiTMoTBhyDIKnEcY FObgg9nvPuY3Ov/Z/vQmA8Nabi/Dpn9Q9hM1ip+c= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 06/11] v4l: subdev: add stream based configuration Date: Fri, 7 May 2021 15:35:53 +0300 Message-Id: <20210507123558.146948-7-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add support to manage configurations (format, crop, compose) per stream, instead of per pad. This is accomplished with data structures that hold an array of all subdev's stream configurations. The number of streams can vary at runtime based on routing. Every time the routing is changed, the stream configurations need to be re-initialized. TODO: use init/deinit instead of alloc/free? Signed-off-by: Tomi Valkeinen --- drivers/media/v4l2-core/v4l2-subdev.c | 61 +++++++++++++++++++++++++++ include/media/v4l2-subdev.h | 19 +++++++++ 2 files changed, 80 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 7b40bf34f8a3..0d2c39aabfc4 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -1101,3 +1101,64 @@ void v4l2_subdev_notify_event(struct v4l2_subdev *sd, v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT, (void *)ev); } EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event); + +void v4l2_free_stream_configs(struct v4l2_subdev_stream_configs *stream_configs) +{ + kvfree(stream_configs->configs); + stream_configs->num_configs = 0; +} +EXPORT_SYMBOL_GPL(v4l2_free_stream_configs); + +int v4l2_alloc_stream_configs(struct v4l2_subdev_stream_configs *stream_configs, + const struct v4l2_subdev_krouting *routing) +{ + u32 num_configs = 0; + unsigned int i; + u32 format_idx = 0; + + v4l2_free_stream_configs(stream_configs); + + /* Count number of formats needed */ + for (i = 0; i < routing->num_routes; ++i) { + struct v4l2_subdev_route *route = &routing->routes[i]; + + if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + /* Each route needs a format on both ends of the route */ + num_configs += 2; + } + + if (num_configs) { + stream_configs->configs = + kvcalloc(num_configs, sizeof(*stream_configs->configs), + GFP_KERNEL); + + if (!stream_configs->configs) + return -ENOMEM; + + stream_configs->num_configs = num_configs; + } + + /* Fill in the 'pad' and stream' value for each item in the array from the routing table */ + for (i = 0; i < routing->num_routes; ++i) { + struct v4l2_subdev_route *route = &routing->routes[i]; + u32 idx; + + if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + idx = format_idx++; + + stream_configs->configs[idx].pad = route->sink_pad; + stream_configs->configs[idx].stream = route->sink_stream; + + idx = format_idx++; + + stream_configs->configs[idx].pad = route->source_pad; + stream_configs->configs[idx].stream = route->source_stream; + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_alloc_stream_configs); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 63a36eead7dc..36be66e18abc 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -665,6 +665,20 @@ struct v4l2_subdev_pad_config { struct v4l2_rect try_compose; }; +struct v4l2_subdev_stream_config { + u32 pad; + u32 stream; + + struct v4l2_mbus_framefmt fmt; + struct v4l2_rect crop; + struct v4l2_rect compose; +}; + +struct v4l2_subdev_stream_configs { + u32 num_configs; + struct v4l2_subdev_stream_config *configs; +}; + /** * struct v4l2_subdev_krouting - subdev routing table * @@ -1267,4 +1281,9 @@ void v4l2_subdev_cpy_routing(struct v4l2_subdev_krouting *dst, bool v4l2_subdev_has_route(struct v4l2_subdev_krouting *routing, unsigned int pad0, unsigned int pad1); +void v4l2_free_stream_configs(struct v4l2_subdev_stream_configs *stream_configs); + +int v4l2_alloc_stream_configs(struct v4l2_subdev_stream_configs *stream_configs, + const struct v4l2_subdev_krouting *routing); + #endif From patchwork Fri May 7 12:35:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432328 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EE0CBC43461 for ; Fri, 7 May 2021 12:37:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BF2A361466 for ; Fri, 7 May 2021 12:37:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236772AbhEGMiE (ORCPT ); Fri, 7 May 2021 08:38:04 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:59748 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236685AbhEGMiD (ORCPT ); Fri, 7 May 2021 08:38:03 -0400 Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E96003F2; Fri, 7 May 2021 14:37:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391022; bh=hu4FW84LuuwUHNiwKGaZeYxPdvq0RWRAGswr5ej6tHw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=X+QjtHVinn7P30micvDwel/2XVfPxtwGyPRCQZX9puSxayTokfxgRt3IdtsedErJ5 zs5tJ4vDdHtqyVFOqUN7pdiKfJHvmGnIKPP44OUvEQoq9KmjHseIgBUNctv0QArtjq fZodwF/JfDLiXw09k5daSIf8s3TyMAHsvUuPbVPI= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 07/11] v4l: subdev: add 'stream' to subdev ioctls Date: Fri, 7 May 2021 15:35:54 +0300 Message-Id: <20210507123558.146948-8-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add 'stream' field to all subdev configuration related ioctls. Signed-off-by: Tomi Valkeinen --- include/uapi/linux/v4l2-subdev.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h index f20491e1f53f..03ef2292f61b 100644 --- a/include/uapi/linux/v4l2-subdev.h +++ b/include/uapi/linux/v4l2-subdev.h @@ -50,7 +50,8 @@ struct v4l2_subdev_format { __u32 which; __u32 pad; struct v4l2_mbus_framefmt format; - __u32 reserved[8]; + __u32 stream; + __u32 reserved[7]; }; /** @@ -88,7 +89,8 @@ struct v4l2_subdev_mbus_code_enum { __u32 code; __u32 which; __u32 flags; - __u32 reserved[7]; + __u32 stream; + __u32 reserved[6]; }; /** @@ -112,7 +114,8 @@ struct v4l2_subdev_frame_size_enum { __u32 min_height; __u32 max_height; __u32 which; - __u32 reserved[8]; + __u32 stream; + __u32 reserved[7]; }; /** @@ -124,7 +127,8 @@ struct v4l2_subdev_frame_size_enum { struct v4l2_subdev_frame_interval { __u32 pad; struct v4l2_fract interval; - __u32 reserved[9]; + __u32 stream; + __u32 reserved[8]; }; /** @@ -146,7 +150,8 @@ struct v4l2_subdev_frame_interval_enum { __u32 height; struct v4l2_fract interval; __u32 which; - __u32 reserved[8]; + __u32 stream; + __u32 reserved[7]; }; /** @@ -170,7 +175,8 @@ struct v4l2_subdev_selection { __u32 target; __u32 flags; struct v4l2_rect r; - __u32 reserved[8]; + __u32 stream; + __u32 reserved[7]; }; /** From patchwork Fri May 7 12:35:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432734 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EAC3BC43460 for ; Fri, 7 May 2021 12:37:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B3CA961464 for ; Fri, 7 May 2021 12:37:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236793AbhEGMiF (ORCPT ); Fri, 7 May 2021 08:38:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59850 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236685AbhEGMiE (ORCPT ); Fri, 7 May 2021 08:38:04 -0400 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 39D52C061574 for ; Fri, 7 May 2021 05:37:05 -0700 (PDT) Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 031E2E41; Fri, 7 May 2021 14:37:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391023; bh=1Dhb8SctwCZVZ3miQx9CuCIjv/e5Cr0Qnos3kAyGXp4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=obuJlJrQ5DarIi3YUeLn4osOOC4g5wWK9r84DDdIPvKFZWYIbg0x5hvGZo9kzBf+P XB9S5fb4gn7sd9FrxlaD5yO1pzbTC4V780FE6uOxz4uOautCQtcGvUgYUCCdeSDZOn cYYEn/Y6UHpry2DDSkc+2XFxFtVhr4WZcy5rTWPY= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 08/11] v4l: subdev: use streams in v4l2_subdev_link_validate() Date: Fri, 7 May 2021 15:35:55 +0300 Message-Id: <20210507123558.146948-9-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Update v4l2_subdev_link_validate() to use routing and streams for validation. Signed-off-by: Tomi Valkeinen --- drivers/media/v4l2-core/v4l2-subdev.c | 184 +++++++++++++++++++++++--- 1 file changed, 166 insertions(+), 18 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 0d2c39aabfc4..52e4290aa8a2 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -894,6 +895,7 @@ EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default); static int v4l2_subdev_link_validate_get_format(struct media_pad *pad, + u32 stream, struct v4l2_subdev_format *fmt) { if (is_media_entity_v4l2_subdev(pad->entity)) { @@ -902,6 +904,7 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad, fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE; fmt->pad = pad->index; + fmt->stream = stream; return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt); } @@ -1001,31 +1004,176 @@ bool v4l2_subdev_has_route(struct v4l2_subdev_krouting *routing, } EXPORT_SYMBOL_GPL(v4l2_subdev_has_route); +static int cmp_u32(const void *a, const void *b) +{ + u32 a32 = *(u32 *)a; + u32 b32 = *(u32 *)b; + + return a32 > b32 ? 1 : (a32 < b32 ? -1 : 0); +} + int v4l2_subdev_link_validate(struct media_link *link) { - struct v4l2_subdev *sink; - struct v4l2_subdev_format sink_fmt, source_fmt; - int rval; + int ret; + unsigned int i; - rval = v4l2_subdev_link_validate_get_format( - link->source, &source_fmt); - if (rval < 0) - return 0; + struct v4l2_subdev *source_subdev = + media_entity_to_v4l2_subdev(link->source->entity); + struct v4l2_subdev *sink_subdev = + media_entity_to_v4l2_subdev(link->sink->entity); + struct device *dev = sink_subdev->entity.graph_obj.mdev->dev; - rval = v4l2_subdev_link_validate_get_format( - link->sink, &sink_fmt); - if (rval < 0) - return 0; + struct v4l2_subdev_krouting routing; - sink = media_entity_to_v4l2_subdev(link->sink->entity); + static const u32 default_streams[] = { 0 }; - rval = v4l2_subdev_call(sink, pad, link_validate, link, - &source_fmt, &sink_fmt); - if (rval != -ENOIOCTLCMD) - return rval; + u32 num_source_streams = 0; + const u32 *source_streams; + u32 num_sink_streams = 0; + const u32 *sink_streams; + + dev_dbg(dev, "validating link \"%s\":%u -> \"%s\":%u\n", + link->source->entity->name, link->source->index, + link->sink->entity->name, link->sink->index); + + /* Get source streams */ + + memset(&routing, 0, sizeof(routing)); + + ret = v4l2_subdev_get_routing(source_subdev, NULL, &routing); + + if (ret && ret != -ENOIOCTLCMD) + return ret; + + if (ret == -ENOIOCTLCMD) { + num_source_streams = 1; + source_streams = default_streams; + } else { + u32 *streams; + + streams = kmalloc_array(routing.num_routes, sizeof(u32), + GFP_KERNEL); + + for (i = 0; i < routing.num_routes; ++i) { + struct v4l2_subdev_route *route = &routing.routes[i]; + + if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + if (route->source_pad == link->source->index) + streams[num_source_streams++] = + route->source_stream; + } + + sort(streams, num_source_streams, sizeof(u32), &cmp_u32, NULL); + + source_streams = streams; + + v4l2_subdev_free_routing(&routing); + } + + /* Get sink streams */ + + memset(&routing, 0, sizeof(routing)); + + ret = v4l2_subdev_get_routing(sink_subdev, NULL, &routing); + + if (ret && ret != -ENOIOCTLCMD) + return ret; + + if (ret == -ENOIOCTLCMD) { + num_sink_streams = 1; + sink_streams = default_streams; + } else { + u32 *streams; - return v4l2_subdev_link_validate_default( - sink, link, &source_fmt, &sink_fmt); + streams = kmalloc_array(routing.num_routes, sizeof(u32), + GFP_KERNEL); + + for (i = 0; i < routing.num_routes; ++i) { + struct v4l2_subdev_route *route = &routing.routes[i]; + + if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + if (route->sink_pad == link->sink->index) + streams[num_sink_streams++] = + route->sink_stream; + } + + sort(streams, num_sink_streams, sizeof(u32), &cmp_u32, NULL); + + sink_streams = streams; + + v4l2_subdev_free_routing(&routing); + } + + if (num_source_streams != num_sink_streams) { + dev_err(dev, + "Sink and source stream count mismatch: %d vs %d\n", + num_source_streams, num_sink_streams); + return -EINVAL; + } + + /* Validate source and sink stream formats */ + + for (i = 0; i < num_source_streams; ++i) { + struct v4l2_subdev_format sink_fmt, source_fmt; + u32 stream; + int ret; + + if (source_streams[i] != sink_streams[i]) { + dev_err(dev, "Sink and source streams do not match\n"); + return -EINVAL; + } + + stream = source_streams[i]; + + dev_dbg(dev, "validating stream \"%s\":%u:%u -> \"%s\":%u:%u\n", + link->source->entity->name, link->source->index, stream, + link->sink->entity->name, link->sink->index, stream); + + ret = v4l2_subdev_link_validate_get_format(link->source, stream, + &source_fmt); + if (ret < 0) { + dev_err(dev, "Failed to get format for \"%s\":%u:%u\n", + link->source->entity->name, link->source->index, + stream); + return ret; + } + + ret = v4l2_subdev_link_validate_get_format(link->sink, stream, + &sink_fmt); + if (ret < 0) { + dev_err(dev, "Failed to get format for \"%s\":%u:%u\n", + link->sink->entity->name, link->sink->index, + stream); + return ret; + } + + /* TODO: add stream number to link_validate() */ + ret = v4l2_subdev_call(sink_subdev, pad, link_validate, link, + &source_fmt, &sink_fmt); + if (!ret) + continue; + + if (ret != -ENOIOCTLCMD) + return ret; + + ret = v4l2_subdev_link_validate_default(sink_subdev, link, + &source_fmt, &sink_fmt); + + if (ret) + return ret; + } + + if (source_streams != default_streams) + kfree(source_streams); + + if (sink_streams != default_streams) + kfree(sink_streams); + + return 0; } EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate); From patchwork Fri May 7 12:35:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432327 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8BDA8C43462 for ; Fri, 7 May 2021 12:37:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5711E61468 for ; Fri, 7 May 2021 12:37:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236820AbhEGMiG (ORCPT ); Fri, 7 May 2021 08:38:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236685AbhEGMiF (ORCPT ); Fri, 7 May 2021 08:38:05 -0400 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 13AEAC061574 for ; Fri, 7 May 2021 05:37:06 -0700 (PDT) Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EDEC3ACF; Fri, 7 May 2021 14:37:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391024; bh=ujWbShictQzSPtJxmY+BOuJqQsuCDncrDAXqtk/0Mfc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uA4xeSC/mCA1pvyI4RsFEpjZl8CFD3jh8LSZXTl+QSvaYeYwyFFQRhhUd4oad9LWO UTNWKmPJJgPWiolYUkkbwsd2iPzdEC3tJ7PnLErkO2vin9iozkbz7SLlzjxRLTnn4n 7bO+7RQDLQRudhHj4bk7iI2gHleFs1rMpVgfFplE= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 09/11] v4l: subdev: add routing & stream config to v4l2_subdev_state Date: Fri, 7 May 2021 15:35:56 +0300 Message-Id: <20210507123558.146948-10-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add routing and stream_configs to struct v4l2_subdev_state. This lets the drivers to implement V4L2_SUBDEV_FORMAT_TRY support for routing and the stream configurations. Signed-off-by: Tomi Valkeinen --- drivers/media/v4l2-core/v4l2-subdev.c | 3 +++ include/media/v4l2-subdev.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 52e4290aa8a2..0acc2607b78c 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -1216,6 +1216,9 @@ EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_state); void v4l2_subdev_free_state(struct v4l2_subdev_state *state) { + v4l2_subdev_free_routing(&state->routing); + v4l2_free_stream_configs(&state->stream_configs); + kvfree(state->pads); kvfree(state); } diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 36be66e18abc..1c3de4a0606e 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -706,6 +706,9 @@ struct v4l2_subdev_krouting { */ struct v4l2_subdev_state { struct v4l2_subdev_pad_config *pads; + + struct v4l2_subdev_krouting routing; + struct v4l2_subdev_stream_configs stream_configs; }; /** From patchwork Fri May 7 12:35:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432733 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 689EFC433B4 for ; Fri, 7 May 2021 12:37:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 32AC661463 for ; Fri, 7 May 2021 12:37:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236827AbhEGMiH (ORCPT ); Fri, 7 May 2021 08:38:07 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:59808 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236794AbhEGMiG (ORCPT ); Fri, 7 May 2021 08:38:06 -0400 Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0C03ABBA; Fri, 7 May 2021 14:37:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391025; bh=T9y0lwkVpTBvak2wxtK0+frKPsFgMQzQ1QwRKrYqRG8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jjfDJiCFVdHPj9AksJ+gnABuZhSqyUWHLpHtU8GTs+mLRBkQDyvh+xAXUSZjwP9xi JJGKwCwn4+wDOyIhLX70QETg7XeOfAtmPOKChM14Qyy/mVP2bTkCf1EAe3+o7nLH8M rUi6r+yuY3lV1q7FuNJv/tg0+52a0lYDBeMIwqSw= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 10/11] v4l: subdev: add V4L2_SUBDEV_FL_MULTIPLEXED Date: Fri, 7 May 2021 15:35:57 +0300 Message-Id: <20210507123558.146948-11-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add V4L2_SUBDEV_FL_MULTIPLEXED, which indicates that the subdev supports routing and per-stream configuration. These drivers do not need the old pad based configuration, so we can skip the allocation in v4l2_subdev_alloc_state(). Signed-off-by: Tomi Valkeinen --- drivers/media/v4l2-core/v4l2-subdev.c | 3 ++- include/media/v4l2-subdev.h | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 0acc2607b78c..f5cca45becf4 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -1188,7 +1188,8 @@ struct v4l2_subdev_state *v4l2_subdev_alloc_state(struct v4l2_subdev *sd) goto err; } - if (sd->entity.num_pads) { + /* Drivers that support streams do not need the legacy pad config */ + if (!(sd->flags & V4L2_SUBDEV_FL_MULTIPLEXED) && sd->entity.num_pads) { state->pads = kvmalloc_array(sd->entity.num_pads, sizeof(*state->pads), GFP_KERNEL | __GFP_ZERO); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 1c3de4a0606e..cc9953d88ce2 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -900,6 +900,12 @@ struct v4l2_subdev_internal_ops { * should set this flag. */ #define V4L2_SUBDEV_FL_HAS_EVENTS (1U << 3) +/* + * Set this flag if this subdev supports multiplexed streams. This means + * that the driver supports routing and handles the stream parameter in its + * v4l2_subdev_pad_ops handlers. + */ +#define V4L2_SUBDEV_FL_MULTIPLEXED (1U << 4) struct regulator_bulk_data; From patchwork Fri May 7 12:35:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 432326 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 56A02C433ED for ; Fri, 7 May 2021 12:37:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2537D61469 for ; Fri, 7 May 2021 12:37:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236829AbhEGMiI (ORCPT ); Fri, 7 May 2021 08:38:08 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:59830 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236825AbhEGMiH (ORCPT ); Fri, 7 May 2021 08:38:07 -0400 Received: from deskari.lan (91-157-208-71.elisa-laajakaista.fi [91.157.208.71]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 07C948A1; Fri, 7 May 2021 14:37:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1620391026; bh=zUd3j8s03e3L+pLIAwivakx8Qe56qIE1R++bB3Nv+4c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E3w+hXCX6IHGRej8qJDM39cCGLUMWP2Rly2BhJYIkp6nddTejbSP1xUTLkdSPgg6R HlHNC9BfNfb2rHcm6uwRLOYFYg4TmuNywBQPhvS7EvikPgmN7Wg+E+u2KPPKUmPIHy XxnaAQtb5AttcBaeyXK+zuFNrSY0p815Jyng8a9M= From: Tomi Valkeinen To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, Jacopo Mondi , Laurent Pinchart , niklas.soderlund+renesas@ragnatech.se Cc: Mauro Carvalho Chehab , Hans Verkuil , Pratyush Yadav , john.wei@mediatek.com, Tomi Valkeinen , Kieran Bingham Subject: [RFC 11/11] media: ti-vpe: cal: add multistream support Date: Fri, 7 May 2021 15:35:58 +0300 Message-Id: <20210507123558.146948-12-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> References: <20210507123558.146948-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add routing and stream_config support to CAL driver. Signed-off-by: Tomi Valkeinen --- drivers/media/platform/ti-vpe/cal-camerarx.c | 322 ++++++++++++++++--- drivers/media/platform/ti-vpe/cal-video.c | 103 +++++- drivers/media/platform/ti-vpe/cal.c | 34 +- drivers/media/platform/ti-vpe/cal.h | 12 +- 4 files changed, 399 insertions(+), 72 deletions(-) diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c index 5b41ba493599..39a2250a2789 100644 --- a/drivers/media/platform/ti-vpe/cal-camerarx.c +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c @@ -49,15 +49,33 @@ static s64 cal_camerarx_get_ext_link_freq(struct cal_camerarx *phy) { struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 = &phy->endpoint.bus.mipi_csi2; u32 num_lanes = mipi_csi2->num_data_lanes; - const struct cal_format_info *fmtinfo; u32 bpp; s64 freq; - fmtinfo = cal_format_by_code(phy->formats[CAL_CAMERARX_PAD_SINK].code); - if (!fmtinfo) + /* + * With multistream input we don't have bpp, and cannot use + * V4L2_CID_PIXEL_RATE. Passing 0 as bpp causes v4l2_get_link_freq() + * to return an error if it falls back to V4L2_CID_PIXEL_RATE. + */ + + if (phy->stream_configs.num_configs == 0) return -EINVAL; - bpp = fmtinfo->bpp; + if (phy->stream_configs.num_configs > 2) { + bpp = 0; + } else { + const struct cal_format_info *fmtinfo; + struct v4l2_mbus_framefmt *fmt; + + /* The first format is for the sink */ + fmt = &phy->stream_configs.configs[0].fmt; + + fmtinfo = cal_format_by_code(fmt->code); + if (!fmtinfo) + return -EINVAL; + + bpp = fmtinfo->bpp; + } freq = v4l2_get_link_freq(phy->source->ctrl_handler, bpp, 2 * num_lanes); if (freq < 0) { @@ -619,19 +637,104 @@ static inline struct cal_camerarx *to_cal_camerarx(struct v4l2_subdev *sd) return container_of(sd, struct cal_camerarx, subdev); } -static struct v4l2_mbus_framefmt * -cal_camerarx_get_pad_format(struct cal_camerarx *phy, - struct v4l2_subdev_state *cfg, - unsigned int pad, u32 which) -{ - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_format(&phy->subdev, cfg, pad); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &phy->formats[pad]; - default: +struct cal_camerarx * +cal_camerarx_get_phy_from_entity(struct media_entity *entity) +{ + struct v4l2_subdev *sd; + + sd = media_entity_to_v4l2_subdev(entity); + if (!sd) return NULL; + + return to_cal_camerarx(sd); +} + +static struct v4l2_subdev_krouting * +cal_camerarx_get_routing_table(struct cal_camerarx *phy, + struct v4l2_subdev_state *state, u32 which) +{ + if (which == V4L2_SUBDEV_FORMAT_ACTIVE) + return &phy->routing; + else + return &state->routing; +} + +static struct v4l2_subdev_stream_configs * +cal_camerarx_get_stream_configs(struct cal_camerarx *phy, + struct v4l2_subdev_state *state, u32 which) +{ + if (which == V4L2_SUBDEV_FORMAT_ACTIVE) + return &phy->stream_configs; + else + return &state->stream_configs; +} + +struct v4l2_mbus_framefmt * +cal_camerarx_get_stream_format(struct cal_camerarx *phy, + struct v4l2_subdev_state *state, + unsigned int pad, u32 stream, u32 which) +{ + struct v4l2_subdev_stream_configs *stream_configs; + unsigned int i; + + stream_configs = cal_camerarx_get_stream_configs(phy, state, which); + + for (i = 0; i < stream_configs->num_configs; ++i) { + if (stream_configs->configs[i].pad == pad && + stream_configs->configs[i].stream == stream) + return &stream_configs->configs[i].fmt; + } + + return NULL; +} + +static int cal_camerarx_find_opposite_end(struct v4l2_subdev_krouting *routing, + u32 pad, u32 stream, u32 *other_pad, + u32 *other_stream) +{ + unsigned int i; + + for (i = 0; i < routing->num_routes; ++i) { + struct v4l2_subdev_route *route = &routing->routes[i]; + + if (cal_rx_pad_is_source(pad)) { + if (route->source_pad == pad && + route->source_stream == stream) { + *other_pad = route->sink_pad; + *other_stream = route->sink_stream; + return 0; + } + } else { + if (route->sink_pad == pad && + route->sink_stream == stream) { + *other_pad = route->source_pad; + *other_stream = route->source_stream; + return 0; + } + } } + + return -EINVAL; +} + +static struct v4l2_mbus_framefmt * +cal_camerarx_get_opposite_stream_format(struct cal_camerarx *phy, + struct v4l2_subdev_state *state, + u32 pad, u32 stream, u32 which) +{ + struct v4l2_subdev_krouting *routing; + u32 other_pad, other_stream; + int ret; + + routing = cal_camerarx_get_routing_table(phy, state, which); + + ret = cal_camerarx_find_opposite_end(routing, pad, stream, &other_pad, + &other_stream); + if (ret) + return NULL; + + return cal_camerarx_get_stream_format(phy, state, other_pad, + other_stream, which); } static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable) @@ -652,7 +755,7 @@ static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable) } static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code) { struct cal_camerarx *phy = to_cal_camerarx(sd); @@ -669,9 +772,15 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd, goto out; } - fmt = cal_camerarx_get_pad_format(phy, cfg, - CAL_CAMERARX_PAD_SINK, - code->which); + fmt = cal_camerarx_get_opposite_stream_format(phy, state, + code->pad, code->stream, + code->which); + + if (!fmt) { + r = -EINVAL; + goto out; + } + code->code = fmt->code; } else { if (code->index >= cal_num_formats) { @@ -689,7 +798,7 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd, } static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_state *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_frame_size_enum *fse) { struct cal_camerarx *phy = to_cal_camerarx(sd); @@ -705,9 +814,14 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd, if (cal_rx_pad_is_source(fse->pad)) { struct v4l2_mbus_framefmt *fmt; - fmt = cal_camerarx_get_pad_format(phy, cfg, - CAL_CAMERARX_PAD_SINK, - fse->which); + fmt = cal_camerarx_get_opposite_stream_format( + phy, state, fse->pad, fse->stream, fse->which); + + if (!fmt) { + r = -EINVAL; + goto out; + } + if (fse->code != fmt->code) { r = -EINVAL; goto out; @@ -739,7 +853,7 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd, } static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format) { struct cal_camerarx *phy = to_cal_camerarx(sd); @@ -747,7 +861,14 @@ static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd, mutex_lock(&phy->mutex); - fmt = cal_camerarx_get_pad_format(phy, cfg, format->pad, format->which); + fmt = cal_camerarx_get_stream_format(phy, state, format->pad, + format->stream, format->which); + + if (!fmt) { + mutex_unlock(&phy->mutex); + return -EINVAL; + } + format->format = *fmt; mutex_unlock(&phy->mutex); @@ -756,17 +877,18 @@ static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd, } static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format) { struct cal_camerarx *phy = to_cal_camerarx(sd); const struct cal_format_info *fmtinfo; struct v4l2_mbus_framefmt *fmt; unsigned int bpp; + int ret = 0; /* No transcoding, source and sink formats must match. */ if (cal_rx_pad_is_source(format->pad)) - return cal_camerarx_sd_get_fmt(sd, cfg, format); + return cal_camerarx_sd_get_fmt(sd, state, format); /* * Default to the first format if the requested media bus code isn't @@ -792,39 +914,124 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd, mutex_lock(&phy->mutex); - fmt = cal_camerarx_get_pad_format(phy, cfg, CAL_CAMERARX_PAD_SINK, - format->which); + fmt = cal_camerarx_get_stream_format(phy, state, format->pad, + format->stream, format->which); + if (!fmt) { + ret = -EINVAL; + goto out; + } + *fmt = format->format; - fmt = cal_camerarx_get_pad_format(phy, cfg, CAL_CAMERARX_PAD_FIRST_SOURCE, - format->which); + fmt = cal_camerarx_get_opposite_stream_format(phy, state, format->pad, + format->stream, + format->which); + if (!fmt) { + ret = -EINVAL; + goto out; + } + *fmt = format->format; +out: mutex_unlock(&phy->mutex); + return ret; +} + +static int cal_camerarx_sd_get_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *routing) +{ + struct cal_camerarx *phy = to_cal_camerarx(sd); + struct v4l2_subdev_krouting *src; + + src = cal_camerarx_get_routing_table(phy, state, routing->which); + + if (routing->num_routes < src->num_routes) { + routing->num_routes = src->num_routes; + return -ENOSPC; + } + + v4l2_subdev_cpy_routing(routing, src); + + return 0; +} + +static void cal_camerarx_init_formats(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 which) +{ + struct cal_camerarx *phy = to_cal_camerarx(sd); + + static const struct v4l2_mbus_framefmt format = { + .width = 640, + .height = 480, + .code = MEDIA_BUS_FMT_UYVY8_2X8, + .field = V4L2_FIELD_NONE, + .colorspace = V4L2_COLORSPACE_SRGB, + .ycbcr_enc = V4L2_YCBCR_ENC_601, + .quantization = V4L2_QUANTIZATION_LIM_RANGE, + .xfer_func = V4L2_XFER_FUNC_SRGB, + }; + + struct v4l2_subdev_stream_configs *stream_configs; + unsigned int i; + + stream_configs = cal_camerarx_get_stream_configs(phy, state, which); + + for (i = 0; i < stream_configs->num_configs; ++i) + stream_configs->configs[i].fmt = format; +} + +static int cal_camerarx_sd_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *routing) +{ + struct cal_camerarx *phy = to_cal_camerarx(sd); + int ret; + struct v4l2_subdev_krouting *dst; + struct v4l2_subdev_stream_configs *stream_configs; + + dst = cal_camerarx_get_routing_table(phy, state, routing->which); + stream_configs = + cal_camerarx_get_stream_configs(phy, state, routing->which); + + ret = v4l2_subdev_dup_routing(dst, routing); + if (ret) + return ret; + + ret = v4l2_alloc_stream_configs(stream_configs, dst); + if (ret) + return ret; + + /* Initialize stream formats */ + cal_camerarx_init_formats(sd, state, routing->which); + return 0; } static int cal_camerarx_sd_init_cfg(struct v4l2_subdev *sd, - struct v4l2_subdev_state *cfg) -{ - struct v4l2_subdev_format format = { - .which = cfg ? V4L2_SUBDEV_FORMAT_TRY - : V4L2_SUBDEV_FORMAT_ACTIVE, - .pad = CAL_CAMERARX_PAD_SINK, - .format = { - .width = 640, - .height = 480, - .code = MEDIA_BUS_FMT_UYVY8_2X8, - .field = V4L2_FIELD_NONE, - .colorspace = V4L2_COLORSPACE_SRGB, - .ycbcr_enc = V4L2_YCBCR_ENC_601, - .quantization = V4L2_QUANTIZATION_LIM_RANGE, - .xfer_func = V4L2_XFER_FUNC_SRGB, - }, + struct v4l2_subdev_state *state) +{ + u32 which = state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + + struct v4l2_subdev_route routes[] = { { + .sink_pad = 0, + .sink_stream = 0, + .source_pad = 1, + .source_stream = 0, + .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, + } }; + + struct v4l2_subdev_krouting routing = { + .which = which, + .num_routes = 1, + .routes = routes, }; - return cal_camerarx_sd_set_fmt(sd, cfg, &format); + /* Initialize routing to single route to the fist source pad */ + return cal_camerarx_sd_set_routing(sd, state, &routing); } static const struct v4l2_subdev_video_ops cal_camerarx_video_ops = { @@ -837,6 +1044,8 @@ static const struct v4l2_subdev_pad_ops cal_camerarx_pad_ops = { .enum_frame_size = cal_camerarx_sd_enum_frame_size, .get_fmt = cal_camerarx_sd_get_fmt, .set_fmt = cal_camerarx_sd_set_fmt, + .get_routing = cal_camerarx_sd_get_routing, + .set_routing = cal_camerarx_sd_set_routing, }; static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = { @@ -844,8 +1053,18 @@ static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = { .pad = &cal_camerarx_pad_ops, }; +static bool cal_camerarx_has_route(struct media_entity *entity, unsigned int pad0, + unsigned int pad1) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct cal_camerarx *phy = to_cal_camerarx(sd); + + return v4l2_subdev_has_route(&phy->routing, pad0, pad1); +} + static struct media_entity_operations cal_camerarx_media_ops = { .link_validate = v4l2_subdev_link_validate, + .has_route = cal_camerarx_has_route, }; /* ------------------------------------------------------------------ @@ -897,11 +1116,12 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, sd = &phy->subdev; v4l2_subdev_init(sd, &cal_camerarx_subdev_ops); sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; - sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_MULTIPLEXED; snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance); sd->dev = cal->dev; phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + for (i = CAL_CAMERARX_PAD_FIRST_SOURCE; i < CAL_CAMERARX_NUM_PADS; ++i) phy->pads[i].flags = MEDIA_PAD_FL_SOURCE; sd->entity.ops = &cal_camerarx_media_ops; @@ -921,6 +1141,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, return phy; error: + v4l2_subdev_free_routing(&phy->routing); + v4l2_free_stream_configs(&phy->stream_configs); media_entity_cleanup(&phy->subdev.entity); kfree(phy); return ERR_PTR(ret); @@ -932,6 +1154,8 @@ void cal_camerarx_destroy(struct cal_camerarx *phy) return; v4l2_device_unregister_subdev(&phy->subdev); + v4l2_subdev_free_routing(&phy->routing); + v4l2_free_stream_configs(&phy->stream_configs); media_entity_cleanup(&phy->subdev.entity); of_node_put(phy->source_ep_node); of_node_put(phy->source_node); diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c index 8ecae7dc2774..234af40a24fa 100644 --- a/drivers/media/platform/ti-vpe/cal-video.c +++ b/drivers/media/platform/ti-vpe/cal-video.c @@ -693,7 +693,11 @@ static int cal_video_check_format(struct cal_ctx *ctx) if (!remote_pad) return -ENODEV; - format = &ctx->phy->formats[remote_pad->index]; + format = cal_camerarx_get_stream_format(ctx->phy, NULL, + remote_pad->index, 0, + V4L2_SUBDEV_FORMAT_ACTIVE); + if (!format) + return -EINVAL; if (ctx->fmtinfo->code != format->code || ctx->v_fmt.fmt.pix.height != format->height || @@ -711,6 +715,48 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) dma_addr_t addr; int ret; + if (cal_mc_api) { + struct v4l2_subdev_route *route = NULL; + struct media_pad *remote_pad; + unsigned int i; + + /* Find the PHY connected to this video device */ + + remote_pad = media_entity_remote_pad(&ctx->pad); + if (!remote_pad) { + ctx_err(ctx, "Context not connected\n"); + ret = -ENODEV; + goto error_release_buffers; + } + + ctx->phy = cal_camerarx_get_phy_from_entity(remote_pad->entity); + + /* Find the stream */ + + for (i = 0; i < ctx->phy->routing.num_routes; ++i) { + struct v4l2_subdev_route *r = + &ctx->phy->routing.routes[i]; + + if (!(r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + if (r->source_pad != remote_pad->index) + continue; + + route = r; + + break; + } + + if (!route) { + ctx_err(ctx, "Failed to find route\n"); + ret = -ENODEV; + goto error_release_buffers; + } + + ctx->stream = route->sink_stream; + } + ret = media_pipeline_start(ctx->vdev.entity.pads, &ctx->phy->pipe); if (ret < 0) { ctx_err(ctx, "Failed to start media pipeline: %d\n", ret); @@ -784,6 +830,9 @@ static void cal_stop_streaming(struct vb2_queue *vq) cal_release_buffers(ctx, VB2_BUF_STATE_ERROR); media_pipeline_stop(ctx->vdev.entity.pads); + + if (cal_mc_api) + ctx->phy = NULL; } static const struct vb2_ops cal_video_qops = { @@ -945,16 +994,48 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx) return ret; } - ret = media_create_pad_link(&ctx->phy->subdev.entity, - CAL_CAMERARX_PAD_FIRST_SOURCE, - &vfd->entity, 0, - MEDIA_LNK_FL_IMMUTABLE | - MEDIA_LNK_FL_ENABLED); - if (ret) { - ctx_err(ctx, "Failed to create media link for context %u\n", - ctx->dma_ctx); - video_unregister_device(vfd); - return ret; + if (cal_mc_api) { + u16 phy_idx; + u16 pad_idx; + + /* Create links from all video nodes to all PHYs */ + + for (phy_idx = 0; phy_idx < ctx->cal->data->num_csi2_phy; ++phy_idx) { + for (pad_idx = 1; pad_idx < CAL_CAMERARX_NUM_PADS; ++pad_idx) { + /* + * Enable only links from video0 to PHY0 pad 1, and + * video1 to PHY1 pad 1. + */ + bool enable = (ctx->dma_ctx == 0 && + phy_idx == 0 && pad_idx == 1) || + (ctx->dma_ctx == 1 && + phy_idx == 1 && pad_idx == 1); + + ret = media_create_pad_link( + &ctx->cal->phy[phy_idx]->subdev.entity, + pad_idx, &vfd->entity, 0, + enable ? MEDIA_LNK_FL_ENABLED : 0); + if (ret) { + ctx_err(ctx, + "Failed to create media link for context %u\n", + ctx->dma_ctx); + video_unregister_device(vfd); + return ret; + } + } + } + } else { + ret = media_create_pad_link( + &ctx->phy->subdev.entity, CAL_CAMERARX_PAD_FIRST_SOURCE, + &vfd->entity, 0, + MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); + if (ret) { + ctx_err(ctx, + "Failed to create media link for context %u\n", + ctx->dma_ctx); + video_unregister_device(vfd); + return ret; + } } ctx_info(ctx, "V4L2 device registered as %s\n", diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index 07386c42574e..c0159637dfdf 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -977,7 +977,6 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst) return NULL; ctx->cal = cal; - ctx->phy = cal->phy[inst]; ctx->dma_ctx = inst; ctx->csi2_ctx = inst; ctx->cport = inst; @@ -1188,18 +1187,33 @@ static int cal_probe(struct platform_device *pdev) } /* Create contexts. */ - for (i = 0; i < cal->data->num_csi2_phy; ++i) { - if (!cal->phy[i]->source_node) - continue; + if (!cal_mc_api) { + for (i = 0; i < cal->data->num_csi2_phy; ++i) { + if (!cal->phy[i]->source_node) + continue; + + cal->ctx[i] = cal_ctx_create(cal, i); + if (!cal->ctx[i]) { + cal_err(cal, "Failed to create context %u\n", i); + ret = -ENODEV; + goto error_context; + } - cal->ctx[i] = cal_ctx_create(cal, i); - if (!cal->ctx[i]) { - cal_err(cal, "Failed to create context %u\n", i); - ret = -ENODEV; - goto error_context; + cal->ctx[i]->phy = cal->phy[i]; + + cal->num_contexts++; } + } else { + for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) { + cal->ctx[i] = cal_ctx_create(cal, i); + if (!cal->ctx[i]) { + cal_err(cal, "Failed to create context %u\n", i); + ret = -ENODEV; + goto error_context; + } - cal->num_contexts++; + cal->num_contexts++; + } } /* Register the media device. */ diff --git a/drivers/media/platform/ti-vpe/cal.h b/drivers/media/platform/ti-vpe/cal.h index 3aea444f8bf8..6626c2a59fc2 100644 --- a/drivers/media/platform/ti-vpe/cal.h +++ b/drivers/media/platform/ti-vpe/cal.h @@ -45,7 +45,7 @@ #define CAL_CAMERARX_PAD_SINK 0 #define CAL_CAMERARX_PAD_FIRST_SOURCE 1 -#define CAL_CAMERARX_NUM_SOURCE_PADS 1 +#define CAL_CAMERARX_NUM_SOURCE_PADS 8 #define CAL_CAMERARX_NUM_PADS (1 + CAL_CAMERARX_NUM_SOURCE_PADS) static inline bool cal_rx_pad_is_sink(u32 pad) @@ -178,12 +178,14 @@ struct cal_camerarx { struct v4l2_subdev subdev; struct media_pad pads[CAL_CAMERARX_NUM_PADS]; - struct v4l2_mbus_framefmt formats[CAL_CAMERARX_NUM_PADS]; /* mutex for camerarx ops */ struct mutex mutex; unsigned int enable_count; + + struct v4l2_subdev_krouting routing; + struct v4l2_subdev_stream_configs stream_configs; }; struct cal_dev { @@ -321,6 +323,7 @@ void cal_quickdump_regs(struct cal_dev *cal); int cal_camerarx_get_remote_frame_desc(struct cal_camerarx *phy, struct v4l2_mbus_frame_desc *fd); +struct cal_camerarx *cal_camerarx_get_phy_from_entity(struct media_entity *entity); void cal_camerarx_disable(struct cal_camerarx *phy); void cal_camerarx_i913_errata(struct cal_camerarx *phy); struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal, @@ -338,4 +341,9 @@ void cal_ctx_v4l2_unregister(struct cal_ctx *ctx); int cal_ctx_v4l2_init(struct cal_ctx *ctx); void cal_ctx_v4l2_cleanup(struct cal_ctx *ctx); +struct v4l2_mbus_framefmt * +cal_camerarx_get_stream_format(struct cal_camerarx *phy, + struct v4l2_subdev_state *state, + unsigned int pad, u32 stream, u32 which); + #endif /* __TI_CAL_H__ */