Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1013109pxb; Thu, 4 Mar 2021 00:30:40 -0800 (PST) X-Google-Smtp-Source: ABdhPJyIWgiK2iekfVGNaqsKYzlshtpXHIBjOQ7DfxGGecP0hXWC00gddiAtSjNDrxvcWkGrxLKr X-Received: by 2002:aa7:c889:: with SMTP id p9mr3062897eds.82.1614846640033; Thu, 04 Mar 2021 00:30:40 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1614846640; cv=pass; d=google.com; s=arc-20160816; b=mFA5qAB3rA0RwC4BqJP3lZhQhK3lZ0VE6w+oiuyqGnW8smW2ivGQTbR9uSSRPXLwq4 50y1Jm/Or6AbaJhjQ1+5g7t+3qJvXphp8CO7JZHH3By21Qxir/SFWdn1lGHpiovKIXwN aSKl70iM4bZKfbaYrSTs1kgT8XlUIVXJTQxbXjgH4IfbCGoa4HlJgzmJ74T1lVeBKbrW t71UdBAPiejW+XDblbJ6ZjK2Br75JSgLNak8YpbxvySGQyQXvio7XyQdi0NsCzNTMHkd CF0Yn5d+7YzrNWFPTerTNnGCH7opDRPqX02MgGEEUUger0AnsSUzi8roQkFF2EFfN8y6 gMXA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:content-transfer-encoding :user-agent:references:in-reply-to:date:cc:to:from:subject :message-id:dkim-signature; bh=h+7FKZ92KErPS66gbhSqZTVpySPAw6CecmKc/cvwuwQ=; b=D7W4mfOIsCqUcinMT7pDY5DObq2uZJ4Vru5T0WOGuOmSrINhWXGtURl3W4UaQxBMd/ SiTTtTATLEa1dk+fqbhMgql1Iyqn9VLwJHFAKf/QInTDo1ONlbZu19lbMXNOyh2bA7XT cR0+nR5Ujy+5BmABots6TXdlFgqStcR7hmE2jbbSiSGol1Qb/yXIfu2XNOWKBRV9VtXU wtt2NyaELttiJWg6VE6uzJDWsniLr0egm7pexJUENfSXDZnhPb/ksNnKvO/4r0eyePh6 Op9n7gtfnlJz83E/cBLATHe3Jj2j6NN2OoLUSQ8BD1ccyIVJJqpK/RHBaPFqwuDuqcqg T7kQ== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@nxp.com header.s=selector2 header.b="JsKe2/EX"; arc=pass (i=1 spf=pass spfdomain=nxp.com dkim=pass dkdomain=nxp.com dmarc=pass fromdomain=nxp.com); spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nxp.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e11si5125173edj.230.2021.03.04.00.30.16; Thu, 04 Mar 2021 00:30:40 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@nxp.com header.s=selector2 header.b="JsKe2/EX"; arc=pass (i=1 spf=pass spfdomain=nxp.com dkim=pass dkdomain=nxp.com dmarc=pass fromdomain=nxp.com); spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nxp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235500AbhCCMHB (ORCPT + 99 others); Wed, 3 Mar 2021 07:07:01 -0500 Received: from mail-eopbgr70042.outbound.protection.outlook.com ([40.107.7.42]:20583 "EHLO EUR04-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1345079AbhCCGZK (ORCPT ); Wed, 3 Mar 2021 01:25:10 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=WrXSsYE/93O7xDyF4CUX4aam4ktOmrNylcEx5MauIz6awOYGkgVnLWdJUA8NgReHjifq8oPvcBA/MLBWoc4q88UJa+YU1fWRZF7zSMqmHAFsPbAhbfc+jMi8bsqy7XIAVaUH1wC9qihmDtWUXteS1T0a/2Y1zo4ZOvlW8XUspFvaM8GKfSyjCPeLrTKYGQyDMs4Rvg/CALiT0FFPoge9maRf1JzPRa4qqiCcAVynFJmKr9IZHX8hc/rz2xH/HlZA6YPdPLMS9gSKu0Axt6A98/ZSfkI2d6JtM7G0QpFY1MLcYKXRCr97CHBCsbsXiOHW4x5FGSVNDJeS30gvfnFYtA== 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-SenderADCheck; bh=h+7FKZ92KErPS66gbhSqZTVpySPAw6CecmKc/cvwuwQ=; b=m/+Cj0AV1DAyVwACom983wKFVPQm7HOvOlAldral8j1PsN845J7MCqooak8WA/5+9fzTKilWHP1W3uZLHDVyt7bshqA+e1ZTn6TVvOUOqRZFQxDB+x61V6BJKzYJNyXN2C+VY1dz8eVx6hpCRYpngu9O8RjTcWo0JhpXokh0PSW3ULERiL/WzOhkGZY8GFL9vNEam5ODqhfSCZi93D7XtiYtMHEbabmrrxgG3EAl9uSHqjSF+jU8c2aWrONxq1ADz5gXGzSYS1sjvXVvWCqWgIT0r/1/v6KDnPNw0xfyClFeSPXTyTb49EZ4OadXk1FR4+6S1OOqAN6Kp2LW4WgijA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=h+7FKZ92KErPS66gbhSqZTVpySPAw6CecmKc/cvwuwQ=; b=JsKe2/EXHJJRZEiLOP+xelZ+Bo3Z8AY2SLYQljpKQhlyhUSba0DPJPogoLCnQLZulq/s8QLN9gLn/SbL76hyL8zd8VRJHK7XLVHi71dSXLzejbwHSuvkXxaM/uspcUg/d5/kAQYh3Tjiri3Zwk/zk23jLo8ZgkJHlSQWHYP9Skk= Authentication-Results: oss.nxp.com; dkim=none (message not signed) header.d=none;oss.nxp.com; dmarc=none action=none header.from=nxp.com; Received: from VI1PR04MB3983.eurprd04.prod.outlook.com (2603:10a6:803:4c::16) by VI1PR04MB6109.eurprd04.prod.outlook.com (2603:10a6:803:101::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3890.23; Wed, 3 Mar 2021 06:22:38 +0000 Received: from VI1PR04MB3983.eurprd04.prod.outlook.com ([fe80::2564:cacc:2da5:52d0]) by VI1PR04MB3983.eurprd04.prod.outlook.com ([fe80::2564:cacc:2da5:52d0%5]) with mapi id 15.20.3890.028; Wed, 3 Mar 2021 06:22:38 +0000 Message-ID: Subject: Re: [PATCH v8 5/6] drm/imx: Introduce i.MX8qm/qxp DPU DRM From: Liu Ying To: Laurentiu Palcu Cc: linux-arm-kernel@lists.infradead.org, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, p.zabel@pengutronix.de, airlied@linux.ie, daniel@ffwll.ch, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, robh+dt@kernel.org, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, guido.gunther@puri.sm Date: Wed, 03 Mar 2021 14:21:07 +0800 In-Reply-To: <20210302143605.d65vodn4o3e4zxdj@fsr-ub1864-141> References: <1614666796-19374-1-git-send-email-victor.liu@nxp.com> <1614666796-19374-6-git-send-email-victor.liu@nxp.com> <20210302143605.d65vodn4o3e4zxdj@fsr-ub1864-141> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.36.4-0ubuntu1 Content-Transfer-Encoding: 7bit X-Originating-IP: [119.31.174.66] X-ClientProxiedBy: HK2PR03CA0055.apcprd03.prod.outlook.com (2603:1096:202:17::25) To VI1PR04MB3983.eurprd04.prod.outlook.com (2603:10a6:803:4c::16) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from blueberry.ap.freescale.net (119.31.174.66) by HK2PR03CA0055.apcprd03.prod.outlook.com (2603:1096:202:17::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3912.9 via Frontend Transport; Wed, 3 Mar 2021 06:22:31 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: a9ce73f5-27e2-4026-2ea7-08d8de0cbd0b X-MS-TrafficTypeDiagnostic: VI1PR04MB6109: X-LD-Processed: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635,ExtAddr X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8882; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: lqiP5Bp8lYVPvEM4anXXa/TygaoZ04panUDvrNK6VtDOdcYZAoyU3TEXEpGLzQ/CMzBpcCd2kkJgrHkOE3wH2vbFxUTqsYWdk4j6WA43BKX8U2f4mkhj/GhPLOru+EiGJyISH1jDzsuZwYFTYYNfaQ5V1/pMyz1S8tV0HnIrAvJV17DGWL7+1haTx2yTzGcL7YbV/3ey+rs0P/rB+/wojVx9sSNYAxhR7pF5xOVlFibRUMx75mev4qIlrY6vEASa/yJblQAtcjl48uKQsd2T6FrsRWv8CUxJFsqWxEWORYvGGenc9TG9n0MzdSaGjwni7iOkYwXi2ODOc+PvMEehxaKTHYsyVPYXZtk/b/y1JTvrNjKVpI9kAkxoXBiwcGSDwaXzhm4orFWed5wfw/XZRIiTpEVjxYMMCuTgVPzfp58tW6m4eL6myP/bwXwkUhZRcXhY9XPR83565WJi2Lsb1Yn3L2j7JeO29IkpG47ELCOlTegn3nOJ6ud5oCk6grB9eKdfRIkw5cMOm2vmkYLg6wSeexO7/tIrKw/nHPSpxlzVW1LSp6unWZiymuMLwYNIRcFdO/hVJoCEDy3GF0SpxLg2EaMIXKIYI8nHQyDJmKo= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VI1PR04MB3983.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(376002)(366004)(39860400002)(136003)(346002)(396003)(8936002)(66946007)(6666004)(478600001)(7416002)(316002)(26005)(6512007)(66476007)(16526019)(186003)(6862004)(5660300002)(52116002)(6486002)(83380400001)(86362001)(66556008)(956004)(6506007)(8676002)(2616005)(36756003)(30864003)(4326008)(2906002)(966005)(559001)(579004);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: =?utf-8?B?cDYyQzRhZi9PdlRKekIraUpHVS9kWk5SbkFUVGc1Y3NKQ2lsOXhPYzlWMXhH?= =?utf-8?B?eW81U3FkZEUyZnJBd3FzbUxSUXFrM2FSdytmaVVPQ3dBcjQ3aUJodHVlY0xW?= =?utf-8?B?dHNuR0dEVEp4SUJIcmNnNk5hbTc3S1NPWExHYVFIaDBBRFdndWN5NHhkTHVN?= =?utf-8?B?TzBZUlVXcnBwNDhDcVBWTG50NkFlcVE4Q1BCS1E5MU1KcS93UWNhUGFhcmZm?= =?utf-8?B?VHZ2bEEvcVBQR2NJbXFuWFdiSGtBdFlNVnlYWVFPeUtuNnMwTXN2NVMvcDJv?= =?utf-8?B?cjV2Ym5IQy84N0NVQnd4aGloMFErQmVrdFduR29hZ1hSMy9SWUlGQ3kxT3hR?= =?utf-8?B?cWYrYUhnelcySTQybHY3c0tQcGd3V3VOTjFDRlUvMWVFL0dIaElLcldaZ3FT?= =?utf-8?B?Uk00ZDZQZEsydXQ3ZFhiUVIyNFEwZHZ2OVZIU1h3NDM1dE5Na1ZlbklONkgw?= =?utf-8?B?Yll3ZFBxVjFlNk9yMzRpRGFBcE5RRk5qMnUraHdxQWtHQTBELzVnenByeHdu?= =?utf-8?B?cEtQVVpJODVndmYzVWp4Vy9VaFdYaXd4OUlVbjNpSE9wRjkyRGJ3bnVJVGpM?= =?utf-8?B?alF2ZWNnb3Z6MFc2Qm5SclJMa0kyeDZacER3amh3VGJ3Zm1lbG9XbEpsZk5L?= =?utf-8?B?aGQrbzR5cmdwSytwQzlVYkNvdEtGMS92bzM1MzZ0RC9uTEhvR3luM3R5ckcz?= =?utf-8?B?K2ZnSVZONVM2OFhGdUZlb0VBMFBqT0VXWVhmNFdQY1pPN29qYmg0YWh3ZEZt?= =?utf-8?B?N1UxU0dlVnFJRkJZSmg2RUREYWNjZkVlc1lkTldRcWlGMEJmSGttVy9UTWJO?= =?utf-8?B?aTdzWU9NU3RrWlBrd2I4YXNiT1hVNkJBM0JaSzBzZmN6azUvbWZLN0tWWExG?= =?utf-8?B?SSs2UXZIeEJjQzZ5V1J2WTlDS1hVRHdFU0w1NzNVYk9qK3dnQmNiODFQTWQ5?= =?utf-8?B?bi92MlkwTUwyMEdndTR3YUZEUVZvNWtLRXN4d05ncTdOL1ZsbjZUWXcyK1Q3?= =?utf-8?B?eWpPc01RZWloSHlmbzNnakc2ZXhHWEpvSE9ONHNsd3A1ZnZtd0NrVjJjV1FS?= =?utf-8?B?QTVhQ1FNOE5ncGR5SllOeThKc01ZYlVBL2p5Sm5ITWtRcEh0bytBMXB5Mm1s?= =?utf-8?B?RGVYWEVNNVU5a1M5MElrUHFlR1Y2RlZ0bXVIb1Z6SDhDUzJIdEFqL1I4VFFu?= =?utf-8?B?OWcya1h4Q0FEVzk2SUFuZWpIY3ovZDVaWlJ2R2RhZ29FYkhCVnJLVlVqYkV1?= =?utf-8?B?aXFjdXdlWVFseVdtcjl0d3RidHlOYnFDOW5ubFJaUTVSaktWNXdGT2NrR0ZK?= =?utf-8?B?UnJIOXU5LzR6NTNCRGZ4elN2aHNkV1BVeHA0OExJbEtZQVdiWXRwamJqVmc5?= =?utf-8?B?d21aRmFDVG5nRkRVY0tDSTdXbHRocnEvMzlzd1pBT0JrUnRYcVhyK1BjQUI0?= =?utf-8?B?c25pWEFIb3hyN2lHWFNST0FWWW4vNFhLR3ZKV3daR3VydVJNZVpWU01YMEpY?= =?utf-8?B?M3U2Q0VWckFpUWtubndwVzZHUWIrNnZacVYySjNvaVY1SEdyMk1jdkw2UDQ0?= =?utf-8?B?RndSYmJkcnpOMzQzeldvZFc2Q281bjZDZ2cyc3VEMlYyMmlZMFRJdXI3N1JS?= =?utf-8?B?ajIvWVZsUjZqdzFqaTFlNEJtZFZWVUlwT2d3U0pvT3ZmYzc2Yy92UEtlYnVR?= =?utf-8?B?b1lKb2lzMFZHRzBMRHJZWlc3Y2pHZ2JOSG5USGZ0a1JLSW01YWdNano3bEE0?= =?utf-8?Q?Lg+5K013yryTBgsinuJWtF0vrElsfx0KoYRjJKI?= X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: a9ce73f5-27e2-4026-2ea7-08d8de0cbd0b X-MS-Exchange-CrossTenant-AuthSource: VI1PR04MB3983.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Mar 2021 06:22:38.7343 (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: 3WfmIXMxXzcJ/Bi9Cz46zU4TdUO89Mhv6NhGW3K/9k5kD3baxUOFoY1i+muuX2ALuc9sovau1oam72IKUuOH2A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR04MB6109 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, 2021-03-02 at 16:36 +0200, Laurentiu Palcu wrote: > Hi Liu Ying, > > One comment below. > > On Tue, Mar 02, 2021 at 02:33:15PM +0800, Liu Ying wrote: > > This patch introduces i.MX8qm/qxp Display Processing Unit(DPU) DRM support. > > > > DPU is comprised of two main components that include a blit engine for > > 2D graphics accelerations(with composition support) and a display controller > > for display output processing, as well as a command sequencer. Outside of > > DPU, optional prefetch engines, a.k.a, Prefetch Resolve Gasket(PRG) and > > Display Prefetch Resolve(DPR), can fetch data from memory prior to some DPU > > fetchunits of blit engine and display controller. The prefetch engines > > support reading linear formats and resolving Vivante GPU tile formats. > > > > This patch adds kernel modesetting support for the display controller part. > > The driver supports two CRTCs per display controller, planes backed by > > four fetchunits(decode0/1, fetchlayer, fetchwarp), fetchunit allocation > > logic for the two CRTCs, prefetch engines(with tile resolving supported), > > plane upscaling/deinterlacing/yuv2rgb CSC/alpha blending and CRTC gamma > > correction. The registers of the controller is accessed without command > > sequencer involved, instead just by using CPU. > > > > Reference manual can be found at: > > https://www.nxp.com/webapp/Download?colCode=IMX8DQXPRM > > > > Signed-off-by: Liu Ying > > --- > > Laurentiu, I see your R-b tag on this patch of v7. > > As this patch is changed in v8, can you please help review and maybe add your > > R-b tag again? > > > > v7->v8: > > * Update dpu_plane_atomic_check() and dpu_plane_atomic_update(), due to DRM > > plane helper functions API change(atomic_check and atomic_update) from DRM > > atomic core. Also, rename plane->state variables and relevant DPU plane > > state variables in those two functions to reflect they are new states, like > > the patch 'drm: Rename plane->state variables in atomic update and disable' > > recently landed in drm-misc-next. > > * Replace drm_gem_fb_prepare_fb() with drm_gem_plane_helper_prepare_fb(), > > due to DRM core API change. > > * Use 256byte DPR burst length for GPU standard tile and 128byte DPR burst > > length for 32bpp GPU super tile to align with the latest version of internal > > HW documention. > > > > v6->v7: > > * Fix return value of dpu_get_irqs() if platform_get_irq() fails. (Laurentiu) > > * Use the function array dpu_irq_handler[] to store individual DPU irq handlers. > > (Laurentiu) > > * Call get/put() hooks directly to get/put DPU fetchunits for DPU plane groups. > > (Laurentiu) > > * Shorten the names of individual DPU irq handlers by using DPU unit abbrev > > names to make writing dpu_irq_handler[] easier. > > > > v5->v6: > > * Do not use macros where possible. (Laurentiu) > > * Break dpu_plane_atomic_check() into some smaller functions. (Laurentiu) > > * Address some minor comments from Laurentiu. > > * Add dpu_crtc_err() helper marco to tell dmesg which CRTC generates error. > > * Drop calling dev_set_drvdata() from dpu_drm_bind/unbind() as it is done > > in dpu_drm_probe(). > > * Some trivial tweaks. > > > > v4->v5: > > * Rebase up onto the latest drm-misc-next branch and remove the hook to > > drm_atomic_helper_legacy_gamma_set(), because it was dropped by the newly > > landed commit 'drm: automatic legacy gamma support'. > > * Remove a redundant blank line from dpu_plane_atomic_update(). > > > > v3->v4: > > * No change. > > > > v2->v3: > > * Fix build warnings Reported-by: kernel test robot . > > * Drop build dependency on IMX_SCU, as dummy SCU functions have been added in > > header files by the patch 'firmware: imx: add dummy functions' which has > > landed in linux-next/master branch. > > > > v1->v2: > > * Add compatible for i.MX8qm DPU, as this is tested with i.MX8qm LVDS displays. > > (Laurentiu) > > * Fix PRG burst size and stride. (Laurentiu) > > * Put 'ports' OF node to fix the bail-out logic in dpu_drm_probe(). (Laurentiu) > > > > drivers/gpu/drm/imx/Kconfig | 1 + > > drivers/gpu/drm/imx/Makefile | 1 + > > drivers/gpu/drm/imx/dpu/Kconfig | 10 + > > drivers/gpu/drm/imx/dpu/Makefile | 10 + > > drivers/gpu/drm/imx/dpu/dpu-constframe.c | 171 +++++ > > drivers/gpu/drm/imx/dpu/dpu-core.c | 1054 +++++++++++++++++++++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-crtc.c | 967 ++++++++++++++++++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-crtc.h | 66 ++ > > drivers/gpu/drm/imx/dpu/dpu-disengcfg.c | 117 ++++ > > drivers/gpu/drm/imx/dpu/dpu-dprc.c | 722 ++++++++++++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-dprc.h | 40 ++ > > drivers/gpu/drm/imx/dpu/dpu-drv.c | 292 ++++++++ > > drivers/gpu/drm/imx/dpu/dpu-drv.h | 28 + > > drivers/gpu/drm/imx/dpu/dpu-extdst.c | 299 ++++++++ > > drivers/gpu/drm/imx/dpu/dpu-fetchdecode.c | 294 ++++++++ > > drivers/gpu/drm/imx/dpu/dpu-fetcheco.c | 224 ++++++ > > drivers/gpu/drm/imx/dpu/dpu-fetchlayer.c | 154 +++++ > > drivers/gpu/drm/imx/dpu/dpu-fetchunit.c | 609 +++++++++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-fetchunit.h | 191 ++++++ > > drivers/gpu/drm/imx/dpu/dpu-fetchwarp.c | 250 +++++++ > > drivers/gpu/drm/imx/dpu/dpu-framegen.c | 395 +++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-gammacor.c | 223 ++++++ > > drivers/gpu/drm/imx/dpu/dpu-hscaler.c | 275 ++++++++ > > drivers/gpu/drm/imx/dpu/dpu-kms.c | 540 +++++++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-kms.h | 23 + > > drivers/gpu/drm/imx/dpu/dpu-layerblend.c | 348 ++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-plane.c | 802 ++++++++++++++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-plane.h | 56 ++ > > drivers/gpu/drm/imx/dpu/dpu-prg.c | 433 ++++++++++++ > > drivers/gpu/drm/imx/dpu/dpu-prg.h | 45 ++ > > drivers/gpu/drm/imx/dpu/dpu-prv.h | 233 +++++++ > > drivers/gpu/drm/imx/dpu/dpu-tcon.c | 250 +++++++ > > drivers/gpu/drm/imx/dpu/dpu-vscaler.c | 308 +++++++++ > > drivers/gpu/drm/imx/dpu/dpu.h | 385 +++++++++++ > > 34 files changed, 9816 insertions(+) > > create mode 100644 drivers/gpu/drm/imx/dpu/Kconfig > > create mode 100644 drivers/gpu/drm/imx/dpu/Makefile > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-constframe.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-core.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-crtc.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-crtc.h > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-disengcfg.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-dprc.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-dprc.h > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-drv.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-drv.h > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-extdst.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-fetchdecode.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-fetcheco.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-fetchlayer.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-fetchunit.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-fetchunit.h > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-fetchwarp.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-framegen.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-gammacor.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-hscaler.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-kms.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-kms.h > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-layerblend.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-plane.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-plane.h > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-prg.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-prg.h > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-prv.h > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-tcon.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu-vscaler.c > > create mode 100644 drivers/gpu/drm/imx/dpu/dpu.h > > > > [...] > > > diff --git a/drivers/gpu/drm/imx/dpu/dpu-plane.c b/drivers/gpu/drm/imx/dpu/dpu-plane.c > > new file mode 100644 > > index 00000000..aaf0fe0 > > --- /dev/null > > +++ b/drivers/gpu/drm/imx/dpu/dpu-plane.c > > @@ -0,0 +1,802 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > + > > +/* > > + * Copyright 2017-2020 NXP > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "dpu.h" > > +#include "dpu-crtc.h" > > +#include "dpu-dprc.h" > > +#include "dpu-plane.h" > > + > > +#define FRAC_16_16(mult, div) (((mult) << 16) / (div)) > > + > > +#define DPU_PLANE_MAX_PITCH 0x10000 > > +#define DPU_PLANE_MAX_PIX_CNT 8192 > > +#define DPU_PLANE_MAX_PIX_CNT_WITH_SCALER 2048 > > + > > +static const uint32_t dpu_plane_formats[] = { > > + DRM_FORMAT_ARGB8888, > > + DRM_FORMAT_XRGB8888, > > + DRM_FORMAT_ABGR8888, > > + DRM_FORMAT_XBGR8888, > > + DRM_FORMAT_RGBA8888, > > + DRM_FORMAT_RGBX8888, > > + DRM_FORMAT_BGRA8888, > > + DRM_FORMAT_BGRX8888, > > + DRM_FORMAT_RGB565, > > + > > + DRM_FORMAT_YUYV, > > + DRM_FORMAT_UYVY, > > + DRM_FORMAT_NV12, > > + DRM_FORMAT_NV21, > > +}; > > + > > +static const uint64_t dpu_plane_format_modifiers[] = { > > + DRM_FORMAT_MOD_VIVANTE_TILED, > > + DRM_FORMAT_MOD_VIVANTE_SUPER_TILED, > > + DRM_FORMAT_MOD_LINEAR, > > + DRM_FORMAT_MOD_INVALID, > > +}; > > + > > +static unsigned int dpu_plane_get_default_zpos(enum drm_plane_type type) > > +{ > > + if (type == DRM_PLANE_TYPE_PRIMARY) > > + return 0; > > + else if (type == DRM_PLANE_TYPE_OVERLAY) > > + return 1; > > + > > + return 0; > > +} > > + > > +static void dpu_plane_destroy(struct drm_plane *plane) > > +{ > > + struct dpu_plane *dpu_plane = to_dpu_plane(plane); > > + > > + drm_plane_cleanup(plane); > > + kfree(dpu_plane); > > +} > > + > > +static void dpu_plane_reset(struct drm_plane *plane) > > +{ > > + struct dpu_plane_state *state; > > + > > + if (plane->state) { > > + __drm_atomic_helper_plane_destroy_state(plane->state); > > + kfree(to_dpu_plane_state(plane->state)); > > + plane->state = NULL; > > + } > > + > > + state = kzalloc(sizeof(*state), GFP_KERNEL); > > + if (!state) > > + return; > > + > > + __drm_atomic_helper_plane_reset(plane, &state->base); > > + > > + plane->state->zpos = dpu_plane_get_default_zpos(plane->type); > > + plane->state->color_encoding = DRM_COLOR_YCBCR_BT709; > > + plane->state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; > > +} > > + > > +static struct drm_plane_state * > > +dpu_drm_atomic_plane_duplicate_state(struct drm_plane *plane) > > +{ > > + struct dpu_plane_state *state, *copy; > > + > > + if (WARN_ON(!plane->state)) > > + return NULL; > > + > > + copy = kmalloc(sizeof(*state), GFP_KERNEL); > > + if (!copy) > > + return NULL; > > + > > + __drm_atomic_helper_plane_duplicate_state(plane, ©->base); > > + state = to_dpu_plane_state(plane->state); > > + copy->stage = state->stage; > > + copy->source = state->source; > > + copy->blend = state->blend; > > + copy->is_top = state->is_top; > > + > > + return ©->base; > > +} > > + > > +static void dpu_drm_atomic_plane_destroy_state(struct drm_plane *plane, > > + struct drm_plane_state *state) > > +{ > > + __drm_atomic_helper_plane_destroy_state(state); > > + kfree(to_dpu_plane_state(state)); > > +} > > + > > +static bool dpu_drm_plane_format_mod_supported(struct drm_plane *plane, > > + uint32_t format, > > + uint64_t modifier) > > +{ > > + switch (format) { > > + case DRM_FORMAT_YUYV: > > + case DRM_FORMAT_UYVY: > > + case DRM_FORMAT_NV12: > > + case DRM_FORMAT_NV21: > > + return modifier == DRM_FORMAT_MOD_LINEAR; > > + case DRM_FORMAT_ARGB8888: > > + case DRM_FORMAT_XRGB8888: > > + case DRM_FORMAT_ABGR8888: > > + case DRM_FORMAT_XBGR8888: > > + case DRM_FORMAT_RGBA8888: > > + case DRM_FORMAT_RGBX8888: > > + case DRM_FORMAT_BGRA8888: > > + case DRM_FORMAT_BGRX8888: > > + case DRM_FORMAT_RGB565: > > + return modifier == DRM_FORMAT_MOD_LINEAR || > > + modifier == DRM_FORMAT_MOD_VIVANTE_TILED || > > + modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED; > > + default: > > + return false; > > + } > > +} > > + > > +static const struct drm_plane_funcs dpu_plane_funcs = { > > + .update_plane = drm_atomic_helper_update_plane, > > + .disable_plane = drm_atomic_helper_disable_plane, > > + .destroy = dpu_plane_destroy, > > + .reset = dpu_plane_reset, > > + .atomic_duplicate_state = dpu_drm_atomic_plane_duplicate_state, > > + .atomic_destroy_state = dpu_drm_atomic_plane_destroy_state, > > + .format_mod_supported = dpu_drm_plane_format_mod_supported, > > +}; > > + > > +static inline dma_addr_t > > +drm_plane_state_to_baseaddr(struct drm_plane_state *state) > > +{ > > + struct drm_framebuffer *fb = state->fb; > > + struct drm_gem_cma_object *cma_obj; > > + unsigned int x = state->src.x1 >> 16; > > + unsigned int y = state->src.y1 >> 16; > > + > > + cma_obj = drm_fb_cma_get_gem_obj(fb, 0); > > + > > + if (fb->flags & DRM_MODE_FB_INTERLACED) > > + y /= 2; > > + > > + return cma_obj->paddr + fb->offsets[0] + fb->pitches[0] * y + > > + fb->format->cpp[0] * x; > > +} > > + > > +static inline dma_addr_t > > +drm_plane_state_to_uvbaseaddr(struct drm_plane_state *state) > > +{ > > + struct drm_framebuffer *fb = state->fb; > > + struct drm_gem_cma_object *cma_obj; > > + int x = state->src.x1 >> 16; > > + int y = state->src.y1 >> 16; > > + > > + cma_obj = drm_fb_cma_get_gem_obj(fb, 1); > > + > > + x /= fb->format->hsub; > > + y /= fb->format->vsub; > > + > > + if (fb->flags & DRM_MODE_FB_INTERLACED) > > + y /= 2; > > + > > + return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + > > + fb->format->cpp[1] * x; > > +} > > + > > +static int dpu_plane_check_no_off_screen(struct drm_plane_state *state, > > + struct drm_crtc_state *crtc_state) > > +{ > > + if (state->dst.x1 < 0 || state->dst.y1 < 0 || > > + (state->dst.x2 > crtc_state->adjusted_mode.hdisplay) || > > + (state->dst.y2 > crtc_state->adjusted_mode.vdisplay)) { > > + dpu_plane_dbg(state->plane, "no off screen\n"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int dpu_plane_check_max_source_resolution(struct drm_plane_state *state) > > +{ > > + u32 src_w = drm_rect_width(&state->src) >> 16; > > + u32 src_h = drm_rect_height(&state->src) >> 16; > > + u32 dst_w = drm_rect_width(&state->dst); > > + u32 dst_h = drm_rect_height(&state->dst); > > + > > + if (src_w == dst_w || src_h == dst_h) { > > + /* without scaling */ > > + if (src_w > DPU_PLANE_MAX_PIX_CNT || > > + src_h > DPU_PLANE_MAX_PIX_CNT) { > > + dpu_plane_dbg(state->plane, > > + "invalid source resolution\n"); > > + return -EINVAL; > > + } > > + } else { > > + /* with scaling */ > > + if (src_w > DPU_PLANE_MAX_PIX_CNT_WITH_SCALER || > > + src_h > DPU_PLANE_MAX_PIX_CNT_WITH_SCALER) { > > + dpu_plane_dbg(state->plane, > > + "invalid source resolution with scale\n"); > > + return -EINVAL; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int dpu_plane_check_source_alignment(struct drm_plane_state *state) > > +{ > > + struct drm_framebuffer *fb = state->fb; > > + bool fb_is_interlaced = !!(fb->flags & DRM_MODE_FB_INTERLACED); > > + u32 src_w = drm_rect_width(&state->src) >> 16; > > + u32 src_h = drm_rect_height(&state->src) >> 16; > > + u32 src_x = state->src.x1 >> 16; > > + u32 src_y = state->src.y1 >> 16; > > + > > + if (fb->format->hsub == 2) { > > + if (src_w % 2) { > > + dpu_plane_dbg(state->plane, "bad uv width\n"); > > + return -EINVAL; > > + } > > + if (src_x % 2) { > > + dpu_plane_dbg(state->plane, "bad uv xoffset\n"); > > + return -EINVAL; > > + } > > + } > > + if (fb->format->vsub == 2) { > > + if (src_h % (fb_is_interlaced ? 4 : 2)) { > > + dpu_plane_dbg(state->plane, "bad uv height\n"); > > + return -EINVAL; > > + } > > + if (src_y % (fb_is_interlaced ? 4 : 2)) { > > + dpu_plane_dbg(state->plane, "bad uv yoffset\n"); > > + return -EINVAL; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static int dpu_plane_check_fb_modifier(struct drm_plane_state *state) > > +{ > > + struct drm_plane *plane = state->plane; > > + struct drm_framebuffer *fb = state->fb; > > + > > + if ((fb->flags & DRM_MODE_FB_MODIFIERS) && > > + !plane->funcs->format_mod_supported(plane, fb->format->format, > > + fb->modifier)) { > > + dpu_plane_dbg(plane, "invalid modifier 0x%016llx", > > + fb->modifier); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +/* for tile formats, framebuffer has to be tile aligned */ > > +static int dpu_plane_check_tiled_fb_alignment(struct drm_plane_state *state) > > +{ > > + struct drm_plane *plane = state->plane; > > + struct drm_framebuffer *fb = state->fb; > > + > > + switch (fb->modifier) { > > + case DRM_FORMAT_MOD_VIVANTE_TILED: > > + if (fb->width % 4) { > > + dpu_plane_dbg(plane, "bad fb width for VIVANTE tile\n"); > > + return -EINVAL; > > + } > > + if (fb->height % 4) { > > + dpu_plane_dbg(plane, "bad fb height for VIVANTE tile\n"); > > + return -EINVAL; > > + } > > + break; > > + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: > > + if (fb->width % 64) { > > + dpu_plane_dbg(plane, > > + "bad fb width for VIVANTE super tile\n"); > > + return -EINVAL; > > + } > > + if (fb->height % 64) { > > + dpu_plane_dbg(plane, > > + "bad fb height for VIVANTE super tile\n"); > > + return -EINVAL; > > + } > > + break; > > + } > > + > > + return 0; > > +} > > + > > +static int dpu_plane_check_no_bt709_full_range(struct drm_plane_state *state) > > +{ > > + if (state->fb->format->is_yuv && > > + state->color_encoding == DRM_COLOR_YCBCR_BT709 && > > + state->color_range == DRM_COLOR_YCBCR_FULL_RANGE) { > > + dpu_plane_dbg(state->plane, "no BT709 full range support\n"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int dpu_plane_check_fb_plane_1(struct drm_plane_state *state) > > +{ > > + struct drm_plane *plane = state->plane; > > + struct drm_framebuffer *fb = state->fb; > > + dma_addr_t baseaddr = drm_plane_state_to_baseaddr(state); > > + int bpp; > > + > > + /* base address alignment */ > > + switch (fb->format->format) { > > + case DRM_FORMAT_YUYV: > > + case DRM_FORMAT_UYVY: > > + bpp = 16; > > + break; > > + case DRM_FORMAT_NV12: > > + case DRM_FORMAT_NV21: > > + bpp = 8; > > + break; > > + default: > > + bpp = fb->format->cpp[0] * 8; > > + break; > > + } > > + if (((bpp == 32) && (baseaddr & 0x3)) || > > + ((bpp == 16) && (baseaddr & 0x1))) { > > + dpu_plane_dbg(plane, "%dbpp fb bad baddr alignment\n", bpp); > > + return -EINVAL; > > + } > > + switch (bpp) { > > + case 32: > > + if (baseaddr & 0x3) { > > + dpu_plane_dbg(plane, "32bpp fb bad baddr alignment\n"); > > + return -EINVAL; > > + } > > + break; > > + case 16: > > + if (fb->modifier) { > > + if (baseaddr & 0x1) { > > + dpu_plane_dbg(plane, > > + "16bpp tile fb bad baddr alignment\n"); > > + return -EINVAL; > > + } > > + } else { > > + if (baseaddr & 0x7) { > > + dpu_plane_dbg(plane, > > + "16bpp fb bad baddr alignment\n"); > > + return -EINVAL; > > + } > > + } > > + break; > > + } > > + > > + /* pitches[0] range */ > > + if (fb->pitches[0] > DPU_PLANE_MAX_PITCH) { > > + dpu_plane_dbg(plane, "fb pitches[0] is out of range\n"); > > + return -EINVAL; > > + } > > + > > + /* pitches[0] alignment */ > > + if (((bpp == 32) && (fb->pitches[0] & 0x3)) || > > + ((bpp == 16) && (fb->pitches[0] & 0x1))) { > > + dpu_plane_dbg(plane, "%dbpp fb bad pitches[0] alignment\n", bpp); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +/* UV planar check, assuming 16bpp */ > > +static int dpu_plane_check_fb_plane_2(struct drm_plane_state *state) > > +{ > > + struct drm_plane *plane = state->plane; > > + struct drm_framebuffer *fb = state->fb; > > + dma_addr_t uv_baseaddr = drm_plane_state_to_uvbaseaddr(state); > > + > > + /* base address alignment */ > > + if (uv_baseaddr & 0x7) { > > + dpu_plane_dbg(plane, "bad uv baddr alignment\n"); > > + return -EINVAL; > > + } > > + > > + /* pitches[1] range */ > > + if (fb->pitches[1] > DPU_PLANE_MAX_PITCH) { > > + dpu_plane_dbg(plane, "fb pitches[1] is out of range\n"); > > + return -EINVAL; > > + } > > + > > + /* pitches[1] alignment */ > > + if (fb->pitches[1] & 0x1) { > > + dpu_plane_dbg(plane, "fb bad pitches[1] alignment\n"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int dpu_plane_check_dprc(struct drm_plane_state *state) > > +{ > > + struct dpu_plane_state *dpstate = to_dpu_plane_state(state); > > + struct drm_framebuffer *fb = state->fb; > > + const struct dpu_fetchunit_ops *fu_ops; > > + struct dpu_dprc *dprc; > > + dma_addr_t baseaddr, uv_baseaddr = 0; > > + u32 src_w = drm_rect_width(&state->src) >> 16; > > + u32 src_x = state->src.x1 >> 16; > > + > > + fu_ops = dpu_fu_get_ops(dpstate->source); > > + dprc = fu_ops->get_dprc(dpstate->source); > > + > > + if (!dpu_dprc_rtram_width_supported(dprc, src_w)) { > > + dpu_plane_dbg(state->plane, "bad RTRAM width for DPRC\n"); > > + return -EINVAL; > > + } > > + > > + baseaddr = drm_plane_state_to_baseaddr(state); > > + if (fb->format->num_planes > 1) > > + uv_baseaddr = drm_plane_state_to_uvbaseaddr(state); > > + > > + if (!dpu_dprc_stride_supported(dprc, fb->pitches[0], fb->pitches[1], > > + src_w, src_x, fb->format, fb->modifier, > > + baseaddr, uv_baseaddr)) { > > + dpu_plane_dbg(state->plane, "bad fb pitches for DPRC\n"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int dpu_plane_atomic_check(struct drm_plane *plane, > > + struct drm_atomic_state *state) > > +{ > > + struct drm_plane_state *new_plane_state = > > + drm_atomic_get_new_plane_state(state, plane); > > + struct dpu_plane_state *new_dpstate = > > + to_dpu_plane_state(new_plane_state); > > + struct drm_framebuffer *fb = new_plane_state->fb; > > + struct drm_crtc_state *crtc_state; > > + int min_scale, ret; > > + > > + /* ok to disable */ > > + if (!fb) { > > + new_dpstate->source = NULL; > > + new_dpstate->stage.ptr = NULL; > > + new_dpstate->blend = NULL; > > + return 0; > > + } > > + > > + if (!new_plane_state->crtc) { > > + dpu_plane_dbg(plane, "no CRTC in plane state\n"); > > + return -EINVAL; > > + } > > + > > + crtc_state = > > + drm_atomic_get_existing_crtc_state(state, new_plane_state->crtc); > > + if (WARN_ON(!crtc_state)) > > + return -EINVAL; > > + > > + min_scale = FRAC_16_16(1, DPU_PLANE_MAX_PIX_CNT_WITH_SCALER); > > + ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, > > + min_scale, > > + DRM_PLANE_HELPER_NO_SCALING, > > + true, false); > > + if (ret) { > > + dpu_plane_dbg(plane, "failed to check plane state: %d\n", ret); > > + return ret; > > + } > > + > > + ret = dpu_plane_check_no_off_screen(new_plane_state, crtc_state); > > + if (ret) > > + return ret; > > + > > + ret = dpu_plane_check_max_source_resolution(new_plane_state); > > + if (ret) > > + return ret; > > + > > + ret = dpu_plane_check_source_alignment(new_plane_state); > > + if (ret) > > + return ret; > > + > > + ret = dpu_plane_check_fb_modifier(new_plane_state); > > + if (ret) > > + return ret; > > + > > + ret = dpu_plane_check_tiled_fb_alignment(new_plane_state); > > + if (ret) > > + return ret; > > + > > + ret = dpu_plane_check_no_bt709_full_range(new_plane_state); > > + if (ret) > > + return ret; > > + > > + ret = dpu_plane_check_fb_plane_1(new_plane_state); > > + if (ret) > > + return ret; > > + > > + if (fb->format->num_planes > 1) { > > + ret = dpu_plane_check_fb_plane_2(new_plane_state); > > + if (ret) > > + return ret; > > + } > > + > > + return dpu_plane_check_dprc(new_plane_state); > > +} > > + > > +static void dpu_plane_atomic_update(struct drm_plane *plane, > > + struct drm_atomic_state *state) > > +{ > > + struct dpu_plane *dplane = to_dpu_plane(plane); > > + struct drm_plane_state *new_state = plane->state; > > I think you want to use the drm_atomic_get_new_plane_state() helper here as > well. See: I think you are right. I'll wait a period of time to see if I can receive more comments on this series or not, and then send a next version with this comment addressed. Thanks, Liu Ying > > 37418bf14c13 ("drm: Use state helper instead of the plane state pointer") > > Thanks, > laurentiu > > > + struct dpu_plane_state *new_dpstate = to_dpu_plane_state(new_state); > > + struct dpu_plane_grp *grp = dplane->grp; > > + struct dpu_crtc *dpu_crtc; > > + struct drm_framebuffer *fb = new_state->fb; > > + struct dpu_fetchunit *fu = new_dpstate->source; > > + struct dpu_layerblend *lb = new_dpstate->blend; > > + struct dpu_dprc *dprc; > > + const struct dpu_fetchunit_ops *fu_ops; > > + dma_addr_t baseaddr, uv_baseaddr; > > + enum dpu_link_id fu_link; > > + enum dpu_link_id lb_src_link, stage_link; > > + enum dpu_link_id vs_link; > > + unsigned int src_w, src_h, src_x, src_y, dst_w, dst_h; > > + unsigned int mt_w = 0, mt_h = 0; /* micro-tile width/height */ > > + int bpp; > > + bool prefetch_start = false; > > + bool need_fetcheco = false, need_hscaler = false, need_vscaler = false; > > + bool need_modeset; > > + bool fb_is_interlaced; > > + > > + /* > > + * Do nothing since the plane is disabled by > > + * crtc_func->atomic_begin/flush. > > + */ > > + if (!fb) > > + return; > > + > > + /* Do nothing if CRTC is inactive. */ > > + if (!new_state->crtc->state->active) > > + return; > > + > > + need_modeset = drm_atomic_crtc_needs_modeset(new_state->crtc->state); > > + > > + fb_is_interlaced = !!(fb->flags & DRM_MODE_FB_INTERLACED); > > + > > + src_w = drm_rect_width(&new_state->src) >> 16; > > + src_h = drm_rect_height(&new_state->src) >> 16; > > + src_x = new_state->src.x1 >> 16; > > + src_y = new_state->src.y1 >> 16; > > + dst_w = drm_rect_width(&new_state->dst); > > + dst_h = drm_rect_height(&new_state->dst); > > + > > + switch (fb->format->format) { > > + case DRM_FORMAT_YUYV: > > + case DRM_FORMAT_UYVY: > > + bpp = 16; > > + break; > > + case DRM_FORMAT_NV12: > > + case DRM_FORMAT_NV21: > > + bpp = 8; > > + break; > > + default: > > + bpp = fb->format->cpp[0] * 8; > > + break; > > + } > > + > > + switch (fb->modifier) { > > + case DRM_FORMAT_MOD_VIVANTE_TILED: > > + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: > > + mt_w = (bpp == 16) ? 8 : 4; > > + mt_h = 4; > > + break; > > + } > > + > > + if (fb->format->num_planes > 1) > > + need_fetcheco = true; > > + > > + if (src_w != dst_w) > > + need_hscaler = true; > > + > > + if ((src_h != dst_h) || fb_is_interlaced) > > + need_vscaler = true; > > + > > + baseaddr = drm_plane_state_to_baseaddr(new_state); > > + if (need_fetcheco) > > + uv_baseaddr = drm_plane_state_to_uvbaseaddr(new_state); > > + > > + dpu_crtc = to_dpu_crtc(new_state->crtc); > > + > > + fu_ops = dpu_fu_get_ops(fu); > > + > > + if (!fu_ops->has_stream_id(fu) || need_modeset) > > + prefetch_start = true; > > + > > + fu_ops->set_layerblend(fu, lb); > > + > > + fu_ops->set_burstlength(fu, src_x, mt_w, bpp, baseaddr); > > + fu_ops->set_src_stride(fu, src_w, src_w, mt_w, bpp, fb->pitches[0], > > + baseaddr); > > + fu_ops->set_src_buf_dimensions(fu, src_w, src_h, fb->format, > > + fb_is_interlaced); > > + fu_ops->set_fmt(fu, fb->format, new_state->color_encoding, > > + new_state->color_range, fb_is_interlaced); > > + fu_ops->set_pixel_blend_mode(fu, new_state->pixel_blend_mode, > > + new_state->alpha, fb->format->has_alpha); > > + fu_ops->enable_src_buf(fu); > > + fu_ops->set_framedimensions(fu, src_w, src_h, fb_is_interlaced); > > + fu_ops->set_baseaddress(fu, src_w, src_x, src_y, mt_w, mt_h, bpp, > > + baseaddr); > > + fu_ops->set_stream_id(fu, dpu_crtc->stream_id); > > + > > + fu_link = fu_ops->get_link_id(fu); > > + lb_src_link = fu_link; > > + > > + dpu_plane_dbg(plane, "uses %s\n", fu_ops->get_name(fu)); > > + > > + if (need_fetcheco) { > > + struct dpu_fetchunit *fe = fu_ops->get_fetcheco(fu); > > + const struct dpu_fetchunit_ops *fe_ops; > > + > > + fe_ops = dpu_fu_get_ops(fe); > > + > > + fu_ops->set_pec_dynamic_src_sel(fu, fe_ops->get_link_id(fe)); > > + > > + fe_ops->set_burstlength(fe, src_x, mt_w, bpp, uv_baseaddr); > > + fe_ops->set_src_stride(fe, src_w, src_x, mt_w, bpp, > > + fb->pitches[1], uv_baseaddr); > > + fe_ops->set_fmt(fe, fb->format, new_state->color_encoding, > > + new_state->color_range, fb_is_interlaced); > > + fe_ops->set_src_buf_dimensions(fe, src_w, src_h, > > + fb->format, fb_is_interlaced); > > + fe_ops->set_framedimensions(fe, src_w, src_h, fb_is_interlaced); > > + fe_ops->set_baseaddress(fe, src_w, src_x, src_y / 2, > > + mt_w, mt_h, bpp, uv_baseaddr); > > + fe_ops->enable_src_buf(fe); > > + > > + dpu_plane_dbg(plane, "uses %s\n", fe_ops->get_name(fe)); > > + } else { > > + if (fu_ops->set_pec_dynamic_src_sel) > > + fu_ops->set_pec_dynamic_src_sel(fu, LINK_ID_NONE); > > + } > > + > > + /* VScaler comes first */ > > + if (need_vscaler) { > > + struct dpu_vscaler *vs = fu_ops->get_vscaler(fu); > > + > > + dpu_vs_pec_dynamic_src_sel(vs, fu_link); > > + dpu_vs_pec_clken(vs, CLKEN_AUTOMATIC); > > + dpu_vs_setup1(vs, src_h, new_state->crtc_h, fb_is_interlaced); > > + dpu_vs_setup2(vs, fb_is_interlaced); > > + dpu_vs_setup3(vs, fb_is_interlaced); > > + dpu_vs_output_size(vs, dst_h); > > + dpu_vs_field_mode(vs, fb_is_interlaced ? > > + SCALER_ALWAYS0 : SCALER_INPUT); > > + dpu_vs_filter_mode(vs, SCALER_LINEAR); > > + dpu_vs_scale_mode(vs, SCALER_UPSCALE); > > + dpu_vs_mode(vs, SCALER_ACTIVE); > > + > > + vs_link = dpu_vs_get_link_id(vs); > > + lb_src_link = vs_link; > > + > > + dpu_plane_dbg(plane, "uses VScaler%u\n", dpu_vs_get_id(vs)); > > + } > > + > > + /* and then, HScaler */ > > + if (need_hscaler) { > > + struct dpu_hscaler *hs = fu_ops->get_hscaler(fu); > > + > > + dpu_hs_pec_dynamic_src_sel(hs, need_vscaler ? vs_link : fu_link); > > + dpu_hs_pec_clken(hs, CLKEN_AUTOMATIC); > > + dpu_hs_setup1(hs, src_w, dst_w); > > + dpu_hs_output_size(hs, dst_w); > > + dpu_hs_filter_mode(hs, SCALER_LINEAR); > > + dpu_hs_scale_mode(hs, SCALER_UPSCALE); > > + dpu_hs_mode(hs, SCALER_ACTIVE); > > + > > + lb_src_link = dpu_hs_get_link_id(hs); > > + > > + dpu_plane_dbg(plane, "uses HScaler%u\n", dpu_hs_get_id(hs)); > > + } > > + > > + dprc = fu_ops->get_dprc(fu); > > + > > + dpu_dprc_configure(dprc, dpu_crtc->stream_id, > > + src_w, src_h, src_x, src_y, > > + fb->pitches[0], fb->format, fb->modifier, > > + baseaddr, uv_baseaddr, > > + prefetch_start, fb_is_interlaced); > > + > > + if (new_state->normalized_zpos == 0) > > + stage_link = dpu_cf_get_link_id(new_dpstate->stage.cf); > > + else > > + stage_link = dpu_lb_get_link_id(new_dpstate->stage.lb); > > + > > + dpu_lb_pec_dynamic_prim_sel(lb, stage_link); > > + dpu_lb_pec_dynamic_sec_sel(lb, lb_src_link); > > + dpu_lb_mode(lb, LB_BLEND); > > + dpu_lb_blendcontrol(lb, new_state->normalized_zpos, > > + new_state->pixel_blend_mode, new_state->alpha); > > + dpu_lb_pec_clken(lb, CLKEN_AUTOMATIC); > > + dpu_lb_position(lb, new_state->dst.x1, new_state->dst.y1); > > + > > + dpu_plane_dbg(plane, "uses LayerBlend%u\n", dpu_lb_get_id(lb)); > > + > > + if (new_dpstate->is_top) > > + dpu_ed_pec_src_sel(grp->ed[dpu_crtc->stream_id], > > + dpu_lb_get_link_id(lb)); > > +} > > + > > +static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = { > > + .prepare_fb = drm_gem_plane_helper_prepare_fb, > > + .atomic_check = dpu_plane_atomic_check, > > + .atomic_update = dpu_plane_atomic_update, > > +}; > > + > > +struct dpu_plane *dpu_plane_initialize(struct drm_device *drm, > > + unsigned int possible_crtcs, > > + struct dpu_plane_grp *grp, > > + enum drm_plane_type type) > > +{ > > + struct dpu_plane *dpu_plane; > > + struct drm_plane *plane; > > + unsigned int zpos = dpu_plane_get_default_zpos(type); > > + int ret; > > + > > + dpu_plane = kzalloc(sizeof(*dpu_plane), GFP_KERNEL); > > + if (!dpu_plane) > > + return ERR_PTR(-ENOMEM); > > + > > + dpu_plane->grp = grp; > > + > > + plane = &dpu_plane->base; > > + > > + ret = drm_universal_plane_init(drm, plane, possible_crtcs, > > + &dpu_plane_funcs, > > + dpu_plane_formats, > > + ARRAY_SIZE(dpu_plane_formats), > > + dpu_plane_format_modifiers, type, NULL); > > + if (ret) { > > + /* > > + * The plane is not added to the global plane list, so > > + * free it manually. > > + */ > > + kfree(dpu_plane); > > + return ERR_PTR(ret); > > + } > > + > > + drm_plane_helper_add(plane, &dpu_plane_helper_funcs); > > + > > + ret = drm_plane_create_zpos_property(plane, > > + zpos, 0, grp->hw_plane_cnt - 1); > > + if (ret) > > + return ERR_PTR(ret); > > + > > + ret = drm_plane_create_alpha_property(plane); > > + if (ret) > > + return ERR_PTR(ret); > > + > > + ret = drm_plane_create_blend_mode_property(plane, > > + BIT(DRM_MODE_BLEND_PIXEL_NONE) | > > + BIT(DRM_MODE_BLEND_PREMULTI) | > > + BIT(DRM_MODE_BLEND_COVERAGE)); > > + if (ret) > > + return ERR_PTR(ret); > > + > > + ret = drm_plane_create_color_properties(plane, > > + BIT(DRM_COLOR_YCBCR_BT601) | > > + BIT(DRM_COLOR_YCBCR_BT709), > > + BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | > > + BIT(DRM_COLOR_YCBCR_FULL_RANGE), > > + DRM_COLOR_YCBCR_BT709, > > + DRM_COLOR_YCBCR_LIMITED_RANGE); > > + if (ret) > > + return ERR_PTR(ret); > > + > > + return dpu_plane; > > +} > > diff --git a/drivers/gpu/drm/imx/dpu/dpu-plane.h b/drivers/gpu/drm/imx/dpu/dpu-plane.h > > new file mode 100644 > > index 00000000..7bdd867 > > --- /dev/null > > +++ b/drivers/gpu/drm/imx/dpu/dpu-plane.h > > @@ -0,0 +1,56 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > + > > +/* > > + * Copyright 2017-2020 NXP > > + */ > > + > > +#ifndef __DPU_PLANE_H__ > > +#define __DPU_PLANE_H__ > > + > > +#include > > + > > +#include > > +#include > > +#include > > + > > +#include "dpu.h" > > + > > +#define dpu_plane_dbg(plane, fmt, ...) \ > > + drm_dbg_kms((plane)->dev, "[PLANE:%d:%s] " fmt, \ > > + (plane)->base.id, (plane)->name, ##__VA_ARGS__) > > + > > +struct dpu_plane { > > + struct drm_plane base; > > + struct dpu_plane_grp *grp; > > +}; > > + > > +union dpu_plane_stage { > > + struct dpu_constframe *cf; > > + struct dpu_layerblend *lb; > > + void *ptr; > > +}; > > + > > +struct dpu_plane_state { > > + struct drm_plane_state base; > > + union dpu_plane_stage stage; > > + struct dpu_fetchunit *source; > > + struct dpu_layerblend *blend; > > + bool is_top; > > +}; > > + > > +static inline struct dpu_plane *to_dpu_plane(struct drm_plane *plane) > > +{ > > + return container_of(plane, struct dpu_plane, base); > > +} > > + > > +static inline struct dpu_plane_state * > > +to_dpu_plane_state(struct drm_plane_state *plane_state) > > +{ > > + return container_of(plane_state, struct dpu_plane_state, base); > > +} > > + > > +struct dpu_plane *dpu_plane_initialize(struct drm_device *drm, > > + unsigned int possible_crtcs, > > + struct dpu_plane_grp *grp, > > + enum drm_plane_type type); > > +#endif /* __DPU_PLANE_H__ */ > > diff --git a/drivers/gpu/drm/imx/dpu/dpu-prg.c b/drivers/gpu/drm/imx/dpu/dpu-prg.c > > new file mode 100644 > > index 00000000..33a1a3e > > --- /dev/null > > +++ b/drivers/gpu/drm/imx/dpu/dpu-prg.c > > @@ -0,0 +1,433 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > + > > +/* > > + * Copyright 2017-2020 NXP > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "dpu-prg.h" > > + > > +#define SET 0x4 > > +#define CLR 0x8 > > +#define TOG 0xc > > + > > +#define PRG_CTRL 0x00 > > +#define BYPASS BIT(0) > > +#define SC_DATA_TYPE_8BIT 0 > > +#define SC_DATA_TYPE_10BIT BIT(2) > > +#define UV_EN BIT(3) > > +#define HANDSHAKE_MODE_4LINES 0 > > +#define HANDSHAKE_MODE_8LINES BIT(4) > > +#define SHADOW_LOAD_MODE BIT(5) > > +#define DES_DATA_TYPE_32BPP (0 << 16) > > +#define DES_DATA_TYPE_24BPP (1 << 16) > > +#define DES_DATA_TYPE_16BPP (2 << 16) > > +#define DES_DATA_TYPE_8BPP (3 << 16) > > +#define SOFTRST BIT(30) > > +#define SHADOW_EN BIT(31) > > + > > +#define PRG_STATUS 0x10 > > +#define BUFFER_VALID_B BIT(1) > > +#define BUFFER_VALID_A BIT(0) > > + > > +#define PRG_REG_UPDATE 0x20 > > +#define REG_UPDATE BIT(0) > > + > > +#define PRG_STRIDE 0x30 > > +#define STRIDE(n) (((n) - 1) & 0xffff) > > + > > +#define PRG_HEIGHT 0x40 > > +#define HEIGHT(n) (((n) - 1) & 0xffff) > > + > > +#define PRG_BADDR 0x50 > > + > > +#define PRG_OFFSET 0x60 > > +#define Y(n) (((n) & 0x7) << 16) > > +#define X(n) ((n) & 0xffff) > > + > > +#define PRG_WIDTH 0x70 > > +#define WIDTH(n) (((n) - 1) & 0xffff) > > + > > +#define DPU_PRG_MAX_STRIDE 0x10000 > > + > > +struct dpu_prg { > > + struct device *dev; > > + void __iomem *base; > > + struct list_head list; > > + struct clk *clk_apb; > > + struct clk *clk_rtram; > > + bool is_auxiliary; > > +}; > > + > > +static DEFINE_MUTEX(dpu_prg_list_mutex); > > +static LIST_HEAD(dpu_prg_list); > > + > > +static inline u32 dpu_prg_read(struct dpu_prg *prg, unsigned int offset) > > +{ > > + return readl(prg->base + offset); > > +} > > + > > +static inline void > > +dpu_prg_write(struct dpu_prg *prg, unsigned int offset, u32 value) > > +{ > > + writel(value, prg->base + offset); > > +} > > + > > +static void dpu_prg_reset(struct dpu_prg *prg) > > +{ > > + usleep_range(10, 20); > > + dpu_prg_write(prg, PRG_CTRL + SET, SOFTRST); > > + usleep_range(10, 20); > > + dpu_prg_write(prg, PRG_CTRL + CLR, SOFTRST); > > +} > > + > > +void dpu_prg_enable(struct dpu_prg *prg) > > +{ > > + dpu_prg_write(prg, PRG_CTRL + CLR, BYPASS); > > +} > > + > > +void dpu_prg_disable(struct dpu_prg *prg) > > +{ > > + dpu_prg_write(prg, PRG_CTRL, BYPASS); > > +} > > + > > +static int dpu_prg_mod_to_mt_w(struct dpu_prg *prg, u64 modifier, > > + unsigned int bits_per_pixel, unsigned int *mt_w) > > +{ > > + switch (modifier) { > > + case DRM_FORMAT_MOD_NONE: > > + *mt_w = 0; > > + break; > > + case DRM_FORMAT_MOD_VIVANTE_TILED: > > + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: > > + *mt_w = (bits_per_pixel == 16) ? 8 : 4; > > + break; > > + default: > > + dev_err(prg->dev, "unsupported modifier 0x%016llx\n", modifier); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int dpu_prg_mod_to_mt_h(struct dpu_prg *prg, u64 modifier, > > + unsigned int *mt_h) > > +{ > > + switch (modifier) { > > + case DRM_FORMAT_MOD_NONE: > > + *mt_h = 0; > > + break; > > + case DRM_FORMAT_MOD_VIVANTE_TILED: > > + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: > > + *mt_h = 4; > > + break; > > + default: > > + dev_err(prg->dev, "unsupported modifier 0x%016llx\n", modifier); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +/* address TKT343664: base address has to align to burst size */ > > +static unsigned int dpu_prg_burst_size_fixup(dma_addr_t baddr) > > +{ > > + unsigned int burst_size; > > + > > + burst_size = 1 << __ffs(baddr); > > + burst_size = round_up(burst_size, 8); > > + burst_size = min(burst_size, 128U); > > + > > + return burst_size; > > +} > > + > > +/* address TKT339017: mismatch between burst size and stride */ > > +static unsigned int dpu_prg_stride_fixup(unsigned int stride, > > + unsigned int burst_size, > > + dma_addr_t baddr, u64 modifier) > > +{ > > + if (modifier) > > + stride = round_up(stride + round_up(baddr % 8, 8), burst_size); > > + else > > + stride = round_up(stride, burst_size); > > + > > + return stride; > > +} > > + > > +void dpu_prg_configure(struct dpu_prg *prg, > > + unsigned int width, unsigned int height, > > + unsigned int x_offset, unsigned int y_offset, > > + unsigned int stride, unsigned int bits_per_pixel, > > + dma_addr_t baddr, > > + const struct drm_format_info *format, u64 modifier, > > + bool start) > > +{ > > + unsigned int mt_w, mt_h; /* micro-tile width/height */ > > + unsigned int burst_size; > > + dma_addr_t _baddr; > > + u32 val; > > + int ret; > > + > > + ret = dpu_prg_mod_to_mt_w(prg, modifier, bits_per_pixel, &mt_w); > > + ret |= dpu_prg_mod_to_mt_h(prg, modifier, &mt_h); > > + if (ret) > > + return; > > + > > + if (modifier) { > > + x_offset %= mt_w; > > + y_offset %= mt_h; > > + > > + /* consider x offset to calculate stride */ > > + _baddr = baddr + (x_offset * (bits_per_pixel / 8)); > > + } else { > > + x_offset = 0; > > + y_offset = 0; > > + _baddr = baddr; > > + } > > + > > + burst_size = dpu_prg_burst_size_fixup(_baddr); > > + > > + stride = dpu_prg_stride_fixup(stride, burst_size, _baddr, modifier); > > + > > + /* > > + * address TKT342628(part 1): > > + * when prg stride is less or equals to burst size, > > + * the auxiliary prg height needs to be a half > > + */ > > + if (prg->is_auxiliary && stride <= burst_size) { > > + height /= 2; > > + if (modifier) > > + y_offset /= 2; > > + } > > + > > + dpu_prg_write(prg, PRG_STRIDE, STRIDE(stride)); > > + dpu_prg_write(prg, PRG_WIDTH, WIDTH(width)); > > + dpu_prg_write(prg, PRG_HEIGHT, HEIGHT(height)); > > + dpu_prg_write(prg, PRG_OFFSET, X(x_offset) | Y(y_offset)); > > + dpu_prg_write(prg, PRG_BADDR, baddr); > > + > > + val = SHADOW_LOAD_MODE | SC_DATA_TYPE_8BIT | BYPASS; > > + if (format->format == DRM_FORMAT_NV21 || > > + format->format == DRM_FORMAT_NV12) { > > + val |= HANDSHAKE_MODE_8LINES; > > + /* > > + * address TKT342628(part 2): > > + * when prg stride is less or equals to burst size, > > + * we disable UV_EN bit for the auxiliary prg > > + */ > > + if (prg->is_auxiliary && stride > burst_size) > > + val |= UV_EN; > > + } else { > > + val |= HANDSHAKE_MODE_4LINES; > > + } > > + switch (bits_per_pixel) { > > + case 32: > > + val |= DES_DATA_TYPE_32BPP; > > + break; > > + case 24: > > + val |= DES_DATA_TYPE_24BPP; > > + break; > > + case 16: > > + val |= DES_DATA_TYPE_16BPP; > > + break; > > + case 8: > > + val |= DES_DATA_TYPE_8BPP; > > + break; > > + } > > + /* no shadow for the first frame */ > > + if (!start) > > + val |= SHADOW_EN; > > + dpu_prg_write(prg, PRG_CTRL, val); > > +} > > + > > +void dpu_prg_reg_update(struct dpu_prg *prg) > > +{ > > + dpu_prg_write(prg, PRG_REG_UPDATE, REG_UPDATE); > > +} > > + > > +void dpu_prg_shadow_enable(struct dpu_prg *prg) > > +{ > > + dpu_prg_write(prg, PRG_CTRL + SET, SHADOW_EN); > > +} > > + > > +bool dpu_prg_stride_supported(struct dpu_prg *prg, > > + unsigned int x_offset, > > + unsigned int bits_per_pixel, u64 modifier, > > + unsigned int stride, dma_addr_t baddr) > > +{ > > + unsigned int mt_w; /* micro-tile width */ > > + unsigned int burst_size; > > + int ret; > > + > > + ret = dpu_prg_mod_to_mt_w(prg, modifier, bits_per_pixel, &mt_w); > > + if (ret) > > + return false; > > + > > + if (modifier) { > > + x_offset %= mt_w; > > + > > + /* consider x offset to calculate stride */ > > + baddr += (x_offset * (bits_per_pixel / 8)); > > + } > > + > > + burst_size = dpu_prg_burst_size_fixup(baddr); > > + > > + stride = dpu_prg_stride_fixup(stride, burst_size, baddr, modifier); > > + > > + if (stride > DPU_PRG_MAX_STRIDE) > > + return false; > > + > > + return true; > > +} > > + > > +void dpu_prg_set_auxiliary(struct dpu_prg *prg) > > +{ > > + prg->is_auxiliary = true; > > +} > > + > > +void dpu_prg_set_primary(struct dpu_prg *prg) > > +{ > > + prg->is_auxiliary = false; > > +} > > + > > +struct dpu_prg * > > +dpu_prg_lookup_by_phandle(struct device *dev, const char *name, int index) > > +{ > > + struct device_node *prg_node = of_parse_phandle(dev->of_node, > > + name, index); > > + struct dpu_prg *prg; > > + > > + mutex_lock(&dpu_prg_list_mutex); > > + list_for_each_entry(prg, &dpu_prg_list, list) { > > + if (prg_node == prg->dev->of_node) { > > + mutex_unlock(&dpu_prg_list_mutex); > > + device_link_add(dev, prg->dev, > > + DL_FLAG_PM_RUNTIME | > > + DL_FLAG_AUTOREMOVE_CONSUMER); > > + return prg; > > + } > > + } > > + mutex_unlock(&dpu_prg_list_mutex); > > + > > + return NULL; > > +} > > + > > +static const struct of_device_id dpu_prg_dt_ids[] = { > > + { .compatible = "fsl,imx8qm-prg", }, > > + { .compatible = "fsl,imx8qxp-prg", }, > > + { /* sentinel */ }, > > +}; > > + > > +static int dpu_prg_probe(struct platform_device *pdev) > > +{ > > + struct device *dev = &pdev->dev; > > + struct resource *res; > > + struct dpu_prg *prg; > > + int ret; > > + > > + prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL); > > + if (!prg) > > + return -ENOMEM; > > + > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + prg->base = devm_ioremap_resource(&pdev->dev, res); > > + if (IS_ERR(prg->base)) > > + return PTR_ERR(prg->base); > > + > > + prg->clk_apb = devm_clk_get(dev, "apb"); > > + if (IS_ERR(prg->clk_apb)) { > > + ret = PTR_ERR(prg->clk_apb); > > + dev_err_probe(dev, ret, "failed to get apb clock\n"); > > + return ret; > > + } > > + > > + prg->clk_rtram = devm_clk_get(dev, "rtram"); > > + if (IS_ERR(prg->clk_rtram)) { > > + ret = PTR_ERR(prg->clk_rtram); > > + dev_err_probe(dev, ret, "failed to get rtram clock\n"); > > + return ret; > > + } > > + > > + prg->dev = dev; > > + platform_set_drvdata(pdev, prg); > > + > > + pm_runtime_enable(dev); > > + > > + mutex_lock(&dpu_prg_list_mutex); > > + list_add(&prg->list, &dpu_prg_list); > > + mutex_unlock(&dpu_prg_list_mutex); > > + > > + return 0; > > +} > > + > > +static int dpu_prg_remove(struct platform_device *pdev) > > +{ > > + struct dpu_prg *prg = platform_get_drvdata(pdev); > > + > > + mutex_lock(&dpu_prg_list_mutex); > > + list_del(&prg->list); > > + mutex_unlock(&dpu_prg_list_mutex); > > + > > + pm_runtime_disable(&pdev->dev); > > + > > + return 0; > > +} > > + > > +static int __maybe_unused dpu_prg_runtime_suspend(struct device *dev) > > +{ > > + struct platform_device *pdev = to_platform_device(dev); > > + struct dpu_prg *prg = platform_get_drvdata(pdev); > > + > > + clk_disable_unprepare(prg->clk_rtram); > > + clk_disable_unprepare(prg->clk_apb); > > + > > + return 0; > > +} > > + > > +static int __maybe_unused dpu_prg_runtime_resume(struct device *dev) > > +{ > > + struct platform_device *pdev = to_platform_device(dev); > > + struct dpu_prg *prg = platform_get_drvdata(pdev); > > + int ret; > > + > > + ret = clk_prepare_enable(prg->clk_apb); > > + if (ret) { > > + dev_err(dev, "failed to enable apb clock: %d\n", ret); > > + return ret; > > + } > > + > > + ret = clk_prepare_enable(prg->clk_rtram); > > + if (ret) { > > + dev_err(dev, "failed to enable rtramclock: %d\n", ret); > > + return ret; > > + } > > + > > + dpu_prg_reset(prg); > > + > > + return ret; > > +} > > + > > +static const struct dev_pm_ops dpu_prg_pm_ops = { > > + SET_RUNTIME_PM_OPS(dpu_prg_runtime_suspend, > > + dpu_prg_runtime_resume, NULL) > > +}; > > + > > +struct platform_driver dpu_prg_driver = { > > + .probe = dpu_prg_probe, > > + .remove = dpu_prg_remove, > > + .driver = { > > + .pm = &dpu_prg_pm_ops, > > + .name = "dpu-prg", > > + .of_match_table = dpu_prg_dt_ids, > > + }, > > +}; > > diff --git a/drivers/gpu/drm/imx/dpu/dpu-prg.h b/drivers/gpu/drm/imx/dpu/dpu-prg.h > > new file mode 100644 > > index 00000000..550e350 > > --- /dev/null > > +++ b/drivers/gpu/drm/imx/dpu/dpu-prg.h > > @@ -0,0 +1,45 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > + > > +/* > > + * Copyright 2017-2020 NXP > > + */ > > + > > +#ifndef _DPU_PRG_H_ > > +#define _DPU_PRG_H_ > > + > > +#include > > +#include > > + > > +#include > > + > > +struct dpu_prg; > > + > > +void dpu_prg_enable(struct dpu_prg *prg); > > + > > +void dpu_prg_disable(struct dpu_prg *prg); > > + > > +void dpu_prg_configure(struct dpu_prg *prg, > > + unsigned int width, unsigned int height, > > + unsigned int x_offset, unsigned int y_offset, > > + unsigned int stride, unsigned int bits_per_pixel, > > + dma_addr_t baddr, > > + const struct drm_format_info *format, u64 modifier, > > + bool start); > > + > > +void dpu_prg_reg_update(struct dpu_prg *prg); > > + > > +void dpu_prg_shadow_enable(struct dpu_prg *prg); > > + > > +bool dpu_prg_stride_supported(struct dpu_prg *prg, > > + unsigned int x_offset, > > + unsigned int bits_per_pixel, u64 modifier, > > + unsigned int stride, dma_addr_t baddr); > > + > > +void dpu_prg_set_auxiliary(struct dpu_prg *prg); > > + > > +void dpu_prg_set_primary(struct dpu_prg *prg); > > + > > +struct dpu_prg * > > +dpu_prg_lookup_by_phandle(struct device *dev, const char *name, int index); > > + > > +#endif > > diff --git a/drivers/gpu/drm/imx/dpu/dpu-prv.h b/drivers/gpu/drm/imx/dpu/dpu-prv.h > > new file mode 100644 > > index 00000000..8931af7 > > --- /dev/null > > +++ b/drivers/gpu/drm/imx/dpu/dpu-prv.h > > @@ -0,0 +1,233 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > + > > +/* > > + * Copyright (C) 2016 Freescale Semiconductor, Inc. > > + * Copyright 2017-2020 NXP > > + */ > > + > > +#ifndef __DPU_PRV_H__ > > +#define __DPU_PRV_H__ > > + > > +#include > > +#include > > +#include > > + > > +#include "dpu.h" > > + > > +/* DPU common control registers */ > > +#define DPU_COMCTRL_REG(offset) (offset) > > + > > +#define IPIDENTIFIER DPU_COMCTRL_REG(0x0) > > +#define LOCKUNLOCK DPU_COMCTRL_REG(0x40) > > +#define LOCKSTATUS DPU_COMCTRL_REG(0x44) > > +#define USERINTERRUPTMASK(n) DPU_COMCTRL_REG(0x48 + 4 * (n)) > > +#define INTERRUPTENABLE(n) DPU_COMCTRL_REG(0x50 + 4 * (n)) > > +#define INTERRUPTPRESET(n) DPU_COMCTRL_REG(0x58 + 4 * (n)) > > +#define INTERRUPTCLEAR(n) DPU_COMCTRL_REG(0x60 + 4 * (n)) > > +#define INTERRUPTSTATUS(n) DPU_COMCTRL_REG(0x68 + 4 * (n)) > > +#define USERINTERRUPTENABLE(n) DPU_COMCTRL_REG(0x80 + 4 * (n)) > > +#define USERINTERRUPTPRESET(n) DPU_COMCTRL_REG(0x88 + 4 * (n)) > > +#define USERINTERRUPTCLEAR(n) DPU_COMCTRL_REG(0x90 + 4 * (n)) > > +#define USERINTERRUPTSTATUS(n) DPU_COMCTRL_REG(0x98 + 4 * (n)) > > +#define GENERALPURPOSE DPU_COMCTRL_REG(0x100) > > + > > +#define DPU_SAFETY_STREAM_OFFSET 4 > > + > > +/* shadow enable bit for several DPU units */ > > +#define SHDEN BIT(0) > > + > > +/* Pixel Engine Configuration register fields */ > > +#define CLKEN_MASK_SHIFT 24 > > +#define CLKEN_MASK (0x3 << CLKEN_MASK_SHIFT) > > +#define CLKEN(n) ((n) << CLKEN_MASK_SHIFT) > > + > > +/* H/Vscaler register fields */ > > +#define SCALE_FACTOR_MASK 0xfffff > > +#define SCALE_FACTOR(n) ((n) & 0xfffff) > > +#define PHASE_OFFSET_MASK 0x1fffff > > +#define PHASE_OFFSET(n) ((n) & 0x1fffff) > > +#define OUTPUT_SIZE_MASK 0x3fff0000 > > +#define OUTPUT_SIZE(n) ((((n) - 1) << 16) & OUTPUT_SIZE_MASK) > > +#define FILTER_MODE_MASK 0x100 > > +#define FILTER_MODE(n) ((n) << 8) > > +#define SCALE_MODE_MASK 0x10 > > +#define SCALE_MODE(n) ((n) << 4) > > + > > +enum dpu_irq { > > + DPU_IRQ_STORE9_SHDLOAD = 0, > > + DPU_IRQ_STORE9_FRAMECOMPLETE = 1, > > + DPU_IRQ_STORE9_SEQCOMPLETE = 2, > > + DPU_IRQ_EXTDST0_SHDLOAD = 3, > > + DPU_IRQ_EXTDST0_FRAMECOMPLETE = 4, > > + DPU_IRQ_EXTDST0_SEQCOMPLETE = 5, > > + DPU_IRQ_EXTDST4_SHDLOAD = 6, > > + DPU_IRQ_EXTDST4_FRAMECOMPLETE = 7, > > + DPU_IRQ_EXTDST4_SEQCOMPLETE = 8, > > + DPU_IRQ_EXTDST1_SHDLOAD = 9, > > + DPU_IRQ_EXTDST1_FRAMECOMPLETE = 10, > > + DPU_IRQ_EXTDST1_SEQCOMPLETE = 11, > > + DPU_IRQ_EXTDST5_SHDLOAD = 12, > > + DPU_IRQ_EXTDST5_FRAMECOMPLETE = 13, > > + DPU_IRQ_EXTDST5_SEQCOMPLETE = 14, > > + DPU_IRQ_DISENGCFG_SHDLOAD0 = 15, > > + DPU_IRQ_DISENGCFG_FRAMECOMPLETE0 = 16, > > + DPU_IRQ_DISENGCFG_SEQCOMPLETE0 = 17, > > + DPU_IRQ_FRAMEGEN0_INT0 = 18, > > + DPU_IRQ_FRAMEGEN0_INT1 = 19, > > + DPU_IRQ_FRAMEGEN0_INT2 = 20, > > + DPU_IRQ_FRAMEGEN0_INT3 = 21, > > + DPU_IRQ_SIG0_SHDLOAD = 22, > > + DPU_IRQ_SIG0_VALID = 23, > > + DPU_IRQ_SIG0_ERROR = 24, > > + DPU_IRQ_DISENGCFG_SHDLOAD1 = 25, > > + DPU_IRQ_DISENGCFG_FRAMECOMPLETE1 = 26, > > + DPU_IRQ_DISENGCFG_SEQCOMPLETE1 = 27, > > + DPU_IRQ_FRAMEGEN1_INT0 = 28, > > + DPU_IRQ_FRAMEGEN1_INT1 = 29, > > + DPU_IRQ_FRAMEGEN1_INT2 = 30, > > + DPU_IRQ_FRAMEGEN1_INT3 = 31, > > + DPU_IRQ_SIG1_SHDLOAD = 32, > > + DPU_IRQ_SIG1_VALID = 33, > > + DPU_IRQ_SIG1_ERROR = 34, > > + DPU_IRQ_RESERVED = 35, > > + DPU_IRQ_CMDSEQ_ERROR = 36, > > + DPU_IRQ_COMCTRL_SW0 = 37, > > + DPU_IRQ_COMCTRL_SW1 = 38, > > + DPU_IRQ_COMCTRL_SW2 = 39, > > + DPU_IRQ_COMCTRL_SW3 = 40, > > + DPU_IRQ_FRAMEGEN0_PRIMSYNC_ON = 41, > > + DPU_IRQ_FRAMEGEN0_PRIMSYNC_OFF = 42, > > + DPU_IRQ_FRAMEGEN0_SECSYNC_ON = 43, > > + DPU_IRQ_FRAMEGEN0_SECSYNC_OFF = 44, > > + DPU_IRQ_FRAMEGEN1_PRIMSYNC_ON = 45, > > + DPU_IRQ_FRAMEGEN1_PRIMSYNC_OFF = 46, > > + DPU_IRQ_FRAMEGEN1_SECSYNC_ON = 47, > > + DPU_IRQ_FRAMEGEN1_SECSYNC_OFF = 48, > > + DPU_IRQ_COUNT = 49, > > +}; > > + > > +enum dpu_unit_type { > > + DPU_DISP, > > + DPU_BLIT, > > +}; > > + > > +struct dpu_soc { > > + struct device *dev; > > + > > + struct device *pd_dc_dev; > > + struct device *pd_pll0_dev; > > + struct device *pd_pll1_dev; > > + struct device_link *pd_dc_link; > > + struct device_link *pd_pll0_link; > > + struct device_link *pd_pll1_link; > > + > > + void __iomem *comctrl_reg; > > + > > + struct clk *clk_cfg; > > + struct clk *clk_axi; > > + > > + int id; > > + > > + int irq[DPU_IRQ_COUNT]; > > + > > + struct irq_domain *domain; > > + > > + struct dpu_constframe *cf_priv[4]; > > + struct dpu_disengcfg *dec_priv[2]; > > + struct dpu_extdst *ed_priv[4]; > > + struct dpu_fetchunit *fd_priv[3]; > > + struct dpu_fetchunit *fe_priv[4]; > > + struct dpu_framegen *fg_priv[2]; > > + struct dpu_fetchunit *fl_priv[1]; > > + struct dpu_fetchunit *fw_priv[2]; > > + struct dpu_gammacor *gc_priv[2]; > > + struct dpu_hscaler *hs_priv[3]; > > + struct dpu_layerblend *lb_priv[4]; > > + struct dpu_tcon *tcon_priv[2]; > > + struct dpu_vscaler *vs_priv[3]; > > +}; > > + > > +struct dpu_units { > > + const unsigned int *ids; > > + const enum dpu_unit_type *types; > > + const unsigned long *ofss; > > + const unsigned long *pec_ofss; /* Pixel Engine Configuration */ > > + const unsigned int cnt; > > + const char *name; > > + > > + /* software initialization */ > > + int (*init)(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > + /* hardware initialization */ > > + void (*hw_init)(struct dpu_soc *dpu, unsigned int index); > > +}; > > + > > +void dpu_cf_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_dec_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_ed_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_fd_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_fe_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_fg_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_fl_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_fw_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_gc_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_hs_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_lb_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_tcon_hw_init(struct dpu_soc *dpu, unsigned int index); > > +void dpu_vs_hw_init(struct dpu_soc *dpu, unsigned int index); > > + > > +int dpu_cf_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +int dpu_dec_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long unused, unsigned long base); > > + > > +int dpu_ed_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +int dpu_fd_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +int dpu_fe_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +int dpu_fg_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long unused, unsigned long base); > > + > > +int dpu_fl_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +int dpu_fw_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +int dpu_gc_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long unused, unsigned long base); > > + > > +int dpu_hs_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +int dpu_lb_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +int dpu_tcon_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long unused, unsigned long base); > > + > > +int dpu_vs_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base); > > + > > +#endif /* __DPU_PRV_H__ */ > > diff --git a/drivers/gpu/drm/imx/dpu/dpu-tcon.c b/drivers/gpu/drm/imx/dpu/dpu-tcon.c > > new file mode 100644 > > index 00000000..143f51f > > --- /dev/null > > +++ b/drivers/gpu/drm/imx/dpu/dpu-tcon.c > > @@ -0,0 +1,250 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > + > > +/* > > + * Copyright (C) 2016 Freescale Semiconductor, Inc. > > + * Copyright 2017-2020 NXP > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#include "dpu.h" > > +#include "dpu-prv.h" > > + > > +#define SSQCNTS 0x0 > > +#define SSQCYCLE 0x408 > > +#define SWRESET 0x40c > > + > > +#define TCON_CTRL 0x410 > > +#define CTRL_RST_VAL 0x01401408 > > +#define BYPASS BIT(3) > > + > > +#define RSDSINVCTRL 0x414 > > + > > +/* red: MAPBIT 29-20, green: MAPBIT 19-10, blue: MAPBIT 9-0 */ > > +#define MAPBIT3_0 0x418 > > +#define MAPBIT7_4 0x41c > > +#define MAPBIT11_8 0x420 > > +#define MAPBIT15_12 0x424 > > +#define MAPBIT19_16 0x428 > > +#define MAPBIT23_20 0x42c > > +#define MAPBIT27_24 0x430 > > +#define MAPBIT31_28 0x434 > > +#define MAPBIT34_32 0x438 > > +#define MAPBIT3_0_DUAL 0x43c > > +#define MAPBIT7_4_DUAL 0x440 > > +#define MAPBIT11_8_DUAL 0x444 > > +#define MAPBIT15_12_DUAL 0x448 > > +#define MAPBIT19_16_DUAL 0x44c > > +#define MAPBIT23_20_DUAL 0x450 > > +#define MAPBIT27_24_DUAL 0x454 > > +#define MAPBIT31_28_DUAL 0x458 > > +#define MAPBIT34_32_DUAL 0x45c > > + > > +#define SPGPOSON(n) (0x460 + (n) * 16) > > +#define SPGMASKON(n) (0x464 + (n) * 16) > > +#define SPGPOSOFF(n) (0x468 + (n) * 16) > > +#define SPGMASKOFF(n) (0x46c + (n) * 16) > > +#define X(n) (((n) & 0x7fff) << 16) > > +#define Y(n) ((n) & 0x7fff) > > + > > +#define SMXSIGS(n) (0x520 + (n) * 8) > > +#define SMXFCTTABLE(n) (0x524 + (n) * 8) > > +#define RESET_OVER_UNFERFLOW 0x580 > > +#define DUAL_DEBUG 0x584 > > + > > +struct dpu_tcon { > > + void __iomem *base; > > + struct mutex mutex; > > + unsigned int id; > > + unsigned int index; > > + bool inuse; > > + struct dpu_soc *dpu; > > +}; > > + > > +static inline u32 dpu_tcon_read(struct dpu_tcon *tcon, unsigned int offset) > > +{ > > + return readl(tcon->base + offset); > > +} > > + > > +static inline void dpu_tcon_write(struct dpu_tcon *tcon, > > + unsigned int offset, u32 value) > > +{ > > + writel(value, tcon->base + offset); > > +} > > + > > +static inline void dpu_tcon_write_mask(struct dpu_tcon *tcon, > > + unsigned int offset, u32 mask, u32 value) > > +{ > > + u32 tmp; > > + > > + tmp = dpu_tcon_read(tcon, offset); > > + tmp &= ~mask; > > + dpu_tcon_write(tcon, offset, tmp | value); > > +} > > + > > +void dpu_tcon_set_fmt(struct dpu_tcon *tcon) > > +{ > > + /* > > + * The pixels reach TCON are always in 30-bit BGR format. > > + * The first bridge always receives pixels in 30-bit RGB format. > > + * So, map the format to MEDIA_BUS_FMT_RGB101010_1X30. > > + */ > > + dpu_tcon_write(tcon, MAPBIT3_0, 0x17161514); > > + dpu_tcon_write(tcon, MAPBIT7_4, 0x1b1a1918); > > + dpu_tcon_write(tcon, MAPBIT11_8, 0x0b0a1d1c); > > + dpu_tcon_write(tcon, MAPBIT15_12, 0x0f0e0d0c); > > + dpu_tcon_write(tcon, MAPBIT19_16, 0x13121110); > > + dpu_tcon_write(tcon, MAPBIT23_20, 0x03020100); > > + dpu_tcon_write(tcon, MAPBIT27_24, 0x07060504); > > + dpu_tcon_write(tcon, MAPBIT31_28, 0x00000908); > > +} > > + > > +void dpu_tcon_set_operation_mode(struct dpu_tcon *tcon) > > +{ > > + dpu_tcon_write_mask(tcon, TCON_CTRL, BYPASS, 0); > > +} > > + > > +void dpu_tcon_cfg_videomode(struct dpu_tcon *tcon, struct drm_display_mode *m) > > +{ > > + int hdisplay, hsync_start, hsync_end; > > + int vdisplay, vsync_start, vsync_end; > > + int y; > > + > > + hdisplay = m->hdisplay; > > + vdisplay = m->vdisplay; > > + hsync_start = m->hsync_start; > > + vsync_start = m->vsync_start; > > + hsync_end = m->hsync_end; > > + vsync_end = m->vsync_end; > > + > > + /* > > + * TKT320590: > > + * Turn TCON into operation mode later after the first dumb frame is > > + * generated by DPU. This makes DPR/PRG be able to evade the frame. > > + */ > > + dpu_tcon_write_mask(tcon, TCON_CTRL, BYPASS, BYPASS); > > + > > + /* dsp_control[0]: hsync */ > > + dpu_tcon_write(tcon, SPGPOSON(0), X(hsync_start)); > > + dpu_tcon_write(tcon, SPGMASKON(0), 0xffff); > > + > > + dpu_tcon_write(tcon, SPGPOSOFF(0), X(hsync_end)); > > + dpu_tcon_write(tcon, SPGMASKOFF(0), 0xffff); > > + > > + dpu_tcon_write(tcon, SMXSIGS(0), 0x2); > > + dpu_tcon_write(tcon, SMXFCTTABLE(0), 0x1); > > + > > + /* dsp_control[1]: vsync */ > > + dpu_tcon_write(tcon, SPGPOSON(1), X(hsync_start) | Y(vsync_start - 1)); > > + dpu_tcon_write(tcon, SPGMASKON(1), 0x0); > > + > > + dpu_tcon_write(tcon, SPGPOSOFF(1), X(hsync_start) | Y(vsync_end - 1)); > > + dpu_tcon_write(tcon, SPGMASKOFF(1), 0x0); > > + > > + dpu_tcon_write(tcon, SMXSIGS(1), 0x3); > > + dpu_tcon_write(tcon, SMXFCTTABLE(1), 0x1); > > + > > + /* dsp_control[2]: data enable */ > > + /* horizontal */ > > + dpu_tcon_write(tcon, SPGPOSON(2), 0x0); > > + dpu_tcon_write(tcon, SPGMASKON(2), 0xffff); > > + > > + dpu_tcon_write(tcon, SPGPOSOFF(2), X(hdisplay)); > > + dpu_tcon_write(tcon, SPGMASKOFF(2), 0xffff); > > + > > + /* vertical */ > > + dpu_tcon_write(tcon, SPGPOSON(3), 0x0); > > + dpu_tcon_write(tcon, SPGMASKON(3), 0x7fff0000); > > + > > + dpu_tcon_write(tcon, SPGPOSOFF(3), Y(vdisplay)); > > + dpu_tcon_write(tcon, SPGMASKOFF(3), 0x7fff0000); > > + > > + dpu_tcon_write(tcon, SMXSIGS(2), 0x2c); > > + dpu_tcon_write(tcon, SMXFCTTABLE(2), 0x8); > > + > > + /* dsp_control[3]: kachuck */ > > + y = vdisplay + 1; > > + > > + dpu_tcon_write(tcon, SPGPOSON(4), X(0x0) | Y(y)); > > + dpu_tcon_write(tcon, SPGMASKON(4), 0x0); > > + > > + dpu_tcon_write(tcon, SPGPOSOFF(4), X(0x20) | Y(y)); > > + dpu_tcon_write(tcon, SPGMASKOFF(4), 0x0); > > + > > + dpu_tcon_write(tcon, SMXSIGS(3), 0x6); > > + dpu_tcon_write(tcon, SMXFCTTABLE(3), 0x2); > > +} > > + > > +struct dpu_tcon *dpu_tcon_get(struct dpu_soc *dpu, unsigned int id) > > +{ > > + struct dpu_tcon *tcon; > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(dpu->tcon_priv); i++) { > > + tcon = dpu->tcon_priv[i]; > > + if (tcon->id == id) > > + break; > > + } > > + > > + if (i == ARRAY_SIZE(dpu->tcon_priv)) > > + return ERR_PTR(-EINVAL); > > + > > + mutex_lock(&tcon->mutex); > > + > > + if (tcon->inuse) { > > + mutex_unlock(&tcon->mutex); > > + return ERR_PTR(-EBUSY); > > + } > > + > > + tcon->inuse = true; > > + > > + mutex_unlock(&tcon->mutex); > > + > > + return tcon; > > +} > > + > > +void dpu_tcon_put(struct dpu_tcon *tcon) > > +{ > > + if (IS_ERR_OR_NULL(tcon)) > > + return; > > + > > + mutex_lock(&tcon->mutex); > > + > > + tcon->inuse = false; > > + > > + mutex_unlock(&tcon->mutex); > > +} > > + > > +void dpu_tcon_hw_init(struct dpu_soc *dpu, unsigned int index) > > +{ > > + /* reset TCON_CTRL to POR default so that TCON works in bypass mode */ > > + dpu_tcon_write(dpu->tcon_priv[index], TCON_CTRL, CTRL_RST_VAL); > > +} > > + > > +int dpu_tcon_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long unused, unsigned long base) > > +{ > > + struct dpu_tcon *tcon; > > + > > + tcon = devm_kzalloc(dpu->dev, sizeof(*tcon), GFP_KERNEL); > > + if (!tcon) > > + return -ENOMEM; > > + > > + dpu->tcon_priv[index] = tcon; > > + > > + tcon->base = devm_ioremap(dpu->dev, base, SZ_2K); > > + if (!tcon->base) > > + return -ENOMEM; > > + > > + tcon->dpu = dpu; > > + tcon->id = id; > > + tcon->index = index; > > + > > + mutex_init(&tcon->mutex); > > + > > + return 0; > > +} > > diff --git a/drivers/gpu/drm/imx/dpu/dpu-vscaler.c b/drivers/gpu/drm/imx/dpu/dpu-vscaler.c > > new file mode 100644 > > index 00000000..bdef0cd > > --- /dev/null > > +++ b/drivers/gpu/drm/imx/dpu/dpu-vscaler.c > > @@ -0,0 +1,308 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > + > > +/* > > + * Copyright 2017-2020 NXP > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#include "dpu.h" > > +#include "dpu-prv.h" > > + > > +#define PIXENGCFG_DYNAMIC 0x8 > > +#define PIXENGCFG_DYNAMIC_SRC_SEL_MASK 0x3f > > + > > +#define STATICCONTROL 0x8 > > + > > +#define SETUP(n) (0xc + ((n) - 1) * 0x4) > > + > > +#define CONTROL 0x20 > > +#define FIELD_MODE_MASK 0x3000 > > +#define FIELD_MODE(n) ((n) << 12) > > +#define CTRL_MODE_MASK BIT(0) > > + > > +struct dpu_vscaler { > > + void __iomem *pec_base; > > + void __iomem *base; > > + struct mutex mutex; > > + unsigned int id; > > + unsigned int index; > > + enum dpu_link_id link_id; > > + bool inuse; > > + struct dpu_soc *dpu; > > +}; > > + > > +static const enum dpu_link_id dpu_vs_link_id[] = { > > + LINK_ID_VSCALER4, LINK_ID_VSCALER5, LINK_ID_VSCALER9 > > +}; > > + > > +static const enum dpu_link_id src_sels[3][4] = { > > + { > > + LINK_ID_NONE, > > + LINK_ID_FETCHDECODE0, > > + LINK_ID_MATRIX4, > > + LINK_ID_HSCALER4, > > + }, { > > + LINK_ID_NONE, > > + LINK_ID_FETCHDECODE1, > > + LINK_ID_MATRIX5, > > + LINK_ID_HSCALER5, > > + }, { > > + LINK_ID_NONE, > > + LINK_ID_MATRIX9, > > + LINK_ID_HSCALER9, > > + }, > > +}; > > + > > +static inline u32 dpu_pec_vs_read(struct dpu_vscaler *vs, > > + unsigned int offset) > > +{ > > + return readl(vs->pec_base + offset); > > +} > > + > > +static inline void dpu_pec_vs_write(struct dpu_vscaler *vs, > > + unsigned int offset, u32 value) > > +{ > > + writel(value, vs->pec_base + offset); > > +} > > + > > +static inline void dpu_pec_vs_write_mask(struct dpu_vscaler *vs, > > + unsigned int offset, > > + u32 mask, u32 value) > > +{ > > + u32 tmp; > > + > > + tmp = dpu_pec_vs_read(vs, offset); > > + tmp &= ~mask; > > + dpu_pec_vs_write(vs, offset, tmp | value); > > +} > > + > > +static inline u32 dpu_vs_read(struct dpu_vscaler *vs, unsigned int offset) > > +{ > > + return readl(vs->base + offset); > > +} > > + > > +static inline void dpu_vs_write(struct dpu_vscaler *vs, > > + unsigned int offset, u32 value) > > +{ > > + writel(value, vs->base + offset); > > +} > > + > > +static inline void dpu_vs_write_mask(struct dpu_vscaler *vs, > > + unsigned int offset, u32 mask, u32 value) > > +{ > > + u32 tmp; > > + > > + tmp = dpu_vs_read(vs, offset); > > + tmp &= ~mask; > > + dpu_vs_write(vs, offset, tmp | value); > > +} > > + > > +enum dpu_link_id dpu_vs_get_link_id(struct dpu_vscaler *vs) > > +{ > > + return vs->link_id; > > +} > > + > > +void dpu_vs_pec_dynamic_src_sel(struct dpu_vscaler *vs, enum dpu_link_id src) > > +{ > > + struct dpu_soc *dpu = vs->dpu; > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(src_sels[vs->index]); i++) { > > + if (src_sels[vs->index][i] == src) { > > + dpu_pec_vs_write_mask(vs, PIXENGCFG_DYNAMIC, > > + PIXENGCFG_DYNAMIC_SRC_SEL_MASK, > > + src); > > + return; > > + } > > + } > > + > > + dev_err(dpu->dev, "VScaler%u - invalid source 0x%02x\n", vs->id, src); > > +} > > + > > +void dpu_vs_pec_clken(struct dpu_vscaler *vs, enum dpu_pec_clken clken) > > +{ > > + dpu_pec_vs_write_mask(vs, PIXENGCFG_DYNAMIC, CLKEN_MASK, CLKEN(clken)); > > +} > > + > > +static void dpu_vs_enable_shden(struct dpu_vscaler *vs) > > +{ > > + dpu_vs_write_mask(vs, STATICCONTROL, SHDEN, SHDEN); > > +} > > + > > +void dpu_vs_setup1(struct dpu_vscaler *vs, > > + unsigned int src_w, unsigned int dst_w, bool deinterlace) > > +{ > > + struct dpu_soc *dpu = vs->dpu; > > + u32 scale_factor; > > + u64 tmp64; > > + > > + if (deinterlace) > > + dst_w *= 2; > > + > > + if (src_w == dst_w) { > > + scale_factor = 0x80000; > > + } else { > > + if (src_w > dst_w) { > > + tmp64 = (u64)((u64)dst_w * 0x80000); > > + do_div(tmp64, src_w); > > + > > + } else { > > + tmp64 = (u64)((u64)src_w * 0x80000); > > + do_div(tmp64, dst_w); > > + } > > + scale_factor = (u32)tmp64; > > + } > > + > > + if (scale_factor > 0x80000) { > > + dev_err(dpu->dev, "VScaler%u - invalid scale factor 0x%08x\n", > > + vs->id, scale_factor); > > + return; > > + } > > + > > + dpu_vs_write(vs, SETUP(1), SCALE_FACTOR(scale_factor)); > > + > > + dev_dbg(dpu->dev, "VScaler%u - scale factor 0x%08x\n", > > + vs->id, scale_factor); > > +} > > + > > +void dpu_vs_setup2(struct dpu_vscaler *vs, bool deinterlace) > > +{ > > + /* 0x20000: +0.25 phase offset for deinterlace */ > > + u32 phase_offset = deinterlace ? 0x20000 : 0; > > + > > + dpu_vs_write(vs, SETUP(2), PHASE_OFFSET(phase_offset)); > > +} > > + > > +void dpu_vs_setup3(struct dpu_vscaler *vs, bool deinterlace) > > +{ > > + /* 0x1e0000: -0.25 phase offset for deinterlace */ > > + u32 phase_offset = deinterlace ? 0x1e0000 : 0; > > + > > + dpu_vs_write(vs, SETUP(3), PHASE_OFFSET(phase_offset)); > > +} > > + > > +void dpu_vs_setup4(struct dpu_vscaler *vs, u32 phase_offset) > > +{ > > + dpu_vs_write(vs, SETUP(4), PHASE_OFFSET(phase_offset)); > > +} > > + > > +void dpu_vs_setup5(struct dpu_vscaler *vs, u32 phase_offset) > > +{ > > + dpu_vs_write(vs, SETUP(5), PHASE_OFFSET(phase_offset)); > > +} > > + > > +void dpu_vs_output_size(struct dpu_vscaler *vs, u32 line_num) > > +{ > > + dpu_vs_write_mask(vs, CONTROL, OUTPUT_SIZE_MASK, OUTPUT_SIZE(line_num)); > > +} > > + > > +void dpu_vs_field_mode(struct dpu_vscaler *vs, enum dpu_scaler_field_mode m) > > +{ > > + dpu_vs_write_mask(vs, CONTROL, FIELD_MODE_MASK, FIELD_MODE(m)); > > +} > > + > > +void dpu_vs_filter_mode(struct dpu_vscaler *vs, enum dpu_scaler_filter_mode m) > > +{ > > + dpu_vs_write_mask(vs, CONTROL, FILTER_MODE_MASK, FILTER_MODE(m)); > > +} > > + > > +void dpu_vs_scale_mode(struct dpu_vscaler *vs, enum dpu_scaler_scale_mode m) > > +{ > > + dpu_vs_write_mask(vs, CONTROL, SCALE_MODE_MASK, SCALE_MODE(m)); > > +} > > + > > +void dpu_vs_mode(struct dpu_vscaler *vs, enum dpu_scaler_mode m) > > +{ > > + dpu_vs_write_mask(vs, CONTROL, CTRL_MODE_MASK, m); > > +} > > + > > +unsigned int dpu_vs_get_id(struct dpu_vscaler *vs) > > +{ > > + return vs->id; > > +} > > + > > +struct dpu_vscaler *dpu_vs_get(struct dpu_soc *dpu, unsigned int id) > > +{ > > + struct dpu_vscaler *vs; > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(dpu->vs_priv); i++) { > > + vs = dpu->vs_priv[i]; > > + if (vs->id == id) > > + break; > > + } > > + > > + if (i == ARRAY_SIZE(dpu->vs_priv)) > > + return ERR_PTR(-EINVAL); > > + > > + mutex_lock(&vs->mutex); > > + > > + if (vs->inuse) { > > + mutex_unlock(&vs->mutex); > > + return ERR_PTR(-EBUSY); > > + } > > + > > + vs->inuse = true; > > + > > + mutex_unlock(&vs->mutex); > > + > > + return vs; > > +} > > + > > +void dpu_vs_put(struct dpu_vscaler *vs) > > +{ > > + if (IS_ERR_OR_NULL(vs)) > > + return; > > + > > + mutex_lock(&vs->mutex); > > + > > + vs->inuse = false; > > + > > + mutex_unlock(&vs->mutex); > > +} > > + > > +void dpu_vs_hw_init(struct dpu_soc *dpu, unsigned int index) > > +{ > > + struct dpu_vscaler *vs = dpu->vs_priv[index]; > > + > > + dpu_vs_enable_shden(vs); > > + dpu_vs_setup2(vs, false); > > + dpu_vs_setup3(vs, false); > > + dpu_vs_setup4(vs, 0); > > + dpu_vs_setup5(vs, 0); > > + dpu_vs_pec_dynamic_src_sel(vs, LINK_ID_NONE); > > +} > > + > > +int dpu_vs_init(struct dpu_soc *dpu, unsigned int index, > > + unsigned int id, enum dpu_unit_type type, > > + unsigned long pec_base, unsigned long base) > > +{ > > + struct dpu_vscaler *vs; > > + > > + vs = devm_kzalloc(dpu->dev, sizeof(*vs), GFP_KERNEL); > > + if (!vs) > > + return -ENOMEM; > > + > > + dpu->vs_priv[index] = vs; > > + > > + vs->pec_base = devm_ioremap(dpu->dev, pec_base, SZ_16); > > + if (!vs->pec_base) > > + return -ENOMEM; > > + > > + vs->base = devm_ioremap(dpu->dev, base, SZ_32); > > + if (!vs->base) > > + return -ENOMEM; > > + > > + vs->dpu = dpu; > > + vs->id = id; > > + vs->index = index; > > + vs->link_id = dpu_vs_link_id[index]; > > + > > + mutex_init(&vs->mutex); > > + > > + return 0; > > +} > > diff --git a/drivers/gpu/drm/imx/dpu/dpu.h b/drivers/gpu/drm/imx/dpu/dpu.h > > new file mode 100644 > > index 00000000..ef012e2 > > --- /dev/null > > +++ b/drivers/gpu/drm/imx/dpu/dpu.h > > @@ -0,0 +1,385 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > + > > +/* > > + * Copyright (C) 2016 Freescale Semiconductor, Inc. > > + * Copyright 2017-2020 NXP > > + */ > > + > > +#ifndef __DPU_H__ > > +#define __DPU_H__ > > + > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > + > > +#define DPU_FRAMEGEN_MAX_FRAME_INDEX 0x3ffff > > +#define DPU_FRAMEGEN_MAX_CLOCK 300000 /* in KHz */ > > + > > +#define DPU_FETCHUNIT_CAP_USE_FETCHECO BIT(0) > > +#define DPU_FETCHUNIT_CAP_USE_SCALER BIT(1) > > +#define DPU_FETCHUNIT_CAP_PACKED_YUV422 BIT(2) > > + > > +struct dpu_dprc; > > +struct dpu_fetchunit; > > +struct dpu_soc; > > + > > +enum dpu_link_id { > > + LINK_ID_NONE = 0x00, > > + LINK_ID_FETCHDECODE9 = 0x01, > > + LINK_ID_FETCHWARP9 = 0x02, > > + LINK_ID_FETCHECO9 = 0x03, > > + LINK_ID_ROP9 = 0x04, > > + LINK_ID_CLUT9 = 0x05, > > + LINK_ID_MATRIX9 = 0x06, > > + LINK_ID_HSCALER9 = 0x07, > > + LINK_ID_VSCALER9 = 0x08, > > + LINK_ID_FILTER9 = 0x09, > > + LINK_ID_BLITBLEND9 = 0x0a, > > + LINK_ID_CONSTFRAME0 = 0x0c, > > + LINK_ID_CONSTFRAME4 = 0x0e, > > + LINK_ID_CONSTFRAME1 = 0x10, > > + LINK_ID_CONSTFRAME5 = 0x12, > > + LINK_ID_FETCHWARP2 = 0x14, > > + LINK_ID_FETCHECO2 = 0x15, > > + LINK_ID_FETCHDECODE0 = 0x16, > > + LINK_ID_FETCHECO0 = 0x17, > > + LINK_ID_FETCHDECODE1 = 0x18, > > + LINK_ID_FETCHECO1 = 0x19, > > + LINK_ID_FETCHLAYER0 = 0x1a, > > + LINK_ID_MATRIX4 = 0x1b, > > + LINK_ID_HSCALER4 = 0x1c, > > + LINK_ID_VSCALER4 = 0x1d, > > + LINK_ID_MATRIX5 = 0x1e, > > + LINK_ID_HSCALER5 = 0x1f, > > + LINK_ID_VSCALER5 = 0x20, > > + LINK_ID_LAYERBLEND0 = 0x21, > > + LINK_ID_LAYERBLEND1 = 0x22, > > + LINK_ID_LAYERBLEND2 = 0x23, > > + LINK_ID_LAYERBLEND3 = 0x24, > > +}; > > + > > +enum dpu_fg_syncmode { > > + FG_SYNCMODE_OFF, /* No side-by-side synchronization. */ > > + FG_SYNCMODE_MASTER, /* Framegen is master. */ > > + FG_SYNCMODE_SLAVE_CYC, /* Runs in cyclic synchronization mode. */ > > + FG_SYNCMODE_SLAVE_ONCE, /* Runs in one time synchronization mode. */ > > +}; > > + > > +enum dpu_fg_dm { > > + FG_DM_BLACK, > > + FG_DM_CONSTCOL, /* Constant Color Background is shown. */ > > + FG_DM_PRIM, > > + FG_DM_SEC, > > + FG_DM_PRIM_ON_TOP, > > + FG_DM_SEC_ON_TOP, > > + FG_DM_TEST, /* White color background with test pattern is shown. */ > > +}; > > + > > +enum dpu_gc_mode { > > + GC_NEUTRAL, /* Input data is bypassed to the output. */ > > + GC_GAMMACOR, > > +}; > > + > > +enum dpu_lb_mode { > > + LB_NEUTRAL, /* Output is same as primary input. */ > > + LB_BLEND, > > +}; > > + > > +enum dpu_scaler_field_mode { > > + /* Constant 0 indicates frame or top field. */ > > + SCALER_ALWAYS0, > > + /* Constant 1 indicates bottom field. */ > > + SCALER_ALWAYS1, > > + /* Output field polarity is taken from input field polarity. */ > > + SCALER_INPUT, > > + /* Output field polarity toggles, starting with 0 after reset. */ > > + SCALER_TOGGLE, > > +}; > > + > > +enum dpu_scaler_filter_mode { > > + SCALER_NEAREST, /* pointer-sampling */ > > + SCALER_LINEAR, /* box filter */ > > +}; > > + > > +enum dpu_scaler_scale_mode { > > + SCALER_DOWNSCALE, > > + SCALER_UPSCALE, > > +}; > > + > > +enum dpu_scaler_mode { > > + /* Pixel by-pass the scaler, all other settings are ignored. */ > > + SCALER_NEUTRAL, > > + /* Scaler is active. */ > > + SCALER_ACTIVE, > > +}; > > + > > +enum dpu_pec_clken { > > + CLKEN_DISABLE = 0x0, > > + CLKEN_AUTOMATIC = 0x1, > > + CLKEN_FULL = 0x3, > > +}; > > + > > +int dpu_map_irq(struct dpu_soc *dpu, int irq); > > + > > +/* Constant Frame Unit */ > > +struct dpu_constframe; > > +enum dpu_link_id dpu_cf_get_link_id(struct dpu_constframe *cf); > > +void dpu_cf_framedimensions(struct dpu_constframe *cf, unsigned int w, > > + unsigned int h); > > +void dpu_cf_constantcolor_black(struct dpu_constframe *cf); > > +void dpu_cf_constantcolor_blue(struct dpu_constframe *cf); > > +struct dpu_constframe *dpu_cf_safe_get(struct dpu_soc *dpu, > > + unsigned int stream_id); > > +void dpu_cf_safe_put(struct dpu_constframe *cf); > > +struct dpu_constframe *dpu_cf_cont_get(struct dpu_soc *dpu, > > + unsigned int stream_id); > > +void dpu_cf_cont_put(struct dpu_constframe *cf); > > + > > +/* Display Engine Configuration Unit */ > > +struct dpu_disengcfg; > > +struct dpu_disengcfg *dpu_dec_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_dec_put(struct dpu_disengcfg *dec); > > + > > +/* External Destination Unit */ > > +struct dpu_extdst; > > +void dpu_ed_pec_poweron(struct dpu_extdst *ed); > > +void dpu_ed_pec_src_sel(struct dpu_extdst *ed, enum dpu_link_id src); > > +void dpu_ed_pec_sync_trigger(struct dpu_extdst *ed); > > +struct dpu_extdst *dpu_ed_safe_get(struct dpu_soc *dpu, > > + unsigned int stream_id); > > +void dpu_ed_safe_put(struct dpu_extdst *ed); > > +struct dpu_extdst *dpu_ed_cont_get(struct dpu_soc *dpu, > > + unsigned int stream_id); > > +void dpu_ed_cont_put(struct dpu_extdst *ed); > > + > > +/* Fetch Decode Unit */ > > +struct dpu_fetchunit *dpu_fd_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_fd_put(struct dpu_fetchunit *fu); > > + > > +/* Fetch ECO Unit */ > > +struct dpu_fetchunit *dpu_fe_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_fe_put(struct dpu_fetchunit *fu); > > + > > +/* Fetch Layer Unit */ > > +struct dpu_fetchunit *dpu_fl_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_fl_put(struct dpu_fetchunit *fu); > > + > > +/* Fetch Warp Unit */ > > +struct dpu_fetchunit *dpu_fw_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_fw_put(struct dpu_fetchunit *fu); > > + > > +/* Frame Generator Unit */ > > +struct dpu_framegen; > > +void dpu_fg_syncmode(struct dpu_framegen *fg, enum dpu_fg_syncmode mode); > > +void dpu_fg_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m); > > +void dpu_fg_displaymode(struct dpu_framegen *fg, enum dpu_fg_dm mode); > > +void dpu_fg_panic_displaymode(struct dpu_framegen *fg, enum dpu_fg_dm mode); > > +void dpu_fg_enable(struct dpu_framegen *fg); > > +void dpu_fg_disable(struct dpu_framegen *fg); > > +void dpu_fg_shdtokgen(struct dpu_framegen *fg); > > +u32 dpu_fg_get_frame_index(struct dpu_framegen *fg); > > +int dpu_fg_get_line_index(struct dpu_framegen *fg); > > +int dpu_fg_wait_for_frame_counter_moving(struct dpu_framegen *fg); > > +bool dpu_fg_secondary_requests_to_read_empty_fifo(struct dpu_framegen *fg); > > +void dpu_fg_secondary_clear_channel_status(struct dpu_framegen *fg); > > +int dpu_fg_wait_for_secondary_syncup(struct dpu_framegen *fg); > > +void dpu_fg_enable_clock(struct dpu_framegen *fg); > > +void dpu_fg_disable_clock(struct dpu_framegen *fg); > > +struct dpu_framegen *dpu_fg_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_fg_put(struct dpu_framegen *fg); > > + > > +/* Gamma Correction Unit */ > > +struct dpu_gammacor; > > +void dpu_gc_enable_rgb_write(struct dpu_gammacor *gc); > > +void dpu_gc_disable_rgb_write(struct dpu_gammacor *gc); > > +void dpu_gc_start_rgb(struct dpu_gammacor *gc, const struct drm_color_lut *lut); > > +void dpu_gc_delta_rgb(struct dpu_gammacor *gc, const struct drm_color_lut *lut); > > +void dpu_gc_mode(struct dpu_gammacor *gc, enum dpu_gc_mode mode); > > +struct dpu_gammacor *dpu_gc_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_gc_put(struct dpu_gammacor *gc); > > + > > +/* Horizontal Scaler Unit */ > > +struct dpu_hscaler; > > +enum dpu_link_id dpu_hs_get_link_id(struct dpu_hscaler *hs); > > +void dpu_hs_pec_dynamic_src_sel(struct dpu_hscaler *hs, enum dpu_link_id src); > > +void dpu_hs_pec_clken(struct dpu_hscaler *hs, enum dpu_pec_clken clken); > > +void dpu_hs_setup1(struct dpu_hscaler *hs, > > + unsigned int src_w, unsigned int dst_w); > > +void dpu_hs_setup2(struct dpu_hscaler *hs, u32 phase_offset); > > +void dpu_hs_output_size(struct dpu_hscaler *hs, u32 line_num); > > +void dpu_hs_filter_mode(struct dpu_hscaler *hs, enum dpu_scaler_filter_mode m); > > +void dpu_hs_scale_mode(struct dpu_hscaler *hs, enum dpu_scaler_scale_mode m); > > +void dpu_hs_mode(struct dpu_hscaler *hs, enum dpu_scaler_mode m); > > +unsigned int dpu_hs_get_id(struct dpu_hscaler *hs); > > +struct dpu_hscaler *dpu_hs_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_hs_put(struct dpu_hscaler *hs); > > + > > +/* Layer Blend Unit */ > > +struct dpu_layerblend; > > +enum dpu_link_id dpu_lb_get_link_id(struct dpu_layerblend *lb); > > +void dpu_lb_pec_dynamic_prim_sel(struct dpu_layerblend *lb, > > + enum dpu_link_id prim); > > +void dpu_lb_pec_dynamic_sec_sel(struct dpu_layerblend *lb, > > + enum dpu_link_id sec); > > +void dpu_lb_pec_clken(struct dpu_layerblend *lb, enum dpu_pec_clken clken); > > +void dpu_lb_mode(struct dpu_layerblend *lb, enum dpu_lb_mode mode); > > +void dpu_lb_blendcontrol(struct dpu_layerblend *lb, unsigned int zpos, > > + unsigned int pixel_blend_mode, u16 alpha); > > +void dpu_lb_position(struct dpu_layerblend *lb, int x, int y); > > +unsigned int dpu_lb_get_id(struct dpu_layerblend *lb); > > +struct dpu_layerblend *dpu_lb_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_lb_put(struct dpu_layerblend *lb); > > + > > +/* Timing Controller Unit */ > > +struct dpu_tcon; > > +void dpu_tcon_set_fmt(struct dpu_tcon *tcon); > > +void dpu_tcon_set_operation_mode(struct dpu_tcon *tcon); > > +void dpu_tcon_cfg_videomode(struct dpu_tcon *tcon, struct drm_display_mode *m); > > +struct dpu_tcon *dpu_tcon_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_tcon_put(struct dpu_tcon *tcon); > > + > > +/* Vertical Scaler Unit */ > > +struct dpu_vscaler; > > +enum dpu_link_id dpu_vs_get_link_id(struct dpu_vscaler *vs); > > +void dpu_vs_pec_dynamic_src_sel(struct dpu_vscaler *vs, enum dpu_link_id src); > > +void dpu_vs_pec_clken(struct dpu_vscaler *vs, enum dpu_pec_clken clken); > > +void dpu_vs_setup1(struct dpu_vscaler *vs, > > + unsigned int src_w, unsigned int dst_w, bool deinterlace); > > +void dpu_vs_setup2(struct dpu_vscaler *vs, bool deinterlace); > > +void dpu_vs_setup3(struct dpu_vscaler *vs, bool deinterlace); > > +void dpu_vs_setup4(struct dpu_vscaler *vs, u32 phase_offset); > > +void dpu_vs_setup5(struct dpu_vscaler *vs, u32 phase_offset); > > +void dpu_vs_output_size(struct dpu_vscaler *vs, u32 line_num); > > +void dpu_vs_field_mode(struct dpu_vscaler *vs, enum dpu_scaler_field_mode m); > > +void dpu_vs_filter_mode(struct dpu_vscaler *vs, enum dpu_scaler_filter_mode m); > > +void dpu_vs_scale_mode(struct dpu_vscaler *vs, enum dpu_scaler_scale_mode m); > > +void dpu_vs_mode(struct dpu_vscaler *vs, enum dpu_scaler_mode m); > > +unsigned int dpu_vs_get_id(struct dpu_vscaler *vs); > > +struct dpu_vscaler *dpu_vs_get(struct dpu_soc *dpu, unsigned int id); > > +void dpu_vs_put(struct dpu_vscaler *vs); > > + > > +/* Fetch Units */ > > +struct dpu_fetchunit_ops { > > + void (*set_pec_dynamic_src_sel)(struct dpu_fetchunit *fu, > > + enum dpu_link_id src); > > + > > + bool (*is_enabled)(struct dpu_fetchunit *fu); > > + > > + void (*set_stream_id)(struct dpu_fetchunit *fu, unsigned int stream_id); > > + > > + unsigned int (*get_stream_id)(struct dpu_fetchunit *fu); > > + > > + void (*set_no_stream_id)(struct dpu_fetchunit *fu); > > + > > + bool (*has_stream_id)(struct dpu_fetchunit *fu); > > + > > + void (*set_numbuffers)(struct dpu_fetchunit *fu, unsigned int num); > > + > > + void (*set_burstlength)(struct dpu_fetchunit *fu, > > + unsigned int x_offset, unsigned int mt_w, > > + int bpp, dma_addr_t baddr); > > + > > + void (*set_baseaddress)(struct dpu_fetchunit *fu, unsigned int width, > > + unsigned int x_offset, unsigned int y_offset, > > + unsigned int mt_w, unsigned int mt_h, > > + int bpp, dma_addr_t baddr); > > + > > + void (*set_src_stride)(struct dpu_fetchunit *fu, > > + unsigned int width, unsigned int x_offset, > > + unsigned int mt_w, int bpp, unsigned int stride, > > + dma_addr_t baddr); > > + > > + void (*set_src_buf_dimensions)(struct dpu_fetchunit *fu, > > + unsigned int w, unsigned int h, > > + const struct drm_format_info *format, > > + bool deinterlace); > > + > > + void (*set_fmt)(struct dpu_fetchunit *fu, > > + const struct drm_format_info *format, > > + enum drm_color_encoding color_encoding, > > + enum drm_color_range color_range, > > + bool deinterlace); > > + > > + void (*set_pixel_blend_mode)(struct dpu_fetchunit *fu, > > + unsigned int pixel_blend_mode, u16 alpha, > > + bool fb_format_has_alpha); > > + > > + void (*enable_src_buf)(struct dpu_fetchunit *fu); > > + void (*disable_src_buf)(struct dpu_fetchunit *fu); > > + > > + void (*set_framedimensions)(struct dpu_fetchunit *fu, > > + unsigned int w, unsigned int h, > > + bool deinterlace); > > + > > + struct dpu_dprc *(*get_dprc)(struct dpu_fetchunit *fu); > > + struct dpu_fetchunit *(*get_fetcheco)(struct dpu_fetchunit *fu); > > + struct dpu_hscaler *(*get_hscaler)(struct dpu_fetchunit *fu); > > + struct dpu_vscaler *(*get_vscaler)(struct dpu_fetchunit *fu); > > + > > + void (*set_layerblend)(struct dpu_fetchunit *fu, > > + struct dpu_layerblend *lb); > > + > > + bool (*is_available)(struct dpu_fetchunit *fu); > > + void (*set_available)(struct dpu_fetchunit *fu); > > + void (*set_inavailable)(struct dpu_fetchunit *fu); > > + > > + enum dpu_link_id (*get_link_id)(struct dpu_fetchunit *fu); > > + > > + u32 (*get_cap_mask)(struct dpu_fetchunit *fu); > > + > > + const char *(*get_name)(struct dpu_fetchunit *fu); > > +}; > > + > > +const struct dpu_fetchunit_ops *dpu_fu_get_ops(struct dpu_fetchunit *fu); > > +struct dpu_fetchunit *dpu_fu_get_from_list(struct list_head *l); > > +void dpu_fu_add_to_list(struct dpu_fetchunit *fu, struct list_head *l); > > + > > +/* HW resources for a plane group */ > > +struct dpu_plane_res { > > + struct dpu_fetchunit **fd; > > + struct dpu_fetchunit **fe; > > + struct dpu_fetchunit **fl; > > + struct dpu_fetchunit **fw; > > + struct dpu_layerblend **lb; > > + unsigned int fd_cnt; > > + unsigned int fe_cnt; > > + unsigned int fl_cnt; > > + unsigned int fw_cnt; > > + unsigned int lb_cnt; > > +}; > > + > > +/* > > + * fetchunit/scaler/layerblend resources of a plane group are > > + * shared by the two CRTCs in a CRTC group > > + */ > > +struct dpu_plane_grp { > > + struct dpu_plane_res res; > > + struct list_head node; > > + struct list_head fu_list; > > + unsigned int hw_plane_cnt; > > + struct dpu_constframe *cf[2]; > > + struct dpu_extdst *ed[2]; > > +}; > > + > > +/* the two CRTCs of one DPU are in a CRTC group */ > > +struct dpu_crtc_grp { > > + u32 crtc_mask; > > + struct dpu_plane_grp *plane_grp; > > +}; > > + > > +struct dpu_client_platformdata { > > + const unsigned int stream_id; > > + const unsigned int dec_frame_complete_irq; > > + const unsigned int dec_seq_complete_irq; > > + const unsigned int dec_shdld_irq; > > + const unsigned int ed_cont_shdld_irq; > > + const unsigned int ed_safe_shdld_irq; > > + struct dpu_crtc_grp *crtc_grp; > > + > > + struct device_node *of_node; > > +}; > > + > > +#endif /* __DPU_H__ */ > > -- > > 2.7.4 > >