forked from torvalds/linux
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drm/imx: Introduce i.MX8qm/qxp DPU DRM
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 <victor.liu@nxp.com>
- Loading branch information
1 parent
bf259fa
commit 9782ac2
Showing
34 changed files
with
9,445 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
config DRM_IMX_DPU | ||
tristate "DRM support for Freescale i.MX DPU Graphics" | ||
select DRM_KMS_HELPER | ||
select VIDEOMODE_HELPERS | ||
select DRM_GEM_CMA_HELPER | ||
select DRM_KMS_CMA_HELPER | ||
depends on DRM && OF && IMX_SCU && ARCH_MXC | ||
depends on COMMON_CLK | ||
help | ||
enable Freescale i.MX DPU graphics support |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# SPDX-License-Identifier: GPL-2.0 | ||
|
||
imx-dpu-drm-objs := dpu-constframe.o dpu-core.o dpu-crtc.o \ | ||
dpu-disengcfg.o dpu-dprc.o dpu-drv.o dpu-extdst.o \ | ||
dpu-fetchdecode.o dpu-fetcheco.o dpu-fetchlayer.o \ | ||
dpu-fetchwarp.o dpu-fetchunit.o dpu-framegen.o \ | ||
dpu-gammacor.o dpu-hscaler.o dpu-kms.o dpu-layerblend.o \ | ||
dpu-plane.o dpu-prg.o dpu-tcon.o dpu-vscaler.o | ||
|
||
obj-$(CONFIG_DRM_IMX_DPU) += imx-dpu-drm.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
// SPDX-License-Identifier: GPL-2.0+ | ||
|
||
/* | ||
* Copyright (C) 2016 Freescale Semiconductor, Inc. | ||
* Copyright 2017-2020 NXP | ||
*/ | ||
|
||
#include <linux/io.h> | ||
#include <linux/kernel.h> | ||
#include <linux/mutex.h> | ||
#include <linux/sizes.h> | ||
|
||
#include "dpu-prv.h" | ||
|
||
#define STATICCONTROL 0x8 | ||
|
||
#define FRAMEDIMENSIONS 0xc | ||
#define WIDTH(w) (((w) - 1) & 0x3fff) | ||
#define HEIGHT(h) ((((h) - 1) & 0x3fff) << 16) | ||
|
||
#define CONSTANTCOLOR 0x10 | ||
#define RED(r) (((r) & 0xff) << 24) | ||
#define GREEN(g) (((g) & 0xff) << 16) | ||
#define BLUE(b) (((b) & 0xff) << 8) | ||
#define ALPHA(a) ((a) & 0xff) | ||
|
||
struct dpu_constframe { | ||
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_cf_link_id[] = {LINK_ID_CONSTFRAME0, LINK_ID_CONSTFRAME1, | ||
LINK_ID_CONSTFRAME4, LINK_ID_CONSTFRAME5}; | ||
|
||
static inline void dpu_cf_write(struct dpu_constframe *cf, | ||
unsigned int offset, u32 value) | ||
{ | ||
writel(value, cf->base + offset); | ||
} | ||
|
||
static void dpu_cf_enable_shden(struct dpu_constframe *cf) | ||
{ | ||
dpu_cf_write(cf, STATICCONTROL, SHDEN); | ||
} | ||
|
||
enum dpu_link_id dpu_cf_get_link_id(struct dpu_constframe *cf) | ||
{ | ||
return cf->link_id; | ||
} | ||
|
||
void dpu_cf_framedimensions(struct dpu_constframe *cf, unsigned int w, | ||
unsigned int h) | ||
{ | ||
dpu_cf_write(cf, FRAMEDIMENSIONS, WIDTH(w) | HEIGHT(h)); | ||
} | ||
|
||
void dpu_cf_constantcolor_black(struct dpu_constframe *cf) | ||
{ | ||
dpu_cf_write(cf, CONSTANTCOLOR, 0); | ||
} | ||
|
||
void dpu_cf_constantcolor_blue(struct dpu_constframe *cf) | ||
{ | ||
dpu_cf_write(cf, CONSTANTCOLOR, BLUE(0xff)); | ||
} | ||
|
||
static struct dpu_constframe *dpu_cf_get(struct dpu_soc *dpu, unsigned int id) | ||
{ | ||
struct dpu_constframe *cf; | ||
int i; | ||
|
||
for (i = 0; i < ARRAY_SIZE(dpu->cf_priv); i++) { | ||
cf = dpu->cf_priv[i]; | ||
if (cf->id == id) | ||
break; | ||
} | ||
|
||
if (i == ARRAY_SIZE(dpu->cf_priv)) | ||
return ERR_PTR(-EINVAL); | ||
|
||
mutex_lock(&cf->mutex); | ||
|
||
if (cf->inuse) { | ||
mutex_unlock(&cf->mutex); | ||
return ERR_PTR(-EBUSY); | ||
} | ||
|
||
cf->inuse = true; | ||
|
||
mutex_unlock(&cf->mutex); | ||
|
||
return cf; | ||
} | ||
|
||
static void dpu_cf_put(struct dpu_constframe *cf) | ||
{ | ||
mutex_lock(&cf->mutex); | ||
|
||
cf->inuse = false; | ||
|
||
mutex_unlock(&cf->mutex); | ||
} | ||
|
||
/* ConstFrame for safety stream */ | ||
struct dpu_constframe *dpu_cf_safe_get(struct dpu_soc *dpu, | ||
unsigned int stream_id) | ||
{ | ||
return dpu_cf_get(dpu, stream_id + DPU_SAFETY_STREAM_OFFSET); | ||
} | ||
|
||
void dpu_cf_safe_put(struct dpu_constframe *cf) | ||
{ | ||
return dpu_cf_put(cf); | ||
} | ||
|
||
/* ConstFrame for content stream */ | ||
struct dpu_constframe *dpu_cf_cont_get(struct dpu_soc *dpu, | ||
unsigned int stream_id) | ||
{ | ||
return dpu_cf_get(dpu, stream_id); | ||
} | ||
|
||
void dpu_cf_cont_put(struct dpu_constframe *cf) | ||
{ | ||
return dpu_cf_put(cf); | ||
} | ||
|
||
void dpu_cf_hw_init(struct dpu_soc *dpu, unsigned int index) | ||
{ | ||
struct dpu_constframe *cf = dpu->cf_priv[index]; | ||
|
||
dpu_cf_enable_shden(cf); | ||
} | ||
|
||
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) | ||
{ | ||
struct dpu_constframe *cf; | ||
|
||
cf = devm_kzalloc(dpu->dev, sizeof(*cf), GFP_KERNEL); | ||
if (!cf) | ||
return -ENOMEM; | ||
|
||
dpu->cf_priv[index] = cf; | ||
|
||
cf->pec_base = devm_ioremap(dpu->dev, pec_base, SZ_16); | ||
if (!cf->pec_base) | ||
return -ENOMEM; | ||
|
||
cf->base = devm_ioremap(dpu->dev, base, SZ_32); | ||
if (!cf->base) | ||
return -ENOMEM; | ||
|
||
cf->dpu = dpu; | ||
cf->id = id; | ||
cf->index = index; | ||
cf->link_id = dpu_cf_link_id[index]; | ||
|
||
mutex_init(&cf->mutex); | ||
|
||
return 0; | ||
} |
Oops, something went wrong.