From nobody Fri Dec 19 18:34:39 2025 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 303BE18D626; Wed, 4 Sep 2024 21:07:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725484081; cv=none; b=iB2Z7CZUnYWTDm+zf/YBi/rgf9EfWDCzbU/xb1rjCSCDlgsikkCA0sYIVjZKDpMlG/5ZrXo5xB96HFllzfKjjR/zgiwBLazqUU85ev0gPUfA8Af17F7lDENJDL45K/1ueGhGz5cFFhw8Gck6YeuqwLa6TlFjtC5VL1UKQI+ccgk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725484081; c=relaxed/simple; bh=I1oNs25s/CngsnNqJwET5V0cEjBj+iPLAzdWDG9ZV40=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KHec8vjxu/KdOaSi7e2CqgN7B936zyXncEydi/J6OajMEzD8p8xlmeku+aO2kRzghMSgH+AGTaKHJK7LRetJwCuwdgwqW29LDkiS2f2cv9FZD+Y8JGbgQnPLkQosDBQ67WDIoEFEFUyWkt4JzrNaVx+ND6hAv99b5vBDOanfgA0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=jQ94xGpr; arc=none smtp.client-ip=209.85.221.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jQ94xGpr" Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-374b25263a3so6930f8f.0; Wed, 04 Sep 2024 14:07:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1725484077; x=1726088877; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=J426v0t4e1crMfA9lHahgdUfXyTzbtJSjN0almmRPYQ=; b=jQ94xGprnb/4py5/WOqGSlV8MQkF0y9s0n5HtrpdGZk73TqR3O1VqzXPPoOUVR1xQB gq2O6iKVd8AL5yRa5sCcoAHhNL+xZyHF+stR3IRoy903aO9zQC+IkJnXd0rhpfAUf2v4 oty2e8y0jCQQx9SIH2PeFL5GFMEn3QEbYmeclJ7EbyCo6E+P+ZJhmxez4OAw3z/FeKih cZ7pkbQom4I5asGwfhe3ILvbKX4rwW+/loITgkG4EwhpbZm8i5liXt7PvEs46+rNuHsO ab+hxIqnpFVY1Qvt6k71suirBckRVjcKwtYj5a1GA1t3x10T6qXQlseub8pNHzIy+RDH dlsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725484077; x=1726088877; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=J426v0t4e1crMfA9lHahgdUfXyTzbtJSjN0almmRPYQ=; b=SVPqu2KzmAjVBPxzt5Y4jHpLBw6BHdd4omc0pd93zoPEVV6D9LeP84iJ14SdLu0+3X pgo95ZgsZmI3H8dZpis3wtnMF88uudZG6lpU7pGDA/pR92bMxX0mAMdXuPyfDC6sTIIy cHNRaKdbK0HkKn65li8EWXJ6kQt/UbLlqTGYR0iWgCBJ6Hafrp3d68eCcSwiAxSqaoNX NT1fb/QTGRYModhBneaspodPMKCf0JzJJzXYNw74fpWmQMbv9IH4ajTvrwH4fxff8csb ZcZYekxElufZUG0zU7XXTbLDrRRgxHEu/pd8+n4zp2pEwkHJCDQM1mqXdGMSKRrXkvFm wTbA== X-Forwarded-Encrypted: i=1; AJvYcCWypNMsgHxBZqD6Imi6hfhm1XMrXHBMxOsljpe4L104RxVfcsU2n2DADH2MhLXN9Y08/jzdSDL9Wjkc1AtOra6Kir4=@vger.kernel.org, AJvYcCXDIYZ4bLGPuFXTtbxsWu/vubn0R6e3a2d+Vx+PjdbJwbwFPz70oVTAmrNHT5JXBnRVD6fQX2A4AV8n1Y8=@vger.kernel.org X-Gm-Message-State: AOJu0Yz3tCIMPCuwsVhQvdD78cW8b0qmusuLzLoi7BUbB9/djFsjCLZp YsLFKde515OqYajNiPq00tK97QJwxOoYDrIoc6aoBsIdq3/Tvw1T X-Google-Smtp-Source: AGHT+IE1GiKVJANdTHXMQYX5WVnza6IY/8YZs4CwJfcbTEBsVHiBMrT8Bto4Xkk/dF2CvYe3e2Pzog== X-Received: by 2002:a05:6000:137a:b0:374:c1f5:affe with SMTP id ffacd0b85a97d-374c1f5b5ebmr9419683f8f.40.1725484077459; Wed, 04 Sep 2024 14:07:57 -0700 (PDT) Received: from prasmi.home ([2a00:23c8:2500:a01:c57c:1e61:792:2ab1]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-42c7a41bdc8sm158821485e9.3.2024.09.04.14.07.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 14:07:56 -0700 (PDT) From: Prabhakar X-Google-Original-From: Prabhakar To: Sakari Ailus , Laurent Pinchart , Kieran Bingham , Tomi Valkeinen , Jacopo Mondi , Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Prabhakar , Biju Das , Fabrizio Castro , Lad Prabhakar Subject: [RFC PATCH 12/12] media: i2c: ov5645: Add virtual channel support Date: Wed, 4 Sep 2024 22:07:19 +0100 Message-Id: <20240904210719.52466-13-prabhakar.mahadev-lad.rj@bp.renesas.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240904210719.52466-1-prabhakar.mahadev-lad.rj@bp.renesas.com> References: <20240904210719.52466-1-prabhakar.mahadev-lad.rj@bp.renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Lad Prabhakar Add routes to configure the virtual channels. Signed-off-by: Lad Prabhakar --- drivers/media/i2c/ov5645.c | 153 ++++++++++++++++++++++++++++--------- 1 file changed, 116 insertions(+), 37 deletions(-) diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index 45762783a19f..cf4a6d8e83e0 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -54,6 +54,7 @@ #define OV5645_TIMING_TC_REG21 0x3821 #define OV5645_SENSOR_MIRROR BIT(1) #define OV5645_MIPI_CTRL00 0x4800 +#define OV5645_REG_DEBUG_MODE 0x4814 #define OV5645_PRE_ISP_TEST_SETTING_1 0x503d #define OV5645_TEST_PATTERN_MASK 0x3 #define OV5645_SET_TEST_PATTERN(x) ((x) & OV5645_TEST_PATTERN_MASK) @@ -65,6 +66,8 @@ #define OV5645_NATIVE_WIDTH 2592 #define OV5645_NATIVE_HEIGHT 1944 =20 +#define OV5645_ROUTES_MAX 4 + /* regulator supplies */ static const char * const ov5645_supply_name[] =3D { "vdddo", /* Digital I/O (1.8V) supply */ @@ -833,25 +836,36 @@ static const struct v4l2_ctrl_ops ov5645_ctrl_ops =3D= { static int ov5645_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *fd) { - const struct v4l2_mbus_framefmt *fmt; struct v4l2_subdev_state *state; + struct v4l2_subdev_route *route; + unsigned int num_routes =3D 0; =20 if (pad !=3D OV5645_PAD_SOURCE) return -EINVAL; =20 state =3D v4l2_subdev_lock_and_get_active_state(sd); - fmt =3D v4l2_subdev_state_get_format(state, OV5645_PAD_SOURCE, 0); - v4l2_subdev_unlock_state(state); =20 - fd->type =3D V4L2_MBUS_FRAME_DESC_TYPE_CSI2; - fd->num_entries =3D 1; + for_each_active_route(&state->routing, route) { + struct v4l2_mbus_frame_desc_entry *entry; + const struct v4l2_mbus_framefmt *fmt; + + fmt =3D v4l2_subdev_state_get_format(state, route->source_pad, + route->source_stream); + + entry =3D &fd->entry[num_routes]; + entry->stream =3D num_routes; + entry->pixelcode =3D fmt->code; =20 - memset(fd->entry, 0, sizeof(fd->entry)); + entry->bus.csi2.vc =3D route->source_stream; + entry->bus.csi2.dt =3D MIPI_CSI2_DT_YUV422_8B; =20 - fd->entry[0].pixelcode =3D fmt->code; - fd->entry[0].stream =3D 0; - fd->entry[0].bus.csi2.vc =3D 0; - fd->entry[0].bus.csi2.dt =3D MIPI_CSI2_DT_YUV422_8B; + num_routes++; + } + + fd->num_entries =3D num_routes; + fd->type =3D V4L2_MBUS_FRAME_DESC_TYPE_CSI2; + + v4l2_subdev_unlock_state(state); =20 return 0; } @@ -923,13 +937,13 @@ static int ov5645_set_format(struct v4l2_subdev *sd, format->format.quantization =3D V4L2_QUANTIZATION_DEFAULT; format->format.xfer_func =3D V4L2_XFER_FUNC_DEFAULT; =20 - __format =3D v4l2_subdev_state_get_format(sd_state, OV5645_PAD_IMAGE); + __format =3D v4l2_subdev_state_get_format(sd_state, OV5645_PAD_IMAGE, 0); *__format =3D format->format; __format->code =3D OV5645_NATIVE_FORMAT; __format->width =3D OV5645_NATIVE_WIDTH; __format->height =3D OV5645_NATIVE_HEIGHT; =20 - __crop =3D v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_IMAGE); + __crop =3D v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_IMAGE, 0); __crop->width =3D format->format.width; __crop->height =3D format->format.height; =20 @@ -937,19 +951,19 @@ static int ov5645_set_format(struct v4l2_subdev *sd, * The compose rectangle models binning, its size is the sensor output * size. */ - compose =3D v4l2_subdev_state_get_compose(sd_state, OV5645_PAD_IMAGE); + compose =3D v4l2_subdev_state_get_compose(sd_state, OV5645_PAD_IMAGE, 0); compose->left =3D 0; compose->top =3D 0; compose->width =3D format->format.width; compose->height =3D format->format.height; =20 - __crop =3D v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_SOURCE); + __crop =3D v4l2_subdev_state_get_crop(sd_state, OV5645_PAD_SOURCE, format= ->stream); __crop->left =3D 0; __crop->top =3D 0; __crop->width =3D format->format.width; __crop->height =3D format->format.height; =20 - __format =3D v4l2_subdev_state_get_format(sd_state, OV5645_PAD_SOURCE); + __format =3D v4l2_subdev_state_get_format(sd_state, OV5645_PAD_SOURCE, fo= rmat->stream); *__format =3D format->format; =20 if (format->which =3D=3D V4L2_SUBDEV_FORMAT_ACTIVE) { @@ -970,43 +984,80 @@ static int ov5645_set_format(struct v4l2_subdev *sd, return 0; } =20 -static int ov5645_init_state(struct v4l2_subdev *subdev, - struct v4l2_subdev_state *sd_state) +static int ov5645_apply_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *routing) { - struct v4l2_subdev_route routes[1] =3D { - { - .sink_pad =3D OV5645_PAD_IMAGE, - .sink_stream =3D 0, - .source_pad =3D OV5645_PAD_SOURCE, - .source_stream =3D 0, - .flags =3D V4L2_SUBDEV_ROUTE_FL_ACTIVE | - V4L2_SUBDEV_ROUTE_FL_IMMUTABLE, - }, - }; - struct v4l2_subdev_krouting routing =3D { - .len_routes =3D ARRAY_SIZE(routes), - .num_routes =3D ARRAY_SIZE(routes), - .routes =3D routes, - }; struct v4l2_subdev_format fmt =3D { .which =3D V4L2_SUBDEV_FORMAT_TRY, .pad =3D OV5645_PAD_SOURCE, - .stream =3D 0, .format =3D { .code =3D OV5645_NATIVE_FORMAT, .width =3D ov5645_mode_info_data[1].width, .height =3D ov5645_mode_info_data[1].height, }, }; + struct v4l2_subdev_route *route; int ret; =20 - ret =3D v4l2_subdev_set_routing(subdev, sd_state, &routing); + if (routing->num_routes > 1) + routing->num_routes =3D 1; + + route =3D &routing->routes[0]; + + if (route->sink_stream > 0 || route->source_stream > 3) + return -EINVAL; + + ret =3D v4l2_subdev_routing_validate(sd, routing, + V4L2_SUBDEV_ROUTING_ONLY_1_TO_1); if (ret) return ret; =20 - ov5645_set_format(subdev, sd_state, &fmt); + ret =3D v4l2_subdev_set_routing(sd, state, routing); + if (ret) + return ret; =20 - return 0; + fmt.stream =3D route->source_stream; + return ov5645_set_format(sd, state, &fmt); +} + +static int ov5645_init_state(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state) +{ + struct v4l2_subdev_route routes[OV5645_ROUTES_MAX] =3D { + { + .sink_pad =3D OV5645_PAD_IMAGE, + .sink_stream =3D 0, + .source_pad =3D OV5645_PAD_SOURCE, + .source_stream =3D 0, + .flags =3D V4L2_SUBDEV_ROUTE_FL_ACTIVE, + }, + { + .sink_pad =3D OV5645_PAD_IMAGE, + .sink_stream =3D 0, + .source_pad =3D OV5645_PAD_SOURCE, + .source_stream =3D 1, + }, + { + .sink_pad =3D OV5645_PAD_IMAGE, + .sink_stream =3D 0, + .source_pad =3D OV5645_PAD_SOURCE, + .source_stream =3D 2, + }, + { + .sink_pad =3D OV5645_PAD_IMAGE, + .sink_stream =3D 0, + .source_pad =3D OV5645_PAD_SOURCE, + .source_stream =3D 3, + }, + }; + struct v4l2_subdev_krouting routing =3D { + .len_routes =3D ARRAY_SIZE(routes), + .num_routes =3D ARRAY_SIZE(routes), + .routes =3D routes, + }; + + return ov5645_apply_routing(subdev, sd_state, &routing); } =20 static int ov5645_get_selection(struct v4l2_subdev *sd, @@ -1016,14 +1067,29 @@ static int ov5645_get_selection(struct v4l2_subdev = *sd, if (sel->target !=3D V4L2_SEL_TGT_CROP) return -EINVAL; =20 - sel->r =3D *v4l2_subdev_state_get_crop(sd_state, sel->pad); + sel->r =3D *v4l2_subdev_state_get_crop(sd_state, sel->pad, sel->stream); return 0; } =20 +static int ov5645_set_virtual_channel(struct ov5645 *ov5645, u8 channel) +{ + int ret; + u8 val; + + ret =3D ov5645_read_reg(ov5645, OV5645_REG_DEBUG_MODE, &val); + if (ret) + return ret; + val &=3D ~(3 << 6); + val |=3D (channel << 6); + + return ov5645_write_reg(ov5645, OV5645_REG_DEBUG_MODE, val); +} + static int ov5645_enable_streams(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, u32 pad, u64 streams_mask) { + struct v4l2_subdev_route *route =3D &state->routing.routes[0]; struct ov5645 *ov5645 =3D to_ov5645(sd); int ret; =20 @@ -1031,6 +1097,10 @@ static int ov5645_enable_streams(struct v4l2_subdev = *sd, if (ret < 0) return ret; =20 + ret =3D ov5645_set_virtual_channel(ov5645, route->source_stream); + if (ret) + goto err_rpm_put; + ret =3D ov5645_set_register_array(ov5645, ov5645->current_mode->data, ov5645->current_mode->data_size); @@ -1083,6 +1153,14 @@ static int ov5645_disable_streams(struct v4l2_subdev= *sd, return ret; } =20 +static int ov5645_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + enum v4l2_subdev_format_whence which, + struct v4l2_subdev_krouting *routing) +{ + return ov5645_apply_routing(sd, state, routing); +} + static const struct v4l2_subdev_video_ops ov5645_video_ops =3D { .s_stream =3D v4l2_subdev_s_stream_helper, }; @@ -1096,6 +1174,7 @@ static const struct v4l2_subdev_pad_ops ov5645_subdev= _pad_ops =3D { .get_selection =3D ov5645_get_selection, .enable_streams =3D ov5645_enable_streams, .disable_streams =3D ov5645_disable_streams, + .set_routing =3D ov5645_set_routing, }; =20 static const struct v4l2_subdev_core_ops ov5645_core_ops =3D { --=20 2.34.1