From patchwork Tue Oct 27 03:19:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68341 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFXS-0022VC-TF; Tue, 27 Oct 2020 03:20:47 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504551AbgJ0DT1 (ORCPT + 1 other); Mon, 26 Oct 2020 23:19:27 -0400 Received: from hqnvemgate26.nvidia.com ([216.228.121.65]:14408 "EHLO hqnvemgate26.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504542AbgJ0DT1 (ORCPT ); Mon, 26 Oct 2020 23:19:27 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate26.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:05 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL105.nvidia.com (172.20.187.12) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:26 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:26 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 01/10] media: tegra-video: Use zero crop settings if subdev has no get_selection Date: Mon, 26 Oct 2020 20:19:14 -0700 Message-ID: <1603768763-25590-2-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768745; bh=ERCkCneZmXlmcSkkK9fGRHPBppn9DardS4Sr/wZUI/E=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=sOXh/7fEqrJnV/vidg8kp7R0h85iGmbLqXyKzGp2Qw3MyJJsutu/NslN6rxYOFxu5 RGASNVlX7rm+sV93TjFDhZ/E23EuRKO9rHqzWpnfkpjhsF0eH+yCk+scKDFByaZY1c dc2lCNdUrmM6GaPrDncVJitRhlpE4uSNtllhqixKZEoJvad33OEebsIt6lwVjy1m3e ZUxd6vxpjtUX1KouLrDOzk2wBAO+R8IA/aTsG8zeknRvF1H4ysBaEtMO3kn3vNr89Y X8Tr8UQRsZzk8RVbsjPhkYBPQvC37cwSz30QZndDwzRjix84V0jU3g5gSgxFwYJo6w XgordTUwoUyyQ== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no Currently try format implementation doesn't check if subdevice has get_selection ops implemented and returns -EINVAL on error from direct v4l2_subdev_call of get_selection. Selection API's are not mandatory for all V4L2 subdevices. This patch fixes it by adding v4l2_subdev_has_ops check prior to calling get_selection ops and continues with try or set format with zero crop settings for subdevices that don't have get_selection and returns -EINVAL only for subdevices that has get_selection ops. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/vi.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 560d8b3..7edd35c 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -533,11 +533,18 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan, fse.code = fmtinfo->code; ret = v4l2_subdev_call(subdev, pad, enum_frame_size, pad_cfg, &fse); if (ret) { - ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel); - if (ret) - return -EINVAL; - pad_cfg->try_crop.width = sdsel.r.width; - pad_cfg->try_crop.height = sdsel.r.height; + if (!v4l2_subdev_has_op(subdev, pad, get_selection)) { + pad_cfg->try_crop.width = 0; + pad_cfg->try_crop.height = 0; + } else { + ret = v4l2_subdev_call(subdev, pad, get_selection, + NULL, &sdsel); + if (ret) + return -EINVAL; + + pad_cfg->try_crop.width = sdsel.r.width; + pad_cfg->try_crop.height = sdsel.r.height; + } } else { pad_cfg->try_crop.width = fse.max_width; pad_cfg->try_crop.height = fse.max_height; From patchwork Tue Oct 27 03:19:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68334 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFWG-0022Tz-E7; Tue, 27 Oct 2020 03:19:32 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504571AbgJ0DTa (ORCPT + 1 other); Mon, 26 Oct 2020 23:19:30 -0400 Received: from hqnvemgate26.nvidia.com ([216.228.121.65]:14410 "EHLO hqnvemgate26.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2441488AbgJ0DT1 (ORCPT ); Mon, 26 Oct 2020 23:19:27 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate26.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:06 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:27 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:26 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 02/10] media: tegra-video: Enable VI pixel transform for YUV and RGB formats Date: Mon, 26 Oct 2020 20:19:15 -0700 Message-ID: <1603768763-25590-3-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768746; bh=3KvReLIRXcuW/kRnBsqtVyD+GiWXJeSQRRku54/yeMg=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=XGjlbH92SXPLcF8XZPx1bllHmakZpxbmhVxrArGKGSy9pV8wnMxHRKgKJ085q7//F fVBY7vp+HFXcziS85D/SKOZeGCLb01O3beVrr2jihH7kzsnDjOGSQ+PD6KtqvoBSzS llv3aOotaapnv7Y1eh7HAnBx3d+wdFDOCusOj1LCx4Auqu+KdjlZon9r+fJd9ttfx1 8Bc0wcQADXmzP3UQFR1CGJXMOxtxtWH63FZDS3eOWsKkZi4QOc1wlq/Iqkc/nAflhn k43KN6BsTn9ERl24gg3DqCTmP/1n3IzAecE8iBJzlE32otCSSwpUgIUh3qewL19ju7 35EWtHO5y+s7Q== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no VI Pixel transforms converts source pixel data to selected destination pixel formats in memory and aligns properly. YUV and RGB formats need this pixel transform to be enabled. RAW formats use T_R16_I destination pixel format in memory and does not need pixel transform as they support direct write to memory. So, this patch enables pixel transform for YUV and RGB and keeps it bypass for RAW formats. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/tegra210.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c index ac066c0..6b23aa7 100644 --- a/drivers/staging/media/tegra-video/tegra210.c +++ b/drivers/staging/media/tegra-video/tegra210.c @@ -178,10 +178,23 @@ static int tegra_channel_capture_setup(struct tegra_vi_channel *chan) u32 format = chan->fmtinfo->img_fmt; u32 data_type = chan->fmtinfo->img_dt; u32 word_count = (width * chan->fmtinfo->bit_width) / 8; + u32 bypass_pixel_transform = BIT(BYPASS_PXL_TRANSFORM_OFFSET); + + /* + * VI Pixel transformation unit converts source pixels data format + * into selected destination pixel format and aligns properly while + * interfacing with memory packer. + * This pixel transformation should be enabled for YUV and RGB + * formats and should be bypassed for RAW formats as RAW formats + * only support direct to memory. + */ + if (chan->pg_mode || data_type == TEGRA_IMAGE_DT_YUV422_8 || + data_type == TEGRA_IMAGE_DT_RGB888) + bypass_pixel_transform = 0; vi_csi_write(chan, TEGRA_VI_CSI_ERROR_STATUS, 0xffffffff); vi_csi_write(chan, TEGRA_VI_CSI_IMAGE_DEF, - ((chan->pg_mode ? 0 : 1) << BYPASS_PXL_TRANSFORM_OFFSET) | + bypass_pixel_transform | (format << IMAGE_DEF_FORMAT_OFFSET) | IMAGE_DEF_DEST_MEM); vi_csi_write(chan, TEGRA_VI_CSI_IMAGE_DT, data_type); From patchwork Tue Oct 27 03:19:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68340 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFXR-0022VC-Qn; Tue, 27 Oct 2020 03:20:46 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504566AbgJ0DT3 (ORCPT + 1 other); Mon, 26 Oct 2020 23:19:29 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:18918 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504557AbgJ0DT2 (ORCPT ); Mon, 26 Oct 2020 23:19:28 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:35 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL111.nvidia.com (172.20.187.18) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:27 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:27 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 03/10] media: tegra-video: Fix V4L2 pixel format for RGB888_1X24 Date: Mon, 26 Oct 2020 20:19:16 -0700 Message-ID: <1603768763-25590-4-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768775; bh=oZ0OoYopq5ZTtCF6PxH3Qip/gBKrvsKPMfv55eO/rZY=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=AFxLr1XhnNXyEPOUQfvApCFn0qp6dxmBbS4RfgdFF6IOKIjfxbt1r6whhUhrDOWKS OKRjIuW32qf7/oyHgUVt2c7r3CGowRtwkwiZyI9lVU38gbSGDX7fpuCgpQ7zr4+5cd dtfgrEaPMKxr8mGZ9E09M04Q02nSyqZFRAJpdm9Ti2F+k723oa1HwO4N+KnI4FnIbp zEeqlzd+8ilq0s7ngOv0DUyN4mLngRnL6dTSraGphIeEaLBHyIbXGCq48FSFyJO+z4 PT3Zs8W8RjFiz8uxXTcirlY4Ymm4o21soYFNuZT6FQXkiNUZZL5y4+q+lt3amhhGFZ pACNTPDp9Twrw== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no V4L2 pixel format is incorrect for RGB888_1X24. This patch fixes it. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/tegra210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c index 6b23aa7..c883925 100644 --- a/drivers/staging/media/tegra-video/tegra210.c +++ b/drivers/staging/media/tegra-video/tegra210.c @@ -619,7 +619,7 @@ static const struct tegra_video_format tegra210_video_formats[] = { TEGRA210_VIDEO_FMT(RAW12, 12, SGBRG12_1X12, 2, T_R16_I, SGBRG12), TEGRA210_VIDEO_FMT(RAW12, 12, SBGGR12_1X12, 2, T_R16_I, SBGGR12), /* RGB888 */ - TEGRA210_VIDEO_FMT(RGB888, 24, RGB888_1X24, 4, T_A8R8G8B8, RGB24), + TEGRA210_VIDEO_FMT(RGB888, 24, RGB888_1X24, 4, T_A8R8G8B8, XRGB32), TEGRA210_VIDEO_FMT(RGB888, 24, RGB888_1X32_PADHI, 4, T_A8B8G8R8, XBGR32), /* YUV422 */ From patchwork Tue Oct 27 03:19:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68335 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFWH-0022Tz-NQ; Tue, 27 Oct 2020 03:19:34 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504579AbgJ0DTa (ORCPT + 1 other); Mon, 26 Oct 2020 23:19:30 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:15478 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504559AbgJ0DT3 (ORCPT ); Mon, 26 Oct 2020 23:19:29 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:32 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL101.nvidia.com (172.20.187.10) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:28 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:28 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 04/10] media: tegra-video: Add support for V4L2_PIX_FMT_NV16 Date: Mon, 26 Oct 2020 20:19:17 -0700 Message-ID: <1603768763-25590-5-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768772; bh=7g4j4fZpOMBVKbjpatehkITEWxrUzWbXQeqo6wEMbWA=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=nqha9HKCoi5PmPO4Bn0Lst9B4v/cunJ/gDwk2OqPgTqUB9dKEI4095NhLJ6UkwYLo 5zK545g49zm0LAOiGcgZh5d+Hr2X+NhZRoffRH+WGJsC05jPBzLd5G/U5hGjfVj/nP fU7lYXBBgDCLeof9lxihUf9sDkpWz/siLy3Rgt0G5BxNkNReOKoELjUDsVEjWa8Zfc N1gbtNQzrC3Ci8HWdfG2cX+ertjU6cv7VZbRoVZkLf5JWAWwLBBB/Hd4ISCAQ6kpdU UH8h3jKWxo1wjIC1Xxr8zPOEBmdcUk0aUN3hnlA93RmsK/IcHrtZ9fFOflwo7gWklf OZLQjvmoosfZA== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no NV16 are two-plane versions of YUV422 format. VI/CSI surface0 registers corresponds to first Y plane and surface1 registers corresponds to seconds UV plane. This patch updates image size for NV16 format to include both planes and programs VI/CSI surface1 registers for UV plane capture. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/tegra210.c | 13 +++++++++++++ drivers/staging/media/tegra-video/vi.c | 2 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c index c883925..929d277 100644 --- a/drivers/staging/media/tegra-video/tegra210.c +++ b/drivers/staging/media/tegra-video/tegra210.c @@ -287,6 +287,7 @@ static int tegra_channel_capture_frame(struct tegra_vi_channel *chan, { u32 thresh, value, frame_start, mw_ack_done; int bytes_per_line = chan->format.bytesperline; + u32 sizeimage = chan->format.sizeimage; int err; /* program buffer address by using surface 0 */ @@ -296,6 +297,18 @@ static int tegra_channel_capture_frame(struct tegra_vi_channel *chan, vi_csi_write(chan, TEGRA_VI_CSI_SURFACE0_STRIDE, bytes_per_line); /* + * Program surface 1 for UV plane with offset sizeimage from Y plane. + */ + if (chan->fmtinfo->fourcc == V4L2_PIX_FMT_NV16) { + vi_csi_write(chan, TEGRA_VI_CSI_SURFACE1_OFFSET_MSB, + ((u64)buf->addr + sizeimage / 2) >> 32); + vi_csi_write(chan, TEGRA_VI_CSI_SURFACE1_OFFSET_LSB, + buf->addr + sizeimage / 2); + vi_csi_write(chan, TEGRA_VI_CSI_SURFACE1_STRIDE, + bytes_per_line); + } + + /* * Tegra VI block interacts with host1x syncpt for synchronizing * programmed condition of capture state and hardware operation. * Frame start and Memory write acknowledge syncpts has their own diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 7edd35c..525c087 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -484,6 +484,8 @@ static void tegra_channel_fmt_align(struct tegra_vi_channel *chan, pix->bytesperline = clamp(bpl, min_bpl, max_bpl); pix->sizeimage = pix->bytesperline * pix->height; + if (pix->pixelformat == V4L2_PIX_FMT_NV16) + pix->sizeimage *= 2; } static int __tegra_channel_try_format(struct tegra_vi_channel *chan, From patchwork Tue Oct 27 03:19:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68344 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFXb-0022YC-SR; Tue, 27 Oct 2020 03:20:56 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504847AbgJ0DUq (ORCPT + 1 other); Mon, 26 Oct 2020 23:20:46 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:15480 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504564AbgJ0DTa (ORCPT ); Mon, 26 Oct 2020 23:19:30 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:33 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL109.nvidia.com (172.20.187.15) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:28 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:28 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 05/10] media: tegra-video: Add DV timing support Date: Mon, 26 Oct 2020 20:19:18 -0700 Message-ID: <1603768763-25590-6-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768773; bh=LiaXgDHJz9gTg1dN9RrtBEXYHCuprW00WoLXWidqB+4=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=cFHiyNEenggApaLAFglCG++JtPQ2HXe9BflQTUEUwj8PQEloCYW1Qk3wC4GI50aTT VNSbAbUSGv4r9iX/dauXPlQ/dow9XqrhicxOWOUVaUIbUvtDTIF+hOwLcddQhXGUG4 QnkAp5yp7epGiv7VTBnih1D97laS5tERbSJRuagxWB7mqtFCF/DFzwpYvxhTcWb1Hq J5FtoXibtXUtQVrnih6DEZXjAh6rYX1bviwH8P4ZxN59kn6rbYu4+e/nvppHXXrUTw sA1iNfIoqn8CcOkm7b4ulEq8Mhr/rR0sJBjZSDwOE6na9XP8h7E9kY16hUgj9Tss0B TYMnC3iJ9thNg== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no This patch adds below v4l2 DV timing ioctls to support HDMI-to-CSI bridges. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/vi.c | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 525c087..d0d84da 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -720,6 +721,97 @@ static int tegra_channel_s_selection(struct file *file, void *fh, return ret; } +static int tegra_channel_g_dv_timings(struct file *file, void *fh, + struct v4l2_dv_timings *timings) +{ + struct tegra_vi_channel *chan = video_drvdata(file); + struct v4l2_subdev *subdev; + + subdev = tegra_channel_get_remote_source_subdev(chan); + if (!v4l2_subdev_has_op(subdev, video, g_dv_timings)) + return -ENOTTY; + + return v4l2_device_call_until_err(chan->video.v4l2_dev, 0, + video, g_dv_timings, timings); +} + +static int tegra_channel_s_dv_timings(struct file *file, void *fh, + struct v4l2_dv_timings *timings) +{ + struct tegra_vi_channel *chan = video_drvdata(file); + struct v4l2_subdev *subdev; + struct v4l2_bt_timings *bt = &timings->bt; + struct v4l2_dv_timings curr_timings; + int ret; + + subdev = tegra_channel_get_remote_source_subdev(chan); + if (!v4l2_subdev_has_op(subdev, video, s_dv_timings)) + return -ENOTTY; + + ret = tegra_channel_g_dv_timings(file, fh, &curr_timings); + if (ret) + return ret; + + if (v4l2_match_dv_timings(timings, &curr_timings, 0, false)) + return 0; + + if (vb2_is_busy(&chan->queue)) + return -EBUSY; + + ret = v4l2_device_call_until_err(chan->video.v4l2_dev, 0, + video, s_dv_timings, timings); + if (ret) + return ret; + + chan->format.width = bt->width; + chan->format.height = bt->height; + chan->format.bytesperline = bt->width * chan->fmtinfo->bpp; + chan->format.sizeimage = chan->format.bytesperline * bt->height; + tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp); + + return 0; +} + +static int tegra_channel_query_dv_timings(struct file *file, void *fh, + struct v4l2_dv_timings *timings) +{ + struct tegra_vi_channel *chan = video_drvdata(file); + struct v4l2_subdev *subdev; + + subdev = tegra_channel_get_remote_source_subdev(chan); + if (!v4l2_subdev_has_op(subdev, video, query_dv_timings)) + return -ENOTTY; + + return v4l2_device_call_until_err(chan->video.v4l2_dev, 0, + video, query_dv_timings, timings); +} + +static int tegra_channel_enum_dv_timings(struct file *file, void *fh, + struct v4l2_enum_dv_timings *timings) +{ + struct tegra_vi_channel *chan = video_drvdata(file); + struct v4l2_subdev *subdev; + + subdev = tegra_channel_get_remote_source_subdev(chan); + if (!v4l2_subdev_has_op(subdev, pad, enum_dv_timings)) + return -ENOTTY; + + return v4l2_subdev_call(subdev, pad, enum_dv_timings, timings); +} + +static int tegra_channel_dv_timings_cap(struct file *file, void *fh, + struct v4l2_dv_timings_cap *cap) +{ + struct tegra_vi_channel *chan = video_drvdata(file); + struct v4l2_subdev *subdev; + + subdev = tegra_channel_get_remote_source_subdev(chan); + if (!v4l2_subdev_has_op(subdev, pad, dv_timings_cap)) + return -ENOTTY; + + return v4l2_subdev_call(subdev, pad, dv_timings_cap, cap); +} + static int tegra_channel_enum_input(struct file *file, void *fh, struct v4l2_input *inp) { @@ -779,6 +871,11 @@ static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = { .vidioc_unsubscribe_event = v4l2_event_unsubscribe, .vidioc_g_selection = tegra_channel_g_selection, .vidioc_s_selection = tegra_channel_s_selection, + .vidioc_g_dv_timings = tegra_channel_g_dv_timings, + .vidioc_s_dv_timings = tegra_channel_s_dv_timings, + .vidioc_query_dv_timings = tegra_channel_query_dv_timings, + .vidioc_enum_dv_timings = tegra_channel_enum_dv_timings, + .vidioc_dv_timings_cap = tegra_channel_dv_timings_cap, }; /* From patchwork Tue Oct 27 03:19:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68339 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFXP-0022VC-2k; Tue, 27 Oct 2020 03:20:44 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504586AbgJ0DTc (ORCPT + 1 other); Mon, 26 Oct 2020 23:19:32 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:18923 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504542AbgJ0DTa (ORCPT ); Mon, 26 Oct 2020 23:19:30 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:36 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL109.nvidia.com (172.20.187.15) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:29 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:29 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 06/10] media: tegra-video: Add support for EDID ioctl ops Date: Mon, 26 Oct 2020 20:19:19 -0700 Message-ID: <1603768763-25590-7-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768777; bh=bHzQRpU16Ph4H6jjekuasUSGwbJ9VXFyRGyVRWLhW1I=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=gRcrriLOY998+iARHUT/omejtD0882kNTOxqtiGqC31zRJ3HfdEvlpD2w1BtqMLqI s4ZuJTb2n9oMspbt9yZ+HdEj3t2KbbxxqDeITFtyG3PuOvcq+rlsZLqTUOhVqFT4c7 MLEJlGShWBmkkttpIAQPdbczwY0WzgsrJdd7pRs0FV6dXUotdvyS2yjky6kErF3+rX 7rzkwL3K++7mdrrZAG34TWiHM3j3KTWg+2zm3vSPn4e4ci92UKD2f9YWuX/9pLJ1Vt 2anzSKimfQkmpGbWhkZoqY3edhsf85tYOcaHtIEZTDXlZTYFHf7YMUtki7rB6XxlWL hZPYe4cjipFfA== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no This patch adds support for EDID get and set v4l2 ioctl ops to use with HDMI to CSI bridges. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/vi.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index d0d84da..92f36b1 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -721,6 +721,32 @@ static int tegra_channel_s_selection(struct file *file, void *fh, return ret; } +static int tegra_channel_g_edid(struct file *file, void *fh, + struct v4l2_edid *edid) +{ + struct tegra_vi_channel *chan = video_drvdata(file); + struct v4l2_subdev *subdev; + + subdev = tegra_channel_get_remote_source_subdev(chan); + if (!v4l2_subdev_has_op(subdev, pad, get_edid)) + return -ENOTTY; + + return v4l2_subdev_call(subdev, pad, get_edid, edid); +} + +static int tegra_channel_s_edid(struct file *file, void *fh, + struct v4l2_edid *edid) +{ + struct tegra_vi_channel *chan = video_drvdata(file); + struct v4l2_subdev *subdev; + + subdev = tegra_channel_get_remote_source_subdev(chan); + if (!v4l2_subdev_has_op(subdev, pad, set_edid)) + return -ENOTTY; + + return v4l2_subdev_call(subdev, pad, set_edid, edid); +} + static int tegra_channel_g_dv_timings(struct file *file, void *fh, struct v4l2_dv_timings *timings) { @@ -871,6 +897,8 @@ static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = { .vidioc_unsubscribe_event = v4l2_event_unsubscribe, .vidioc_g_selection = tegra_channel_g_selection, .vidioc_s_selection = tegra_channel_s_selection, + .vidioc_g_edid = tegra_channel_g_edid, + .vidioc_s_edid = tegra_channel_s_edid, .vidioc_g_dv_timings = tegra_channel_g_dv_timings, .vidioc_s_dv_timings = tegra_channel_s_dv_timings, .vidioc_query_dv_timings = tegra_channel_query_dv_timings, From patchwork Tue Oct 27 03:19:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68336 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFWg-0022Uo-Q5; Tue, 27 Oct 2020 03:19:59 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504807AbgJ0DTy (ORCPT + 1 other); Mon, 26 Oct 2020 23:19:54 -0400 Received: from hqnvemgate25.nvidia.com ([216.228.121.64]:15487 "EHLO hqnvemgate25.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504574AbgJ0DTa (ORCPT ); Mon, 26 Oct 2020 23:19:30 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate25.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:34 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL101.nvidia.com (172.20.187.10) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:30 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:29 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 07/10] media: tegra-video: Add support for VIDIOC_LOG_STATUS ioctl Date: Mon, 26 Oct 2020 20:19:20 -0700 Message-ID: <1603768763-25590-8-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768774; bh=SF21BnA36cQvnemUV9ucdhKRKNHO+gD0lDF9mm2flJQ=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=ey8ih83EpHuyzFS1fmvkXHyUC4UpJM9Hnts6hAhW/VwW9Jvs4oYRlRSYh3Fy14uET C4O2sooKtgQecbCpjuKPNy3lCgOos32JoV5LCaU8KjAl9h+SYzf8NAOldLgU5I6rnC s4Wk6OIrRd36W4Noek6uOO0+dy61CcK4mz6a96Sy/vhJm6n/g7O0rk3ExCDPy3peId kncEEO1R1srUl2GbIHHoU5QP5WU9BEGQlaGo68XeORHN54iuXd63e6tsJWhM7rUA7g MQRruTHwz+WSzr4+QmYk8IqinSpDxlzncJWiZx5OifhLtPGRtmVQ//33umWgFeWnUB twritOzua+aVw== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no This patch adds support for log_status ioctl. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/vi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 92f36b1..936e5e5 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -838,6 +838,15 @@ static int tegra_channel_dv_timings_cap(struct file *file, void *fh, return v4l2_subdev_call(subdev, pad, dv_timings_cap, cap); } +static int tegra_channel_log_status(struct file *file, void *fh) +{ + struct tegra_vi_channel *chan = video_drvdata(file); + + v4l2_device_call_all(chan->video.v4l2_dev, 0, core, log_status); + + return 0; +} + static int tegra_channel_enum_input(struct file *file, void *fh, struct v4l2_input *inp) { @@ -904,6 +913,7 @@ static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = { .vidioc_query_dv_timings = tegra_channel_query_dv_timings, .vidioc_enum_dv_timings = tegra_channel_enum_dv_timings, .vidioc_dv_timings_cap = tegra_channel_dv_timings_cap, + .vidioc_log_status = tegra_channel_log_status, }; /* From patchwork Tue Oct 27 03:19:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68343 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFXV-0022VC-4n; Tue, 27 Oct 2020 03:20:49 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504843AbgJ0DUo (ORCPT + 1 other); Mon, 26 Oct 2020 23:20:44 -0400 Received: from hqnvemgate26.nvidia.com ([216.228.121.65]:14418 "EHLO hqnvemgate26.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504581AbgJ0DTb (ORCPT ); Mon, 26 Oct 2020 23:19:31 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate26.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:10 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL105.nvidia.com (172.20.187.12) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:30 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:30 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 08/10] media: tegra-video: Add support for V4L2_EVENT_SOURCE_CHANGE Date: Mon, 26 Oct 2020 20:19:21 -0700 Message-ID: <1603768763-25590-9-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768750; bh=Ri7BxP7rB/ENWqYxoUtmefRCrq9hjpVnsW9TW30TSIw=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=OFd5+DkbyQnBgj43UyYugOZ27efYnd8qJ9qCzySYtgojoaPBF2Gw69n6sp1IHJ81q JMK3+R4iraH/c2iyZk452DNLzJvLYPibzEc4igGEIWTre5Z3fRvW20RnFmxqcdBcut h70yNLKVwjjntgmw6Ktqqvjkx9U2Kt7Gm1NY4zuOw51Ai+2djEst3lfBKZQjAAFYj0 KngzMntgcIGgpoiaqk/PhK+zglDz5dXAmpXg8HZdDJ4pimsagS1OI/RANb7mKQyXKj PLldgHk2VDs8IwSldzL1oyqN8EDLOqHaTX/9P9gIXDcX4BCbv7zCR9cjDY1lWAjv8Z BTDJ8FVTM9PZw== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no Current implementation uses v4l2_ctrl_subscribe_event() and this does not handle V4L2_EVENT_SOURCE_CHANGE. So, update driver to handle V4L2_EVENT_SOURCE_CHANGE. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/vi.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 936e5e5..28c06a9 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -642,6 +642,18 @@ static int tegra_channel_set_subdev_active_fmt(struct tegra_vi_channel *chan) return 0; } +static int +tegra_channel_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_SOURCE_CHANGE: + return v4l2_event_subscribe(fh, sub, 4, NULL); + } + + return v4l2_ctrl_subscribe_event(fh, sub); +} + static int tegra_channel_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { @@ -902,7 +914,7 @@ static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = { .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_streamon = vb2_ioctl_streamon, .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_subscribe_event = tegra_channel_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, .vidioc_g_selection = tegra_channel_g_selection, .vidioc_s_selection = tegra_channel_s_selection, From patchwork Tue Oct 27 03:19:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68342 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFXU-0022VC-0X; Tue, 27 Oct 2020 03:20:48 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504832AbgJ0DUn (ORCPT + 1 other); Mon, 26 Oct 2020 23:20:43 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:18928 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504583AbgJ0DTc (ORCPT ); Mon, 26 Oct 2020 23:19:32 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:38 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL107.nvidia.com (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:31 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:30 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 09/10] media: tegra-video: Implement V4L2 device notify callback Date: Mon, 26 Oct 2020 20:19:22 -0700 Message-ID: <1603768763-25590-10-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768778; bh=xWtjeqZACAKCgSw2RHdrYwyQIBNwajqC+8SWI/tdbs0=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=YgnaC/R+07E1WDGY25IESREdCQuRe4naJtX6MQCJuo0lj89OK1OJfzG7sZN3Mr0/1 7ukxL6jhGemgW9/+j5Q5c4Ya75rcFnCOgzM+73oxH+E/UsOerTl3ow/CtuBTdBVkFG AXwGRQVTdE1KVQW974qkJ1z10mardt069K48SLChVSU0IG94BH2Hc0/zajTynvMLHz tAcKQ8BhuAmb29MH/XRccZ05Pnc6aD4hGBGqPDchraQuhuqNgURk7eoT7gzwmZtJ1B Bs4gHwfba997dz2oESJwkol4h1vjH756SBXE3YZc7HdyXzfvYRBU0eJQMfVEdXDF89 lJ+/wBUgQ5Tlg== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no Implement V4L2 device notify callback to handle V4L2_EVENT_SOURCE_CHANGE event from subdevices. HDMI-to-CSI bridge drivers trigger V4L2_EVENT_SOURCE_CHANGE when source DV timing changes are detected or when HDMI hotplug happens. Runtime source parameter changes during active streaming is not allowed and Tegra video driver calls vb2_queue_error to signal a fatal error if a notification of this event happens during an active streaming. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/vi.c | 3 +++ drivers/staging/media/tegra-video/video.c | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 28c06a9..e866f7d 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1634,6 +1634,9 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier) v4l2_set_subdev_hostdata(subdev, chan); + subdev = tegra_channel_get_remote_source_subdev(chan); + v4l2_set_subdev_hostdata(subdev, chan); + return 0; unregister_video: diff --git a/drivers/staging/media/tegra-video/video.c b/drivers/staging/media/tegra-video/video.c index e50bd70..d966b31 100644 --- a/drivers/staging/media/tegra-video/video.c +++ b/drivers/staging/media/tegra-video/video.c @@ -7,6 +7,8 @@ #include #include +#include + #include "video.h" static void tegra_v4l2_dev_release(struct v4l2_device *v4l2_dev) @@ -24,6 +26,21 @@ static void tegra_v4l2_dev_release(struct v4l2_device *v4l2_dev) kfree(vid); } +static void tegra_v4l2_dev_notify(struct v4l2_subdev *sd, + unsigned int notification, void *arg) +{ + struct tegra_vi_channel *chan; + const struct v4l2_event *ev = arg; + + if (notification != V4L2_DEVICE_NOTIFY_EVENT) + return; + + chan = v4l2_get_subdev_hostdata(sd); + v4l2_event_queue(&chan->video, arg); + if (ev->type == V4L2_EVENT_SOURCE_CHANGE && vb2_is_streaming(&chan->queue)) + vb2_queue_error(&chan->queue); +} + static int host1x_video_probe(struct host1x_device *dev) { struct tegra_video_device *vid; @@ -49,6 +66,7 @@ static int host1x_video_probe(struct host1x_device *dev) vid->v4l2_dev.mdev = &vid->media_dev; vid->v4l2_dev.release = tegra_v4l2_dev_release; + vid->v4l2_dev.notify = tegra_v4l2_dev_notify; ret = v4l2_device_register(&dev->dev, &vid->v4l2_dev); if (ret < 0) { dev_err(&dev->dev, From patchwork Tue Oct 27 03:19:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 68337 X-Patchwork-Delegate: hverkuil@xs4all.nl Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1kXFWn-0022VC-CO; Tue, 27 Oct 2020 03:20:07 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2504800AbgJ0DTw (ORCPT + 1 other); Mon, 26 Oct 2020 23:19:52 -0400 Received: from hqnvemgate24.nvidia.com ([216.228.121.143]:18930 "EHLO hqnvemgate24.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2504585AbgJ0DTd (ORCPT ); Mon, 26 Oct 2020 23:19:33 -0400 Received: from hqmail.nvidia.com (Not Verified[216.228.121.13]) by hqnvemgate24.nvidia.com (using TLS: TLSv1.2, AES256-SHA) id ; Mon, 26 Oct 2020 20:19:39 -0700 Received: from HQMAIL109.nvidia.com (172.20.187.15) by HQMAIL101.nvidia.com (172.20.187.10) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 27 Oct 2020 03:19:31 +0000 Received: from skomatineni-linux.nvidia.com (172.20.13.39) by mail.nvidia.com (172.20.187.15) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 27 Oct 2020 03:19:31 +0000 From: Sowjanya Komatineni To: , , , CC: , , , Subject: [PATCH v2 10/10] media: tegra-video: Add support for x8 captures with gang ports Date: Mon, 26 Oct 2020 20:19:23 -0700 Message-ID: <1603768763-25590-11-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> References: <1603768763-25590-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1603768779; bh=h/mVfHw5pkkHAqpAzS0xJifsCukHVrv0H/ojnwO4sIw=; h=From:To:CC:Subject:Date:Message-ID:X-Mailer:In-Reply-To: References:X-NVConfidentiality:MIME-Version:Content-Type; b=Wckd2W7QPkLbcnRzJTjUQebgKay+XlmoMZb37nIe/Mn+wV2D/cjyJfyosN8VDkwXM JadwLRHkyQ4iRXTfvpw5mCVDtVNn74YX7Pl1Qm7lSEXrYBRlqazxYv3sDqR2vtMFbd Poltsjwm7RZbk8BOk8RT51YSq4sTrzHlv3CDtn5mHCvVn4qk4B8BSzpRPqwc1KmwKb WKtwZS8Asbpd7Tk1GMp1cIYDppQE4Nsm1E8/DOm2D9dQsPWMkIbjwJz1RYWMGFr0oZ 5dJKVFWylVoQ2hIOAuHfQXj3d/TZxk7h56jpJm719poenA0aa3IPD/ZxR4NUArBGAy yGxFiRAMX5oSQ== Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIMWL_WL_HIGH=0.001,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no Tegra VI/CSI hardware don't have native 8 lane capture support. Each CSI port has max 4 lanes only. So for x8 captures, consecutive ports are ganged up for left half and right half captures on to each x4 ports with buffer offsets based on source image split width to align side-by-side. All ports in gang are configured together during the corresponding video device node streaming for x8 captures. x8 capture with gang ports are supported with HDMI-to-CSI bridges where they split 4K image into left half onto one x4 port and right half onto second x4 port. Signed-off-by: Sowjanya Komatineni --- drivers/staging/media/tegra-video/csi.c | 47 ++++- drivers/staging/media/tegra-video/csi.h | 14 +- drivers/staging/media/tegra-video/tegra210.c | 304 ++++++++++++++++++--------- drivers/staging/media/tegra-video/vi.c | 117 ++++++++--- drivers/staging/media/tegra-video/vi.h | 17 +- 5 files changed, 347 insertions(+), 152 deletions(-) diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index a19c85c..a6c54f8 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -253,13 +253,14 @@ static unsigned int csi_get_pixel_rate(struct tegra_csi_channel *csi_chan) } void tegra_csi_calc_settle_time(struct tegra_csi_channel *csi_chan, + u8 csi_port_num, u8 *clk_settle_time, u8 *ths_settle_time) { struct tegra_csi *csi = csi_chan->csi; unsigned int cil_clk_mhz; unsigned int pix_clk_mhz; - int clk_idx = (csi_chan->csi_port_num >> 1) + 1; + int clk_idx = (csi_port_num >> 1) + 1; cil_clk_mhz = clk_get_rate(csi->clks[clk_idx].clk) / MHZ; pix_clk_mhz = csi_get_pixel_rate(csi_chan) / MHZ; @@ -410,7 +411,7 @@ static int tegra_csi_channel_alloc(struct tegra_csi *csi, unsigned int num_pads) { struct tegra_csi_channel *chan; - int ret = 0; + int ret = 0, i; chan = kzalloc(sizeof(*chan), GFP_KERNEL); if (!chan) @@ -418,8 +419,21 @@ static int tegra_csi_channel_alloc(struct tegra_csi *csi, list_add_tail(&chan->list, &csi->csi_chans); chan->csi = csi; - chan->csi_port_num = port_num; - chan->numlanes = lanes; + /* + * Each CSI brick has maximum of 4 lanes. + * For lanes more than 4, use multiple of immediate CSI bricks as gang. + */ + if (lanes <= CSI_LANES_PER_BRICK) { + chan->numlanes = lanes; + chan->numgangports = 1; + } else { + chan->numlanes = CSI_LANES_PER_BRICK; + chan->numgangports = lanes / CSI_LANES_PER_BRICK; + } + + for (i = 0; i < chan->numgangports; i++) + chan->csi_port_nums[i] = port_num + i * CSI_PORTS_PER_BRICK; + chan->of_node = node; chan->numpads = num_pads; if (num_pads & 0x2) { @@ -461,9 +475,6 @@ static int tegra_csi_tpg_channels_alloc(struct tegra_csi *csi) static int tegra_csi_channels_alloc(struct tegra_csi *csi) { struct device_node *node = csi->dev->of_node; - struct v4l2_fwnode_endpoint v4l2_ep = { - .bus_type = V4L2_MBUS_CSI2_DPHY - }; struct fwnode_handle *fwh; struct device_node *channel; struct device_node *ep; @@ -471,6 +482,8 @@ static int tegra_csi_channels_alloc(struct tegra_csi *csi) int ret; for_each_child_of_node(node, channel) { + struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; + if (!of_node_name_eq(channel, "channel")) continue; @@ -499,8 +512,20 @@ static int tegra_csi_channels_alloc(struct tegra_csi *csi) goto err_node_put; } - lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes; - if (!lanes || ((lanes & (lanes - 1)) != 0)) { + if (v4l2_ep.bus_type == V4L2_MBUS_PARALLEL) + lanes = v4l2_ep.bus.parallel.bus_width; + else + lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes; + + /* + * Each CSI brick has maximum 4 data lanes. + * For lanes more than 4, validate lanes to be multiple of 4 + * so multiple of consecutive CSI bricks can be ganged up for + * streaming. + */ + if (!lanes || ((lanes & (lanes - 1)) != 0) || + (lanes > CSI_LANES_PER_BRICK && (((lanes & 3) != 0) || + ((portno & 1) != 0)))) { dev_err(csi->dev, "invalid data-lanes %d for %pOF\n", lanes, channel); ret = -EINVAL; @@ -544,7 +569,7 @@ static int tegra_csi_channel_init(struct tegra_csi_channel *chan) subdev->dev = csi->dev; if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "%s-%d", "tpg", - chan->csi_port_num); + chan->csi_port_nums[0]); else snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "%s", kbasename(chan->of_node->full_name)); @@ -596,7 +621,7 @@ static int tegra_csi_channels_init(struct tegra_csi *csi) if (ret) { dev_err(csi->dev, "failed to initialize channel-%d: %d\n", - chan->csi_port_num, ret); + chan->csi_port_nums[0], ret); return ret; } } diff --git a/drivers/staging/media/tegra-video/csi.h b/drivers/staging/media/tegra-video/csi.h index c65ff73..386f7c6 100644 --- a/drivers/staging/media/tegra-video/csi.h +++ b/drivers/staging/media/tegra-video/csi.h @@ -17,6 +17,10 @@ * CILB. */ #define CSI_PORTS_PER_BRICK 2 +#define CSI_LANES_PER_BRICK 4 + +/* Maximum 2 CSI x4 ports can be ganged up for streaming */ +#define GANG_PORTS_MAX 2 /* each CSI channel can have one sink and one source pads */ #define TEGRA_CSI_PADS_NUM 2 @@ -43,8 +47,10 @@ struct tegra_csi; * @numpads: number of pads. * @csi: Tegra CSI device structure * @of_node: csi device tree node - * @numlanes: number of lanes used per port/channel - * @csi_port_num: CSI channel port number + * @numgangports: number of immediate ports ganged up to meet the + * channel bus-width + * @numlanes: number of lanes used per port + * @csi_port_nums: CSI channel port numbers * @pg_mode: test pattern generator mode for channel * @format: active format of the channel * @framerate: active framerate for TPG @@ -60,8 +66,9 @@ struct tegra_csi_channel { unsigned int numpads; struct tegra_csi *csi; struct device_node *of_node; + u8 numgangports; unsigned int numlanes; - u8 csi_port_num; + u8 csi_port_nums[GANG_PORTS_MAX]; u8 pg_mode; struct v4l2_mbus_framefmt format; unsigned int framerate; @@ -150,6 +157,7 @@ extern const struct tegra_csi_soc tegra210_csi_soc; void tegra_csi_error_recover(struct v4l2_subdev *subdev); void tegra_csi_calc_settle_time(struct tegra_csi_channel *csi_chan, + u8 csi_port_num, u8 *clk_settle_time, u8 *ths_settle_time); #endif diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c index 929d277..aff56fc 100644 --- a/drivers/staging/media/tegra-video/tegra210.c +++ b/drivers/staging/media/tegra-video/tegra210.c @@ -149,21 +149,22 @@ static u32 tegra_vi_read(struct tegra_vi_channel *chan, unsigned int addr) } /* Tegra210 VI_CSI registers accessors */ -static void vi_csi_write(struct tegra_vi_channel *chan, unsigned int addr, - u32 val) +static void vi_csi_write(struct tegra_vi_channel *chan, u8 portno, + unsigned int addr, u32 val) { void __iomem *vi_csi_base; - vi_csi_base = chan->vi->iomem + TEGRA210_VI_CSI_BASE(chan->portno); + vi_csi_base = chan->vi->iomem + TEGRA210_VI_CSI_BASE(portno); writel_relaxed(val, vi_csi_base + addr); } -static u32 vi_csi_read(struct tegra_vi_channel *chan, unsigned int addr) +static u32 vi_csi_read(struct tegra_vi_channel *chan, u8 portno, + unsigned int addr) { void __iomem *vi_csi_base; - vi_csi_base = chan->vi->iomem + TEGRA210_VI_CSI_BASE(chan->portno); + vi_csi_base = chan->vi->iomem + TEGRA210_VI_CSI_BASE(portno); return readl_relaxed(vi_csi_base + addr); } @@ -171,7 +172,8 @@ static u32 vi_csi_read(struct tegra_vi_channel *chan, unsigned int addr) /* * Tegra210 VI channel capture operations */ -static int tegra_channel_capture_setup(struct tegra_vi_channel *chan) +static int tegra_channel_capture_setup(struct tegra_vi_channel *chan, + u8 portno) { u32 height = chan->format.height; u32 width = chan->format.width; @@ -192,19 +194,30 @@ static int tegra_channel_capture_setup(struct tegra_vi_channel *chan) data_type == TEGRA_IMAGE_DT_RGB888) bypass_pixel_transform = 0; - vi_csi_write(chan, TEGRA_VI_CSI_ERROR_STATUS, 0xffffffff); - vi_csi_write(chan, TEGRA_VI_CSI_IMAGE_DEF, + /* + * For x8 source streaming, the source image is split onto two x4 ports + * with left half to first x4 port and right half to second x4 port. + * So, use split width and corresponding word count for each x4 port. + */ + if (chan->numgangports > 1) { + width = width >> 1; + word_count = (width * chan->fmtinfo->bit_width) / 8; + } + + vi_csi_write(chan, portno, TEGRA_VI_CSI_ERROR_STATUS, 0xffffffff); + vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_DEF, bypass_pixel_transform | (format << IMAGE_DEF_FORMAT_OFFSET) | IMAGE_DEF_DEST_MEM); - vi_csi_write(chan, TEGRA_VI_CSI_IMAGE_DT, data_type); - vi_csi_write(chan, TEGRA_VI_CSI_IMAGE_SIZE_WC, word_count); - vi_csi_write(chan, TEGRA_VI_CSI_IMAGE_SIZE, + vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_DT, data_type); + vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_SIZE_WC, word_count); + vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_SIZE, (height << IMAGE_SIZE_HEIGHT_OFFSET) | width); return 0; } -static void tegra_channel_vi_soft_reset(struct tegra_vi_channel *chan) +static void tegra_channel_vi_soft_reset(struct tegra_vi_channel *chan, + u8 portno) { /* disable clock gating to enable continuous clock */ tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, 0); @@ -212,15 +225,16 @@ static void tegra_channel_vi_soft_reset(struct tegra_vi_channel *chan) * Soft reset memory client interface, pixel format logic, sensor * control logic, and a shadow copy logic to bring VI to clean state. */ - vi_csi_write(chan, TEGRA_VI_CSI_SW_RESET, 0xf); + vi_csi_write(chan, portno, TEGRA_VI_CSI_SW_RESET, 0xf); usleep_range(100, 200); - vi_csi_write(chan, TEGRA_VI_CSI_SW_RESET, 0x0); + vi_csi_write(chan, portno, TEGRA_VI_CSI_SW_RESET, 0x0); /* enable back VI clock gating */ tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, VI_CG_2ND_LEVEL_EN); } -static void tegra_channel_capture_error_recover(struct tegra_vi_channel *chan) +static void tegra_channel_capture_error_recover(struct tegra_vi_channel *chan, + u8 portno) { struct v4l2_subdev *subdev; u32 val; @@ -232,9 +246,9 @@ static void tegra_channel_capture_error_recover(struct tegra_vi_channel *chan) * events which can cause CSI and VI hardware hang. * This helps to have a clean capture for next frame. */ - val = vi_csi_read(chan, TEGRA_VI_CSI_ERROR_STATUS); + val = vi_csi_read(chan, portno, TEGRA_VI_CSI_ERROR_STATUS); dev_dbg(&chan->video.dev, "TEGRA_VI_CSI_ERROR_STATUS 0x%08x\n", val); - vi_csi_write(chan, TEGRA_VI_CSI_ERROR_STATUS, val); + vi_csi_write(chan, portno, TEGRA_VI_CSI_ERROR_STATUS, val); val = tegra_vi_read(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR); dev_dbg(&chan->video.dev, @@ -242,8 +256,8 @@ static void tegra_channel_capture_error_recover(struct tegra_vi_channel *chan) tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR, val); /* recover VI by issuing software reset and re-setup for capture */ - tegra_channel_vi_soft_reset(chan); - tegra_channel_capture_setup(chan); + tegra_channel_vi_soft_reset(chan, portno); + tegra_channel_capture_setup(chan, portno); /* recover CSI block */ subdev = tegra_channel_get_remote_csi_subdev(chan); @@ -282,80 +296,114 @@ static void release_buffer(struct tegra_vi_channel *chan, vb2_buffer_done(&vb->vb2_buf, state); } -static int tegra_channel_capture_frame(struct tegra_vi_channel *chan, - struct tegra_channel_buffer *buf) +static void tegra_channel_vi_buffer_setup(struct tegra_vi_channel *chan, + u8 portno, u32 buf_offset, + struct tegra_channel_buffer *buf) { - u32 thresh, value, frame_start, mw_ack_done; - int bytes_per_line = chan->format.bytesperline; + int bytesperline = chan->format.bytesperline; u32 sizeimage = chan->format.sizeimage; - int err; /* program buffer address by using surface 0 */ - vi_csi_write(chan, TEGRA_VI_CSI_SURFACE0_OFFSET_MSB, - (u64)buf->addr >> 32); - vi_csi_write(chan, TEGRA_VI_CSI_SURFACE0_OFFSET_LSB, buf->addr); - vi_csi_write(chan, TEGRA_VI_CSI_SURFACE0_STRIDE, bytes_per_line); + vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_OFFSET_MSB, + ((u64)buf->addr + buf_offset) >> 32); + vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_OFFSET_LSB, + buf->addr + buf_offset); + vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_STRIDE, bytesperline); + if (chan->fmtinfo->fourcc != V4L2_PIX_FMT_NV16) + return; /* * Program surface 1 for UV plane with offset sizeimage from Y plane. */ - if (chan->fmtinfo->fourcc == V4L2_PIX_FMT_NV16) { - vi_csi_write(chan, TEGRA_VI_CSI_SURFACE1_OFFSET_MSB, - ((u64)buf->addr + sizeimage / 2) >> 32); - vi_csi_write(chan, TEGRA_VI_CSI_SURFACE1_OFFSET_LSB, - buf->addr + sizeimage / 2); - vi_csi_write(chan, TEGRA_VI_CSI_SURFACE1_STRIDE, - bytes_per_line); - } - - /* - * Tegra VI block interacts with host1x syncpt for synchronizing - * programmed condition of capture state and hardware operation. - * Frame start and Memory write acknowledge syncpts has their own - * FIFO of depth 2. - * - * Syncpoint trigger conditions set through VI_INCR_SYNCPT register - * are added to HW syncpt FIFO and when the HW triggers, syncpt - * condition is removed from the FIFO and counter at syncpoint index - * will be incremented by the hardware and software can wait for - * counter to reach threshold to synchronize capturing frame with the - * hardware capture events. - */ + vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_OFFSET_MSB, + (((u64)buf->addr + sizeimage / 2) + buf_offset) >> 32); + vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_OFFSET_LSB, + buf->addr + sizeimage / 2 + buf_offset); + vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_STRIDE, bytesperline); +} - /* increase channel syncpoint threshold for FRAME_START */ - thresh = host1x_syncpt_incr_max(chan->frame_start_sp, 1); +static int tegra_channel_capture_frame(struct tegra_vi_channel *chan, + struct tegra_channel_buffer *buf) +{ + u32 thresh, value, frame_start, mw_ack_done; + u32 fs_thresh[GANG_PORTS_MAX]; + u8 *portnos = chan->portnos; + int gang_bpl = (chan->format.width >> 1) * chan->fmtinfo->bpp; + u32 buf_offset; + bool capture_timedout = false; + int err, i; + + for (i = 0; i < chan->numgangports; i++) { + /* + * Align buffers side-by-side for all consecutive x4 ports + * in gang ports using bytes per line based on source split + * width. + */ + buf_offset = i * roundup(gang_bpl, SURFACE_ALIGN_BYTES); + tegra_channel_vi_buffer_setup(chan, portnos[i], buf_offset, + buf); - /* Program FRAME_START trigger condition syncpt request */ - frame_start = VI_CSI_PP_FRAME_START(chan->portno); - value = VI_CFG_VI_INCR_SYNCPT_COND(frame_start) | - host1x_syncpt_id(chan->frame_start_sp); - tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, value); + /* + * Tegra VI block interacts with host1x syncpt to synchronize + * programmed condition and hardware operation for capture. + * Frame start and Memory write acknowledge syncpts has their + * own FIFO of depth 2. + * + * Syncpoint trigger conditions set through VI_INCR_SYNCPT + * register are added to HW syncpt FIFO and when HW triggers, + * syncpt condition is removed from the FIFO and counter at + * syncpoint index will be incremented by the hardware and + * software can wait for counter to reach threshold to + * synchronize capturing frame with hardware capture events. + */ - /* increase channel syncpoint threshold for MW_ACK_DONE */ - buf->mw_ack_sp_thresh = host1x_syncpt_incr_max(chan->mw_ack_sp, 1); + /* increase channel syncpoint threshold for FRAME_START */ + thresh = host1x_syncpt_incr_max(chan->frame_start_sp[i], 1); + fs_thresh[i] = thresh; + + /* Program FRAME_START trigger condition syncpt request */ + frame_start = VI_CSI_PP_FRAME_START(portnos[i]); + value = VI_CFG_VI_INCR_SYNCPT_COND(frame_start) | + host1x_syncpt_id(chan->frame_start_sp[i]); + tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, value); + + /* increase channel syncpoint threshold for MW_ACK_DONE */ + thresh = host1x_syncpt_incr_max(chan->mw_ack_sp[i], 1); + buf->mw_ack_sp_thresh[i] = thresh; + + /* Program MW_ACK_DONE trigger condition syncpt request */ + mw_ack_done = VI_CSI_MW_ACK_DONE(portnos[i]); + value = VI_CFG_VI_INCR_SYNCPT_COND(mw_ack_done) | + host1x_syncpt_id(chan->mw_ack_sp[i]); + tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, value); + } - /* Program MW_ACK_DONE trigger condition syncpt request */ - mw_ack_done = VI_CSI_MW_ACK_DONE(chan->portno); - value = VI_CFG_VI_INCR_SYNCPT_COND(mw_ack_done) | - host1x_syncpt_id(chan->mw_ack_sp); - tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, value); + /* enable single shot capture after all ganged ports are ready */ + for (i = 0; i < chan->numgangports; i++) + vi_csi_write(chan, portnos[i], TEGRA_VI_CSI_SINGLE_SHOT, + SINGLE_SHOT_CAPTURE); - /* enable single shot capture */ - vi_csi_write(chan, TEGRA_VI_CSI_SINGLE_SHOT, SINGLE_SHOT_CAPTURE); + for (i = 0; i < chan->numgangports; i++) { + /* + * Wait for syncpt counter to reach frame start event threshold + */ + err = host1x_syncpt_wait(chan->frame_start_sp[i], fs_thresh[i], + TEGRA_VI_SYNCPT_WAIT_TIMEOUT, &value); + if (err) { + capture_timedout = true; + /* increment syncpoint counter for timedout events */ + host1x_syncpt_incr(chan->frame_start_sp[i]); + spin_lock(&chan->sp_incr_lock[i]); + host1x_syncpt_incr(chan->mw_ack_sp[i]); + spin_unlock(&chan->sp_incr_lock[i]); + /* clear errors and recover */ + tegra_channel_capture_error_recover(chan, portnos[i]); + } + } - /* wait for syncpt counter to reach frame start event threshold */ - err = host1x_syncpt_wait(chan->frame_start_sp, thresh, - TEGRA_VI_SYNCPT_WAIT_TIMEOUT, &value); - if (err) { + if (capture_timedout) { dev_err_ratelimited(&chan->video.dev, "frame start syncpt timeout: %d\n", err); - /* increment syncpoint counter for timedout events */ - host1x_syncpt_incr(chan->frame_start_sp); - spin_lock(&chan->sp_incr_lock); - host1x_syncpt_incr(chan->mw_ack_sp); - spin_unlock(&chan->sp_incr_lock); - /* clear errors and recover */ - tegra_channel_capture_error_recover(chan); release_buffer(chan, buf, VB2_BUF_STATE_ERROR); return err; } @@ -376,21 +424,29 @@ static void tegra_channel_capture_done(struct tegra_vi_channel *chan, { enum vb2_buffer_state state = VB2_BUF_STATE_DONE; u32 value; - int ret; + bool capture_timedout = false; + int ret, i; - /* wait for syncpt counter to reach MW_ACK_DONE event threshold */ - ret = host1x_syncpt_wait(chan->mw_ack_sp, buf->mw_ack_sp_thresh, - TEGRA_VI_SYNCPT_WAIT_TIMEOUT, &value); - if (ret) { - dev_err_ratelimited(&chan->video.dev, - "MW_ACK_DONE syncpt timeout: %d\n", ret); - state = VB2_BUF_STATE_ERROR; - /* increment syncpoint counter for timedout event */ - spin_lock(&chan->sp_incr_lock); - host1x_syncpt_incr(chan->mw_ack_sp); - spin_unlock(&chan->sp_incr_lock); + for (i = 0; i < chan->numgangports; i++) { + /* + * Wait for syncpt counter to reach MW_ACK_DONE event threshold + */ + ret = host1x_syncpt_wait(chan->mw_ack_sp[i], + buf->mw_ack_sp_thresh[i], + TEGRA_VI_SYNCPT_WAIT_TIMEOUT, &value); + if (ret) { + capture_timedout = true; + state = VB2_BUF_STATE_ERROR; + /* increment syncpoint counter for timedout event */ + spin_lock(&chan->sp_incr_lock[i]); + host1x_syncpt_incr(chan->mw_ack_sp[i]); + spin_unlock(&chan->sp_incr_lock[i]); + } } + if (capture_timedout) + dev_err_ratelimited(&chan->video.dev, + "MW_ACK_DONE syncpt timeout: %d\n", ret); release_buffer(chan, buf, state); } @@ -463,14 +519,12 @@ static int tegra210_vi_start_streaming(struct vb2_queue *vq, u32 count) struct tegra_vi_channel *chan = vb2_get_drv_priv(vq); struct media_pipeline *pipe = &chan->video.pipe; u32 val; - int ret; + u8 *portnos = chan->portnos; + int ret, i; tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, VI_CG_2ND_LEVEL_EN); - /* clear errors */ - val = vi_csi_read(chan, TEGRA_VI_CSI_ERROR_STATUS); - vi_csi_write(chan, TEGRA_VI_CSI_ERROR_STATUS, val); - + /* clear syncpt errors */ val = tegra_vi_read(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR); tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR, val); @@ -489,7 +543,14 @@ static int tegra210_vi_start_streaming(struct vb2_queue *vq, u32 count) if (ret < 0) goto error_pipeline_start; - tegra_channel_capture_setup(chan); + /* clear csi errors and do capture setup for all ports in gang mode */ + for (i = 0; i < chan->numgangports; i++) { + val = vi_csi_read(chan, portnos[i], TEGRA_VI_CSI_ERROR_STATUS); + vi_csi_write(chan, portnos[i], TEGRA_VI_CSI_ERROR_STATUS, val); + + tegra_channel_capture_setup(chan, portnos[i]); + } + ret = tegra_channel_set_stream(chan, true); if (ret < 0) goto error_set_stream; @@ -743,10 +804,10 @@ static void tpg_write(struct tegra_csi *csi, u8 portno, unsigned int addr, /* * Tegra210 CSI operations */ -static void tegra210_csi_error_recover(struct tegra_csi_channel *csi_chan) +static void tegra210_csi_port_recover(struct tegra_csi_channel *csi_chan, + u8 portno) { struct tegra_csi *csi = csi_chan->csi; - unsigned int portno = csi_chan->csi_port_num; u32 val; /* @@ -795,16 +856,26 @@ static void tegra210_csi_error_recover(struct tegra_csi_channel *csi_chan) } } -static int tegra210_csi_start_streaming(struct tegra_csi_channel *csi_chan) +static void tegra210_csi_error_recover(struct tegra_csi_channel *csi_chan) +{ + u8 *portnos = csi_chan->csi_port_nums; + int i; + + for (i = 0; i < csi_chan->numgangports; i++) + tegra210_csi_port_recover(csi_chan, portnos[i]); +} + +static int +tegra210_csi_port_start_streaming(struct tegra_csi_channel *csi_chan, + u8 portno) { struct tegra_csi *csi = csi_chan->csi; - unsigned int portno = csi_chan->csi_port_num; u8 clk_settle_time = 0; u8 ths_settle_time = 10; u32 val; if (!csi_chan->pg_mode) - tegra_csi_calc_settle_time(csi_chan, &clk_settle_time, + tegra_csi_calc_settle_time(csi_chan, portno, &clk_settle_time, &ths_settle_time); csi_write(csi, portno, TEGRA_CSI_CLKEN_OVERRIDE, 0); @@ -903,10 +974,10 @@ static int tegra210_csi_start_streaming(struct tegra_csi_channel *csi_chan) return 0; } -static void tegra210_csi_stop_streaming(struct tegra_csi_channel *csi_chan) +static void +tegra210_csi_port_stop_streaming(struct tegra_csi_channel *csi_chan, u8 portno) { struct tegra_csi *csi = csi_chan->csi; - unsigned int portno = csi_chan->csi_port_num; u32 val; val = pp_read(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS); @@ -944,6 +1015,35 @@ static void tegra210_csi_stop_streaming(struct tegra_csi_channel *csi_chan) } } +static int tegra210_csi_start_streaming(struct tegra_csi_channel *csi_chan) +{ + u8 *portnos = csi_chan->csi_port_nums; + int ret, i; + + for (i = 0; i < csi_chan->numgangports; i++) { + ret = tegra210_csi_port_start_streaming(csi_chan, portnos[i]); + if (ret) + goto stream_start_fail; + } + + return 0; + +stream_start_fail: + for (i = i - 1; i >= 0; i--) + tegra210_csi_port_stop_streaming(csi_chan, portnos[i]); + + return ret; +} + +static void tegra210_csi_stop_streaming(struct tegra_csi_channel *csi_chan) +{ + u8 *portnos = csi_chan->csi_port_nums; + int i; + + for (i = 0; i < csi_chan->numgangports; i++) + tegra210_csi_port_stop_streaming(csi_chan, portnos[i]); +} + /* * Tegra210 CSI TPG frame rate table with horizontal and vertical * blanking intervals for corresponding format and resolution. diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index e866f7d..4812f2c 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -30,7 +30,6 @@ #include "vi.h" #include "video.h" -#define SURFACE_ALIGN_BYTES 64 #define MAX_CID_CONTROLS 1 static const struct tegra_video_format tegra_default_format = { @@ -1090,12 +1089,20 @@ static int vi_fmts_bitmap_init(struct tegra_vi_channel *chan) return 0; } +static void tegra_channel_host1x_syncpts_free(struct tegra_vi_channel *chan) +{ + int i; + + for (i = 0; i < chan->numgangports; i++) { + host1x_syncpt_free(chan->mw_ack_sp[i]); + host1x_syncpt_free(chan->frame_start_sp[i]); + } +} + static void tegra_channel_cleanup(struct tegra_vi_channel *chan) { v4l2_ctrl_handler_free(&chan->ctrl_handler); media_entity_cleanup(&chan->video.entity); - host1x_syncpt_free(chan->mw_ack_sp); - host1x_syncpt_free(chan->frame_start_sp); mutex_destroy(&chan->video_lock); } @@ -1107,6 +1114,7 @@ void tegra_channels_cleanup(struct tegra_vi *vi) return; list_for_each_entry_safe(chan, tmp, &vi->vi_chans, list) { + tegra_channel_host1x_syncpts_free(chan); tegra_channel_cleanup(chan); list_del(&chan->list); kfree(chan); @@ -1117,7 +1125,6 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) { struct tegra_vi *vi = chan->vi; struct tegra_video_device *vid = dev_get_drvdata(vi->client.host); - unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; int ret; mutex_init(&chan->video_lock); @@ -1125,7 +1132,6 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) INIT_LIST_HEAD(&chan->done); spin_lock_init(&chan->start_lock); spin_lock_init(&chan->done_lock); - spin_lock_init(&chan->sp_incr_lock); init_waitqueue_head(&chan->start_wait); init_waitqueue_head(&chan->done_wait); @@ -1140,26 +1146,13 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) chan->format.sizeimage = chan->format.bytesperline * TEGRA_DEF_HEIGHT; tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp); - chan->frame_start_sp = host1x_syncpt_request(&vi->client, flags); - if (!chan->frame_start_sp) { - dev_err(vi->dev, "failed to request frame start syncpoint\n"); - return -ENOMEM; - } - - chan->mw_ack_sp = host1x_syncpt_request(&vi->client, flags); - if (!chan->mw_ack_sp) { - dev_err(vi->dev, "failed to request memory ack syncpoint\n"); - ret = -ENOMEM; - goto free_fs_syncpt; - } - /* initialize the media entity */ chan->pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_pads_init(&chan->video.entity, 1, &chan->pad); if (ret < 0) { dev_err(vi->dev, "failed to initialize media entity: %d\n", ret); - goto free_mw_ack_syncpt; + return ret; } ret = v4l2_ctrl_handler_init(&chan->ctrl_handler, MAX_CID_CONTROLS); @@ -1175,7 +1168,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) chan->video.release = video_device_release_empty; chan->video.queue = &chan->queue; snprintf(chan->video.name, sizeof(chan->video.name), "%s-%s-%u", - dev_name(vi->dev), "output", chan->portno); + dev_name(vi->dev), "output", chan->portnos[0]); chan->video.vfl_type = VFL_TYPE_VIDEO; chan->video.vfl_dir = VFL_DIR_RX; chan->video.ioctl_ops = &tegra_channel_ioctl_ops; @@ -1211,10 +1204,6 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) v4l2_ctrl_handler_free(&chan->ctrl_handler); cleanup_media: media_entity_cleanup(&chan->video.entity); -free_mw_ack_syncpt: - host1x_syncpt_free(chan->mw_ack_sp); -free_fs_syncpt: - host1x_syncpt_free(chan->frame_start_sp); return ret; } @@ -1234,7 +1223,8 @@ static int tegra_vi_channel_alloc(struct tegra_vi *vi, unsigned int port_num, return -ENOMEM; chan->vi = vi; - chan->portno = port_num; + chan->portnos[0] = port_num; + chan->numgangports = 1; chan->of_node = node; list_add_tail(&chan->list, &vi->vi_chans); @@ -1312,7 +1302,7 @@ static int tegra_vi_channels_init(struct tegra_vi *vi) if (ret < 0) { dev_err(vi->dev, "failed to initialize channel-%d: %d\n", - chan->portno, ret); + chan->portnos[0], ret); goto cleanup; } } @@ -1326,6 +1316,46 @@ static int tegra_vi_channels_init(struct tegra_vi *vi) return ret; } +static int tegra_vi_channel_syncpt_init(struct tegra_vi *vi) +{ + struct tegra_vi_channel *chan; + unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; + struct host1x_syncpt *fs_sp; + struct host1x_syncpt *mw_sp; + int ret, i; + + list_for_each_entry(chan, &vi->vi_chans, list) { + for (i = 0; i < chan->numgangports; i++) { + fs_sp = host1x_syncpt_request(&vi->client, flags); + if (!fs_sp) { + dev_err(vi->dev, "failed to request frame start syncpoint\n"); + ret = -ENOMEM; + goto free_syncpts; + } + + mw_sp = host1x_syncpt_request(&vi->client, flags); + if (!mw_sp) { + dev_err(vi->dev, "failed to request memory ack syncpoint\n"); + ret = -ENOMEM; + host1x_syncpt_free(fs_sp); + goto free_syncpts; + } + + chan->frame_start_sp[i] = fs_sp; + chan->mw_ack_sp[i] = mw_sp; + spin_lock_init(&chan->sp_incr_lock[i]); + } + } + + return 0; + +free_syncpts: + list_for_each_entry_continue_reverse(chan, &vi->vi_chans, list) + tegra_channel_host1x_syncpts_free(chan); + + return ret; +} + void tegra_v4l2_nodes_cleanup_tpg(struct tegra_video_device *vid) { struct tegra_vi *vi = vid->vi; @@ -1576,8 +1606,9 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier) struct v4l2_async_subdev *asd; struct v4l2_subdev *subdev; struct tegra_vi_channel *chan; + struct tegra_csi_channel *csi_chan; struct tegra_vi *vi; - int ret; + int ret, i; chan = container_of(notifier, struct tegra_vi_channel, notifier); vi = chan->vi; @@ -1634,6 +1665,15 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier) v4l2_set_subdev_hostdata(subdev, chan); + /* + * Retrieve number of gang ports from csi channel and add consecutive + * ports to vi channel ports. + */ + csi_chan = v4l2_get_subdevdata(subdev); + chan->numgangports = csi_chan->numgangports; + for (i = 1; i < chan->numgangports; i++) + chan->portnos[i] = chan->portnos[0] + i * CSI_PORTS_PER_BRICK; + subdev = tegra_channel_get_remote_source_subdev(chan); v4l2_set_subdev_hostdata(subdev, chan); @@ -1759,7 +1799,8 @@ static int tegra_vi_graph_init(struct tegra_vi *vi) * next channels. */ list_for_each_entry(chan, &vi->vi_chans, list) { - remote = fwnode_graph_get_remote_node(fwnode, chan->portno, 0); + remote = fwnode_graph_get_remote_node(fwnode, chan->portnos[0], + 0); if (!remote) continue; @@ -1774,7 +1815,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi) if (ret < 0) { dev_err(vi->dev, "failed to register channel %d notifier: %d\n", - chan->portno, ret); + chan->portnos[0], ret); v4l2_async_notifier_cleanup(&chan->notifier); } } @@ -1825,11 +1866,27 @@ static int tegra_vi_init(struct host1x_client *client) if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) { ret = tegra_vi_graph_init(vi); if (ret < 0) - goto free_chans; + goto cleanup_chans; } + /* + * x8 capture uses multiple ports as gang with simultaneous capture + * of left half onto one x4 port and right half onto second x4 port. + * Total ports grouped together as gang is retrieved from CSI subdev + * during graph build. + * So, create host1x syncpts for all ports in a gang after graph init. + */ + ret = tegra_vi_channel_syncpt_init(vi); + if (ret < 0) + goto cleanup_graph; + return 0; +cleanup_graph: + tegra_vi_graph_cleanup(vi); +cleanup_chans: + list_for_each_entry(chan, &vi->vi_chans, list) + tegra_channel_cleanup(chan); free_chans: list_for_each_entry_safe(chan, tmp, &vi->vi_chans, list) { list_del(&chan->list); diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index 7d6b7a6..947e641 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -21,6 +21,8 @@ #include #include +#include "csi.h" + #define TEGRA_MIN_WIDTH 32U #define TEGRA_MAX_WIDTH 32768U #define TEGRA_MIN_HEIGHT 32U @@ -31,6 +33,7 @@ #define TEGRA_IMAGE_FORMAT_DEF 32 #define MAX_FORMAT_NUM 64 +#define SURFACE_ALIGN_BYTES 64 enum tegra_vi_pg_mode { TEGRA_VI_PG_DISABLED = 0, @@ -151,7 +154,8 @@ struct tegra_vi_graph_entity { * @done: list of capture done queued buffers * @done_lock: protects the capture done queue list * - * @portno: VI channel port number + * @portnos: VI channel port numbers + * @numgangports: number of ports combined together as a gang for capture * @of_node: device node of VI channel * * @ctrl_handler: V4L2 control handler of this video channel @@ -168,10 +172,10 @@ struct tegra_vi_channel { struct media_pad pad; struct tegra_vi *vi; - struct host1x_syncpt *frame_start_sp; - struct host1x_syncpt *mw_ack_sp; + struct host1x_syncpt *frame_start_sp[GANG_PORTS_MAX]; + struct host1x_syncpt *mw_ack_sp[GANG_PORTS_MAX]; /* protects the cpu syncpoint increment */ - spinlock_t sp_incr_lock; + spinlock_t sp_incr_lock[GANG_PORTS_MAX]; struct task_struct *kthread_start_capture; wait_queue_head_t start_wait; @@ -190,7 +194,8 @@ struct tegra_vi_channel { /* protects the capture done queue list */ spinlock_t done_lock; - unsigned char portno; + unsigned char portnos[GANG_PORTS_MAX]; + u8 numgangports; struct device_node *of_node; struct v4l2_ctrl_handler ctrl_handler; @@ -216,7 +221,7 @@ struct tegra_channel_buffer { struct list_head queue; struct tegra_vi_channel *chan; dma_addr_t addr; - u32 mw_ack_sp_thresh; + u32 mw_ack_sp_thresh[GANG_PORTS_MAX]; }; /*