Commit cd907bf0 authored by Guido Gunther's avatar Guido Gunther

gpu: imx: Drop dpu only present in i.MX8Q*

Signed-off-by: Guido Gunther's avatarGuido Günther <guido.gunther@puri.sm>
parent 25a8cc5f
......@@ -8,6 +8,5 @@ config IMX8_DPRC
default y if IMX_DPU_CORE=y
default m if IMX_DPU_CORE=m
source drivers/gpu/imx/dpu/Kconfig
source drivers/gpu/imx/dpu-blit/Kconfig
source drivers/gpu/imx/dcss/Kconfig
obj-$(CONFIG_IMX8_PRG) += imx8_prg.o
obj-$(CONFIG_IMX8_DPRC) += imx8_dprc.o
obj-$(CONFIG_IMX_DPU_CORE) += dpu/
obj-$(CONFIG_IMX_DPU_BLIT) += dpu-blit/
obj-$(CONFIG_IMX_DCSS_CORE) += dcss/
config IMX_DPU_CORE
tristate "i.MX DPU core support"
depends on ARCH_FSL_IMX8QM || ARCH_FSL_IMX8QXP
depends on RESET_CONTROLLER
select GENERIC_IRQ_CHIP
select IMX8_PRG
select IMX8_DPRC
help
Choose this if you have a Freescale i.MX8QM or i.MX8QXP system and
want to use the Display Processing Unit. This option only enables
DPU base support.
obj-$(CONFIG_IMX_DPU_CORE) += imx-dpu-core.o
imx-dpu-core-objs := dpu-common.o dpu-constframe.o dpu-disengcfg.o \
dpu-extdst.o dpu-fetchdecode.o dpu-fetcheco.o \
dpu-framegen.o dpu-fetchlayer.o dpu-hscaler.o \
dpu-layerblend.o dpu-tcon.o dpu-vscaler.o
This diff is collapsed.
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <video/dpu.h>
#include "dpu-prv.h"
static unsigned int safety_stream_cf_color = 0x0;
module_param(safety_stream_cf_color, uint, 0444);
MODULE_PARM_DESC(safety_stream_cf_color,
"Safety stream constframe color in hex(0xRRGGBBAA) [default=0x00000000]");
#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)
#define CONTROLTRIGGER 0x14
#define START 0x18
#define STATUS 0x1C
static const shadow_load_req_t cf_shdlreqs[] = {
SHLDREQID_CONSTFRAME0, SHLDREQID_CONSTFRAME1,
SHLDREQID_CONSTFRAME4, SHLDREQID_CONSTFRAME5,
};
struct dpu_constframe {
void __iomem *pec_base;
void __iomem *base;
struct mutex mutex;
int id;
bool inuse;
struct dpu_soc *dpu;
shadow_load_req_t shdlreq;
};
static inline void dpu_cf_write(struct dpu_constframe *cf, u32 value,
unsigned int offset)
{
writel(value, cf->base + offset);
}
void constframe_shden(struct dpu_constframe *cf, bool enable)
{
u32 val;
val = enable ? SHDEN : 0;
mutex_lock(&cf->mutex);
dpu_cf_write(cf, val, STATICCONTROL);
mutex_unlock(&cf->mutex);
}
EXPORT_SYMBOL_GPL(constframe_shden);
void constframe_framedimensions(struct dpu_constframe *cf, unsigned int w,
unsigned int h)
{
u32 val;
val = WIDTH(w) | HEIGHT(h);
mutex_lock(&cf->mutex);
dpu_cf_write(cf, val, FRAMEDIMENSIONS);
mutex_unlock(&cf->mutex);
}
EXPORT_SYMBOL_GPL(constframe_framedimensions);
void constframe_constantcolor(struct dpu_constframe *cf, unsigned int r,
unsigned int g, unsigned int b, unsigned int a)
{
u32 val;
val = RED(r) | GREEN(g) | BLUE(b) | ALPHA(a);
mutex_lock(&cf->mutex);
dpu_cf_write(cf, val, CONSTANTCOLOR);
mutex_unlock(&cf->mutex);
}
EXPORT_SYMBOL_GPL(constframe_constantcolor);
void constframe_controltrigger(struct dpu_constframe *cf, bool trigger)
{
u32 val;
val = trigger ? SHDTOKGEN : 0;
mutex_lock(&cf->mutex);
dpu_cf_write(cf, val, CONTROLTRIGGER);
mutex_unlock(&cf->mutex);
}
EXPORT_SYMBOL_GPL(constframe_controltrigger);
shadow_load_req_t constframe_to_shdldreq_t(struct dpu_constframe *cf)
{
shadow_load_req_t t = 0;
switch (cf->id) {
case 0:
t = SHLDREQID_CONSTFRAME0;
break;
case 1:
t = SHLDREQID_CONSTFRAME1;
break;
case 4:
t = SHLDREQID_CONSTFRAME4;
break;
case 5:
t = SHLDREQID_CONSTFRAME5;
break;
}
return t;
}
EXPORT_SYMBOL_GPL(constframe_to_shdldreq_t);
struct dpu_constframe *dpu_cf_get(struct dpu_soc *dpu, int id)
{
struct dpu_constframe *cf;
int i;
for (i = 0; i < ARRAY_SIZE(cf_ids); i++)
if (cf_ids[i] == id)
break;
if (i == ARRAY_SIZE(cf_ids))
return ERR_PTR(-EINVAL);
cf = dpu->cf_priv[i];
mutex_lock(&cf->mutex);
if (cf->inuse) {
cf = ERR_PTR(-EBUSY);
goto out;
}
cf->inuse = true;
out:
mutex_unlock(&cf->mutex);
return cf;
}
EXPORT_SYMBOL_GPL(dpu_cf_get);
void dpu_cf_put(struct dpu_constframe *cf)
{
mutex_lock(&cf->mutex);
cf->inuse = false;
mutex_unlock(&cf->mutex);
}
EXPORT_SYMBOL_GPL(dpu_cf_put);
void _dpu_cf_init(struct dpu_soc *dpu, unsigned int id)
{
struct dpu_constframe *cf;
int i;
for (i = 0; i < ARRAY_SIZE(cf_ids); i++)
if (cf_ids[i] == id)
break;
if (WARN_ON(i == ARRAY_SIZE(cf_ids)))
return;
cf = dpu->cf_priv[i];
constframe_shden(cf, true);
if (id == 4 || id == 5) {
mutex_lock(&cf->mutex);
dpu_cf_write(cf, safety_stream_cf_color, CONSTANTCOLOR);
mutex_unlock(&cf->mutex);
}
}
int dpu_cf_init(struct dpu_soc *dpu, unsigned int id,
unsigned long pec_base, unsigned long base)
{
struct dpu_constframe *cf;
int i;
cf = devm_kzalloc(dpu->dev, sizeof(*cf), GFP_KERNEL);
if (!cf)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(cf_ids); i++)
if (cf_ids[i] == id)
break;
dpu->cf_priv[i] = 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->shdlreq = cf_shdlreqs[i];
mutex_init(&cf->mutex);
_dpu_cf_init(dpu, id);
return 0;
}
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <drm/drm_mode.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include "dpu-prv.h"
#define CLOCKCTRL 0x8
typedef enum {
DSPCLKDIVIDE__DIV1, /* Ext disp clk signal has pix clk freq. */
DSPCLKDIVIDE__DIV2, /* Ext disp clk signal has 2x the pix clk freq. */
} clkdivide_t;
#define POLARITYCTRL 0xC
#define POLHS_HIGH BIT(0)
#define POLVS_HIGH BIT(1)
#define POLEN_HIGH BIT(2)
#define PIXINV_INV BIT(3)
#define SRCSELECT 0x10
struct dpu_disengcfg {
void __iomem *base;
struct mutex mutex;
int id;
bool inuse;
struct dpu_soc *dpu;
};
static inline u32 dpu_dec_read(struct dpu_disengcfg *dec, unsigned int offset)
{
return readl(dec->base + offset);
}
static inline void dpu_dec_write(struct dpu_disengcfg *dec, u32 value,
unsigned int offset)
{
writel(value, dec->base + offset);
}
void disengcfg_polarity_ctrl(struct dpu_disengcfg *dec, unsigned int flags)
{
const struct dpu_devtype *devtype = dec->dpu->devtype;
u32 val;
mutex_lock(&dec->mutex);
val = dpu_dec_read(dec, POLARITYCTRL);
if (devtype->pixel_link_nhvsync) {
val &= ~POLHS_HIGH;
val &= ~POLVS_HIGH;
} else {
if (flags & DRM_MODE_FLAG_PHSYNC)
val |= POLHS_HIGH;
if (flags & DRM_MODE_FLAG_NHSYNC)
val &= ~POLHS_HIGH;
if (flags & DRM_MODE_FLAG_PVSYNC)
val |= POLVS_HIGH;
if (flags & DRM_MODE_FLAG_NVSYNC)
val &= ~POLVS_HIGH;
}
dpu_dec_write(dec, val, POLARITYCTRL);
mutex_unlock(&dec->mutex);
}
EXPORT_SYMBOL_GPL(disengcfg_polarity_ctrl);
struct dpu_disengcfg *dpu_dec_get(struct dpu_soc *dpu, int id)
{
struct dpu_disengcfg *dec;
int i;
for (i = 0; i < ARRAY_SIZE(dec_ids); i++)
if (dec_ids[i] == id)
break;
if (i == ARRAY_SIZE(dec_ids))
return ERR_PTR(-EINVAL);
dec = dpu->dec_priv[i];
mutex_lock(&dec->mutex);
if (dec->inuse) {
dec = ERR_PTR(-EBUSY);
goto out;
}
dec->inuse = true;
out:
mutex_unlock(&dec->mutex);
return dec;
}
EXPORT_SYMBOL_GPL(dpu_dec_get);
void dpu_dec_put(struct dpu_disengcfg *dec)
{
mutex_lock(&dec->mutex);
dec->inuse = false;
mutex_unlock(&dec->mutex);
}
EXPORT_SYMBOL_GPL(dpu_dec_put);
void _dpu_dec_init(struct dpu_soc *dpu, unsigned int id)
{
}
int dpu_dec_init(struct dpu_soc *dpu, unsigned int id,
unsigned long unused, unsigned long base)
{
struct dpu_disengcfg *dec;
dec = devm_kzalloc(dpu->dev, sizeof(*dec), GFP_KERNEL);
if (!dec)
return -ENOMEM;
dpu->dec_priv[id] = dec;
dec->base = devm_ioremap(dpu->dev, base, SZ_16);
if (!dec->base)
return -ENOMEM;
dec->dpu = dpu;
dec->id = id;
mutex_init(&dec->mutex);
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <video/dpu.h>
#include "dpu-prv.h"
#define PIXENGCFG_STATUS 0x8
#define BASEADDRESS(n) (0x10 + (n) * 0x28)
#define SOURCEBUFFERATTRIBUTES(n) (0x14 + (n) * 0x28)
#define SOURCEBUFFERDIMENSION(n) (0x18 + (n) * 0x28)
#define COLORCOMPONENTBITS(n) (0x1C + (n) * 0x28)
#define COLORCOMPONENTSHIFT(n) (0x20 + (n) * 0x28)
#define LAYEROFFSET(n) (0x24 + (n) * 0x28)
#define CLIPWINDOWOFFSET(n) (0x28 + (n) * 0x28)
#define CLIPWINDOWDIMENSIONS(n) (0x2C + (n) * 0x28)
#define CONSTANTCOLOR(n) (0x30 + (n) * 0x28)
#define LAYERPROPERTY(n) (0x34 + (n) * 0x28)
#define FRAMEDIMENSIONS 0x150
#define FRAMERESAMPLING 0x154
#define CONTROL 0x158
#define TRIGGERENABLE 0x15C
#define SHDLDREQ(lm) ((lm) & 0xFF)
#define CONTROLTRIGGER 0x160
#define START 0x164
#define FETCHTYPE 0x168
#define BURSTBUFFERPROPERTIES 0x16C
#define STATUS 0x170
#define HIDDENSTATUS 0x174
static const shadow_load_req_t fl_shdlreqs[] = {
SHLDREQID_FETCHLAYER0, SHLDREQID_FETCHLAYER1,
};
struct dpu_fetchlayer {
void __iomem *pec_base;
void __iomem *base;
struct mutex mutex;
int id;
bool inuse;
struct dpu_soc *dpu;
fetchtype_t fetchtype;
shadow_load_req_t shdlreq;
};
static inline u32 dpu_fl_read(struct dpu_fetchlayer *fl, unsigned int offset)
{
return readl(fl->base + offset);
}
static inline void dpu_fl_write(struct dpu_fetchlayer *fl, u32 value,
unsigned int offset)
{
writel(value, fl->base + offset);
}
static inline u32 rgb_color(u8 r, u8 g, u8 b, u8 a)
{
return (r << 24) | (g << 16) | (b << 8) | a;
}
static inline u32 yuv_color(u8 y, u8 u, u8 v)
{
return (y << 24) | (u << 16) | (v << 8);
}
void fetchlayer_shden(struct dpu_fetchlayer *fl, bool enable)
{
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, STATICCONTROL);
if (enable)
val |= SHDEN;
else
val &= ~SHDEN;
dpu_fl_write(fl, val, STATICCONTROL);
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_shden);
void fetchlayer_baddr_autoupdate(struct dpu_fetchlayer *fl, u8 layer_mask)
{
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, STATICCONTROL);
val &= ~BASEADDRESSAUTOUPDATE_MASK;
val |= BASEADDRESSAUTOUPDATE(layer_mask);
dpu_fl_write(fl, val, STATICCONTROL);
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_baddr_autoupdate);
void fetchlayer_framedimensions(struct dpu_fetchlayer *fl, unsigned int w,
unsigned int h)
{
u32 val;
val = FRAMEWIDTH(w) | FRAMEHEIGHT(h);
mutex_lock(&fl->mutex);
dpu_fl_write(fl, val, FRAMEDIMENSIONS);
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_framedimensions);
void fetchlayer_rgb_constantcolor(struct dpu_fetchlayer *fl,
u8 r, u8 g, u8 b, u8 a)
{
u32 val;
val = rgb_color(r, g, b, a);
mutex_lock(&fl->mutex);
dpu_fl_write(fl, val, CONSTANTCOLOR(fl->id));
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_rgb_constantcolor);
void fetchlayer_yuv_constantcolor(struct dpu_fetchlayer *fl, u8 y, u8 u, u8 v)
{
u32 val;
val = yuv_color(y, u, v);
mutex_lock(&fl->mutex);
dpu_fl_write(fl, val, CONSTANTCOLOR(fl->id));
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_yuv_constantcolor);
void fetchlayer_controltrigger(struct dpu_fetchlayer *fl, bool trigger)
{
u32 val;
val = trigger ? SHDTOKGEN : 0;
mutex_lock(&fl->mutex);
dpu_fl_write(fl, val, CONTROLTRIGGER);
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(fetchlayer_controltrigger);
int fetchlayer_fetchtype(struct dpu_fetchlayer *fl, fetchtype_t *type)
{
struct dpu_soc *dpu = fl->dpu;
u32 val;
mutex_lock(&fl->mutex);
val = dpu_fl_read(fl, FETCHTYPE);
val &= FETCHTYPE_MASK;
mutex_unlock(&fl->mutex);
switch (val) {
case FETCHTYPE__DECODE:
dev_dbg(dpu->dev, "FetchLayer%d with RL and RLAD decoder\n",
fl->id);
break;
case FETCHTYPE__LAYER:
dev_dbg(dpu->dev, "FetchLayer%d with fractional "
"plane(8 layers)\n", fl->id);
break;
case FETCHTYPE__WARP:
dev_dbg(dpu->dev, "FetchLayer%d with arbitrary warping and "
"fractional plane(8 layers)\n", fl->id);
break;
case FETCHTYPE__ECO:
dev_dbg(dpu->dev, "FetchLayer%d with minimum feature set for "
"alpha, chroma and coordinate planes\n",
fl->id);
break;
case FETCHTYPE__PERSP:
dev_dbg(dpu->dev, "FetchLayer%d with affine, perspective and "
"arbitrary warping\n", fl->id);
break;
case FETCHTYPE__ROT:
dev_dbg(dpu->dev, "FetchLayer%d with affine and arbitrary "
"warping\n", fl->id);
break;
case FETCHTYPE__DECODEL:
dev_dbg(dpu->dev, "FetchLayer%d with RL and RLAD decoder, "
"reduced feature set\n", fl->id);
break;
case FETCHTYPE__LAYERL:
dev_dbg(dpu->dev, "FetchLayer%d with fractional "
"plane(8 layers), reduced feature set\n",
fl->id);
break;
case FETCHTYPE__ROTL:
dev_dbg(dpu->dev, "FetchLayer%d with affine and arbitrary "
"warping, reduced feature set\n", fl->id);
break;
default:
dev_warn(dpu->dev, "Invalid fetch type %u for FetchLayer%d\n",
val, fl->id);
return -EINVAL;
}
*type = val;
return 0;
}
EXPORT_SYMBOL_GPL(fetchlayer_fetchtype);
struct dpu_fetchlayer *dpu_fl_get(struct dpu_soc *dpu, int id)
{
struct dpu_fetchlayer *fl;
int i;
for (i = 0; i < ARRAY_SIZE(fl_ids); i++)
if (fl_ids[i] == id)
break;
if (i == ARRAY_SIZE(fl_ids))
return ERR_PTR(-EINVAL);
fl = dpu->fl_priv[i];
mutex_lock(&fl->mutex);
if (fl->inuse) {
fl = ERR_PTR(-EBUSY);
goto out;
}
fl->inuse = true;
out:
mutex_unlock(&fl->mutex);
return fl;
}
EXPORT_SYMBOL_GPL(dpu_fl_get);
void dpu_fl_put(struct dpu_fetchlayer *fl)
{
mutex_lock(&fl->mutex);
fl->inuse = false;
mutex_unlock(&fl->mutex);
}
EXPORT_SYMBOL_GPL(dpu_fl_put);
void _dpu_fl_init(struct dpu_soc *dpu, unsigned int id)
{
}
int dpu_fl_init(struct dpu_soc *dpu, unsigned int id,
unsigned long pec_base, unsigned long base)
{
struct dpu_fetchlayer *fl;
int ret, i;
fl = devm_kzalloc(dpu->dev, sizeof(*fl), GFP_KERNEL);
if (!fl)
return -ENOMEM;
dpu->fl_priv[id] = fl;
fl->pec_base = devm_ioremap(dpu->dev, base, SZ_16);
if (!fl->pec_base)
return -ENOMEM;
fl->base = devm_ioremap(dpu->dev, base, SZ_512);
if (!fl->base)
return -ENOMEM;
fl->dpu = dpu;
fl->id = id;
for (i = 0; i < ARRAY_SIZE(fl_ids); i++) {
if (fl_ids[i] == id) {
fl->shdlreq = fl_shdlreqs[i];
break;
}
}
mutex_init(&fl->mutex);
ret = fetchlayer_fetchtype(fl, &fl->fetchtype);
if (ret < 0)
return ret;
return 0;
}
This diff is collapsed.
/*
* Copyright 2017 NXP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.