From patchwork Thu Jun 23 14:31:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xavier Roumegue \(OSS\)" X-Patchwork-Id: 584443 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E4F9CCA485 for ; Thu, 23 Jun 2022 14:32:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231935AbiFWOck (ORCPT ); Thu, 23 Jun 2022 10:32:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231873AbiFWOci (ORCPT ); Thu, 23 Jun 2022 10:32:38 -0400 Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-eopbgr60050.outbound.protection.outlook.com [40.107.6.50]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0816E457A8; Thu, 23 Jun 2022 07:32:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hXXZZ4L3nnknqm7qq7itRw1D1V6zSAr1eC07LY0vboupk0yMqU4WeTH1Lpreew3OSJThYycCfpqVcylOA0ZhmXleXyRAazlCP3AQR7XpzithKRajuPoTk6DcXCmg7BxLLMEk1PMnAdNoImJq1Cz3dYZhq8iAtcplcijj0GpJftjJ/MOtlKlXSb6E/Bmm3Ch1PJDeht8EhGwqPrpENevomeKBCL9qGwNx0ykHND2MmIe533eCsKnWY2LXqV/JQI9aVOvd1PMaSU8isa9Urs5tQkEJj+9Ig4LUsvAZ3FrOkxs/IZSRkJVyYwDUYXCPlMYkmaTnGPXLkCnOrICQy6XV+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=eURltwAV4tNodGbg1ojZs9s+OEBwtGLfriuLHC1afSc=; b=ZuGTne2paSvd/EtlqW2o8/TZJggEa4Go+psFEy0ZoTm8ZK2pgQi4cIY0UNAFayQrUuLBSb+LxiLlubOTjoygkxJNxzuefWKtLOiXbcYVpr5ksUcdCfljcmfJD4lc9oScV4BRcml4q5K7Rf/7eJFisBc27y5SUpvmyCiSK5vcnm6LAvSovgzlJBfhnqmQBd/C+91ZYN3zHZPN0zSA6S9u2OvPK6l75h8HjRkXTGMJltjlPudh2YCYC+9AGv6jCk7Hxu5xnS3pilXqYpDr/oqKFkfv6UMuZVpp5L/j+BYuL1gVQvtU8BVXAg9F3CYxQcqq4GNFYhPrR7gak6y6MxaygQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=eURltwAV4tNodGbg1ojZs9s+OEBwtGLfriuLHC1afSc=; b=fBucCHlmJOn2E2TlHrQOEQNhFgUFm02Xc6PJgx3ksKFSb1NW5CZRdgEvNLEOQ5AjnlMYwVlgBRZewDIzLQArFu/mkZO1VpJUsWJsh7a3QPYnKddUX+lyU3LohdyfZEGL0YD9TJ7Q5Th1GAVDh1ytODZS3G2QN7BgAYfEeshAGjs= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) by VI1PR0401MB2288.eurprd04.prod.outlook.com (2603:10a6:800:28::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5373.16; Thu, 23 Jun 2022 14:32:32 +0000 Received: from PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485]) by PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485%5]) with mapi id 15.20.5353.022; Thu, 23 Jun 2022 14:32:31 +0000 From: Xavier Roumegue To: mchehab@kernel.org, hverkuil-cisco@xs4all.nl, stanimir.varbanov@linaro.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ideasonboard.com, robh+dt@kernel.org, nicolas@ndufresne.ca, alexander.stein@ew.tq-group.com Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v6 01/14] videodev2.h: add V4L2_CTRL_FLAG_DYNAMIC_ARRAY Date: Thu, 23 Jun 2022 16:31:02 +0200 Message-Id: <20220623143115.3185297-2-xavier.roumegue@oss.nxp.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> References: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> X-ClientProxiedBy: PR2P264CA0026.FRAP264.PROD.OUTLOOK.COM (2603:10a6:101:1::14) To PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 50bc2ca6-5d0a-4080-984c-08da552534bf X-MS-TrafficTypeDiagnostic: VI1PR0401MB2288:EE_ X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: I3BQO6PQEB5k7MWt0v6x0glSWVfGVHW1uqUHMxo7ORuwCp98Q5hAG954cnH7ACFMSsLefAkWK4RA0HDSnfd9HW4CvwWV09BVD47s/aakAMwrg8UpYcIDXB8vTWASeEDjj5CaFk3nCZpSNm+Xk7oJ7vFuMLMQmmeOJ8iyVRvM3hTZBR4hh7AJgi4YvT0IzRldvXUg/D7HqSpO1bQap+AKcJqpWHrjdFXbgazBi8XiJJps07bsVR+4fSVib45ttWicV6Lu4kG6i1y2fRNLaFpgqGZn23rbMdGPnG+IHtMuP2ug5AtOM8VzIJjai08MBpY9HGnVBSThxdYDenXa51teYTEW5wawS0hKmZuxD5cQCTjukWpD4oOgtC3kuV74NPtRjAH0pa+lNVMYjrTmTa4wYDOeknCSrQ/qmj2/viTCUsnk1BqmVvpwb+gAhOdzRDPWuhDchb1pjTxEC/1kd72qibWrKrBLoQPg8BBJHn6n9P+2AKwn/d6GQcg6ksMqKoeiK33To7oYr+uwDlQVApRIQB/QuJH6q6j3F1/vyqCuhq+t8hBpfLqjTBzuHbgIMTO7psr7bf+ahXKBPVtuPbzwIYqil2lYHXov/pUpIF0gnPSgbPL7n3OG6KI2lMWiFk5C+05G2xa7s4CFRWCbLLWUTHB7tNA2UaTpv1/TRNCmrn/Ws2YZTfXjKlbW3jIX9I5OMGsHemTYY4DIbkWyq5CiTA== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(346002)(136003)(376002)(366004)(396003)(39860400002)(52116002)(66476007)(4326008)(6506007)(86362001)(2616005)(38100700002)(6666004)(41300700001)(66556008)(8676002)(66946007)(2906002)(316002)(1076003)(44832011)(478600001)(8936002)(83380400001)(7416002)(6512007)(5660300002)(186003)(6486002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: Y4Qkw8Y7fBzr4nwteS3ta+yTo2qs3cd/yApj8Nlb18mYNIQikhqbh+0wrUbI9Z0PFfyOIjrUGTUPwEt37YDrVyM7T/kSzzbqpCRStnfDe0aq3bOrhX6BlrCavf5njdTHQN4mnhSc9XOsKoj7iGMbz6j7H9t4JmTBBchPhZB0v/9XZ8A9gXMHlue5L13B6gci9UcYfwyAU2ctk7CJdQSWPcpXleBbKtCqy706GEu+YqZFS9vzVBcibp/2JDKoJZf3+K6pzieHfPy78emEp8KO17c2bGCPl5tVeMukuUgnTWZw6ebkQ20/0u/aCsa96WxBUa4CCsOsFSwKO30N+Di/afRHAspYsO9QCq3jevW1tuFuDZDiLWlo5iOGzbNNVQ10MBowZIXa+8sWtqQ3qdWg/hHjJxHNa/iPuqvnGZ+RJNj+fEguyqTXzqg4a54ISiNj2DTVizjoAwIPtjpiSUbBhbkYfeCi8gcW7Hg02djMt7TFK1MCfJBPdobPSuJg7whcqJr+JFAH8GBadaNkdVgLAbSAAxvEzCRbaSerybtYf2q8pEwVc9+4vr7XI6S0ZGIeZmzYTDRjSEK1nXZLSXgZN2kuJF1cwKIrMkTAmCJM7FmhHD9yqCBW7sP7/RDejnVlV/C9ZgrwWtAU3tjOa31ve3oTob6tDDGzmRJ/wOcaq32+3PAm7auZ8YqTVPmGOeVaLcxyEiZ/Mf/OQhx4ePKEE+VVD0Lcc0fDnoeetrHnUv7TGAW76z7GFoU2sVtsayNkd+PCi03jNJODtOzxU3qbMmDl6rZOoi1DLVml9HzFl/aSOa/5TxTesIyuIpHwqahyte6Oh9VSXnYhm/g857USllWfvskpeMPRR6/s7iWYlk6et0WcTW4Yphr9AcnBQhGaOQcJltc2PGBJ0iloNwmeOiSL46oWkzGkji+SfN/vFMdnc+OGAmP0Zzlrg3w4qP6uXVWvtu+CUnRz3c2+K07iBTSlJkAIehapKQOzMY2QpVV/B614Ebfov0Kr3iJRIklwkPQyQi3WLhTZNOYRurkmUA+ZPpSDPm6tZhunLpCpWtua35BuoUtkwRLGUmtqZUtOvEHBj6yWRsjbrOWTpZD0wfcGhgacmq85jQ3c0G9xtigFNpcDam3ROssSWeorJ/YLmlfxsWbf97UyXDnUxbDOfob/zlg8IbKPcXUpM38K3j97zb4Tptn0M9C2DaOC4M7jKTQWTk8TtuDIQWg+Kj7ENMQlJvg6YEzhXYaNidIV+X2wiRrHv6naboMEITBP8s9IThdCfs+tOggKSo/LdazR7pSC9w1PjCc+87NKpupbOnrtUZlGed+l57Hc0Hf/ZGKiyg1O1GxpJxlG6bFV5n/wKsbsDQOU+qizN0z0/DPeib99Ec8ft8KmKiI1Cwxw/zZmHzwUUIuiSg0CX3Aghq/lztLk1yFNrE6GijznHUtoIqXTiv7kBVDgHmGYPRN+uPl1cYuRpmG6ywbOsQXrhbrAwo+JvORU/+JY09ZYNkCeENc/nw96aSJi6+PWS0BBrZsRi5SoFQZhsN00F9LzDJK1uMinla4PWaoH+zhJlyvG0u1oXjOz50X7WzbWU7k7uZEzxSCUxKp07QxYOtOGsYESWFiZMxuiz6KNYxmCcnKJYBtHB3+7tEZFEpuDYFKn2afHjItmxoQzLtshUHuLOPxtDX/UAi7rwDyJfb8OyOCRi2+Iy002g6YqRL9suZDjMVV6s0SM8bMtdxmi2eNZWNuIQSLubMc6nHdgVTqNiIoPirz6dNpdchp3TzgycC/OJLLkttgb52al X-MS-Exchange-AntiSpam-MessageData-1: uOxpGIesddbX9IsCghUihEoU7cuAwtvthD4= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 50bc2ca6-5d0a-4080-984c-08da552534bf X-MS-Exchange-CrossTenant-AuthSource: PAXPR04MB8703.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2022 14:32:31.5499 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: QsaispBxIdTNw5JImvEFimsbc4KCFPQIPpna2KOdZdFi//0EkuA8KWQIVkymMJRfHBfC63UDv+eqtUAY4b4p+Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0401MB2288 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil Add a new flag that indicates that this control is a dynamically sized array. Also document this flag. Currently dynamically sized arrays are limited to one dimensional arrays, but that might change in the future if there is a need for it. The initial use-case of dynamic arrays are stateless codecs. A frame can be divided in many slices, so you want to provide an array containing slice information for each slice. Typically the number of slices is small, but the standard allow for hundreds or thousands of slices. Dynamic arrays are a good solution since sizing the array for the worst case would waste substantial amounts of memory. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart --- .../userspace-api/media/v4l/vidioc-queryctrl.rst | 8 ++++++++ include/uapi/linux/videodev2.h | 1 + 2 files changed, 9 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst index 88f630252d98..a20dfa2a933b 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -625,6 +625,14 @@ See also the examples in :ref:`control`. ``V4L2_CTRL_FLAG_GRABBED`` flag when buffers are allocated or streaming is in progress since most drivers do not support changing the format in that case. + * - ``V4L2_CTRL_FLAG_DYNAMIC_ARRAY`` + - 0x0800 + - This control is a dynamically sized 1-dimensional array. It + behaves the same as a regular array, except that the number + of elements as reported by the ``elems`` field is between 1 and + ``dims[0]``. So setting the control with a differently sized + array will change the ``elems`` field when the control is + queried afterwards. Return Value ============ diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 343b95107fce..5c45ca18fac9 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1889,6 +1889,7 @@ struct v4l2_querymenu { #define V4L2_CTRL_FLAG_HAS_PAYLOAD 0x0100 #define V4L2_CTRL_FLAG_EXECUTE_ON_WRITE 0x0200 #define V4L2_CTRL_FLAG_MODIFY_LAYOUT 0x0400 +#define V4L2_CTRL_FLAG_DYNAMIC_ARRAY 0x0800 /* Query flags, to be ORed with the control ID */ #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 From patchwork Thu Jun 23 14:31:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xavier Roumegue \(OSS\)" X-Patchwork-Id: 584444 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E28D2CCA47E for ; Thu, 23 Jun 2022 14:32:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231834AbiFWOci (ORCPT ); Thu, 23 Jun 2022 10:32:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59936 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230448AbiFWOch (ORCPT ); Thu, 23 Jun 2022 10:32:37 -0400 Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05on2076.outbound.protection.outlook.com [40.107.20.76]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D2D1457A8; Thu, 23 Jun 2022 07:32:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=V0VMl/uyjT7RFjTx7wcfo3StecosDi0JT3BOaMyO2Oy+EAxmcmYS7u1cPFWcnNKQmlaKapIkmOXdFL72VIPaewC1xdKJTya+Tl6uETBluSa2JwPbNFAOji+U3XTFKUUSTcNt57NE1io7VmGstRXe1vZQZPtYU2HqLTdkv+DBHwrACCyevoydcUFih1UdWfTf0Z57fxGFetW3AM5I7QC6SornhVFPgZxWtTomf3Q4XdjCPTwbasrT9zmqtDxGxo3c4xmPSc/uWuTYaTrZ4uT65tsqBa3fbkCRtyp1Uqlu99wZS3CBhIyI+w91pbM4xszBLcl3+Pc+ggZmuAuTkQCdZg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=JGxcG32LmKX7ooLpNWYR/t/fuh6ioFzqYcaeGxBFXRs=; b=QX7FNUFgGrqAJ3IGZ9OOg2zzw+XptHsFiEg9bc0lTFrs70qnoxlzQUCXLgmEBz7F1xj7A0erhPXGbVsO0FCoROFsOFi4m1LWmNNNVkPfZce1FsAf42pTflnClZgFaDiBTUYaGEEhgOrlL+50aDTQE+ozDys7S4ZQ1GNIF8/Y2HXrbZinlEmU2EV0AgmDx2T2N51KNcEkN9zKCGn6ckkTBjCMgZLWcfMRQ+4/VccQ1f9ptpuADKEz/nDQBoLFHwjQbj5974HtrlCl5R5k4fqjazlJPzlVZg46LM9KFPxe6vmOw7C/ll/dxnI2SyQFyJ9vxIy1MexllvWvkFZNTcnEdg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=JGxcG32LmKX7ooLpNWYR/t/fuh6ioFzqYcaeGxBFXRs=; b=OG06HR/OwyEmUnCSKV24qe/xe+YIYmTTb3aZtIIv3I9s8FCp/m+yrtxRW0c8LEcSvkbAfdwUoKQV9maM4d6e+vHZFSlPszx6G470Hjjt/5An3JJfvgB3sRmYzarERas/MT4yEi0dJuOeOcvGvP5NXfvFtPNiX4XloRNKXaL4Hs0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) by DB8PR04MB6505.eurprd04.prod.outlook.com (2603:10a6:10:10d::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5353.22; Thu, 23 Jun 2022 14:32:32 +0000 Received: from PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485]) by PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485%5]) with mapi id 15.20.5353.022; Thu, 23 Jun 2022 14:32:32 +0000 From: Xavier Roumegue To: mchehab@kernel.org, hverkuil-cisco@xs4all.nl, stanimir.varbanov@linaro.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ideasonboard.com, robh+dt@kernel.org, nicolas@ndufresne.ca, alexander.stein@ew.tq-group.com Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v6 02/14] v4l2-ctrls: add support for dynamically allocated arrays. Date: Thu, 23 Jun 2022 16:31:03 +0200 Message-Id: <20220623143115.3185297-3-xavier.roumegue@oss.nxp.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> References: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> X-ClientProxiedBy: PR2P264CA0026.FRAP264.PROD.OUTLOOK.COM (2603:10a6:101:1::14) To PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: ebb0a6c2-4891-4845-68c7-08da55253515 X-MS-TrafficTypeDiagnostic: DB8PR04MB6505:EE_ X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: xMUsWflM3o5kAJ+J3nVU94tjAGzbRlFro6SBwytCIujj15njWHBeAq8VnYIQH7E97poBWZywP4sjDR7zs4B1ofpLqH7M0+LuElNGwKZJnXq9Z4iflNdD2iYg+QaRbFiQfWbDwhxA53EoWN2yrl/bVYUjsRArOyp/f9iMJyOESw4q/LuSNEEk/YmlBdZefGCDyB1TeWhu2IYn2P5pZkIAfit7AiWTH1MsyA7PRseugS2HK2TPwmFtcLlbRGo79INQXeC7Vs0Ne21v/FR4Ju+RIHrrUHGxx6opLSgSDCyvRmBtNel067QM8D2V94iUAqbgEIt1y4ZAMUEqFzHmeneiY9pMVikBOnkBLlJY7MD8sysB8QrTpXH3xf5dmCgwS5SsgV4GysNDvkRTrQqLonzaknwFvsa9hSwfV3ZrvCn81UWD/kGjaEXAk/Yd17lFIU2PHSftfutq1YPjL9QFb1QdH+HbGSgg7TmdCoacKL4oYahn+MGsncLekp3lMeO3TEbWmvLrzwJlny4GtItw1wxmqxp8oNIv83jL4pufi7gC6iXStVFKa+pEoCSyHyDNHfKpQPkH0sj+FS5VKQ86ryJNdv33QWtoGtDPq7JTEct2y7Cco5g5NYqzzebmsW+M5j3SamULf/CsPCcGL+lFewq9IaPGF6UFGGfewn8E/EvKENSCcERACJ5ORekaEDhc5bIj7bAoVUWlxxG69TWfIKDiYA== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(39860400002)(136003)(376002)(366004)(396003)(346002)(2906002)(38100700002)(6666004)(66946007)(86362001)(1076003)(66556008)(44832011)(8676002)(66476007)(6486002)(316002)(4326008)(478600001)(6512007)(5660300002)(7416002)(186003)(83380400001)(2616005)(52116002)(6506007)(8936002)(30864003)(41300700001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: 61pVj5qBKifZVyOOXlcIKBGdMnm1ksU+aJhZn6udqqT6/905oOurKc8vUFttxelU4titF84x2V/vDXxUdt22TAEkBEukbhk0ZMuezjcGl4zpd/aCWmWWvAP5qQkcqqyBIwK5LXKwzpG62ztC9kekE8N0acH0XtacShAVLJSJbIdaJ/gP8x41WhwtRKVYcVtChhFHiAhIDW2X4XyAEbeuwrhUnpxhKWJ64igy7XjGzLC9AVgRvL6ih6EqbLl9ilGm4+C2voqRycdDdcnRXqG3U9lpU+koQxdE+EH9VaG5iW3/7z3NQnh1Anr8W2Y8BzQdPPCQT9WxvusbyNNfF4w+RltbEmfmie4cqeG+ZCnEghqEY6RQ/rVtCglwIE5iiPJzCgH4wHDJO1yzxGRNgYgp4n5ldC4t/znNrerSgwp/vfRIEC29JqncAFyimeKxaHLroB6ip88h2YJHCvGP0mJXTDEU/dEd0Izv5vi9yWKHvZryuFxay//X/AWNYqK7QLCooXhVFtcjUtHZ2dNiTkhXxX/3rHHwRTZ9rqQdVKVct5hxin1gT1fP4+oHywXfVdVGZlVwD8MmEqNqX/Y//G1RHENbFn+T0tvcv8UrJwRTPcZiQdv7XOUNKMrO8inqCPuapRkQyaL5Ux1GjGTSLHbE2q+JoVwcvxdPwDaop3v61N+ZwfVAh2qlI8QakjhijDbRD+UjRtX/a/t7wUJlqKI82Af38wlGJgIfGrEbsMUufe6BBrv2/hJeJPKuWEkXXXtPxpp696r35KB4aKr+2Bl96y/+w1meroi//0n8K0L3fy4iw1GfRq4rDnKY4npn1n9l5x+zr4BISiz62HYusVq2in1ce7DQvYV9ixvEBByiLCf4e5qrmXYv4+yA4T+XLsAk1a3C3T7elGbUV4J38Ji4whRoMP/O/41h/sjH6lMYUug3Wjao4d1EbRwn8WWZoOKhIXMoUXckCE+1/lycu5/WfDQMDc9QONF6f5pahGjFfhwQ0+62AL/zaITQHVd1Y4KjbgHUEDqiYAGpum+KM+7daJUOMVjrfm5tTMK9ghBHWAJNbvypcpPhKcj0B1+ht4HjSaWo3RyOBYiOkzXflwlTSYJHUoNm9xNbXpyQYBIhTLVkpZjY+RuEAcj2sqMaW+SVvcu2AA3LaSqpZ+WVOQ7aw/7JhOc3dIsJPQ9U6YQxEOFrCz17KZFomO4YhQGB5iLP6+AT7AsvWUK8h+abORersGGMtA+n76JXsFEb4wNVzCNXG3yDIVrlizRxNgi04IKVfYlhy4cEiqs2BW2CbatrDhKjNmNbK9u2DxZ2JP+EoiQtCkm59nl5G9DFrDwS9FFDrsP8YftI3VayohzuGTTP56bAIN1t7dKJGQKTfAyUcOIJLUaAdjC0fYZgY/Pcl4+ulcfoCKzbMo0SJfb7n0aFWi4z2z1ozTfG08gevVCqQFnHj3VHFV9xRhjRcAtbD5S4wr0DUn/PbkK5zjVFygLfAhYVhm1UbDqYZs9G2viaX16KGFdpghQiCXn3oyhFOIfDGxTJTzmapBNuPULXeUUaWnzbv8By1QcNy1PCxycVbN4sf93ziDUcLVijc3korSkzSXSa1XPCJGQ6ZhniaKZne39gaKeAIlH+2JND5TK+W/BSpPITZE7+CmNhhQUdFrtjE3pLNpx1zDp0kLcgdxDy3HF//VU9gXjjE55Vj1wF/mt67ac3c0/ughJB/FaYRfl9yF1S7leNcUyaGaNWucxWVyjRh+8XaAesKBMM0aODeCepGBWq4fkGVi92KXCBcU8TWk5LpeSE X-MS-Exchange-AntiSpam-MessageData-1: CMKx+hdp8LCvfVBCvG+QMvo30Pv9aOzAZ6g= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: ebb0a6c2-4891-4845-68c7-08da55253515 X-MS-Exchange-CrossTenant-AuthSource: PAXPR04MB8703.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2022 14:32:32.0811 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: o/Dne1WZb/WTN3DVEBEjhdYKDrXgv1thqY6/lMpc0K7i5jeBOhxGw7fQ1J89cLamNdYZG9deW8uaIquOBf3Eww== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR04MB6505 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil Implement support for dynamically allocated arrays. Most of the changes concern keeping track of the number of elements of the array and the number of elements allocated for the array and reallocating memory if needed. Signed-off-by: Hans Verkuil --- drivers/media/v4l2-core/v4l2-ctrls-api.c | 103 ++++++++--- drivers/media/v4l2-core/v4l2-ctrls-core.c | 182 +++++++++++++++---- drivers/media/v4l2-core/v4l2-ctrls-priv.h | 3 +- drivers/media/v4l2-core/v4l2-ctrls-request.c | 13 +- include/media/v4l2-ctrls.h | 42 ++++- 5 files changed, 272 insertions(+), 71 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c index db9baa0bd05f..50d012ba3c02 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c @@ -97,29 +97,47 @@ static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) return ptr_to_user(c, ctrl, ctrl->p_new); } -/* Helper function: copy the caller-provider value to the given control value */ -static int user_to_ptr(struct v4l2_ext_control *c, - struct v4l2_ctrl *ctrl, - union v4l2_ctrl_ptr ptr) +/* Helper function: copy the caller-provider value as the new control value */ +static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) { int ret; u32 size; - ctrl->is_new = 1; + ctrl->is_new = 0; + if (ctrl->is_dyn_array && + c->size > ctrl->p_dyn_alloc_elems * ctrl->elem_size) { + void *old = ctrl->p_dyn; + void *tmp = kvzalloc(2 * c->size, GFP_KERNEL); + + if (!tmp) + return -ENOMEM; + memcpy(tmp, ctrl->p_new.p, ctrl->elems * ctrl->elem_size); + memcpy(tmp + c->size, ctrl->p_cur.p, ctrl->elems * ctrl->elem_size); + ctrl->p_new.p = tmp; + ctrl->p_cur.p = tmp + c->size; + ctrl->p_dyn = tmp; + ctrl->p_dyn_alloc_elems = c->size / ctrl->elem_size; + kvfree(old); + } + if (ctrl->is_ptr && !ctrl->is_string) { + unsigned int elems = c->size / ctrl->elem_size; unsigned int idx; - ret = copy_from_user(ptr.p, c->ptr, c->size) ? -EFAULT : 0; - if (ret || !ctrl->is_array) - return ret; - for (idx = c->size / ctrl->elem_size; idx < ctrl->elems; idx++) - ctrl->type_ops->init(ctrl, idx, ptr); + if (copy_from_user(ctrl->p_new.p, c->ptr, c->size)) + return -EFAULT; + ctrl->is_new = 1; + if (ctrl->is_dyn_array) + ctrl->new_elems = elems; + else if (ctrl->is_array) + for (idx = elems; idx < ctrl->elems; idx++) + ctrl->type_ops->init(ctrl, idx, ctrl->p_new); return 0; } switch (ctrl->type) { case V4L2_CTRL_TYPE_INTEGER64: - *ptr.p_s64 = c->value64; + *ctrl->p_new.p_s64 = c->value64; break; case V4L2_CTRL_TYPE_STRING: size = c->size; @@ -127,32 +145,27 @@ static int user_to_ptr(struct v4l2_ext_control *c, return -ERANGE; if (size > ctrl->maximum + 1) size = ctrl->maximum + 1; - ret = copy_from_user(ptr.p_char, c->string, size) ? -EFAULT : 0; + ret = copy_from_user(ctrl->p_new.p_char, c->string, size) ? -EFAULT : 0; if (!ret) { - char last = ptr.p_char[size - 1]; + char last = ctrl->p_new.p_char[size - 1]; - ptr.p_char[size - 1] = 0; + ctrl->p_new.p_char[size - 1] = 0; /* * If the string was longer than ctrl->maximum, * then return an error. */ - if (strlen(ptr.p_char) == ctrl->maximum && last) + if (strlen(ctrl->p_new.p_char) == ctrl->maximum && last) return -ERANGE; } return ret; default: - *ptr.p_s32 = c->value; + *ctrl->p_new.p_s32 = c->value; break; } + ctrl->is_new = 1; return 0; } -/* Helper function: copy the caller-provider value as the new control value */ -static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl) -{ - return user_to_ptr(c, ctrl, ctrl->p_new); -} - /* * VIDIOC_G/TRY/S_EXT_CTRLS implementation */ @@ -254,7 +267,31 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, have_clusters = true; if (ctrl->cluster[0] != ctrl) ref = find_ref_lock(hdl, ctrl->cluster[0]->id); - if (ctrl->is_ptr && !ctrl->is_string) { + if (ctrl->is_dyn_array) { + unsigned int max_size = ctrl->dims[0] * ctrl->elem_size; + unsigned int tot_size = ctrl->elem_size; + + if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) + tot_size *= ref->p_req_elems; + else + tot_size *= ctrl->elems; + + c->size = ctrl->elem_size * (c->size / ctrl->elem_size); + if (get) { + if (c->size < tot_size) { + c->size = tot_size; + return -ENOSPC; + } + c->size = tot_size; + } else { + if (c->size > max_size) { + c->size = max_size; + return -ENOSPC; + } + if (!c->size) + return -EFAULT; + } + } else if (ctrl->is_ptr && !ctrl->is_string) { unsigned int tot_size = ctrl->elems * ctrl->elem_size; if (c->size < tot_size) { @@ -346,7 +383,7 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) * * Note that v4l2_g_ext_ctrls_common() with 'which' set to * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was - * completed, and in that case valid_p_req is true for all controls. + * completed, and in that case p_req_valid is true for all controls. */ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs, @@ -430,7 +467,9 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, if (is_default) ret = def_to_user(cs->controls + idx, ref->ctrl); - else if (is_request && ref->valid_p_req) + else if (is_request && ref->p_req_dyn_enomem) + ret = -ENOMEM; + else if (is_request && ref->p_req_valid) ret = req_to_user(cs->controls + idx, ref); else if (is_volatile) ret = new_to_user(cs->controls + idx, ref->ctrl); @@ -457,6 +496,17 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev, } EXPORT_SYMBOL(v4l2_g_ext_ctrls); +/* Validate a new control */ +static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new) +{ + unsigned int idx; + int err = 0; + + for (idx = 0; !err && idx < ctrl->new_elems; idx++) + err = ctrl->type_ops->validate(ctrl, idx, p_new); + return err; +} + /* Validate controls. */ static int validate_ctrls(struct v4l2_ext_controls *cs, struct v4l2_ctrl_helper *helpers, @@ -872,6 +922,9 @@ int __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl, /* It's a driver bug if this happens. */ if (WARN_ON(ctrl->type != type)) return -EINVAL; + /* Setting dynamic arrays is not (yet?) supported. */ + if (WARN_ON(ctrl->is_dyn_array)) + return -EINVAL; memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size); return set_ctrl(NULL, ctrl, 0); } diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 949c1884d9c1..ff8a61f24d0a 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -991,11 +991,12 @@ EXPORT_SYMBOL(v4l2_ctrl_notify); /* Copy the one value to another. */ static void ptr_to_ptr(struct v4l2_ctrl *ctrl, - union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to) + union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to, + unsigned int elems) { if (ctrl == NULL) return; - memcpy(to.p, from.p_const, ctrl->elems * ctrl->elem_size); + memcpy(to.p, from.p_const, elems * ctrl->elem_size); } /* Copy the new value to the current value. */ @@ -1008,8 +1009,11 @@ void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) /* has_changed is set by cluster_changed */ changed = ctrl->has_changed; - if (changed) - ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur); + if (changed) { + if (ctrl->is_dyn_array) + ctrl->elems = ctrl->new_elems; + ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur, ctrl->elems); + } if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) { /* Note: CH_FLAGS is only set for auto clusters. */ @@ -1039,36 +1043,122 @@ void cur_to_new(struct v4l2_ctrl *ctrl) { if (ctrl == NULL) return; - ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new); + if (ctrl->is_dyn_array) + ctrl->new_elems = ctrl->elems; + ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new, ctrl->new_elems); +} + +static bool req_alloc_dyn_array(struct v4l2_ctrl_ref *ref, u32 elems) +{ + void *tmp; + + if (elems < ref->p_req_dyn_alloc_elems) + return true; + + tmp = kvmalloc(elems * ref->ctrl->elem_size, GFP_KERNEL); + + if (!tmp) { + ref->p_req_dyn_enomem = true; + return false; + } + ref->p_req_dyn_enomem = false; + kvfree(ref->p_req.p); + ref->p_req.p = tmp; + ref->p_req_dyn_alloc_elems = elems; + return true; } /* Copy the new value to the request value */ void new_to_req(struct v4l2_ctrl_ref *ref) { + struct v4l2_ctrl *ctrl; + if (!ref) return; - ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req); - ref->valid_p_req = true; + + ctrl = ref->ctrl; + if (ctrl->is_dyn_array && !req_alloc_dyn_array(ref, ctrl->new_elems)) + return; + + ref->p_req_elems = ctrl->new_elems; + ptr_to_ptr(ctrl, ctrl->p_new, ref->p_req, ref->p_req_elems); + ref->p_req_valid = true; } /* Copy the current value to the request value */ void cur_to_req(struct v4l2_ctrl_ref *ref) { + struct v4l2_ctrl *ctrl; + if (!ref) return; - ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req); - ref->valid_p_req = true; + + ctrl = ref->ctrl; + if (ctrl->is_dyn_array && !req_alloc_dyn_array(ref, ctrl->elems)) + return; + + ref->p_req_elems = ctrl->elems; + ptr_to_ptr(ctrl, ctrl->p_cur, ref->p_req, ctrl->elems); + ref->p_req_valid = true; } /* Copy the request value to the new value */ -void req_to_new(struct v4l2_ctrl_ref *ref) +int req_to_new(struct v4l2_ctrl_ref *ref) { + struct v4l2_ctrl *ctrl; + if (!ref) - return; - if (ref->valid_p_req) - ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new); - else - ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new); + return 0; + + ctrl = ref->ctrl; + + /* + * This control was never set in the request, so just use the current + * value. + */ + if (!ref->p_req_valid) { + if (ctrl->is_dyn_array) + ctrl->new_elems = ctrl->elems; + ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new, ctrl->new_elems); + return 0; + } + + /* Not a dynamic array, so just copy the request value */ + if (!ctrl->is_dyn_array) { + ptr_to_ptr(ctrl, ref->p_req, ctrl->p_new, ctrl->new_elems); + return 0; + } + + /* Sanity check, should never happen */ + if (WARN_ON(!ref->p_req_dyn_alloc_elems)) + return -ENOMEM; + + /* + * Check if the number of elements in the request is more than the + * elements in ctrl->p_dyn. If so, attempt to realloc ctrl->p_dyn. + * Note that p_dyn is allocated with twice the number of elements + * in the dynamic array since it has to store both the current and + * new value of such a control. + */ + if (ref->p_req_elems > ctrl->p_dyn_alloc_elems) { + unsigned int sz = ref->p_req_elems * ctrl->elem_size; + void *old = ctrl->p_dyn; + void *tmp = kvzalloc(2 * sz, GFP_KERNEL); + + if (!tmp) + return -ENOMEM; + memcpy(tmp, ctrl->p_new.p, ctrl->elems * ctrl->elem_size); + memcpy(tmp + sz, ctrl->p_cur.p, ctrl->elems * ctrl->elem_size); + ctrl->p_new.p = tmp; + ctrl->p_cur.p = tmp + sz; + ctrl->p_dyn = tmp; + ctrl->p_dyn_alloc_elems = ref->p_req_elems; + kvfree(old); + } + + ctrl->new_elems = ref->p_req_elems; + ptr_to_ptr(ctrl, ref->p_req, ctrl->p_new, ctrl->new_elems); + return 0; } /* Control range checking */ @@ -1110,17 +1200,6 @@ int check_range(enum v4l2_ctrl_type type, } } -/* Validate a new control */ -int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new) -{ - unsigned idx; - int err = 0; - - for (idx = 0; !err && idx < ctrl->elems; idx++) - err = ctrl->type_ops->validate(ctrl, idx, p_new); - return err; -} - /* Set the handler's error code if it wasn't set earlier already */ static inline int handler_set_err(struct v4l2_ctrl_handler *hdl, int err) { @@ -1164,6 +1243,8 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl) /* Free all nodes */ list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) { list_del(&ref->node); + if (ref->p_req_dyn_alloc_elems) + kvfree(ref->p_req.p); kfree(ref); } /* Free all controls owned by the handler */ @@ -1171,6 +1252,7 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl) list_del(&ctrl->node); list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node) list_del(&sev->node); + kvfree(ctrl->p_dyn); kvfree(ctrl); } kvfree(hdl->buckets); @@ -1286,7 +1368,7 @@ int handler_new_ref(struct v4l2_ctrl_handler *hdl, if (hdl->error) return hdl->error; - if (allocate_req) + if (allocate_req && !ctrl->is_dyn_array) size_extra_req = ctrl->elems * ctrl->elem_size; new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL); if (!new_ref) @@ -1460,7 +1542,6 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, elem_size = sizeof(s32); break; } - tot_ctrl_size = elem_size * elems; /* Sanity checks */ if (id == 0 || name == NULL || !elem_size || @@ -1481,17 +1562,33 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, handler_set_err(hdl, -EINVAL); return NULL; } + if (flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY) { + /* + * For now only support this for one-dimensional arrays only. + * + * This can be relaxed in the future, but this will + * require more effort. + */ + if (nr_of_dims != 1) { + handler_set_err(hdl, -EINVAL); + return NULL; + } + /* Start with just 1 element */ + elems = 1; + } + tot_ctrl_size = elem_size * elems; sz_extra = 0; if (type == V4L2_CTRL_TYPE_BUTTON) flags |= V4L2_CTRL_FLAG_WRITE_ONLY | V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; else if (type == V4L2_CTRL_TYPE_CTRL_CLASS) flags |= V4L2_CTRL_FLAG_READ_ONLY; - else if (type == V4L2_CTRL_TYPE_INTEGER64 || - type == V4L2_CTRL_TYPE_STRING || - type >= V4L2_CTRL_COMPOUND_TYPES || - is_array) + else if (!(flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY) && + (type == V4L2_CTRL_TYPE_INTEGER64 || + type == V4L2_CTRL_TYPE_STRING || + type >= V4L2_CTRL_COMPOUND_TYPES || + is_array)) sz_extra += 2 * tot_ctrl_size; if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) @@ -1520,7 +1617,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, ctrl->is_ptr = is_array || type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string; ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64; ctrl->is_array = is_array; + ctrl->is_dyn_array = !!(flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY); ctrl->elems = elems; + ctrl->new_elems = elems; ctrl->nr_of_dims = nr_of_dims; if (nr_of_dims) memcpy(ctrl->dims, dims, nr_of_dims * sizeof(dims[0])); @@ -1533,6 +1632,16 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, ctrl->cur.val = ctrl->val = def; data = &ctrl[1]; + if (ctrl->is_dyn_array) { + ctrl->p_dyn_alloc_elems = elems; + ctrl->p_dyn = kvzalloc(2 * elems * elem_size, GFP_KERNEL); + if (!ctrl->p_dyn) { + kvfree(ctrl); + return NULL; + } + data = ctrl->p_dyn; + } + if (!ctrl->is_int) { ctrl->p_new.p = data; ctrl->p_cur.p = data + tot_ctrl_size; @@ -1542,7 +1651,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, } if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) { - ctrl->p_def.p = ctrl->p_cur.p + tot_ctrl_size; + if (ctrl->is_dyn_array) + ctrl->p_def.p = &ctrl[1]; + else + ctrl->p_def.p = ctrl->p_cur.p + tot_ctrl_size; memcpy(ctrl->p_def.p, p_def.p_const, elem_size); } @@ -1552,6 +1664,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, } if (handler_new_ref(hdl, ctrl, NULL, false, false)) { + kvfree(ctrl->p_dyn); kvfree(ctrl); return NULL; } @@ -1889,6 +2002,9 @@ static int cluster_changed(struct v4l2_ctrl *master) continue; } + if (ctrl->elems != ctrl->new_elems) + ctrl_changed = true; + for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++) ctrl_changed = !ctrl->type_ops->equal(ctrl, idx, ctrl->p_cur, ctrl->p_new); diff --git a/drivers/media/v4l2-core/v4l2-ctrls-priv.h b/drivers/media/v4l2-core/v4l2-ctrls-priv.h index d4bf2c716f97..aba6176fab6c 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-priv.h +++ b/drivers/media/v4l2-core/v4l2-ctrls-priv.h @@ -57,10 +57,9 @@ void cur_to_new(struct v4l2_ctrl *ctrl); void cur_to_req(struct v4l2_ctrl_ref *ref); void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags); void new_to_req(struct v4l2_ctrl_ref *ref); -void req_to_new(struct v4l2_ctrl_ref *ref); +int req_to_new(struct v4l2_ctrl_ref *ref); void send_initial_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl); void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes); -int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new); int handler_new_ref(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl *ctrl, struct v4l2_ctrl_ref **ctrl_ref, diff --git a/drivers/media/v4l2-core/v4l2-ctrls-request.c b/drivers/media/v4l2-core/v4l2-ctrls-request.c index 7d098f287fd9..c637049d7a2b 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-request.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-request.c @@ -143,7 +143,7 @@ v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id) { struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id); - return (ref && ref->valid_p_req) ? ref->ctrl : NULL; + return (ref && ref->p_req_valid) ? ref->ctrl : NULL; } EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find); @@ -373,7 +373,7 @@ void v4l2_ctrl_request_complete(struct media_request *req, v4l2_ctrl_unlock(master); continue; } - if (ref->valid_p_req) + if (ref->p_req_valid) continue; /* Copy the current control value into the request */ @@ -442,7 +442,7 @@ int v4l2_ctrl_request_setup(struct media_request *req, struct v4l2_ctrl_ref *r = find_ref(hdl, master->cluster[i]->id); - if (r->valid_p_req) { + if (r->p_req_valid) { have_new_data = true; break; } @@ -458,7 +458,11 @@ int v4l2_ctrl_request_setup(struct media_request *req, struct v4l2_ctrl_ref *r = find_ref(hdl, master->cluster[i]->id); - req_to_new(r); + ret = req_to_new(r); + if (ret) { + v4l2_ctrl_unlock(master); + goto error; + } master->cluster[i]->is_new = 1; r->req_done = true; } @@ -490,6 +494,7 @@ int v4l2_ctrl_request_setup(struct media_request *req, break; } +error: media_request_object_put(obj); return ret; } diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index b3ce438f1329..f4105de8a8d2 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -185,6 +185,8 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); * and/or has type %V4L2_CTRL_TYPE_STRING. In other words, &struct * v4l2_ext_control uses field p to point to the data. * @is_array: If set, then this control contains an N-dimensional array. + * @is_dyn_array: If set, then this control contains a dynamically sized 1-dimensional array. + * If this is set, then @is_array is also set. * @has_volatiles: If set, then one or more members of the cluster are volatile. * Drivers should never touch this flag. * @call_notify: If set, then call the handler's notify function whenever the @@ -205,6 +207,9 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); * @step: The control's step value for non-menu controls. * @elems: The number of elements in the N-dimensional array. * @elem_size: The size in bytes of the control. + * @new_elems: The number of elements in p_new. This is the same as @elems, + * except for dynamic arrays. In that case it is in the range of + * 1 to @p_dyn_alloc_elems. * @dims: The size of each dimension. * @nr_of_dims:The number of dimensions in @dims. * @menu_skip_mask: The control's skip mask for menu controls. This makes it @@ -223,15 +228,21 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv); * :math:`ceil(\frac{maximum - minimum}{step}) + 1`. * Used only if the @type is %V4L2_CTRL_TYPE_INTEGER_MENU. * @flags: The control's flags. - * @cur: Structure to store the current value. - * @cur.val: The control's current value, if the @type is represented via - * a u32 integer (see &enum v4l2_ctrl_type). - * @val: The control's new s32 value. * @priv: The control's private pointer. For use by the driver. It is * untouched by the control framework. Note that this pointer is * not freed when the control is deleted. Should this be needed * then a new internal bitfield can be added to tell the framework * to free this pointer. + * @p_dyn: Pointer to the dynamically allocated array. Only valid if + * @is_dyn_array is true. + * @p_dyn_alloc_elems: The number of elements in the dynamically allocated + * array for both the cur and new values. So @p_dyn is actually + * sized for 2 * @p_dyn_alloc_elems * @elem_size. Only valid if + * @is_dyn_array is true. + * @cur: Structure to store the current value. + * @cur.val: The control's current value, if the @type is represented via + * a u32 integer (see &enum v4l2_ctrl_type). + * @val: The control's new s32 value. * @p_def: The control's default value represented via a union which * provides a standard way of accessing control types * through a pointer (for compound controls only). @@ -260,6 +271,7 @@ struct v4l2_ctrl { unsigned int is_string:1; unsigned int is_ptr:1; unsigned int is_array:1; + unsigned int is_dyn_array:1; unsigned int has_volatiles:1; unsigned int call_notify:1; unsigned int manual_mode_value:8; @@ -272,6 +284,7 @@ struct v4l2_ctrl { s64 minimum, maximum, default_value; u32 elems; u32 elem_size; + u32 new_elems; u32 dims[V4L2_CTRL_MAX_DIMS]; u32 nr_of_dims; union { @@ -284,6 +297,8 @@ struct v4l2_ctrl { }; unsigned long flags; void *priv; + void *p_dyn; + u32 p_dyn_alloc_elems; s32 val; struct { s32 val; @@ -309,12 +324,22 @@ struct v4l2_ctrl { * the control has been applied. This prevents applying controls * from a cluster with multiple controls twice (when the first * control of a cluster is applied, they all are). - * @valid_p_req: If set, then p_req contains the control value for the request. + * @p_req_valid: If set, then p_req contains the control value for the request. + * @p_req_dyn_enomem: If set, then p_req is invalid since allocating space for + * a dynamic array failed. Attempting to read this value shall + * result in ENOMEM. Only valid if ctrl->is_dyn_array is true. + * @p_req_dyn_alloc_elems: The number of elements allocated for the dynamic + * array. Only valid if @p_req_valid and ctrl->is_dyn_array are + * true. + * @p_req_elems: The number of elements in @p_req. This is the same as + * ctrl->elems, except for dynamic arrays. In that case it is in + * the range of 1 to @p_req_dyn_alloc_elems. Only valid if + * @p_req_valid is true. * @p_req: If the control handler containing this control reference * is bound to a media request, then this points to the * value of the control that must be applied when the request * is executed, or to the value of the control at the time - * that the request was completed. If @valid_p_req is false, + * that the request was completed. If @p_req_valid is false, * then this control was never set for this request and the * control will not be updated when this request is applied. * @@ -329,7 +354,10 @@ struct v4l2_ctrl_ref { struct v4l2_ctrl_helper *helper; bool from_other_dev; bool req_done; - bool valid_p_req; + bool p_req_valid; + bool p_req_dyn_enomem; + u32 p_req_dyn_alloc_elems; + u32 p_req_elems; union v4l2_ctrl_ptr p_req; }; From patchwork Thu Jun 23 14:31:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xavier Roumegue \(OSS\)" X-Patchwork-Id: 584442 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3AE4EC433EF for ; Thu, 23 Jun 2022 14:32:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231962AbiFWOcm (ORCPT ); Thu, 23 Jun 2022 10:32:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59982 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231922AbiFWOck (ORCPT ); Thu, 23 Jun 2022 10:32:40 -0400 Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-eopbgr60050.outbound.protection.outlook.com [40.107.6.50]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E53FE4578F; Thu, 23 Jun 2022 07:32:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RyA5qKy4RZNhrpY2FVsLpq65caBkSFfIA1obzzgVQX6d5fSrsE7dE5QBqqqoS7PIT05dtfyK0D/t5NIMiN+grswbGI/TwyeIEf1eQeo9a24nvqQfXRj2CwDH5fKqj59eWlaHCankAZ5qDfYuH4VxjdjV5rRQlZxi42mEuMPhFNefFmrvgiOJtYtQsbyrpho2y7Xnnum3cVr69MfzYJpRcTTqxg8ORfiREOQxJXs8LGfnMo0bxMa7yZoDxYXjxivkxOMx1NRQsvLJBn4ly/d6V+z7o6NobRNDaj9vwTsLYTeihw0uKUAHf6ZDJ0DU1vcTMwRNYP9ozH6MOBLQkZvPwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=fmGxDEt04njvwKMMNcP8XCQYF55GlfvOprSaEwf1L2o=; b=UpJ6R9cjxdv9RQ/HmaAM/EKJdGqadKoK7THcj2VctOZHvvRTpPuhHmOh/XF9IcrleFUxmjnQ6+U0EegCcXTz5XdYLUIRNHWuBFQlVs7l08Y3EDSFhTDMSxHB9DjjhgKWEM9VfKvwLOp0d7+MYUqjp+/OmYjbaK0BUX7t8WFXi3U6QhIkAKyvH29BAx51YA5SkZt0UJUF+1+UjfCD0GgVyWBBRa+VdvUzSMsVzTxyTpOf6DCCfEtFBFf8wHHc9j2sXMCX7raPy0xiU6y+mhE44cuxoL11nQfOQOoimXbRjqyhP5NJw+qE2vXCR0a5maD99aWVwrSOyJv24Fnog87Eww== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=fmGxDEt04njvwKMMNcP8XCQYF55GlfvOprSaEwf1L2o=; b=c3937Ug6mtJnE7MYGRDx4GKpBJkDEVqs8HK+uQIC27D8PB4KRTFgzSs39hKOM19xSoIRKbaXc70pGYBOreHzHTax0g508MeYEtrHcVscsuX0ucALAk35bmLDp2Ls3/w/9PO3cee9tujEO0xEgSqvNhj+Y7YxwcjH+tYIz1qZZqk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) by VI1PR0401MB2288.eurprd04.prod.outlook.com (2603:10a6:800:28::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5373.16; Thu, 23 Jun 2022 14:32:33 +0000 Received: from PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485]) by PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485%5]) with mapi id 15.20.5353.022; Thu, 23 Jun 2022 14:32:33 +0000 From: Xavier Roumegue To: mchehab@kernel.org, hverkuil-cisco@xs4all.nl, stanimir.varbanov@linaro.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ideasonboard.com, robh+dt@kernel.org, nicolas@ndufresne.ca, alexander.stein@ew.tq-group.com Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v6 05/14] v4l2-ctrls: alloc arrays in ctrl_ref Date: Thu, 23 Jun 2022 16:31:06 +0200 Message-Id: <20220623143115.3185297-6-xavier.roumegue@oss.nxp.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> References: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> X-ClientProxiedBy: PR2P264CA0026.FRAP264.PROD.OUTLOOK.COM (2603:10a6:101:1::14) To PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: f3b3404d-9569-4307-b67c-08da55253614 X-MS-TrafficTypeDiagnostic: VI1PR0401MB2288:EE_ X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: y1/XUa25vburSrduT0DewbmrY/ZIsggzlEb+FnqAIDs2PoQR8eXKg3Ob/78FtmUZ+kEEFcn2uDu6O2ONCZG4qQCat5I7tGOrgMSx+3Uvq6yXNarhpLDzSFzbhjB+9+J0ysmiKo9bWSVtuHBTrPjYN0n1vrU4u5uk55FdlBMqqTbXESxkAS6h/PT8tb/EJHRNbYmI9N2FgorSZks9BNGlzAJS+V6TFsJp8kdcoTgyoU2KjoTofGG8ueI35gnk6rMJdMoR2wfhXMFAPAihd6yLnWl+G/E60Rlo3suvZ+NMPrHuOKE7GexL1aVoMQ22lYwH/1I8HVLq9pdKYsc0atoaQQR123Pwb4Wxv920NbzhP5bzZGrdO5BbR8XLmZkgR1CD0IRz5/8BvliWL9ak4WwD120N+8HUzjIU3k5n7N5G0p0co+fX0v015qysbxToMyjWwtrMPLEoqrhLAJWM5/wyb8FIdsVHlvxV59TVEgfUoiROeE+Rw5S6+eG71LxNueWGFH/8wmJHjMThcGWBN7GV5t/TT/C3/qiZTzmDJUtdly/RYsioCgkvvLATx4D3RywdtDo9ymt0EqQokt9gtw6B/+iTU53l8YEOpGtmVBQY9k+Kzs78b6FlrgWhare9J+2Dfemiv7gMcY+B9rwD/9pOtlfAUcN1wWxwewL6txE/zLLtsXK1ab9KxJOA4l4k0V2Kf7YPf7jEBPc292/e1rC/kQ== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(346002)(136003)(376002)(366004)(396003)(39860400002)(52116002)(66476007)(4326008)(6506007)(86362001)(2616005)(38100700002)(6666004)(41300700001)(66556008)(8676002)(66946007)(2906002)(316002)(1076003)(44832011)(478600001)(8936002)(83380400001)(7416002)(6512007)(5660300002)(186003)(6486002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: HQPrUcbJNjBSpBcEnaqs+o9U9V0+2B8mrohUEDfbii40ltoo+f7m9TvZQ0Sd8OdqIO1VeEKliIdaa/vADnHzjJabAGGQJFhtN+WItu/h96Gf22HadqS06MGDLmGK/n1UNNSPeXCsVA+NzTtDtnipVLVroSnfBOVnmxh3pBNCEK4xjqfmLEFvMM4xZA5OSnpMipPvg40Zwr+t0FqJxKgVLE0c9E1npuVICBna0EaIl/4J7Y59/tCtyK64bw5+OBBLVhVCCdNDMqV9r2slYfdJX/KDTgu/l+GdUVijVf7lkiTJ15UnybtGx0in6SqU6EZZInS8V35QOhgv30pINrXqWwVoAPcitga2KOgx40+7FWJhRCFtk4kJHq+KEuwpeFvpjDIBbMz2ddn2xUWGaQ+tOv0xyDJw6JJcKwDZLQnmdFRyMjlwCPk/yZ4IFlgGYLESzXRDi2JR39IuxByCm61iu1x0N5z/3V0bQ7tefrfdsqL2SCxbhkdoYMoiyrpE1xKDE9+TVK4i8NCCXgHeSrqLKcrHOqfjyV8FXDCIm5MLTHp8n3l+mnthtno/tZwnxgf/lkqCy8g1aKUHssR/s5NdIdLjVXoVXmNypo9jP/tlsH+K8qw4NngtAhwdzRdecJYLgnpNnGCD3HZ6v3BWoTxHba3WMzUgTqAcfL1FW+4YLh0wB7xo7+sn66eRAVXyrvue5WAPNdo2twTxJOBVB9ZmGfn84xKSkzNdKVsZHWnOnVxybeDSavFZJYmdi/YHrfg6SS16ASaf5LjV9zgLIPHUcVqenKPaRwwvb6i0dpmV/l2Kl+tkfg9eh8S1l20J6zsNK1Iwdp2JRSk56xUqmkPQt62mLX1sfltpqxAXvgwfLlLuLTDeC8bzNWW2RG+f+4VftSMJxEUyWhWUqWitcKCaI4ISWOiIoxhrw1CY0jZKuk8wJuDbMuSbRVRvCLqxTM07g4nsv18SIi+SlWc+ck49oEHZpcYMIsJuU7rDPcKZyrny9YWIglTRJQD0NkiDc4rGfdyhAkPjXuQXzt65GTWfZwEEtwiT5bvFhasMU8oPt6FIPr4ncQiO9v75X1YwzPZpyvTAAKhHGRbYCV/IbjsDPviZXCQsRTOuCcGFHdNZl51rSGxpO6PmgwbX5L0lB6FzE/Q/v3Lh+DD+fYkyIjVL6akTTxNfkEVBhuLnJZiViZ8XQFGUD65MU7KrYxNmofvr4enH0lePipbQdeTSdJaDpeQ+rNCMIGuPNzbgDdfgAVtf6cPCGNWNVh+EmRIuvoOIYRESZu+uO+Dit+n4x3z+NCgQn+CeGyDN20AM+eX9I6/DdrtabzYxaQA+IBoY54h56KtFjonXIZ50l90zmk5S/kAn6pMV+XpV2G/XCxzsFEs9RyXLfaL0M8A1g1y1FR5836TAPMiDkUor+Ic8fHWjJaaUDxvE3f/nkhc9rR5r5Mpmw6orU5pepotzs21JWi+5SsWltOcsIHiMptm7pmuo2j51Z1OtzD5SjFiVBfAlN9IR15PVL82Nal2dBok09mSuhf16k+sDlJZLyKi25pQ62eMDsQ+MKLJJ8RY65zJkf7CNdF2Krjb92bkmzNOJ+7977chYLM0Fq9fs4lKxsCv90tIYT+ZqzWQwPiQucdSQeX3JbPgUBeld/eWiQrs5Vqd1Pg25oG90Lq75dwSf2Pq0KIuYq0mD1YEHg7jCOIdxrGT1zw3F/LwzjmOVOcJaQYm/Fkgzu1hPbfhDK3pHsaRoP/RWGyypWmJ+qwRY1rFPGrUUMMlXtb6MeQhyGBseXmpPLR/Ws2Cl X-MS-Exchange-AntiSpam-MessageData-1: TjuAiO3RCMEYtYlWUZlmp22t9cyYoZvrpkg= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: f3b3404d-9569-4307-b67c-08da55253614 X-MS-Exchange-CrossTenant-AuthSource: PAXPR04MB8703.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2022 14:32:33.6761 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 7j7wzru3TjatlrqbUF5yBS6/b9t9QwxEZE9gLpaC+gWFCFifWgl6J40kdRC6N2jKLkFhzjVpXPUXWRVBSbcxHw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0401MB2288 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil Signed-off-by: Hans Verkuil --- drivers/media/v4l2-core/v4l2-ctrls-api.c | 2 +- drivers/media/v4l2-core/v4l2-ctrls-core.c | 31 ++++++++++++++--------- include/media/v4l2-ctrls.h | 16 ++++++------ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c index 1b90bd7c4010..6f1b72c59e8e 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c @@ -467,7 +467,7 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, if (is_default) ret = def_to_user(cs->controls + idx, ref->ctrl); - else if (is_request && ref->p_req_dyn_enomem) + else if (is_request && ref->p_req_array_enomem) ret = -ENOMEM; else if (is_request && ref->p_req_valid) ret = req_to_user(cs->controls + idx, ref); diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 1372b7b45681..38030a7cb233 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -1048,23 +1048,26 @@ void cur_to_new(struct v4l2_ctrl *ctrl) ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new, ctrl->new_elems); } -static bool req_alloc_dyn_array(struct v4l2_ctrl_ref *ref, u32 elems) +static bool req_alloc_array(struct v4l2_ctrl_ref *ref, u32 elems) { void *tmp; - if (elems < ref->p_req_dyn_alloc_elems) + if (elems == ref->p_req_array_alloc_elems) + return true; + if (ref->ctrl->is_dyn_array && + elems < ref->p_req_array_alloc_elems) return true; tmp = kvmalloc(elems * ref->ctrl->elem_size, GFP_KERNEL); if (!tmp) { - ref->p_req_dyn_enomem = true; + ref->p_req_array_enomem = true; return false; } - ref->p_req_dyn_enomem = false; + ref->p_req_array_enomem = false; kvfree(ref->p_req.p); ref->p_req.p = tmp; - ref->p_req_dyn_alloc_elems = elems; + ref->p_req_array_alloc_elems = elems; return true; } @@ -1077,7 +1080,7 @@ void new_to_req(struct v4l2_ctrl_ref *ref) return; ctrl = ref->ctrl; - if (ctrl->is_dyn_array && !req_alloc_dyn_array(ref, ctrl->new_elems)) + if (ctrl->is_array && !req_alloc_array(ref, ctrl->new_elems)) return; ref->p_req_elems = ctrl->new_elems; @@ -1094,7 +1097,7 @@ void cur_to_req(struct v4l2_ctrl_ref *ref) return; ctrl = ref->ctrl; - if (ctrl->is_dyn_array && !req_alloc_dyn_array(ref, ctrl->elems)) + if (ctrl->is_array && !req_alloc_array(ref, ctrl->elems)) return; ref->p_req_elems = ctrl->elems; @@ -1123,14 +1126,18 @@ int req_to_new(struct v4l2_ctrl_ref *ref) return 0; } - /* Not a dynamic array, so just copy the request value */ - if (!ctrl->is_dyn_array) { + /* Not an array, so just copy the request value */ + if (!ctrl->is_array) { ptr_to_ptr(ctrl, ref->p_req, ctrl->p_new, ctrl->new_elems); return 0; } /* Sanity check, should never happen */ - if (WARN_ON(!ref->p_req_dyn_alloc_elems)) + if (WARN_ON(!ref->p_req_array_alloc_elems)) + return -ENOMEM; + + if (!ctrl->is_dyn_array && + ref->p_req_elems != ctrl->p_array_alloc_elems) return -ENOMEM; /* @@ -1243,7 +1250,7 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl) /* Free all nodes */ list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) { list_del(&ref->node); - if (ref->p_req_dyn_alloc_elems) + if (ref->p_req_array_alloc_elems) kvfree(ref->p_req.p); kfree(ref); } @@ -1368,7 +1375,7 @@ int handler_new_ref(struct v4l2_ctrl_handler *hdl, if (hdl->error) return hdl->error; - if (allocate_req && !ctrl->is_dyn_array) + if (allocate_req && !ctrl->is_array) size_extra_req = ctrl->elems * ctrl->elem_size; new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL); if (!new_ref) diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index a2f147873265..e0f32e8b886a 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -324,15 +324,15 @@ struct v4l2_ctrl { * from a cluster with multiple controls twice (when the first * control of a cluster is applied, they all are). * @p_req_valid: If set, then p_req contains the control value for the request. - * @p_req_dyn_enomem: If set, then p_req is invalid since allocating space for - * a dynamic array failed. Attempting to read this value shall - * result in ENOMEM. Only valid if ctrl->is_dyn_array is true. - * @p_req_dyn_alloc_elems: The number of elements allocated for the dynamic - * array. Only valid if @p_req_valid and ctrl->is_dyn_array are + * @p_req_array_enomem: If set, then p_req is invalid since allocating space for + * an array failed. Attempting to read this value shall + * result in ENOMEM. Only valid if ctrl->is_array is true. + * @p_req_array_alloc_elems: The number of elements allocated for the + * array. Only valid if @p_req_valid and ctrl->is_array are * true. * @p_req_elems: The number of elements in @p_req. This is the same as * ctrl->elems, except for dynamic arrays. In that case it is in - * the range of 1 to @p_req_dyn_alloc_elems. Only valid if + * the range of 1 to @p_req_array_alloc_elems. Only valid if * @p_req_valid is true. * @p_req: If the control handler containing this control reference * is bound to a media request, then this points to the @@ -354,8 +354,8 @@ struct v4l2_ctrl_ref { bool from_other_dev; bool req_done; bool p_req_valid; - bool p_req_dyn_enomem; - u32 p_req_dyn_alloc_elems; + bool p_req_array_enomem; + u32 p_req_array_alloc_elems; u32 p_req_elems; union v4l2_ctrl_ptr p_req; }; From patchwork Thu Jun 23 14:31:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xavier Roumegue \(OSS\)" X-Patchwork-Id: 584440 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 92AE0C43334 for ; Thu, 23 Jun 2022 14:32:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232005AbiFWOcs (ORCPT ); Thu, 23 Jun 2022 10:32:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231951AbiFWOcn (ORCPT ); Thu, 23 Jun 2022 10:32:43 -0400 Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-eopbgr60050.outbound.protection.outlook.com [40.107.6.50]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE7DA4578F; Thu, 23 Jun 2022 07:32:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=SOBdpPYZUsg5GBehG9fDtVchRFnYLTJJ1rUPQDCmqk8ov2KeWYu2gEcOes7TQXl6TlFsJuhwMFGuflW3tHjMYoDhHq641QeR2Kmmt7DDSK4wicvJfpecX8pv/ZZnIljTqbNXNt4/P2WiKkhneQI1l+A0VhgdiyodAk+zcmoSNUcxOujUXKLdRCf8ZMsj7rj26D8/0BpliyE5ga+pnBZqdl+vYpSkhmad/0baXLjiNWY7RZn0b45SrGtkXQ7X5IGEH90FRKelgQkrUptkhvkvu6fcjRu63m2PIAFjJ1PZi8v2Kw/g++AD7oa37Zu5HKZ4qATUE583HlttUsO+UTyKMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Qo/HmeunH1NHG1XXb0xWwHqLuUBAYsnJzAwWvlhyq0U=; b=lk5K9j/JeiI4WAwwEv0RyiLJVuU5sDRS69yqemaBPAgzw5IWbWzDypGRM3JRjo+WnA3YINZvfpIusW7FLwqCXWkKKtHs9gY4P8/3DptY8OxDE+FzcgVyd4xhE9vxtBsX4sWenLmfC1+cdsSYl6egaBgzV9UZN8ezvJIPvGwLIS8JagS9iERiljkziJ4CvV+2UUiYB4wS6PGTR5j0pCtUToPyK9MZMwch4+ELibBPECkFGNkDXk6DqkKZYgeZKBkZuppDarAbU18s+YhFwrE8vEyOkO1+6ICkmiwW8WF38uQvzg6QpzEb3F4Q8QE8g2ZVkY+Tiz1kECEWLNXKH5ihMA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Qo/HmeunH1NHG1XXb0xWwHqLuUBAYsnJzAwWvlhyq0U=; b=DwSW738D9b0o1KhQsFlW1GKinngn8Lsph6i5GN2FdGmAlMrXMALwBWl7Oxp4j05Gtd2cfpRueQeE0YFtyawKyf3bgkHW2VDI+wzi6SKPXOeoErX1sXUiMIEjh+ey0uKe5BBX1MKcCkS89tbqikfIw6h0+22d7VpIYbNUkCzVlHA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) by VI1PR0401MB2288.eurprd04.prod.outlook.com (2603:10a6:800:28::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5373.16; Thu, 23 Jun 2022 14:32:36 +0000 Received: from PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485]) by PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485%5]) with mapi id 15.20.5353.022; Thu, 23 Jun 2022 14:32:36 +0000 From: Xavier Roumegue To: mchehab@kernel.org, hverkuil-cisco@xs4all.nl, stanimir.varbanov@linaro.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ideasonboard.com, robh+dt@kernel.org, nicolas@ndufresne.ca, alexander.stein@ew.tq-group.com Cc: Xavier Roumegue , linux-media@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v6 09/14] media: Documentation: dw100: Add user documentation for the DW100 driver Date: Thu, 23 Jun 2022 16:31:10 +0200 Message-Id: <20220623143115.3185297-10-xavier.roumegue@oss.nxp.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> References: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> X-ClientProxiedBy: PR2P264CA0026.FRAP264.PROD.OUTLOOK.COM (2603:10a6:101:1::14) To PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: cc8d3994-0c56-494b-9b86-08da5525378d X-MS-TrafficTypeDiagnostic: VI1PR0401MB2288:EE_ X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: o61Qypm9yxq1JddZvTjkjyRai1cqPfEO3wrA6TSvfxcocfvFJq3McUnVTSbxFqVjSU9rvxoUnGEW4m+QrSEz2rWAiOdSalu1caU54ArtUgS5cNFBIWqT44u8+FubPvVfhMHh1aTuJpQnz99w8JGUFvntGtJHdOGlVOp/sCdRPWfrd7OHH37N4IAXzQbwSzgrMoPuThXa8fE+GDca5Pq8S3OiOKLWrF0qedFLtCSKGUA7RTmkWFgySYu9eCrm8+kkUeY5GgX+nA6iesW2zcShc7BCXMc+AZbB7M6E883oGlddKDoBJPyzXwYGoyXtw8v1zmkH/zUPcf9Isrbt5pAVe0fT7l2WLLmNW2je3NZQO9AUY4Hrs8PG4kfmIjlr2LyU/9ZzKMZR9c5IYgTWoBNzSP/XkWrG/qr3N/rUpxS8fhQ83RaAmsfXA3EJhmFCQwXDuA6QD6biiw41QI6BjheUWtfRFxkhhBNvojCLlT5UG+3/VvNbL6ztOVfsR9dsXpk6xC9kOJRA0mstr3cUMMOg5tz88V/2Dkq2td9vDwJMHGP+FKkTXM6+NaYjaMCoB51nKdBIyhmt6lLTIqAbr5ide6JPhqqhFVj6JOxhl6pvq4TiCh+opyF28hyh4WlFPnZb3KTipNDvQGMj53UFKeYOV98GczQJ8udgWRl5bPYTyL/W09ONRfz2HoTVYaNcNOVBKqCO9+rmBD+7NAAlMIdASkQ+iATNfF4pv6gKW4lg+S0= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(346002)(136003)(376002)(366004)(396003)(39860400002)(52116002)(66476007)(4326008)(6506007)(86362001)(2616005)(38100700002)(6666004)(41300700001)(66556008)(8676002)(66946007)(2906002)(316002)(1076003)(44832011)(478600001)(8936002)(83380400001)(7416002)(6512007)(5660300002)(966005)(186003)(6486002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: VHQjTIoS8A2opovVxFiFqMV875j6dmByl00hxF2IyD1sNsXOVFzpndFOQv+nEoJhmzG7WCCGhz7jIxdGRiPR+cf9mEvcRjxEEddffL21BqFv0IufTYeC5wyIaogipZVCSNg7VhWL1UG/lWmGkW8rRyAMLgH0IIgHeh05jsOUJHptSSbd8yKq3kQGKMPbrFlQCSPmrMrEBtQkjkBqqLJLy9FvsKVf9jNS/zxjN2Pb+JgHILC3YPSPhDM3al7tMca0YYl2L3WvbHHtAPTbCaSsataKNqzMPfZCk/FOckEF+MMx58/xr6CPeHCeaN8esNdbOPxvVE1U474e/lhrqRnXRHQYE5OV+TkHL5NLDjuDcPXCF6uNhBLAJW2E+k3UVKbtkbH2tHcoSRfVgE/1nuGhz32Qj6+Fa3WajgAvCzhcKGGCzvShWVsVRHvZijvQXtlt4TZ/cLqUhtToMt3DJicCIUnAU31BNa0NXIIN+LSvdS1qW3MpQ78w/TwKsaI1UTUwBRLLiB3hTvToe1gamYcXvF20v3dIL6vDaGTVoFZeQNpRBLb6dg9HWcv7b/3F3yzdZQDOvIeJ0PwrLQMypCsY/9HgG12GHlBx4yrW8jwWTk8Sv094Ma4lnNh0S7PXltLn8CdsaUWdTJbw9SB9EaRJ8imDcpiKpk34al+BIwjuW+hMlMC7F0C1v2+xS/ogFC2RkRtv7ZW01Syow2sNSVruxrROoXgO6oacc7BiimvvVkSyO/yfjIsNY/0Znxm8AD2/q+dP82LowJxN83+VbpRkbz+80wRtsWSVqIiZY6xwrQ2ZX6xkbDnPW03Bs9CDgld+YtorgzEnDtLEkjKujEZwzl3ebZwCPkg+pcw8S6nkAemUiYdilcgJMTwxWH358iMc/70QxsSisrHCZ1JT3fd6lo9qyjo0Swz7vlj2prTKSWFc3XI8wb7uRJtRTE/hAPTajJ3t+TL2mB+ShdVEu3UClYv2x6fpdOG53548QmFzjt+sBy806vg5DODW08StBCKv0V/P8FG6D6MAEl8H7Tba2xg5LvWJkyNLYU8K0CZqlxZ4Xlq/fqy+UW+q7xNbCwJgLCVKG8R1r9fC/xWugXuEt95jDyzZrRGF3wBbkGKSWyUBtB0ySDvHNsA49U83yVPTMZQGLZJ2t5EMMD70Qy26OncPb8qeWnp3GGgzVlaC/kDeFDoTWCjkv5yNggYF134OWZiyeLETky3arCq0R57xo2MtfSOw/O+fr4ZgkShI2uQNERleLjV+ndIu6wNtsN/5OGTIXwjPjlnpcaQ8FVjwxqAnTDmyq0u5oKB6eHkYLhwNZGVRzBj/Sig2wm2h57vu+Ozz1Wsh2DeSXn3G9q7oO2ASny2cgXAk8eWqQzOZBCwO6UYF9oMPrOV5+Odn3a24p8AWvWkxYT0ZRGB/1BusZOQxuFS3hOw7R4xLvBpA0HCb9URTMO7m9xSxZzYhXwgdE9iMdvE5snSSgQHv5vcjB9nTz5qjNVHMgAVHO5yCNSQv7U5lwA9IUlNligLU4BJ9MCqEL0v/ScIYzU9RxKHLP2Lad9luAz//4IM42b0jEVMyvf6r0gZDZx4ibFDBflVwKC0gHibR8gwyRUM2ewHmcS6i+mdxkxlsbuGytZJBzuVuAhUzFfjqe9pepcT4FQdGEgH+eF/rXSbFgzXYh85uKTmXVv18e9d4GHOrPPclpUM8r1akiK8rLR0iexv7tTbvB8Ol7ZhFIFd6ldwpWR3wSdNXL5YPtnhREyhygDMl7OlA0fY3Eft9zQyDvtllA2TSyRagtv4Y X-MS-Exchange-AntiSpam-MessageData-1: 9aE+wApQtkIg86jTZgcRcm7bti+mhMhgWw4= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: cc8d3994-0c56-494b-9b86-08da5525378d X-MS-Exchange-CrossTenant-AuthSource: PAXPR04MB8703.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2022 14:32:36.2086 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Yx81t//Y8aXWxujuRSwqRtmBjj4uQGmTHy6e+b7K48+7qVWUO+x1IEmGrFI1hEwWoGdSeUDKJ0o2jTy1wbpUuQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0401MB2288 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add user documentation for the DW100 driver. while at it, replace spaces with tab on drivers list. Signed-off-by: Xavier Roumegue Reviewed-by: Laurent Pinchart --- .../userspace-api/media/drivers/dw100.rst | 69 +++++++++++++++++++ .../userspace-api/media/drivers/index.rst | 3 +- 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 Documentation/userspace-api/media/drivers/dw100.rst diff --git a/Documentation/userspace-api/media/drivers/dw100.rst b/Documentation/userspace-api/media/drivers/dw100.rst new file mode 100644 index 000000000000..1ca6fa55f539 --- /dev/null +++ b/Documentation/userspace-api/media/drivers/dw100.rst @@ -0,0 +1,69 @@ +.. SPDX-License-Identifier: GPL-2.0 + +DW100 dewarp driver +=================== + +The Vivante DW100 Dewarp Processor IP core found on i.MX8MP SoC applies a +programmable geometrical transformation on the input image to correct distortion +introduced by lenses. + +The transformation function is exposed by the hardware as a grid map with 16x16 +pixel macroblocks indexed using X, Y vertex coordinates. +:: + + Image width + <---------------------------------------> + + ^ .-------.-------.-------.-------.-------. + | | 16x16 | | | | | + I | | pixel | | | | | + m | | block | | | | | + a | .-------.-------.-------.-------.-------. + g | | | | | | | + e | | | | | | | + | | | | | | | + h | .-------.-------.-------.-------.-------. + e | | | | | | | + i | | | | | | | + g | | | | | | | + h | .-------.-------.-------.-------.-------. + t | | | | | | | + | | | | | | | + | | | | | | | + v '-------'-------'-------'-------'-------' + + Grid of Image Blocks for Dewarping Map + + +Each x, y coordinate register uses 16 bits to record the coordinate address in +an unsigned 12.4 fixed point format (UQ12.4). +:: + + .----------------------.--------..----------------------.--------. + | 31~20 | 19~16 || 15~4 | 3~0 | + | (integer) | (frac) || (integer) | (frac) | + '----------------------'--------''----------------------'--------' + <-------------------------------><-------------------------------> + Y coordinate X coordinate + + Remap Register Layout + +The dewarping map is set from applications using the +V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP control. The control contains +an array of u32 values storing (x, y) destination coordinates for each +vertex of the grid. The x coordinate is stored in the 16 LSBs and the y +coordinate in the 16 MSBs. + +The number of elements in the array must match the image size: + +.. code-block:: C + + elems = (DIV_ROUND_UP(width, 16) + 1) * (DIV_ROUND_UP(height, 16) + 1); + +If the control has not been set by the application, the driver uses an identity +map. + +More details on the DW100 hardware operations can be found in +*chapter 13.15 DeWarp* of IMX8MP_ reference manual. + +.. _IMX8MP: https://www.nxp.com/webapp/Download?colCode=IMX8MPRM diff --git a/Documentation/userspace-api/media/drivers/index.rst b/Documentation/userspace-api/media/drivers/index.rst index 12e3c512d718..0c720ca1a27d 100644 --- a/Documentation/userspace-api/media/drivers/index.rst +++ b/Documentation/userspace-api/media/drivers/index.rst @@ -33,7 +33,8 @@ For more details see the file COPYING in the source distribution of Linux. ccs cx2341x-uapi - hantro + dw100 + hantro imx-uapi max2175 meye-uapi From patchwork Thu Jun 23 14:31:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xavier Roumegue \(OSS\)" X-Patchwork-Id: 584439 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7BEF0C433EF for ; Thu, 23 Jun 2022 14:32:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231974AbiFWOcz (ORCPT ); Thu, 23 Jun 2022 10:32:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60090 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231993AbiFWOcq (ORCPT ); Thu, 23 Jun 2022 10:32:46 -0400 Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-eopbgr60050.outbound.protection.outlook.com [40.107.6.50]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD52C45AC3; Thu, 23 Jun 2022 07:32:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=LDJ1HYt71CD2xwO58e2mhl0kt1gPAkYClHciKg2ilM45OQDzJeJXwt7ih2v+Lps/BPm2bin60s83Aeu7JhFUt7NZHE1AUV3hpnegx6NjKS2q3wiDQrVpX4+vhArukZ1NvIZWtQoPuV7neofTGPRk3OjQr5czEctBknJz2ZTfivCiFCtQuatiK7dqhXv5kcOZsvaYBoNbH4CiT4pSpzYO70kXlt5fgjCoLj9rYBxYjLwqlpFqcg/bYswBfiT6XtPZsMGLTZCE1GbTvqr6lX95O47inNinzxfeb2yrRp3lk6zPELnML/pKuEBg7e/pM/Ho7jjJGK21RRvGgSe0KtvVnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=i8s/Cgb9sV9a+MqR7FU9scBugSxVonky71LBOV83KLs=; b=EOFzdNp6OaUkeGJ/ivQ655+yAa+TwetE7M7Gn8UPtofmfUvceYgkTUB6onDrjHktKm8SEt4fod95OpPSpFe9lAMkF53JbuWGol6Qs9c2eYkMP3ATXNmZiR6N/uupOJGarpCjtlrv/iweubcM1ht+ZCDZuZD+75h3SEdif1va7U6iYpab4I28ckA4QqMpIgtusmjYO8f+SPDac0JZTQnsehxTgf6tsh56VP+bvZoSwr+2UwL/6mb0gbjcEgH2L2N56sE38tmO0qD6Ccs2nxOuW+3i6P7Lt7ZntZgy3gzQAXBVLvkEySwDAlDUNDMYvAifVnw3Mq4eGaaqtgqeUqaUEg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=i8s/Cgb9sV9a+MqR7FU9scBugSxVonky71LBOV83KLs=; b=cqTkJCS0uw6hdPzsKbqX6nxx7vW+52Jn7jlJ7W3gCnRNuQZa8CgAtxZyjttYQh4mhOX/sBuoZOMS3iZH46AOSJCKMiVshqjCHWJYahqGAJ5vh9PAWuA7rdm8TFizY0NcFTT2Qq4xc5S3J0tdKrdwOV/MenDfGVpusqrQCMwbKjc= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) by VI1PR0401MB2288.eurprd04.prod.outlook.com (2603:10a6:800:28::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5373.16; Thu, 23 Jun 2022 14:32:37 +0000 Received: from PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485]) by PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485%5]) with mapi id 15.20.5353.022; Thu, 23 Jun 2022 14:32:37 +0000 From: Xavier Roumegue To: mchehab@kernel.org, hverkuil-cisco@xs4all.nl, stanimir.varbanov@linaro.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ideasonboard.com, robh+dt@kernel.org, nicolas@ndufresne.ca, alexander.stein@ew.tq-group.com Cc: Xavier Roumegue , linux-media@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v6 11/14] media: uapi: Add a control for DW100 driver Date: Thu, 23 Jun 2022 16:31:12 +0200 Message-Id: <20220623143115.3185297-12-xavier.roumegue@oss.nxp.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> References: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> X-ClientProxiedBy: PR2P264CA0026.FRAP264.PROD.OUTLOOK.COM (2603:10a6:101:1::14) To PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a7fdf33f-94af-4426-8ce5-08da55253828 X-MS-TrafficTypeDiagnostic: VI1PR0401MB2288:EE_ X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: mcd8KPVDOZBgFKBgZtkLNxxbOENuV2JCR3QSCGtSnOvcC0mzLh2S5MCnaeYYoHSyifsiS5bpClckB70wMRVik3ppFF9nYazrxS/PNbXiCRxmQbDDN0fmLTNppBSDl8M9AdHzQn1MNKygIPljn7AFWKMcWGFxCg1Ui+0f+QJY/tfRYGo/XWZA3emFWo1VY6Ui1xEFu7epb+TjbHexQ1YH2N4awJzLZX5pPLllU6NtwKzjRQ+7gPqx4VHi0Lty44W7N5t5A4sjUUlIbVnHxMm22NJj6oM4SGmMzYkVeoOw+bU7LIjf/44QPSaovobPMf5gQWRMN5WC9D4/cOJcz8uFuYVCfharBFItHM0k04Z/kf0UtRQxyz/Vh3nbaIZAjrSQ9szgif04UdkJrGODmY4XtVZ2mjcTa2Dsrvjy96WS5QnDKJiWKDygyZlYWDf71Znh//HnjXhiu/YQUx9cL9s6U4WCqwN0MlG8FhEE3KThValgk1zJac/CB47Im1luoYNj4q/KurNC4JO6+6kgg1GrM/go2oXUUAOgSD8ItDpVeCEr4EOCEFM4xLCCCWgLTDKu/DUEC3F6rlTJmLp7KJCcqkzCtiDDkHcswc7mKQ2+maiPb/f96kS3Dj1BO6eIRP5F7AY+46a9usZF2L9kFpqby+3hxunNrRjHRJ4P0h3JnaVrCHwKG6TmdfJhjCZuRVfIN+0bnsi9KqfSa3B7mpSbD13l3a8PC41UM8G0IdcqvdA= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(346002)(136003)(376002)(366004)(396003)(39860400002)(52116002)(66476007)(4326008)(6506007)(86362001)(2616005)(38100700002)(6666004)(41300700001)(66556008)(8676002)(66946007)(2906002)(316002)(1076003)(44832011)(478600001)(8936002)(83380400001)(7416002)(6512007)(5660300002)(966005)(186003)(6486002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: u5kkgaXjFmOYing+L5BeGCHtZf2MDEz9ONHNmg546w7DHLtl801vTAoRscPy0rqlm1lD4BjdXK43yJBxgncOBwnbplhy/Wjb1HR6K9FwVcgzPpXT4plmMjLq6X1BrUX4QQ95gegRSChB7SmXYdJRrPotYEiRnsZWhMbV7KTK9CH51P72Sabqfj72GTbcfM34TMiDDxz52w3VZ3t+3c+aP/gqTJHVrigsWk+wn89AeYzgJ9uLdcj+YNSfpQl9f1bOYps7KWHroBc+1TKxC6lGYdCP1qTFjTCVYi3uyClTzgLsoCVwNo2K6gx5dMJy3eFvWVGpKtYTu9YEI1dRrIK4WMBnlz/IakAzm5D8ErUK/D7dWCBBO9Baqr+nLIKk6JQtqJy725YaRYFnWHCxYchIRAp0J7NC9WNLOBLKTeEaIU0h0yOS1dRrh/P2FN4h/QXeTJjCmKR79G+uXb4PKKW85g2F4p8fhyyEwMrOX7QY5IhDb0cUqMzSUDYzPmwZj6yMAdDmAmyOKWfSyxewtl7/lpufF8LKyyUh+bQjfQ2E1TVtQBrkd1voTtoiIdjdaOlF434Hu+NjbnR4p8jjLyLWIHvMt960yUFwdPr5mij+orA8o4+9XirbCarypt6eKg05xujYCudqfA1w1u6aYYWHVT/hhAWQP16491aR9RvBTQY6eo8f0PaE5aw7g/rjDs+nUbWWxvbK3sFABEk5Ev4m3yK/rQdf5qq/tsulIdg94RKVy0mr0bA228lDOvqbaJQPRgNWO2Z3GRS4CkB0HUAbXNjc6FbGQLhFMqtKFl4xAsN6B+e+b35HGvZH9eDYcWezytKXXvFtHNo7mKBIzsieHxa949pMS0QV0Njf6FAjG8kXj+RYcDkpp5zKbKV2joqO92EG1Tna4X1Mdn/BIbMmy+qHJVaywNNrl7CEd5jGFuuSsUmLICT7W+fLrU15uXE19B4cp+xbwg1x5lRQj9UyXmh8T+GJ6D4FFoJRvCM2PABN0JwochYfjgkBymx4LU8nPFi+LPbZBb7PPgT+aFJmCUpvJwGeSmpLcBkxBGThraXJ+5j/HIuqOkmMAb+OVpDDG5nkNF+AJALG92HKGjHpmcEDLR47G6yjiQ1G9zeK+5AJiTb+vaYHHKqgmZVK5acdYMgn0Bl/L3abbmZsUa3L8NLmPdyH+6KpWFXcyTzqY57Tp700mo+YCGRzmkKwwdO2HBbuyc6OWsfb4J3pVDVLrUVfPSU4jdBsxsTTyGXtON3/Osx2mTzonhHfWNy1DKORtAVnk3HTWJZcnHkIBc8V/NR3cCDABtjWfYZtkvRr+UJZpqOW+irtsXy6sCkNg+HxhtL5zzi4iSsiBki11h5Wa6cChU6jsVE1ZT7H3R1CU2u2xKZFe6qp2ny5Q6hAHBbtFWC7LaEMDthSWQjc/kLQy7pqCGtwI/oxDLJgdfqf7jnXXXNLupQj2dORQe+eFEUPE0+yL89a15mB744x69WxSJZ5XMXHmCL7RzACjFdVZzjkDKPnaWUITvptFirL72oDVZm8NhPQvtUpDi5Bar4iwn7up48JHTQfg2QvMcR+RfQrgBxr41KpR72csoky/GlDwmicnW2r5KqMH6GK5/brTjtqeYuLzim1eOPEUH3cZlxe7Fe1KlrEhHDfE5Lw1KBPDLOXJEdRf1Fo6dMJ0sU1p2BHyVUs2jBvJFR+Bs7Ei8ZLGmn5Twie+SZNFirF2fyu27Vt0//WgswDKu6niABkFmp0LYADOG6sDGOnPZKriU2IGyantgm+uJLv80BAIrYi9qNBgEwO X-MS-Exchange-AntiSpam-MessageData-1: 3/mfnlH7UbM1L9YmKsOuBhXQWwiQXwSdEOk= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: a7fdf33f-94af-4426-8ce5-08da55253828 X-MS-Exchange-CrossTenant-AuthSource: PAXPR04MB8703.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2022 14:32:37.2709 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: wk6kN8AnS4KiwTU6/78n+NCLCBi+QuHI3qEAL7fuXZqiczjRMVLIzc/FLdOrFr2ZRJlJM3cRH3yyZZ1st9IaDg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0401MB2288 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The DW100 driver gets the dewarping mapping as a binary blob from the userspace application through a custom control. The blob format is hardware specific so create a dedicated control for this purpose. Signed-off-by: Xavier Roumegue Reviewed-by: Laurent Pinchart --- .../userspace-api/media/drivers/dw100.rst | 13 +++++++++++++ include/uapi/linux/dw100.h | 14 ++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 include/uapi/linux/dw100.h diff --git a/Documentation/userspace-api/media/drivers/dw100.rst b/Documentation/userspace-api/media/drivers/dw100.rst index 1ca6fa55f539..d8a6e10b4395 100644 --- a/Documentation/userspace-api/media/drivers/dw100.rst +++ b/Documentation/userspace-api/media/drivers/dw100.rst @@ -66,4 +66,17 @@ map. More details on the DW100 hardware operations can be found in *chapter 13.15 DeWarp* of IMX8MP_ reference manual. +The Vivante DW100 m2m driver implements the following driver-specific control: + +``V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP (__u32 array)`` + Specifies to DW100 driver its dewarping map (aka LUT) blob as described in + *chapter 13.15.2.3 Dewarping Remap* of IMX8MP_ reference manual as an U32 + dynamic array. The image is divided into many small 16x16 blocks. If the + width/height of the image is not divisible by 16, the size of the + rightmost/bottommost block is the remainder. The dewarping map only saves + the vertex coordinates of the block. The dewarping grid map is comprised of + vertex coordinates for x and y. Each x, y coordinate register uses 16 bits + (UQ12.4) to record the coordinate address, with the Y coordinate in the + upper bits and X in the lower bits. + .. _IMX8MP: https://www.nxp.com/webapp/Download?colCode=IMX8MPRM diff --git a/include/uapi/linux/dw100.h b/include/uapi/linux/dw100.h new file mode 100644 index 000000000000..3356496edd6b --- /dev/null +++ b/include/uapi/linux/dw100.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* Copyright 2022 NXP */ + +#ifndef __UAPI_DW100_H__ +#define __UAPI_DW100_H__ + +#include + +/* + * Check Documentation/userspace-api/media/drivers/dw100.rst for control details. + */ +#define V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP (V4L2_CID_USER_DW100_BASE + 1) + +#endif From patchwork Thu Jun 23 14:31:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xavier Roumegue \(OSS\)" X-Patchwork-Id: 584438 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6725ECCA47E for ; Thu, 23 Jun 2022 14:32:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232017AbiFWOcw (ORCPT ); Thu, 23 Jun 2022 10:32:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231989AbiFWOcp (ORCPT ); Thu, 23 Jun 2022 10:32:45 -0400 Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05on2071.outbound.protection.outlook.com [40.107.20.71]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 51B73457AD; Thu, 23 Jun 2022 07:32:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZztvGrDnmqmjhXfX3nmrRdOY7jEonqVrLz+qCMrpfhIr1HNi9iaFcMxdjkoydwfQvLcUk+m3cPDI6E0pPzohcsM5+uleRJw31Cmd7MMH+Hx+t6lCNBnCIyLO92cYs4bEqN2D1TVYKvVGQZNj8T2845FibKDPu/luVBTwoaxyVm1nWmqL40vShEISubgokfZUjkStYHaozqbgMUH8KhwCj9zBq4rQ3wpQa0LPEp+XFFedwkpIQA0ZhlIynuFtjv/xFgvDB3ekcBTdyF4g1Ur8PH1Pc+cVjJaR9NKElSrhCbM9HAjhZ6t0utmkCJY+oLbWS5h4ZWtHPBNK6rWOE3dJBA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=onwaSo5Bu+7wvj+/qpEX10LZ/o2HEoIPyjqZth8FTbg=; b=BN1dtF9lF1SThNUrIARJKPGdUXkuw6e20LmDjSVaz1bpbSjQ0J8CZOhkaSNBYYPrjHA91UJ7q5TR8DwUdYdZk8ac/gDLpTCEavwXXOB2E8CZuH80dOdo+Lwk9ApeSQWTFeNwrEoS7cGpgasD6juwKSaFn3mOqCGSZ1YHfRw1mseA2SzVLVu/YO9TuVhyK1xMupbE8ysiFTrZNMJ6WoAqAlOs1t03cVt0+5HmfYhS2nrrVjwoW5Iejn8ksyUTkXt9hF0F7hjpjmJrlBP/LWVNbb9eBWMWywxvMh0aPBqrLimEdbGSTuE1XX3wNrSUo9GGo78X8lgcKob9j8V8ykIIgw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=onwaSo5Bu+7wvj+/qpEX10LZ/o2HEoIPyjqZth8FTbg=; b=krbLYNaZv3f4XG2C1orGfNMNWNgObHk2F6IULkVCld5JJUNeKFzz4gAmiNiMHvvFLhElTHVCftnfsA9J8iM3vuSNR3P8XOpSllYAYxIIspmY/KKLHjQwCf1oihGbbhOXWYpx2K4F2uT+VQof14jazao3RyCJaELrmoV0/wr4Rdw= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) by DB8PR04MB6505.eurprd04.prod.outlook.com (2603:10a6:10:10d::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5353.22; Thu, 23 Jun 2022 14:32:38 +0000 Received: from PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485]) by PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485%5]) with mapi id 15.20.5353.022; Thu, 23 Jun 2022 14:32:38 +0000 From: Xavier Roumegue To: mchehab@kernel.org, hverkuil-cisco@xs4all.nl, stanimir.varbanov@linaro.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ideasonboard.com, robh+dt@kernel.org, nicolas@ndufresne.ca, alexander.stein@ew.tq-group.com Cc: Xavier Roumegue , linux-media@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v6 13/14] media: dw100: Add i.MX8MP dw100 dewarper driver Date: Thu, 23 Jun 2022 16:31:14 +0200 Message-Id: <20220623143115.3185297-14-xavier.roumegue@oss.nxp.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> References: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> X-ClientProxiedBy: PR2P264CA0026.FRAP264.PROD.OUTLOOK.COM (2603:10a6:101:1::14) To PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 0c0f9da8-3902-4ce6-14d6-08da552538c6 X-MS-TrafficTypeDiagnostic: DB8PR04MB6505:EE_ X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: wQpjGRVK8DQxXIbCM/t6cqRCSPntUuCaLf4wzAdBX521KGPzzJIpZ+SZCilhlNqZ9/XJVv6T83pQ1IUmr64LozRFPJc1bWTgVT81oH5rPVLMaMXjKFffZbUVTtTr5Lgtg3nkIZMrQ02SXgriTevxnOdHj8kBfwIVM1p22R7/iLPEXiw8OvJtEl1xUkBgFuwHlPxTJJVe3EVqEJYFqNMQQUQjfbDRyx/SxgkrQK7Zczf1PTKdW3b+L7tBp5Gy8Y7r5ReZjbyiJr+EW8RY5wvukkQRftHFYKcbZth0iG5CmCa+AOhBM2vN2MnjIu1uoEMyy9gBr5GrymLgtG4TWXGf4U9jyrzPGd6IrdoGHWbFcttAzU6rcrVVjDdT457KeHLiZfkz9iKSke+Mpg/ZvNlgqiFvkUQVPAD6fpkWZu5MRG5utkxrit7b+RXDtBRFRqRBjJZS026dVZuffIXXAoEVEanKtRrX7mYW7AM6ZKHahYkLhYxEgX6xhO16XuU57T5WkYYEnwlU3/ctr74pniLm3l6VhpnD/whHDJv2alhCJ8orVJvILUkYzz9i9RmPSyZv0GPCm20XxhLbOAFRIqtZVRLuDRqQNwOkuSWuSekM3OCu8ulnP3oEXStBW3cNL9GANcra+LoYYrhhUM3wfNme5Rqj+mki3jFBkPj4EOanfBTKVFp+BHgHDAUfe4rdZRYEExoptpRMSXIrPKLQaQ7+dg== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(39860400002)(136003)(376002)(366004)(396003)(346002)(2906002)(38100700002)(6666004)(66946007)(86362001)(1076003)(66556008)(44832011)(8676002)(66476007)(6486002)(316002)(4326008)(478600001)(6512007)(5660300002)(7416002)(186003)(83380400001)(2616005)(52116002)(6506007)(8936002)(30864003)(41300700001)(579004)(559001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: mzsSMLwTEQbG2XqgtF8lAxq2VeJB/xDfnrALsnYHrWkO/lxUswMj3xDONukuIw4VFOJ8y7HoUTcw2guZL5XKXgUWZBrxP8teJbCdc355pLK+bd2Z9hsJK8FYxyYPC7NcGJvG21VBM5/8qZDCn3+gEHDXkJy61RZBQx/GspTNDS9LiBFM9o4f778xTVEwDDXGdfRMEitEH3WmRoxpLHiGVD5MwWgcteGKY/GBuoIXBUdLNbc3/pXu510I0X1WuWo3T+NrzWObO5G0CX7Xw3Yyi0M5MJX72g5jlxZuoq4BR2hQqjdik+xt0K7OfqAdBqHUlTsIUttVbfxCWXRj96JeomUGZ9HzLwKymmUflVLvokeRJB9g3EsTyeeiMIpLoVgrJz7bLeXS9QvdO3tsWOeHmEtEnQrQjnbZ92YV5JU6xRYdTp86E5VwzPYDMj9zau4WVWE7514KJGFEsm+tOvKUUQa7WKQNOo7vmAT1QMbsrME4jYbXjgZTXJPoTTm8mn7aGCTjJ5RxaPTnByOPMioqN5qLO58170WVJ2ONJ21vp7W7Mw5iLnqfRkgfVEkhm/PadqtOQfKSkmmn87RQ8a1I93Ty/upipJ/RNpnN87fgJpwq0sjYB6PiJjnAs5NXx++PS6mNfl2kkXN6I1oO6+iV48yVYuJsOGoiKInkylUxj6XCD9Pq/TNYTFAcBK6P+adsNO6N2ECTjs/95ZS9M8k8YmMVFWUWsyUaVvNipEYd5u56ZGoQJSIYzqE5qJdQB3d2QPZn4s88b9nOp17LZYHoBcK8vIJE8mwlQOBk+wWaW3xspJas8XfeCa4oI+C4hDNUg6i/uAa8LYsVsib+1SHk3g1lnpchx/WE2OKVlMKyj2PihEMkvDFJAZvL4HT1K5soYiTBYhXaJ5pCac8FmrwMkGk1SF1tFU/4MMmabVsXkaG5yHabBIyXy7jAigyK/dj/+nEvyinaMyzRXzD57mPsMhOP7+jzRbMrpgYyZ1Llc2By1bYRC07t2J8NquBlHyFmk7/oHv8WDrrgUqtu7Em0NV7lKyP7Swjla+tsoQQMBR57rfgZTiair7EfgWISyER6dzbeeywhHurTHqU8YAQ8oNhMakOwZH+0AK4AyHWQDjHnv+opKL4Lohv/UVRvEPXbognY6EIj4RV6pDqgQDlotCvyNeSNvayET9G9NpjY/0Ic6pqANYZl/qOHwY1p8HGnWj3pxIECsPF57XKFowxKUOzwBFe60MrnvhI15RNsmdQ4OBlLG/hwO0ScTVGcgzT3LXvJr9SAp6T3ZMV81JE+JKc2fIu4q9rrwsvV7C34Kn2a2Zypi/LIeUPKlCHxNQRLHmADHVo79R3yVA80luP77Vdi1FN70TagNdnmQsSaACHQR0JtrFNNgjrgM6wNMnGPK1ecRyEn5giCJO83nF5CcVa55FsWySx5jzqDu4Xg5SL76qKwPE/5PvosT55VGFeT042VuX/7gPpXWy5rK0u4yPFZx4fwdDA1WCIj3oB4L0CgFg1gLOwOvr5vPZW/lN17APimXQMEAFtrYmJGVln+VSyNm2lZkAOhM9R3dR1LvvpLezBFggm1Vf68x4xrt/zsImJU54fKxIJlU4zZ6fLYB91/I1m/R3JGexZY1GWO3QF9GriOZUHMzt2GG1ZCdjEUh7+UoofuEEfzpky0iysD/73fNHv63XxLe0jdzYbry/3ioihZijavSq4A+novGZLNSTwYfxkbecoKXBgNF1uU9qnBSifaPtAyx3S4eelXcW6p+z2HMWWJhZ9fQH/P34qkX0JfAoiu X-MS-Exchange-AntiSpam-MessageData-1: G/IhU9WKMpYb39s0/QTWpNTer8hwVEg7mOU= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 0c0f9da8-3902-4ce6-14d6-08da552538c6 X-MS-Exchange-CrossTenant-AuthSource: PAXPR04MB8703.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2022 14:32:38.3971 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: pzj/F+kopGtRgE/9YZBtopO+w7Sd4gvRs5ORsG9cTIpQeiTcQJ4klh6lU/Y7p+VfZkqtvgTkKNLsolM6Ivn71g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR04MB6505 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add a V4L2 mem-to-mem driver for the Vivante DW100 Dewarp Processor IP core found on i.MX8MP SoC. The processor core applies a programmable geometrical transformation on input images to correct distorsion introduced by lenses. The transformation function is exposed as a grid map with 16x16 pixel macroblocks indexed using X, Y vertex coordinates. The dewarping map can be set from application through a dedicated v4l2 control. If not set or invalid, the driver computes an identity map prior to starting the processing engine. The driver supports scaling, cropping and pixel format conversion. Signed-off-by: Xavier Roumegue Reviewed-by: Ezequiel Garcia --- drivers/media/platform/nxp/Kconfig | 1 + drivers/media/platform/nxp/Makefile | 1 + drivers/media/platform/nxp/dw100/Kconfig | 17 + drivers/media/platform/nxp/dw100/Makefile | 3 + drivers/media/platform/nxp/dw100/dw100.c | 1687 +++++++++++++++++ drivers/media/platform/nxp/dw100/dw100_regs.h | 117 ++ 6 files changed, 1826 insertions(+) create mode 100644 drivers/media/platform/nxp/dw100/Kconfig create mode 100644 drivers/media/platform/nxp/dw100/Makefile create mode 100644 drivers/media/platform/nxp/dw100/dw100.c create mode 100644 drivers/media/platform/nxp/dw100/dw100_regs.h diff --git a/drivers/media/platform/nxp/Kconfig b/drivers/media/platform/nxp/Kconfig index 1ac0a6e91111..4c76656e353e 100644 --- a/drivers/media/platform/nxp/Kconfig +++ b/drivers/media/platform/nxp/Kconfig @@ -51,4 +51,5 @@ config VIDEO_MX2_EMMAPRP memory to memory. Operations include resizing and format conversion. +source "drivers/media/platform/nxp/dw100/Kconfig" source "drivers/media/platform/nxp/imx-jpeg/Kconfig" diff --git a/drivers/media/platform/nxp/Makefile b/drivers/media/platform/nxp/Makefile index efc38c6578ce..22ba28ac6d63 100644 --- a/drivers/media/platform/nxp/Makefile +++ b/drivers/media/platform/nxp/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only +obj-y += dw100/ obj-y += imx-jpeg/ obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o diff --git a/drivers/media/platform/nxp/dw100/Kconfig b/drivers/media/platform/nxp/dw100/Kconfig new file mode 100644 index 000000000000..45e01baf3b27 --- /dev/null +++ b/drivers/media/platform/nxp/dw100/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config VIDEO_DW100 + tristate "NXP i.MX DW100 dewarper" + depends on V4L_MEM2MEM_DRIVERS + depends on VIDEO_DEV + depends on ARCH_MXC || COMPILE_TEST + select MEDIA_CONTROLLER + select V4L2_MEM2MEM_DEV + select VIDEOBUF2_DMA_CONTIG + help + DW100 is a memory-to-memory engine performing geometrical + transformation on source images through a programmable dewarping map. + + To compile this driver as a module, choose M here: the module + will be called dw100. + diff --git a/drivers/media/platform/nxp/dw100/Makefile b/drivers/media/platform/nxp/dw100/Makefile new file mode 100644 index 000000000000..49db80589e9a --- /dev/null +++ b/drivers/media/platform/nxp/dw100/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_VIDEO_DW100) += dw100.o diff --git a/drivers/media/platform/nxp/dw100/dw100.c b/drivers/media/platform/nxp/dw100/dw100.c new file mode 100644 index 000000000000..2d4a35d8303e --- /dev/null +++ b/drivers/media/platform/nxp/dw100/dw100.c @@ -0,0 +1,1687 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * DW100 Hardware dewarper + * + * Copyright 2022 NXP + * Author: Xavier Roumegue (xavier.roumegue@oss.nxp.com) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "dw100_regs.h" + +#define DRV_NAME "dw100" + +#define DW100_MIN_W 176 +#define DW100_MIN_H 144 +#define DW100_MAX_W 4096 +#define DW100_MAX_H 3072 +#define DW100_ALIGN_W 3 +#define DW100_ALIGN_H 3 + +#define DW100_BLOCK_SIZE 16 + +#define DW100_MAX_LUT_W ((DW100_MAX_W / DW100_BLOCK_SIZE) + 1) +#define DW100_MIN_LUT_W ((DW100_MIN_W / DW100_BLOCK_SIZE) + 1) +#define DW100_MAX_LUT_H ((DW100_MAX_H / DW100_BLOCK_SIZE) + 1) +#define DW100_MIN_LUT_H ((DW100_MIN_H / DW100_BLOCK_SIZE) + 1) +#define DW100_MAX_LUT_NELEMS (DW100_MAX_LUT_W * DW100_MAX_LUT_H) +#define DW100_MIN_LUT_NELEMS (DW100_MIN_LUT_W * DW100_MIN_LUT_H) + +/* + * 16 controls have been reserved for this driver for future extension, but + * let's limit the related driver allocation to the effective number of controls + * in use. + */ +#define DW100_MAX_CTRLS 1 +#define DW100_CTRL_DEWARPING_MAP 0 + +enum { + DW100_QUEUE_SRC = 0, + DW100_QUEUE_DST = 1, +}; + +enum { + DW100_FMT_CAPTURE = BIT(0), + DW100_FMT_OUTPUT = BIT(1), +}; + +struct dw100_device { + struct platform_device *pdev; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_device v4l2_dev; + struct video_device vfd; + struct media_device mdev; + /* Video device lock */ + struct mutex vfd_mutex; + void __iomem *mmio; + struct clk_bulk_data *clks; + int num_clks; + struct dentry *debugfs_root; +}; + +struct dw100_q_data { + struct v4l2_pix_format_mplane pix_fmt; + unsigned int sequence; + const struct dw100_fmt *fmt; + struct v4l2_rect crop; +}; + +struct dw100_ctx { + struct v4l2_fh fh; + struct dw100_device *dw_dev; + struct v4l2_ctrl_handler hdl; + struct v4l2_ctrl *ctrls[DW100_MAX_CTRLS]; + /* per context m2m queue lock */ + struct mutex vq_mutex; + + /* Look Up Table for pixel remapping */ + unsigned int *map; + dma_addr_t map_dma; + size_t map_size; + unsigned int map_width; + unsigned int map_height; + bool user_map_is_valid; + + /* Related colorspace properties propagated from input to output */ + enum v4l2_colorspace colorspace; + enum v4l2_xfer_func xfer_func; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_quantization quant; + + /* Source and destination queue data */ + struct dw100_q_data q_data[2]; +}; + +static const struct v4l2_frmsize_stepwise dw100_frmsize_stepwise = { + .min_width = DW100_MIN_W, + .min_height = DW100_MIN_H, + .max_width = DW100_MAX_W, + .max_height = DW100_MAX_H, + .step_width = 1UL << DW100_ALIGN_W, + .step_height = 1UL << DW100_ALIGN_H, +}; + +static const struct dw100_fmt { + u32 fourcc; + u32 types; + u32 reg_format; + bool reg_swap_uv; +} formats[] = { + { + .fourcc = V4L2_PIX_FMT_NV16, + .types = DW100_FMT_OUTPUT | DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV422_SP, + .reg_swap_uv = false, + }, { + .fourcc = V4L2_PIX_FMT_NV16M, + .types = DW100_FMT_OUTPUT | DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV422_SP, + .reg_swap_uv = false, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .types = DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV422_SP, + .reg_swap_uv = true, + }, { + .fourcc = V4L2_PIX_FMT_NV61M, + .types = DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV422_SP, + .reg_swap_uv = true, + }, { + .fourcc = V4L2_PIX_FMT_YUYV, + .types = DW100_FMT_OUTPUT | DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV422_PACKED, + .reg_swap_uv = false, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .types = DW100_FMT_OUTPUT | DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV422_PACKED, + .reg_swap_uv = true, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .types = DW100_FMT_OUTPUT | DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV420_SP, + .reg_swap_uv = false, + }, { + .fourcc = V4L2_PIX_FMT_NV12M, + .types = DW100_FMT_OUTPUT | DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV420_SP, + .reg_swap_uv = false, + }, { + .fourcc = V4L2_PIX_FMT_NV21, + .types = DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV420_SP, + .reg_swap_uv = true, + }, { + .fourcc = V4L2_PIX_FMT_NV21M, + .types = DW100_FMT_CAPTURE, + .reg_format = DW100_DEWARP_CTRL_FORMAT_YUV420_SP, + .reg_swap_uv = true, + }, +}; + +static inline int to_dw100_fmt_type(enum v4l2_buf_type type) +{ + if (V4L2_TYPE_IS_OUTPUT(type)) + return DW100_FMT_OUTPUT; + else + return DW100_FMT_CAPTURE; +} + +static const struct dw100_fmt *dw100_find_pixel_format(u32 pixel_format, + int fmt_type) +{ + const struct dw100_fmt *fmt; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + fmt = &formats[i]; + if (fmt->fourcc == pixel_format && fmt->types & fmt_type) + return fmt; + } + + return NULL; +} + +static const struct dw100_fmt *dw100_find_format(struct v4l2_format *f) +{ + return dw100_find_pixel_format(f->fmt.pix_mp.pixelformat, + to_dw100_fmt_type(f->type)); +} + +static inline u32 dw100_read(struct dw100_device *dw_dev, u32 reg) +{ + return readl(dw_dev->mmio + reg); +} + +static inline void dw100_write(struct dw100_device *dw_dev, u32 reg, u32 val) +{ + writel(val, dw_dev->mmio + reg); +} + +static inline int dw100_dump_regs(struct seq_file *m) +{ + struct dw100_device *dw_dev = m->private; +#define __DECLARE_REG(x) { #x, x } + int i; + struct reg_desc { + const char * const name; + unsigned int addr; + } dw100_regs[] = { + __DECLARE_REG(DW100_DEWARP_ID), + __DECLARE_REG(DW100_DEWARP_CTRL), + __DECLARE_REG(DW100_MAP_LUT_ADDR), + __DECLARE_REG(DW100_MAP_LUT_SIZE), + __DECLARE_REG(DW100_MAP_LUT_ADDR2), + __DECLARE_REG(DW100_MAP_LUT_SIZE2), + __DECLARE_REG(DW100_SRC_IMG_Y_BASE), + __DECLARE_REG(DW100_SRC_IMG_UV_BASE), + __DECLARE_REG(DW100_SRC_IMG_SIZE), + __DECLARE_REG(DW100_SRC_IMG_STRIDE), + __DECLARE_REG(DW100_DST_IMG_Y_BASE), + __DECLARE_REG(DW100_DST_IMG_UV_BASE), + __DECLARE_REG(DW100_DST_IMG_SIZE), + __DECLARE_REG(DW100_DST_IMG_STRIDE), + __DECLARE_REG(DW100_DST_IMG_Y_SIZE1), + __DECLARE_REG(DW100_DST_IMG_UV_SIZE1), + __DECLARE_REG(DW100_SRC_IMG_Y_BASE2), + __DECLARE_REG(DW100_SRC_IMG_UV_BASE2), + __DECLARE_REG(DW100_SRC_IMG_SIZE2), + __DECLARE_REG(DW100_SRC_IMG_STRIDE2), + __DECLARE_REG(DW100_DST_IMG_Y_BASE2), + __DECLARE_REG(DW100_DST_IMG_UV_BASE2), + __DECLARE_REG(DW100_DST_IMG_SIZE2), + __DECLARE_REG(DW100_DST_IMG_STRIDE2), + __DECLARE_REG(DW100_DST_IMG_Y_SIZE2), + __DECLARE_REG(DW100_DST_IMG_UV_SIZE2), + __DECLARE_REG(DW100_SWAP_CONTROL), + __DECLARE_REG(DW100_VERTICAL_SPLIT_LINE), + __DECLARE_REG(DW100_HORIZON_SPLIT_LINE), + __DECLARE_REG(DW100_SCALE_FACTOR), + __DECLARE_REG(DW100_ROI_START), + __DECLARE_REG(DW100_BOUNDARY_PIXEL), + __DECLARE_REG(DW100_INTERRUPT_STATUS), + __DECLARE_REG(DW100_BUS_CTRL), + __DECLARE_REG(DW100_BUS_CTRL1), + __DECLARE_REG(DW100_BUS_TIME_OUT_CYCLE), + }; + + for (i = 0; i < ARRAY_SIZE(dw100_regs); i++) + seq_printf(m, "%s: %#x\n", dw100_regs[i].name, + dw100_read(dw_dev, dw100_regs[i].addr)); + + return 0; +} + +static inline struct dw100_ctx *file2ctx(struct file *file) +{ + return container_of(file->private_data, struct dw100_ctx, fh); +} + +static struct dw100_q_data *get_q_data(struct dw100_ctx *ctx, + enum v4l2_buf_type type) +{ + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + return &ctx->q_data[DW100_QUEUE_SRC]; + else + return &ctx->q_data[DW100_QUEUE_DST]; +} + +static u32 dw100_get_n_vertices_from_length(u32 length) +{ + return DIV_ROUND_UP(length, DW100_BLOCK_SIZE) + 1; +} + +static u16 dw100_map_convert_to_uq12_4(u32 a) +{ + return (u16)((a & 0xfff) << 4); +} + +static u32 dw100_map_format_coordinates(u16 xq, u16 yq) +{ + return (u32)((yq << 16) | xq); +} + +static u32 *dw100_get_user_map(struct dw100_ctx *ctx) +{ + struct v4l2_ctrl *ctrl = ctx->ctrls[DW100_CTRL_DEWARPING_MAP]; + + if (!ctx->user_map_is_valid) + return NULL; + + return ctrl->p_cur.p_u32; +} + +/* + * Create the dewarp map from the V4L2 control. If the control hasn't been set + * by the application, generate an identity mapping. + * + * A 16 pixels cell size grid is mapped on the destination image. + * The last cells width/height might be lesser than 16 if the destination image + * width/height is not divisible by 16. This dewarping grid map specifies the + * source image pixel location (x, y) on each grid intersection point. + * Bilinear interpolation is used to compute inner cell points locations. + * + * The coordinates are saved in UQ12.4 fixed point format. + */ +static int dw100_create_mapping(struct dw100_ctx *ctx) +{ + u32 sw, sh, dw, dh, mw, mh, i, j; + u16 qx, qy, qdx, qdy, qsh, qsw; + bool is_user_map = false; + u32 *user_map, *map; + + sw = ctx->q_data[DW100_QUEUE_SRC].pix_fmt.width; + dw = ctx->q_data[DW100_QUEUE_DST].pix_fmt.width; + sh = ctx->q_data[DW100_QUEUE_SRC].pix_fmt.height; + dh = ctx->q_data[DW100_QUEUE_DST].pix_fmt.height; + + mw = dw100_get_n_vertices_from_length(dw); + mh = dw100_get_n_vertices_from_length(dh); + + qsh = dw100_map_convert_to_uq12_4(sh); + qsw = dw100_map_convert_to_uq12_4(sw); + qdx = qsw / (mw - 1); + qdy = qsh / (mh - 1); + + if (ctx->map) + dma_free_coherent(&ctx->dw_dev->pdev->dev, ctx->map_size, + ctx->map, ctx->map_dma); + + ctx->map_width = mw; + ctx->map_height = mh; + ctx->map_size = mh * mw * sizeof(u32); + + ctx->map = dma_alloc_coherent(&ctx->dw_dev->pdev->dev, ctx->map_size, + &ctx->map_dma, GFP_KERNEL); + + if (!ctx->map) + return -ENOMEM; + + user_map = dw100_get_user_map(ctx); + if (user_map) { + is_user_map = true; + memcpy(ctx->map, user_map, ctx->map_size); + goto out; + } + + map = ctx->map; + for (i = 0, qy = 0; i < mh; i++, qy += qdy) { + if (qy > qsh) + qy = qsh; + for (j = 0, qx = 0; j < mw; j++, qx += qdx) { + if (qx > qsw) + qx = qsw; + *map++ = dw100_map_format_coordinates(qx, qy); + } + } +out: + dev_dbg(&ctx->dw_dev->pdev->dev, + "%dx%d %s mapping created (d:%pa-c:%p) for stream %ux%u->%ux%u\n", + mw, mh, is_user_map ? "user" : "identity", + &ctx->map_dma, ctx->map, sw, sh, dw, dh); + + return 0; +} + +static void dw100_destroy_mapping(struct dw100_ctx *ctx) +{ + if (ctx->map) { + dma_free_coherent(&ctx->dw_dev->pdev->dev, ctx->map_size, + ctx->map, ctx->map_dma); + ctx->map = NULL; + } +} + +static int dw100_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct dw100_ctx *ctx = + container_of(ctrl->handler, struct dw100_ctx, hdl); + + switch (ctrl->id) { + case V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP: + ctx->user_map_is_valid = true; + break; + } + + return 0; +} + +static const struct v4l2_ctrl_ops dw100_ctrl_ops = { + .s_ctrl = dw100_s_ctrl, +}; + +static const struct v4l2_ctrl_config controls[] = { + [DW100_CTRL_DEWARPING_MAP] = { + .ops = &dw100_ctrl_ops, + .id = V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP, + .name = "Look-Up Table", + .type = V4L2_CTRL_TYPE_U32, + .min = 0x00000000, + .max = 0xffffffff, + .step = 1, + .def = 0, + .dims = { DW100_MAX_LUT_W, DW100_MAX_LUT_H }, + }, +}; + +static int dw100_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) +{ + struct dw100_ctx *ctx = vb2_get_drv_priv(vq); + const struct v4l2_pix_format_mplane *format; + unsigned int i; + + format = &get_q_data(ctx, vq->type)->pix_fmt; + + if (*nplanes) { + if (*nplanes != format->num_planes) + return -EINVAL; + + for (i = 0; i < *nplanes; ++i) { + if (sizes[i] < format->plane_fmt[i].sizeimage) + return -EINVAL; + } + + return 0; + } + + *nplanes = format->num_planes; + + for (i = 0; i < format->num_planes; ++i) + sizes[i] = format->plane_fmt[i].sizeimage; + + return 0; +} + +static int dw100_buf_prepare(struct vb2_buffer *vb) +{ + unsigned int i; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct dw100_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct dw100_device *dw_dev = ctx->dw_dev; + const struct v4l2_pix_format_mplane *pix_fmt = + &get_q_data(ctx, vb->vb2_queue->type)->pix_fmt; + + if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + if (vbuf->field != V4L2_FIELD_NONE) { + dev_err(&dw_dev->pdev->dev, "%x field isn't supported\n", + vbuf->field); + return -EINVAL; + } + } + + for (i = 0; i < pix_fmt->num_planes; i++) { + unsigned long size = pix_fmt->plane_fmt[i].sizeimage; + + if (vb2_plane_size(vb, i) < size) { + dev_err(&dw_dev->pdev->dev, + "User buffer too small (%lu < %lu)\n", + vb2_plane_size(vb, i), size); + return -EINVAL; + } + + vb2_set_plane_payload(vb, i, size); + } + + return 0; +} + +static void dw100_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct dw100_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); +} + +static int dw100_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct dw100_ctx *ctx = vb2_get_drv_priv(q); + struct dw100_q_data *q_data = get_q_data(ctx, q->type); + int ret; + + q_data->sequence = 0; + + ret = dw100_create_mapping(ctx); + if (ret) + return ret; + + return pm_runtime_resume_and_get(&ctx->dw_dev->pdev->dev); +} + +static void dw100_stop_streaming(struct vb2_queue *q) +{ + struct dw100_ctx *ctx = vb2_get_drv_priv(q); + struct vb2_v4l2_buffer *vbuf; + + for (;;) { + if (V4L2_TYPE_IS_OUTPUT(q->type)) + vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + else + vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + if (!vbuf) + break; + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); + } + + pm_runtime_put_sync(&ctx->dw_dev->pdev->dev); + + dw100_destroy_mapping(ctx); +} + +static const struct vb2_ops dw100_qops = { + .queue_setup = dw100_queue_setup, + .buf_prepare = dw100_buf_prepare, + .buf_queue = dw100_buf_queue, + .start_streaming = dw100_start_streaming, + .stop_streaming = dw100_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static int dw100_m2m_queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct dw100_ctx *ctx = priv; + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + src_vq->ops = &dw100_qops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->vq_mutex; + src_vq->dev = ctx->dw_dev->v4l2_dev.dev; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->ops = &dw100_qops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->vq_mutex; + dst_vq->dev = ctx->dw_dev->v4l2_dev.dev; + + return vb2_queue_init(dst_vq); +} + +static int dw100_open(struct file *file) +{ + struct dw100_device *dw_dev = video_drvdata(file); + struct dw100_ctx *ctx; + struct v4l2_ctrl_handler *hdl; + struct v4l2_pix_format_mplane *pix_fmt; + int ret, i; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + mutex_init(&ctx->vq_mutex); + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; + ctx->dw_dev = dw_dev; + + hdl = &ctx->hdl; + v4l2_ctrl_handler_init(hdl, ARRAY_SIZE(controls)); + for (i = 0; i < ARRAY_SIZE(controls); i++) { + ctx->ctrls[i] = v4l2_ctrl_new_custom(hdl, &controls[i], NULL); + if (hdl->error) { + dev_err(&ctx->dw_dev->pdev->dev, + "Adding control (%d) failed\n", i); + ret = hdl->error; + goto with_err; + } + } + ctx->fh.ctrl_handler = hdl; + ctx->user_map_is_valid = false; + + ctx->q_data[DW100_QUEUE_SRC].fmt = &formats[0]; + + pix_fmt = &ctx->q_data[DW100_QUEUE_SRC].pix_fmt; + pix_fmt->field = V4L2_FIELD_NONE; + pix_fmt->colorspace = V4L2_COLORSPACE_REC709; + pix_fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix_fmt->colorspace); + pix_fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix_fmt->colorspace); + pix_fmt->quantization = + V4L2_MAP_QUANTIZATION_DEFAULT(false, pix_fmt->colorspace, + pix_fmt->ycbcr_enc); + + v4l2_fill_pixfmt_mp(pix_fmt, formats[0].fourcc, 640, 480); + + ctx->q_data[DW100_QUEUE_SRC].crop.top = 0; + ctx->q_data[DW100_QUEUE_SRC].crop.left = 0; + ctx->q_data[DW100_QUEUE_SRC].crop.width = 640; + ctx->q_data[DW100_QUEUE_SRC].crop.height = 480; + + ctx->q_data[DW100_QUEUE_DST] = ctx->q_data[DW100_QUEUE_SRC]; + + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dw_dev->m2m_dev, + ctx, &dw100_m2m_queue_init); + + if (IS_ERR(ctx->fh.m2m_ctx)) { + ret = PTR_ERR(ctx->fh.m2m_ctx); + goto with_err; + } + + v4l2_fh_add(&ctx->fh); + + return 0; + +with_err: + v4l2_ctrl_handler_free(hdl); + v4l2_fh_exit(&ctx->fh); + mutex_destroy(&ctx->vq_mutex); + kfree(ctx); + + return ret; +} + +static int dw100_release(struct file *file) +{ + struct dw100_ctx *ctx = file2ctx(file); + + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_ctrl_handler_free(&ctx->hdl); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + mutex_destroy(&ctx->vq_mutex); + kfree(ctx); + + return 0; +} + +static const struct v4l2_file_operations dw100_fops = { + .owner = THIS_MODULE, + .open = dw100_open, + .release = dw100_release, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +}; + +static int dw100_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strscpy(cap->driver, DRV_NAME, sizeof(cap->driver)); + strscpy(cap->card, "DW100 dewarper", sizeof(cap->card)); + + return 0; +} + +static int dw100_enum_fmt_vid(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + int i, num = 0; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + if (formats[i].types & to_dw100_fmt_type(f->type)) { + if (num == f->index) { + f->pixelformat = formats[i].fourcc; + return 0; + } + ++num; + } + } + + return -EINVAL; +} + +static int dw100_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + const struct dw100_fmt *fmt; + + if (fsize->index) + return -EINVAL; + + fmt = dw100_find_pixel_format(fsize->pixel_format, + DW100_FMT_OUTPUT | DW100_FMT_CAPTURE); + if (!fmt) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + fsize->stepwise = dw100_frmsize_stepwise; + + return 0; +} + +static int dw100_g_fmt_vid(struct file *file, void *priv, struct v4l2_format *f) +{ + struct dw100_ctx *ctx = file2ctx(file); + struct vb2_queue *vq; + struct dw100_q_data *q_data; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(ctx, f->type); + + f->fmt.pix_mp = q_data->pix_fmt; + + return 0; +} + +static int dw100_try_fmt(struct v4l2_format *f) +{ + struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; + const struct dw100_fmt *fmt; + + fmt = dw100_find_format(f); + if (!fmt) { + f->fmt.pix_mp.pixelformat = formats[0].fourcc; + fmt = dw100_find_format(f); + } + + v4l2_apply_frmsize_constraints(&pix->width, &pix->height, + &dw100_frmsize_stepwise); + + v4l2_fill_pixfmt_mp(pix, fmt->fourcc, pix->width, pix->height); + + pix->field = V4L2_FIELD_NONE; + + if (pix->colorspace == V4L2_COLORSPACE_DEFAULT) + pix->colorspace = V4L2_COLORSPACE_REC709; + if (pix->xfer_func == V4L2_XFER_FUNC_DEFAULT) + pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace); + if (pix->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) + pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace); + if (pix->quantization == V4L2_QUANTIZATION_DEFAULT) + pix->quantization = + V4L2_MAP_QUANTIZATION_DEFAULT(false, pix->colorspace, + pix->ycbcr_enc); + + return 0; +} + +static int dw100_s_fmt(struct dw100_ctx *ctx, struct v4l2_format *f) +{ + struct dw100_q_data *q_data; + struct dw100_q_data *src_q_data, *dst_q_data; + struct vb2_queue *vq; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(ctx, f->type); + if (!q_data) + return -EINVAL; + + if (vb2_is_busy(vq)) { + dev_err(&ctx->dw_dev->pdev->dev, "%s queue busy\n", __func__); + return -EBUSY; + } + + q_data->fmt = dw100_find_format(f); + q_data->pix_fmt = f->fmt.pix_mp; + q_data->crop.top = 0; + q_data->crop.left = 0; + q_data->crop.width = f->fmt.pix_mp.width; + q_data->crop.height = f->fmt.pix_mp.height; + + /* Propagate buffers encoding */ + src_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + dst_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + dst_q_data->pix_fmt.colorspace = src_q_data->pix_fmt.colorspace; + dst_q_data->pix_fmt.ycbcr_enc = src_q_data->pix_fmt.ycbcr_enc; + dst_q_data->pix_fmt.quantization = src_q_data->pix_fmt.quantization; + dst_q_data->pix_fmt.xfer_func = src_q_data->pix_fmt.xfer_func; + + dev_dbg(&ctx->dw_dev->pdev->dev, + "Setting format for type %u, wxh: %ux%u, fmt: %u\n", + f->type, q_data->pix_fmt.width, q_data->pix_fmt.height, + q_data->pix_fmt.pixelformat); + + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + u32 dims[V4L2_CTRL_MAX_DIMS] = {}; + struct v4l2_ctrl *ctrl = ctx->ctrls[DW100_CTRL_DEWARPING_MAP]; + + dims[0] = + dw100_get_n_vertices_from_length(q_data->pix_fmt.width); + dims[1] = + dw100_get_n_vertices_from_length(q_data->pix_fmt.height); + + if (memcmp(ctrl->dims, dims, + ctrl->nr_of_dims * sizeof(dims[0]))) { + int ret; + + v4l2_ctrl_lock(ctrl); + ctx->user_map_is_valid = false; + ret = __v4l2_ctrl_modify_dimensions(ctrl, dims); + v4l2_ctrl_unlock(ctrl); + if (ret) { + dev_err(&ctx->dw_dev->pdev->dev, + "Modifying LUT dimensions failed with error %d\n", + ret); + return ret; + } + } + } + + return 0; +} + +static int dw100_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + return -EINVAL; + + return dw100_try_fmt(f); +} + +static int dw100_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct dw100_ctx *ctx = file2ctx(file); + int ret; + + ret = dw100_try_fmt_vid_cap(file, priv, f); + if (ret) + return ret; + + ret = dw100_s_fmt(ctx, f); + if (ret) + return ret; + + return 0; +} + +static int dw100_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + return -EINVAL; + + return dw100_try_fmt(f); +} + +static int dw100_s_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct dw100_ctx *ctx = file2ctx(file); + int ret; + + ret = dw100_try_fmt_vid_out(file, priv, f); + if (ret) + return ret; + + ret = dw100_s_fmt(ctx, f); + if (ret) + return ret; + + return 0; +} + +static int dw100_g_selection(struct file *file, void *fh, + struct v4l2_selection *sel) +{ + struct dw100_ctx *ctx = file2ctx(file); + struct dw100_q_data *src_q_data; + + if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + src_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = src_q_data->pix_fmt.width; + sel->r.height = src_q_data->pix_fmt.height; + break; + case V4L2_SEL_TGT_CROP: + sel->r.top = src_q_data->crop.top; + sel->r.left = src_q_data->crop.left; + sel->r.width = src_q_data->crop.width; + sel->r.height = src_q_data->crop.height; + break; + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + case V4L2_SEL_TGT_COMPOSE: + default: + return -EINVAL; + } + + dev_dbg(&ctx->dw_dev->pdev->dev, + "<<< Buffer Type: %d Target: %d Rect: %dx%d@%d.%d\n", + sel->type, sel->target, + sel->r.width, sel->r.height, sel->r.left, sel->r.top); + + return 0; +} + +static int dw100_s_selection(struct file *file, void *fh, + struct v4l2_selection *sel) +{ + struct dw100_ctx *ctx = file2ctx(file); + struct dw100_q_data *src_q_data; + u32 qscalex, qscaley, qscale; + int x, y, w, h; + unsigned int wframe, hframe; + + if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + src_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + dev_dbg(&ctx->dw_dev->pdev->dev, + ">>> Buffer Type: %d Target: %d Rect: %dx%d@%d.%d\n", + sel->type, sel->target, + sel->r.width, sel->r.height, sel->r.left, sel->r.top); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + wframe = src_q_data->pix_fmt.width; + hframe = src_q_data->pix_fmt.height; + + if (sel->r.top < 0) + sel->r.top = 0; + if (sel->r.left < 0) + sel->r.left = 0; + if (sel->r.left + sel->r.width > wframe) + sel->r.width = wframe - sel->r.left; + if (sel->r.top + sel->r.height > hframe) + sel->r.height = hframe - sel->r.top; + + /* UQ16.16 for float operations */ + qscalex = (sel->r.width << 16) / wframe; + qscaley = (sel->r.height << 16) / hframe; + y = sel->r.top; + x = sel->r.left; + if (qscalex == qscaley) { + qscale = qscalex; + } else { + switch (sel->flags) { + case 0: + qscale = (qscalex + qscaley) / 2; + break; + case V4L2_SEL_FLAG_GE: + qscale = max(qscaley, qscalex); + break; + case V4L2_SEL_FLAG_LE: + qscale = min(qscaley, qscalex); + break; + case V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE: + return -ERANGE; + default: + return -EINVAL; + } + } + + w = (u32)((((u64)wframe << 16) * qscale) >> 32); + h = (u32)((((u64)hframe << 16) * qscale) >> 32); + x = x + (sel->r.width - w) / 2; + y = y + (sel->r.height - h) / 2; + x = min(wframe - w, (unsigned int)max(0, x)); + y = min(hframe - h, (unsigned int)max(0, y)); + + sel->r.top = y; + sel->r.left = x; + sel->r.width = w; + sel->r.height = h; + + src_q_data->crop.top = sel->r.top; + src_q_data->crop.left = sel->r.left; + src_q_data->crop.width = sel->r.width; + src_q_data->crop.height = sel->r.height; + break; + case V4L2_SEL_TGT_COMPOSE: + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_COMPOSE_DEFAULT: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + default: + return -EINVAL; + } + + dev_dbg(&ctx->dw_dev->pdev->dev, + "<<< Buffer Type: %d Target: %d Rect: %dx%d@%d.%d\n", + sel->type, sel->target, + sel->r.width, sel->r.height, sel->r.left, sel->r.top); + + return 0; +} + +static const struct v4l2_ioctl_ops dw100_ioctl_ops = { + .vidioc_querycap = dw100_querycap, + + .vidioc_enum_fmt_vid_cap = dw100_enum_fmt_vid, + .vidioc_enum_framesizes = dw100_enum_framesizes, + .vidioc_g_fmt_vid_cap_mplane = dw100_g_fmt_vid, + .vidioc_try_fmt_vid_cap_mplane = dw100_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap_mplane = dw100_s_fmt_vid_cap, + + .vidioc_enum_fmt_vid_out = dw100_enum_fmt_vid, + .vidioc_g_fmt_vid_out_mplane = dw100_g_fmt_vid, + .vidioc_try_fmt_vid_out_mplane = dw100_try_fmt_vid_out, + .vidioc_s_fmt_vid_out_mplane = dw100_s_fmt_vid_out, + + .vidioc_g_selection = dw100_g_selection, + .vidioc_s_selection = dw100_s_selection, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static void dw100_job_finish(struct dw100_device *dw_dev, bool with_error) +{ + struct dw100_ctx *curr_ctx; + struct vb2_v4l2_buffer *src_vb, *dst_vb; + enum vb2_buffer_state buf_state; + + curr_ctx = v4l2_m2m_get_curr_priv(dw_dev->m2m_dev); + + if (!curr_ctx) { + dev_err(&dw_dev->pdev->dev, + "Instance released before the end of transaction\n"); + return; + } + + src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); + dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); + + if (likely(!with_error)) + buf_state = VB2_BUF_STATE_DONE; + else + buf_state = VB2_BUF_STATE_ERROR; + + v4l2_m2m_buf_done(src_vb, buf_state); + v4l2_m2m_buf_done(dst_vb, buf_state); + + dev_dbg(&dw_dev->pdev->dev, "Finishing transaction with%s error(s)\n", + with_error ? "" : "out"); + + v4l2_m2m_job_finish(dw_dev->m2m_dev, curr_ctx->fh.m2m_ctx); +} + +static void dw100_hw_reset(struct dw100_device *dw_dev) +{ + u32 val; + + val = dw100_read(dw_dev, DW100_DEWARP_CTRL); + val |= DW100_DEWARP_CTRL_ENABLE; + val |= DW100_DEWARP_CTRL_SOFT_RESET; + dw100_write(dw_dev, DW100_DEWARP_CTRL, val); + val &= ~DW100_DEWARP_CTRL_SOFT_RESET; + dw100_write(dw_dev, DW100_DEWARP_CTRL, val); +} + +static void _dw100_hw_set_master_bus_enable(struct dw100_device *dw_dev, + unsigned int enable) +{ + u32 val; + + dev_dbg(&dw_dev->pdev->dev, "%sable master bus\n", + enable ? "En" : "Dis"); + + val = dw100_read(dw_dev, DW100_BUS_CTRL); + + if (enable) + val |= DW100_BUS_CTRL_AXI_MASTER_ENABLE; + else + val &= ~DW100_BUS_CTRL_AXI_MASTER_ENABLE; + + dw100_write(dw_dev, DW100_BUS_CTRL, val); +} + +static void dw100_hw_master_bus_enable(struct dw100_device *dw_dev) +{ + _dw100_hw_set_master_bus_enable(dw_dev, 1); +} + +static void dw100_hw_master_bus_disable(struct dw100_device *dw_dev) +{ + _dw100_hw_set_master_bus_enable(dw_dev, 0); +} + +static void dw100_hw_dewarp_start(struct dw100_device *dw_dev) +{ + u32 val; + + val = dw100_read(dw_dev, DW100_DEWARP_CTRL); + + dev_dbg(&dw_dev->pdev->dev, "Starting Hardware CTRL:%x\n", val); + dw100_write(dw_dev, DW100_DEWARP_CTRL, val | DW100_DEWARP_CTRL_START); + dw100_write(dw_dev, DW100_DEWARP_CTRL, val); +} + +static void dw100_hw_init_ctrl(struct dw100_device *dw_dev) +{ + u32 val; + /* + * Input format YUV422_SP + * Output format YUV422_SP + * No hardware handshake (SW) + * No automatic double src buffering (Single) + * No automatic double dst buffering (Single) + * No Black Line + * Prefetch image pixel traversal + */ + + val = DW100_DEWARP_CTRL_ENABLE + /* Valid only for auto prefetch mode*/ + | DW100_DEWARP_CTRL_PREFETCH_THRESHOLD(32); + + /* + * Calculation mode required to support any scaling factor, + * but x4 slower than traversal mode. + * + * DW100_DEWARP_CTRL_PREFETCH_MODE_TRAVERSAL + * DW100_DEWARP_CTRL_PREFETCH_MODE_CALCULATION + * DW100_DEWARP_CTRL_PREFETCH_MODE_AUTO + * + * TODO: Find heuristics requiring calculation mode + */ + val |= DW100_DEWARP_CTRL_PREFETCH_MODE_CALCULATION; + + dw100_write(dw_dev, DW100_DEWARP_CTRL, val); +} + +static void dw100_hw_set_pixel_boundary(struct dw100_device *dw_dev) +{ + u32 val; + + val = DW100_BOUNDARY_PIXEL_V(128) + | DW100_BOUNDARY_PIXEL_U(128) + | DW100_BOUNDARY_PIXEL_Y(0); + + dw100_write(dw_dev, DW100_BOUNDARY_PIXEL, val); +} + +static void dw100_hw_set_scale(struct dw100_device *dw_dev, u8 scale) +{ + dev_dbg(&dw_dev->pdev->dev, "Setting scale factor to %d\n", scale); + + dw100_write(dw_dev, DW100_SCALE_FACTOR, scale); +} + +static void dw100_hw_set_roi(struct dw100_device *dw_dev, u32 x, u32 y) +{ + u32 val; + + dev_dbg(&dw_dev->pdev->dev, "Setting ROI region to %d.%d\n", x, y); + + val = DW100_ROI_START_X(x) | DW100_ROI_START_Y(y); + + dw100_write(dw_dev, DW100_ROI_START, val); +} + +static void dw100_hw_set_src_crop(struct dw100_device *dw_dev, + const struct dw100_q_data *src_q_data, + const struct dw100_q_data *dst_q_data) +{ + const struct v4l2_rect *rect = &src_q_data->crop; + u32 src_scale, qscale, left_scale, top_scale; + + /* HW Scale is UQ1.7 encoded */ + src_scale = (rect->width << 7) / src_q_data->pix_fmt.width; + dw100_hw_set_scale(dw_dev, src_scale); + + qscale = (dst_q_data->pix_fmt.width << 7) / src_q_data->pix_fmt.width; + + left_scale = ((rect->left << 7) * qscale) >> 14; + top_scale = ((rect->top << 7) * qscale) >> 14; + + dw100_hw_set_roi(dw_dev, left_scale, top_scale); +} + +static void dw100_hw_set_source(struct dw100_device *dw_dev, + struct dw100_q_data *q_data, + struct vb2_buffer *buffers) +{ + u32 width, height, stride, fourcc, val; + const struct dw100_fmt *fmt = q_data->fmt; + dma_addr_t addr_y = vb2_dma_contig_plane_dma_addr(buffers, 0); + dma_addr_t addr_uv; + + width = q_data->pix_fmt.width; + height = q_data->pix_fmt.height; + stride = q_data->pix_fmt.plane_fmt[0].bytesperline; + fourcc = q_data->fmt->fourcc; + + if (q_data->pix_fmt.num_planes == 2) + addr_uv = vb2_dma_contig_plane_dma_addr(buffers, 1); + else + addr_uv = addr_y + (stride * height); + + dev_dbg(&dw_dev->pdev->dev, + "Set HW source registers for %dx%d - stride %d, pixfmt: %x, dma:%pa\n", + width, height, stride, fourcc, &addr_y); + + /* Pixel Format */ + val = dw100_read(dw_dev, DW100_DEWARP_CTRL); + + val &= ~DW100_DEWARP_CTRL_INPUT_FORMAT_MASK; + val |= DW100_DEWARP_CTRL_INPUT_FORMAT(fmt->reg_format); + + dw100_write(dw_dev, DW100_DEWARP_CTRL, val); + + /* Swap */ + val = dw100_read(dw_dev, DW100_SWAP_CONTROL); + + val &= ~DW100_SWAP_CONTROL_SRC_MASK; + /* + * Data swapping is performed only on Y plane for source image. + */ + if (fmt->reg_swap_uv && + fmt->reg_format == DW100_DEWARP_CTRL_FORMAT_YUV422_PACKED) + val |= DW100_SWAP_CONTROL_SRC(DW100_SWAP_CONTROL_Y + (DW100_SWAP_CONTROL_BYTE)); + + dw100_write(dw_dev, DW100_SWAP_CONTROL, val); + + /* Image resolution */ + dw100_write(dw_dev, DW100_SRC_IMG_SIZE, + DW100_IMG_SIZE_WIDTH(width) | DW100_IMG_SIZE_HEIGHT(height)); + + dw100_write(dw_dev, DW100_SRC_IMG_STRIDE, stride); + + /* Buffers */ + dw100_write(dw_dev, DW100_SRC_IMG_Y_BASE, DW100_IMG_Y_BASE(addr_y)); + dw100_write(dw_dev, DW100_SRC_IMG_UV_BASE, DW100_IMG_UV_BASE(addr_uv)); +} + +static void dw100_hw_set_destination(struct dw100_device *dw_dev, + struct dw100_q_data *q_data, + const struct dw100_fmt *ifmt, + struct vb2_buffer *buffers) +{ + u32 width, height, stride, fourcc, val, size_y, size_uv; + const struct dw100_fmt *fmt = q_data->fmt; + dma_addr_t addr_y, addr_uv; + + width = q_data->pix_fmt.width; + height = q_data->pix_fmt.height; + stride = q_data->pix_fmt.plane_fmt[0].bytesperline; + fourcc = fmt->fourcc; + + addr_y = vb2_dma_contig_plane_dma_addr(buffers, 0); + size_y = q_data->pix_fmt.plane_fmt[0].sizeimage; + + if (q_data->pix_fmt.num_planes == 2) { + addr_uv = vb2_dma_contig_plane_dma_addr(buffers, 1); + size_uv = q_data->pix_fmt.plane_fmt[1].sizeimage; + } else { + addr_uv = addr_y + ALIGN(stride * height, 16); + size_uv = size_y; + if (fmt->reg_format == DW100_DEWARP_CTRL_FORMAT_YUV420_SP) + size_uv /= 2; + } + + dev_dbg(&dw_dev->pdev->dev, + "Set HW source registers for %dx%d - stride %d, pixfmt: %x, dma:%pa\n", + width, height, stride, fourcc, &addr_y); + + /* Pixel Format */ + val = dw100_read(dw_dev, DW100_DEWARP_CTRL); + + val &= ~DW100_DEWARP_CTRL_OUTPUT_FORMAT_MASK; + val |= DW100_DEWARP_CTRL_OUTPUT_FORMAT(fmt->reg_format); + + dw100_write(dw_dev, DW100_DEWARP_CTRL, val); + + /* Swap */ + val = dw100_read(dw_dev, DW100_SWAP_CONTROL); + + val &= ~DW100_SWAP_CONTROL_DST_MASK; + + /* + * Avoid to swap twice + */ + if (fmt->reg_swap_uv ^ + (ifmt->reg_swap_uv && ifmt->reg_format != + DW100_DEWARP_CTRL_FORMAT_YUV422_PACKED)) { + if (fmt->reg_format == DW100_DEWARP_CTRL_FORMAT_YUV422_PACKED) + val |= DW100_SWAP_CONTROL_DST(DW100_SWAP_CONTROL_Y + (DW100_SWAP_CONTROL_BYTE)); + else + val |= DW100_SWAP_CONTROL_DST(DW100_SWAP_CONTROL_UV + (DW100_SWAP_CONTROL_BYTE)); + } + + dw100_write(dw_dev, DW100_SWAP_CONTROL, val); + + /* Image resolution */ + dw100_write(dw_dev, DW100_DST_IMG_SIZE, + DW100_IMG_SIZE_WIDTH(width) | DW100_IMG_SIZE_HEIGHT(height)); + dw100_write(dw_dev, DW100_DST_IMG_STRIDE, stride); + dw100_write(dw_dev, DW100_DST_IMG_Y_BASE, DW100_IMG_Y_BASE(addr_y)); + dw100_write(dw_dev, DW100_DST_IMG_UV_BASE, DW100_IMG_UV_BASE(addr_uv)); + dw100_write(dw_dev, DW100_DST_IMG_Y_SIZE1, DW100_DST_IMG_Y_SIZE(size_y)); + dw100_write(dw_dev, DW100_DST_IMG_UV_SIZE1, + DW100_DST_IMG_UV_SIZE(size_uv)); +} + +static void dw100_hw_set_mapping(struct dw100_device *dw_dev, dma_addr_t addr, + u32 width, u32 height) +{ + dev_dbg(&dw_dev->pdev->dev, + "Set HW mapping registers for %dx%d addr:%pa", + width, height, &addr); + + dw100_write(dw_dev, DW100_MAP_LUT_ADDR, DW100_MAP_LUT_ADDR_ADDR(addr)); + dw100_write(dw_dev, DW100_MAP_LUT_SIZE, DW100_MAP_LUT_SIZE_WIDTH(width) + | DW100_MAP_LUT_SIZE_HEIGHT(height)); +} + +static void dw100_hw_clear_irq(struct dw100_device *dw_dev, unsigned int irq) +{ + dw100_write(dw_dev, DW100_INTERRUPT_STATUS, + DW100_INTERRUPT_STATUS_INT_CLEAR(irq)); +} + +static void dw100_hw_enable_irq(struct dw100_device *dw_dev) +{ + dw100_write(dw_dev, DW100_INTERRUPT_STATUS, + DW100_INTERRUPT_STATUS_INT_ENABLE_MASK); +} + +static void dw100_hw_disable_irq(struct dw100_device *dw_dev) +{ + dw100_write(dw_dev, DW100_INTERRUPT_STATUS, 0); +} + +static u32 dw_hw_get_pending_irqs(struct dw100_device *dw_dev) +{ + u32 val; + + val = dw100_read(dw_dev, DW100_INTERRUPT_STATUS); + + return DW100_INTERRUPT_STATUS_INT_STATUS(val); +} + +static irqreturn_t dw100_irq_handler(int irq, void *dev_id) +{ + struct dw100_device *dw_dev = dev_id; + u32 pending_irqs, err_irqs, frame_done_irq; + bool with_error = true; + + pending_irqs = dw_hw_get_pending_irqs(dw_dev); + frame_done_irq = pending_irqs & DW100_INTERRUPT_STATUS_INT_FRAME_DONE; + err_irqs = DW100_INTERRUPT_STATUS_INT_ERR_STATUS(pending_irqs); + + if (frame_done_irq) { + dev_dbg(&dw_dev->pdev->dev, "Frame done interrupt\n"); + with_error = false; + err_irqs &= ~DW100_INTERRUPT_STATUS_INT_ERR_STATUS + (DW100_INTERRUPT_STATUS_INT_ERR_FRAME_DONE); + } + + if (err_irqs) + dev_err(&dw_dev->pdev->dev, "Interrupt error: %#x\n", err_irqs); + + dw100_hw_disable_irq(dw_dev); + dw100_hw_master_bus_disable(dw_dev); + dw100_hw_clear_irq(dw_dev, pending_irqs | + DW100_INTERRUPT_STATUS_INT_ERR_TIME_OUT); + + dw100_job_finish(dw_dev, with_error); + + return IRQ_HANDLED; +} + +static void dw100_start(struct dw100_ctx *ctx, struct vb2_v4l2_buffer *in_vb, + struct vb2_v4l2_buffer *out_vb) +{ + struct dw100_device *dw_dev = ctx->dw_dev; + + out_vb->sequence = + get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)->sequence++; + in_vb->sequence = + get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)->sequence++; + + dev_dbg(&ctx->dw_dev->pdev->dev, + "Starting queues %p->%p, sequence %d->%d\n", + v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE), + v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE), + in_vb->sequence, out_vb->sequence); + + v4l2_m2m_buf_copy_metadata(in_vb, out_vb, true); + + /* Now, let's deal with hardware ... */ + dw100_hw_master_bus_disable(dw_dev); + dw100_hw_init_ctrl(dw_dev); + dw100_hw_set_pixel_boundary(dw_dev); + dw100_hw_set_src_crop(dw_dev, &ctx->q_data[DW100_QUEUE_SRC], + &ctx->q_data[DW100_QUEUE_DST]); + dw100_hw_set_source(dw_dev, &ctx->q_data[DW100_QUEUE_SRC], + &in_vb->vb2_buf); + dw100_hw_set_destination(dw_dev, &ctx->q_data[DW100_QUEUE_DST], + ctx->q_data[DW100_QUEUE_SRC].fmt, + &out_vb->vb2_buf); + dw100_hw_set_mapping(dw_dev, ctx->map_dma, + ctx->map_width, ctx->map_height); + dw100_hw_enable_irq(dw_dev); + dw100_hw_dewarp_start(dw_dev); + + /* Enable Bus */ + dw100_hw_master_bus_enable(dw_dev); +} + +static void dw100_device_run(void *priv) +{ + struct dw100_ctx *ctx = priv; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + + dw100_start(ctx, src_buf, dst_buf); +} + +static const struct v4l2_m2m_ops dw100_m2m_ops = { + .device_run = dw100_device_run, +}; + +static struct video_device *dw100_init_video_device(struct dw100_device *dw_dev) +{ + struct video_device *vfd = &dw_dev->vfd; + + vfd->vfl_dir = VFL_DIR_M2M; + vfd->fops = &dw100_fops; + vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; + vfd->ioctl_ops = &dw100_ioctl_ops; + vfd->minor = -1; + vfd->release = video_device_release_empty; + vfd->v4l2_dev = &dw_dev->v4l2_dev; + vfd->lock = &dw_dev->vfd_mutex; + + strscpy(vfd->name, DRV_NAME, sizeof(vfd->name)); + mutex_init(vfd->lock); + video_set_drvdata(vfd, dw_dev); + + return vfd; +} + +static int dw100_dump_regs_show(struct seq_file *m, void *private) +{ + struct dw100_device *dw_dev = m->private; + int ret; + + ret = pm_runtime_resume_and_get(&dw_dev->pdev->dev); + if (ret < 0) + return ret; + + ret = dw100_dump_regs(m); + + pm_runtime_put_sync(&dw_dev->pdev->dev); + + return ret; +} +DEFINE_SHOW_ATTRIBUTE(dw100_dump_regs); + +static void dw100_debugfs_init(struct dw100_device *dw_dev) +{ + dw_dev->debugfs_root = + debugfs_create_dir(dev_name(&dw_dev->pdev->dev), NULL); + + debugfs_create_file("dump_regs", 0600, dw_dev->debugfs_root, dw_dev, + &dw100_dump_regs_fops); +} + +static void dw100_debugfs_exit(struct dw100_device *dw_dev) +{ + debugfs_remove_recursive(dw_dev->debugfs_root); +} + +static int dw100_probe(struct platform_device *pdev) +{ + struct dw100_device *dw_dev; + struct video_device *vfd; + struct resource *res; + int ret, irq; + + dw_dev = devm_kzalloc(&pdev->dev, sizeof(*dw_dev), GFP_KERNEL); + if (!dw_dev) + return -ENOMEM; + dw_dev->pdev = pdev; + + ret = devm_clk_bulk_get_all(&pdev->dev, &dw_dev->clks); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to get clocks: %d\n", ret); + return ret; + } + dw_dev->num_clks = ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dw_dev->mmio = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dw_dev->mmio)) + return PTR_ERR(dw_dev->mmio); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + platform_set_drvdata(pdev, dw_dev); + + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to enable clks: %d\n", ret); + goto err_clk; + } + + pm_runtime_put_sync(&pdev->dev); + + ret = devm_request_irq(&pdev->dev, irq, dw100_irq_handler, IRQF_ONESHOT, + dev_name(&pdev->dev), dw_dev); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); + return ret; + } + + ret = v4l2_device_register(&pdev->dev, &dw_dev->v4l2_dev); + if (ret) + goto err_clk; + + vfd = dw100_init_video_device(dw_dev); + + dw_dev->m2m_dev = v4l2_m2m_init(&dw100_m2m_ops); + if (IS_ERR(dw_dev->m2m_dev)) { + dev_err(&pdev->dev, "Failed to init mem2mem device\n"); + ret = PTR_ERR(dw_dev->m2m_dev); + goto err_v4l2; + } + + dw_dev->mdev.dev = &pdev->dev; + strscpy(dw_dev->mdev.model, "dw100", sizeof(dw_dev->mdev.model)); + media_device_init(&dw_dev->mdev); + dw_dev->v4l2_dev.mdev = &dw_dev->mdev; + + ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); + if (ret) { + dev_err(&pdev->dev, "Failed to register video device\n"); + goto err_m2m; + } + + ret = v4l2_m2m_register_media_controller(dw_dev->m2m_dev, vfd, + MEDIA_ENT_F_PROC_VIDEO_SCALER); + if (ret) { + dev_err(&pdev->dev, "Failed to init mem2mem media controller\n"); + goto error_v4l2; + } + + ret = media_device_register(&dw_dev->mdev); + if (ret) { + dev_err(&pdev->dev, "Failed to register mem2mem media device\n"); + goto error_m2m_mc; + } + + dw100_debugfs_init(dw_dev); + + dev_info(&pdev->dev, + "dw100 v4l2 m2m registered as /dev/video%d\n", vfd->num); + + return 0; + +error_m2m_mc: + v4l2_m2m_unregister_media_controller(dw_dev->m2m_dev); +error_v4l2: + video_unregister_device(vfd); +err_m2m: + v4l2_m2m_release(dw_dev->m2m_dev); +err_v4l2: + v4l2_device_unregister(&dw_dev->v4l2_dev); +err_clk: + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static int dw100_remove(struct platform_device *pdev) +{ + struct dw100_device *dw_dev = platform_get_drvdata(pdev); + + dw100_debugfs_exit(dw_dev); + + pm_runtime_disable(&pdev->dev); + + media_device_unregister(&dw_dev->mdev); + v4l2_m2m_unregister_media_controller(dw_dev->m2m_dev); + media_device_cleanup(&dw_dev->mdev); + + video_unregister_device(&dw_dev->vfd); + mutex_destroy(dw_dev->vfd.lock); + v4l2_m2m_release(dw_dev->m2m_dev); + v4l2_device_unregister(&dw_dev->v4l2_dev); + + return 0; +} + +static int __maybe_unused dw100_runtime_suspend(struct device *dev) +{ + struct dw100_device *dw_dev = dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(dw_dev->num_clks, dw_dev->clks); + + return 0; +} + +static int __maybe_unused dw100_runtime_resume(struct device *dev) +{ + int ret; + struct dw100_device *dw_dev = dev_get_drvdata(dev); + + ret = clk_bulk_prepare_enable(dw_dev->num_clks, dw_dev->clks); + + if (!ret) + dw100_hw_reset(dw_dev); + + return ret; +} + +static const struct dev_pm_ops dw100_pm = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(dw100_runtime_suspend, + dw100_runtime_resume, NULL) +}; + +static const struct of_device_id dw100_dt_ids[] = { + { .compatible = "nxp,imx8mp-dw100", .data = NULL }, + { }, +}; +MODULE_DEVICE_TABLE(of, dw100_dt_ids); + +static struct platform_driver dw100_driver = { + .probe = dw100_probe, + .remove = dw100_remove, + .driver = { + .name = DRV_NAME, + .pm = &dw100_pm, + .of_match_table = dw100_dt_ids, + }, +}; + +module_platform_driver(dw100_driver); + +MODULE_DESCRIPTION("DW100 Hardware dewarper"); +MODULE_AUTHOR("Xavier Roumegue "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/nxp/dw100/dw100_regs.h b/drivers/media/platform/nxp/dw100/dw100_regs.h new file mode 100644 index 000000000000..e85dfeff9056 --- /dev/null +++ b/drivers/media/platform/nxp/dw100/dw100_regs.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * DW100 Hardware dewarper + * + * Copyright 2022 NXP + * Author: Xavier Roumegue (xavier.roumegue@oss.nxp.com) + */ + +#ifndef _DW100_REGS_H_ +#define _DW100_REGS_H_ + +/* AHB register offset */ +#define DW100_DEWARP_ID 0x00 +#define DW100_DEWARP_CTRL 0x04 +#define DW100_DEWARP_CTRL_ENABLE BIT(0) +#define DW100_DEWARP_CTRL_START BIT(1) +#define DW100_DEWARP_CTRL_SOFT_RESET BIT(2) +#define DW100_DEWARP_CTRL_FORMAT_YUV422_SP 0UL +#define DW100_DEWARP_CTRL_FORMAT_YUV422_PACKED 1UL +#define DW100_DEWARP_CTRL_FORMAT_YUV420_SP 2UL +#define DW100_DEWARP_CTRL_INPUT_FORMAT_MASK GENMASK(5, 4) +#define DW100_DEWARP_CTRL_INPUT_FORMAT(x) ((x) << 4) +#define DW100_DEWARP_CTRL_OUTPUT_FORMAT(x) ((x) << 6) +#define DW100_DEWARP_CTRL_OUTPUT_FORMAT_MASK GENMASK(7, 6) +#define DW100_DEWARP_CTRL_SRC_AUTO_SHADOW BIT(8) +#define DW100_DEWARP_CTRL_HW_HANDSHAKE BIT(9) +#define DW100_DEWARP_CTRL_DST_AUTO_SHADOW BIT(10) +#define DW100_DEWARP_CTRL_SPLIT_LINE BIT(11) +#define DW100_DEWARP_CTRL_PREFETCH_MODE_MASK GENMASK(17, 16) +#define DW100_DEWARP_CTRL_PREFETCH_MODE_TRAVERSAL (0UL << 16) +#define DW100_DEWARP_CTRL_PREFETCH_MODE_CALCULATION (1UL << 16) +#define DW100_DEWARP_CTRL_PREFETCH_MODE_AUTO (2UL << 16) +#define DW100_DEWARP_CTRL_PREFETCH_THRESHOLD_MASK GENMASK(24, 18) +#define DW100_DEWARP_CTRL_PREFETCH_THRESHOLD(x) ((x) << 18) + +#define DW100_MAP_LUT_ADDR 0x08 +#define DW100_MAP_LUT_ADDR_ADDR(addr) (((addr) >> 4) & GENMASK(29, 0)) +#define DW100_MAP_LUT_SIZE 0x0c +#define DW100_MAP_LUT_SIZE_WIDTH(w) (((w) & GENMASK(10, 0)) << 0) +#define DW100_MAP_LUT_SIZE_HEIGHT(h) (((h) & GENMASK(10, 0)) << 16) +#define DW100_SRC_IMG_Y_BASE 0x10 +#define DW100_IMG_Y_BASE(base) (((base) >> 4) & GENMASK(29, 0)) +#define DW100_SRC_IMG_UV_BASE 0x14 +#define DW100_IMG_UV_BASE(base) (((base) >> 4) & GENMASK(29, 0)) +#define DW100_SRC_IMG_SIZE 0x18 +#define DW100_IMG_SIZE_WIDTH(w) (((w) & GENMASK(12, 0)) << 0) +#define DW100_IMG_SIZE_HEIGHT(h) (((h) & GENMASK(12, 0)) << 16) + +#define DW100_SRC_IMG_STRIDE 0x1c +#define DW100_MAP_LUT_ADDR2 0x20 +#define DW100_MAP_LUT_SIZE2 0x24 +#define DW100_SRC_IMG_Y_BASE2 0x28 +#define DW100_SRC_IMG_UV_BASE2 0x2c +#define DW100_SRC_IMG_SIZE2 0x30 +#define DW100_SRC_IMG_STRIDE2 0x34 +#define DW100_DST_IMG_Y_BASE 0x38 +#define DW100_DST_IMG_UV_BASE 0x3c +#define DW100_DST_IMG_SIZE 0x40 +#define DW100_DST_IMG_STRIDE 0x44 +#define DW100_DST_IMG_Y_BASE2 0x48 +#define DW100_DST_IMG_UV_BASE2 0x4c +#define DW100_DST_IMG_SIZE2 0x50 +#define DW100_DST_IMG_STRIDE2 0x54 +#define DW100_SWAP_CONTROL 0x58 +#define DW100_SWAP_CONTROL_BYTE BIT(0) +#define DW100_SWAP_CONTROL_SHORT BIT(1) +#define DW100_SWAP_CONTROL_WORD BIT(2) +#define DW100_SWAP_CONTROL_LONG BIT(3) +#define DW100_SWAP_CONTROL_Y(x) (((x) & GENMASK(3, 0)) << 0) +#define DW100_SWAP_CONTROL_UV(x) (((x) & GENMASK(3, 0)) << 4) +#define DW100_SWAP_CONTROL_SRC(x) (((x) & GENMASK(7, 0)) << 0) +#define DW100_SWAP_CONTROL_DST(x) (((x) & GENMASK(7, 0)) << 8) +#define DW100_SWAP_CONTROL_SRC2(x) (((x) & GENMASK(7, 0)) << 16) +#define DW100_SWAP_CONTROL_DST2(x) (((x) & GENMASK(7, 0)) << 24) +#define DW100_SWAP_CONTROL_SRC_MASK GENMASK(7, 0) +#define DW100_SWAP_CONTROL_DST_MASK GENMASK(15, 8) +#define DW100_SWAP_CONTROL_SRC2_MASK GENMASK(23, 16) +#define DW100_SWAP_CONTROL_DST2_MASK GENMASK(31, 24) +#define DW100_VERTICAL_SPLIT_LINE 0x5c +#define DW100_HORIZON_SPLIT_LINE 0x60 +#define DW100_SCALE_FACTOR 0x64 +#define DW100_ROI_START 0x68 +#define DW100_ROI_START_X(x) (((x) & GENMASK(12, 0)) << 0) +#define DW100_ROI_START_Y(y) (((y) & GENMASK(12, 0)) << 16) +#define DW100_BOUNDARY_PIXEL 0x6c +#define DW100_BOUNDARY_PIXEL_V(v) (((v) & GENMASK(7, 0)) << 0) +#define DW100_BOUNDARY_PIXEL_U(u) (((u) & GENMASK(7, 0)) << 8) +#define DW100_BOUNDARY_PIXEL_Y(y) (((y) & GENMASK(7, 0)) << 16) + +#define DW100_INTERRUPT_STATUS 0x70 +#define DW100_INTERRUPT_STATUS_INT_FRAME_DONE BIT(0) +#define DW100_INTERRUPT_STATUS_INT_ERR_TIME_OUT BIT(1) +#define DW100_INTERRUPT_STATUS_INT_ERR_AXI_RESP BIT(2) +#define DW100_INTERRUPT_STATUS_INT_ERR_X BIT(3) +#define DW100_INTERRUPT_STATUS_INT_ERR_MB_FETCH BIT(4) +#define DW100_INTERRUPT_STATUS_INT_ERR_FRAME2 BIT(5) +#define DW100_INTERRUPT_STATUS_INT_ERR_FRAME3 BIT(6) +#define DW100_INTERRUPT_STATUS_INT_ERR_FRAME_DONE BIT(7) +#define DW100_INTERRUPT_STATUS_INT_ERR_STATUS(x) (((x) >> 1) & 0x7f) +#define DW100_INTERRUPT_STATUS_INT_STATUS(x) ((x) & 0xff) + +#define DW100_INTERRUPT_STATUS_INT_ENABLE_MASK GENMASK(15, 8) +#define DW100_INTERRUPT_STATUS_INT_ENABLE(x) (((x) & GENMASK(7, 0)) << 8) +#define DW100_INTERRUPT_STATUS_FRAME_BUSY BIT(16) +#define DW100_INTERRUPT_STATUS_INT_CLEAR(x) (((x) & GENMASK(7, 0)) << 24) +#define DW100_BUS_CTRL 0x74 +#define DW100_BUS_CTRL_AXI_MASTER_ENABLE BIT(31) +#define DW100_BUS_CTRL1 0x78 +#define DW100_BUS_TIME_OUT_CYCLE 0x7c +#define DW100_DST_IMG_Y_SIZE1 0x80 +#define DW100_DST_IMG_Y_SIZE(sz) (((sz) >> 4) & GENMASK(29, 0)) +#define DW100_DST_IMG_UV_SIZE(sz) (((sz) >> 4) & GENMASK(29, 0)) +#define DW100_DST_IMG_UV_SIZE1 0x84 +#define DW100_DST_IMG_Y_SIZE2 0x88 +#define DW100_DST_IMG_UV_SIZE2 0x8c + +#endif /* _DW100_REGS_H_ */ From patchwork Thu Jun 23 14:31:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xavier Roumegue \(OSS\)" X-Patchwork-Id: 584441 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id ABCC6C433EF for ; Thu, 23 Jun 2022 14:32:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231981AbiFWOco (ORCPT ); Thu, 23 Jun 2022 10:32:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60018 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231960AbiFWOcm (ORCPT ); Thu, 23 Jun 2022 10:32:42 -0400 Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05on2071.outbound.protection.outlook.com [40.107.20.71]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87A8A457A8; Thu, 23 Jun 2022 07:32:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FNTdd4rC1auTXGXiLYtjhqBieHFRiA9G3Yo5wrWfPwcxNCNfm6kNGGsKMg3683vx7pkyDzDHhmjsnn2wNSwWuaWhb3UgfpZFwjyo6m+Q3bNyELiFUqDczy4ZV5Z5pQnwRCCMpCghW+MykKimaxWWCYBziO3067J8ZLS7lgMlbHZJglztbtNoxuqQ913fpmzihRQUghzHZgw4PijgcMxRZAFfmngwCi/w/endHb6ZltetfqAQXkRYbvd1bWwZ8AiNOjJbF8syqxVTHNR8fd509jiNFsrfgqj0fsFj8aWR7O/Irje69qJBhNdR+sC34XrmoI+HsIYh055cpaoU9sb5uQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Ovrcl+8ua66la0c/B04Ms+KmUl+7NtWMDBTceDurdr4=; b=el8zfdjotJFmJhBVSs2AkkiqlJ075J/HgbJyzI1PoPeJ9Nuhtm5FL0tthhhbUBBIx50aL4CBFn+2mC2L0XytA3QX29gzeiPdZC7qodTE2Vyqy7uAKwnSgysbCppwR11zUrXlhUZfKfaB34tskP97KPYd44C3kBRlLVBKMlpD0dkzTshQyGFTx8oh5K06kn1JHC7y2Aeef5KiB7T5pXEu1UXeHMAFftKAjoqLnHHsL/W0OWH6+yrMM6M4y6nO4l8Z5CvVqvUHOzGNeKQDdnRr2suG9t9W1bl/8p2qdOwjuCWTjYTflpnniZkqMVXRFRcUOryIeK6BxIgkC7iBUHac3w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Ovrcl+8ua66la0c/B04Ms+KmUl+7NtWMDBTceDurdr4=; b=C0/6w0cInUc91Jyrps4xh6u7XS/p8amsREVjiW2KGUDXvsa1iuaoSJwW01yuc90HwDuqr8NXEMhdloHL0gbiYL4Qadybk2mCzRw/dEf6bj8NDPiWky6RV7nKvoF9Ub9fTjMhJWtUJeGYVxPQdKocp4yYkim/DYHJ2SZGGzvmayQ= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) by DB8PR04MB6505.eurprd04.prod.outlook.com (2603:10a6:10:10d::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5353.22; Thu, 23 Jun 2022 14:32:39 +0000 Received: from PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485]) by PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::9127:3fe0:f694:9485%5]) with mapi id 15.20.5353.022; Thu, 23 Jun 2022 14:32:39 +0000 From: Xavier Roumegue To: mchehab@kernel.org, hverkuil-cisco@xs4all.nl, stanimir.varbanov@linaro.org, laurent.pinchart@ideasonboard.com, tomi.valkeinen@ideasonboard.com, robh+dt@kernel.org, nicolas@ndufresne.ca, alexander.stein@ew.tq-group.com Cc: Xavier Roumegue , linux-media@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v6 14/14] media: MAINTAINERS: add entry for i.MX8MP DW100 v4l2 mem2mem driver Date: Thu, 23 Jun 2022 16:31:15 +0200 Message-Id: <20220623143115.3185297-15-xavier.roumegue@oss.nxp.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> References: <20220623143115.3185297-1-xavier.roumegue@oss.nxp.com> X-ClientProxiedBy: PR2P264CA0026.FRAP264.PROD.OUTLOOK.COM (2603:10a6:101:1::14) To PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a74882ea-75c9-44f1-32d5-08da5525392a X-MS-TrafficTypeDiagnostic: DB8PR04MB6505:EE_ X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: sXFAqNYI8Jmjjqa7E+JOOTW9xHcA41qboVHd81JN01/Ebu6KcZ82P9oIqwn34lQ8bGtBa6SVVy3t9yo5VVsUnNqxgWg/AmF/mHIeukAorsXwPNdUXc+eRD40PnBWCDviNxrdUUUy6v53KdjqtzJv28kVyUMFetoc59HigXF97Z/edCBcmpJRm3OA3oLGYDJvIwLH1Zg3f+wAJKJU3EtAomR0tD/4g5dwejAJd38YC1rUajuSk++/RgGl7ptdd6iNE9fKFDE3o2MUaL+x2xOH/mvj3J0dl7j2/yKit18Jjc0FLCGppTaSuURiDE0a/8MEvMOv1d5tWXP0V7YQdZz6ru8XOH7qdLctVhbSQYxsP57ZGerapCKRj6VKzS17sQTblox6cv88mHUTeZ/Lye7y7N9bwAgMHlgx8aVsZzYA8Kod/qJWDDGM8G2f1btmJ/eNEZAojwYIKN1Tr8k+Hsb+b17ZoAXyb2gFnhszHr1nKE5OkIXt/lCV3w5Fscn5iZ8mk7heZUHDxyU7bldVfbHBP1T4Gei8ieL40V79lzLYg/WpPJz8x2sXOmVrUq/CkV6X86erc2N+EsCsf6qEBaft9AlGqhO8FKRndCRff2lv1LkTof1JzNHYCkfnnwNKFdNrsnT//6+R1sTvnWG3QYDqoFiEPhCoZkattwA7Wq9bn1vBq4gwmr+4PDeYckW7Xa2MJpmtZWhpNj91/Ur57nhffA== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(39860400002)(136003)(376002)(366004)(396003)(346002)(2906002)(38100700002)(6666004)(66946007)(86362001)(1076003)(66556008)(44832011)(8676002)(66476007)(6486002)(316002)(4326008)(478600001)(6512007)(5660300002)(7416002)(186003)(2616005)(52116002)(6506007)(8936002)(41300700001)(4744005); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: eAHUGoxGimwnqTDzyVyxryC6r5YBsK/ZdLlhQ6SBwz+MpQSPGvH0riWtaLRynKANLC5wnPkYrhF8pdoBS5ykTd3dIRsHFotcbIZYCt13HxV7lub5Cfe9RXr+WORKFQx4DeH8qWK6FxX4PAVYwvqMRMbiPclSJ2IITnhz770HzH409jHtH8zhQXGc8F9mamL4fFJGZBwCF1KOgav+H7itzrZpD0p3O73EFVNDtq+GD9w6A0NpA3Ge93AkJrvlDiIevBGXZepm5gpZimO3fuUWwOOee7dg9g8UnN6C/lsOTzTillzXKzqAAe0hlm0yRB+4iD+MCOazEmHMdPUJ4MkzVviXN1tozQ4uYvq8+Hzf+qGPuMN8CLzLhznZTFtiFGFUh8BzkvZfazxumDL/GoVwZ2SFbp2S6lNn8IbmKm08pYjE539R1ocbEbi3uSejCaPIMbFiyFGAWE/jt6JTnJOiVexahGNfYIaBTPC/otmQThRDmILiKXia6PWBSTNVIo/RWY9ZPO56+Cicvqbj53e+wsdeWO8d8IaJ8fqUv/J6D463ExmkIrREwxLtRcm8P2oafv1RfVJCNQ1k5Tz5+UQrW1+CNwVzW/95ZL64yarapgCYuE2/XNYmjClZhmizaxCnUSI9Pog8zgZHUAMJRGJHKeYntddleZZNnnQ7RYIII7byYPu467R5BTmF/cyOZ4Hoyqf+4x3vtsIvv4nW+4mUER3Iq/tn0aJtNGHWgO6yO/ylekHQZrJ0Oj8Ld0WN56Kj3rVUKpI3fFTRC5N2NWQjYxMqE9W1vTrAH8oPHBRJvqpm5NaEQg/y5Xvz3lWFSNMNvcWoDrnWQr0ahkfdjbxiCpVN+VSH/Te0jACqUresPHDWJDhRd0/jACg07mKr5JuoG8LyQKZTLuT1QAGXVueBaHDwRc62dRkb5FlZjnR4VuNSH4ht/BdXQXpm1Ma0f/u7sOS17nB2BAXst0eqxJ43/lBuTqNSvIDMB3K8lPLLgQ8h+fgbR/Lypomgsh4cz1lJMp8m2ZqtnNB3Vh/qJjxBLIm0FdyPvnDiP1Rm4LNtUKkq6Qao3M1VXSwEhmde0X+6uH0MsQEYfwmeM/W2zz9bUH5WcQ8rTJsrVlOrTf5GCGtjN5j+fCB/cXlLsMX2ULBQs7imdvS6HyCG99lWi7vuMH2fy4sXwntfV4ylj+zXShoEawFih8oHI6Hs1dF0yavazN93Gd+hFoGasft63PrepBs/QvNuvMaBidtQejmGb+QPEXhMicQaUHjSRLNzsqNJfGSNHy+YVMeQEA4UZmAi/40qQmbjuwZCULP8Wu9RE/oXzM/xPXt0StCFB5yhFvoGmoaNWNrNv7Fi2618L5ocCKIXJMvYcTGgO32IlwGXs5tJ7Oz/0tRBmVp1FGDcoIj2HounuuxdkRfU8pPx9q+MixJ2IyRIlttVMgSfV/7KBQ4NdbKFC/O6hHCJR1O8SQkDnjMCxactqKr9ZWbIE7sYmlFgrfkoNQGMZwML5lIYvqVhvWpKVdlc+yih4+IyMd7UZI9L3hnqa2ThKw4dEyigo80TWamS8sd+sd0WGINuKWAx71cP4qDNijolP13TfbXKstDyO7j+eytodCS/OxdUjiuD4n3ci8YJBKhPH5OZcpw7cYOphr3kRXh7yfxa855/EFBmQqI80sb94wlcnK8Th0cgQmT5LKVreC1AH5bY51VP4q+V0g7d6opJmTGIGDHrp4tswhozOesP/ontnJz987TTevxCCSAWGu/xoOey2gfMEmMWgF8GCyMELmnTQEkFxWWaA0Qw X-MS-Exchange-AntiSpam-MessageData-1: Bcj7+QfE3/TFPMnOjVmsQkIF6ZdIY/4twsI= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: a74882ea-75c9-44f1-32d5-08da5525392a X-MS-Exchange-CrossTenant-AuthSource: PAXPR04MB8703.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2022 14:32:38.8501 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: JsfO5WX1B+OFWJwa3o6ghoKdEPXofo2wYiPPIePUi75pHDYw8EwVAo9lGNIyM801oMzZaFj7fOz2roG/HNdhbA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR04MB6505 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add myself as maintainer of the dw100 driver which offers hardware accelerated dewarping operations through a v4l2 mem2mem interface. Signed-off-by: Xavier Roumegue Reviewed-by: Laurent Pinchart --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1fc9ead83d2a..a2e1174bc0be 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14355,6 +14355,15 @@ S: Supported F: Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml F: drivers/nfc/nxp-nci +NXP i.MX 8MP DW100 V4L2 DRIVER +M: Xavier Roumegue +L: linux-media@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/media/nxp,dw100.yaml +F: Documentation/userspace-api/media/drivers/dw100.rst +F: drivers/media/platform/nxp/dw100/ +F: include/uapi/linux/dw100.h + NXP i.MX 8QXP/8QM JPEG V4L2 DRIVER M: Mirela Rabulea R: NXP Linux Team