summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/imx/dpu/Makefile3
-rw-r--r--drivers/gpu/imx/dpu/dpu-common.c44
-rw-r--r--drivers/gpu/imx/dpu/dpu-prv.h13
-rw-r--r--drivers/gpu/imx/dpu/dpu-signature.c392
-rw-r--r--include/video/dpu.h37
5 files changed, 487 insertions, 2 deletions
diff --git a/drivers/gpu/imx/dpu/Makefile b/drivers/gpu/imx/dpu/Makefile
index 569ef08c5751..5b568e998d7e 100644
--- a/drivers/gpu/imx/dpu/Makefile
+++ b/drivers/gpu/imx/dpu/Makefile
@@ -4,4 +4,5 @@ imx-dpu-core-objs := dpu-common.o dpu-constframe.o dpu-disengcfg.o \
dpu-extdst.o dpu-fetchdecode.o dpu-fetcheco.o \
dpu-fetchlayer.o dpu-fetchwarp.o dpu-fetchunit.o \
dpu-framegen.o dpu-hscaler.o dpu-layerblend.o \
- dpu-sc-misc.o dpu-store.o dpu-tcon.o dpu-vscaler.o
+ dpu-sc-misc.o dpu-signature.o dpu-store.o dpu-tcon.o \
+ dpu-vscaler.o
diff --git a/drivers/gpu/imx/dpu/dpu-common.c b/drivers/gpu/imx/dpu/dpu-common.c
index 7d0395b166f9..9fdf9fd06663 100644
--- a/drivers/gpu/imx/dpu/dpu-common.c
+++ b/drivers/gpu/imx/dpu/dpu-common.c
@@ -111,6 +111,9 @@ static const unsigned long hs_pec_ofss[] = {0xb00, 0xb60, 0x8c0};
static const unsigned long lb_ofss[] = {0xa400, 0xa800, 0xac00, 0xb000};
static const unsigned long lb_pec_ofss[] = {0xba0, 0xbc0, 0xbe0, 0xc00};
+/* Signature Unit */
+static const unsigned long sig_ofss[] = {0xd000, 0xec00};
+
/* Store Unit */
static const unsigned long st_ofss[] = {0x4000};
static const unsigned long st_pec_ofss[] = {0x940};
@@ -205,6 +208,14 @@ static const struct dpu_unit _lbs = {
.ofss = lb_ofss,
};
+static const struct dpu_unit _sigs = {
+ .name = "Signature",
+ .num = ARRAY_SIZE(sig_ids),
+ .ids = sig_ids,
+ .pec_ofss = NULL,
+ .ofss = sig_ofss,
+};
+
static const struct dpu_unit _sts = {
.name = "Store",
.num = ARRAY_SIZE(st_ids),
@@ -259,6 +270,7 @@ static const struct dpu_data dpu_data_qxp = {
.fws = &_fws,
.hss = &_hss,
.lbs = &_lbs,
+ .sigs = &_sigs,
.sts = &_sts,
.tcons = &_tcons,
.vss = &_vss,
@@ -283,6 +295,7 @@ static const struct dpu_data dpu_data_qm = {
.fws = &_fws,
.hss = &_hss,
.lbs = &_lbs,
+ .sigs = &_sigs,
.sts = &_sts,
.tcons = &_tcons,
.vss = &_vss,
@@ -540,6 +553,7 @@ static void dpu_units_addr_dbg(struct dpu_soc *dpu,
DPU_UNITS_ADDR_DBG(fw);
DPU_UNITS_ADDR_DBG(hs);
DPU_UNITS_ADDR_DBG(lb);
+ DPU_UNITS_ADDR_DBG(sig);
DPU_UNITS_ADDR_DBG(st);
DPU_UNITS_ADDR_DBG(tcon);
DPU_UNITS_ADDR_DBG(vs);
@@ -563,8 +577,12 @@ static int dpu_get_irq(struct platform_device *pdev, struct dpu_soc *dpu)
DPU_GET_IRQ(extdst5_shdload);
DPU_GET_IRQ(disengcfg_shdload0);
DPU_GET_IRQ(disengcfg_framecomplete0);
+ DPU_GET_IRQ(sig0_shdload);
+ DPU_GET_IRQ(sig0_valid);
DPU_GET_IRQ(disengcfg_shdload1);
DPU_GET_IRQ(disengcfg_framecomplete1);
+ DPU_GET_IRQ(sig1_shdload);
+ DPU_GET_IRQ(sig1_valid);
return 0;
}
@@ -604,8 +622,12 @@ DPU_IRQ_HANDLER_DEFINE(extdst1_shdload, EXTDST1_SHDLOAD)
DPU_IRQ_HANDLER_DEFINE(extdst5_shdload, EXTDST5_SHDLOAD)
DPU_IRQ_HANDLER_DEFINE(disengcfg_shdload0, DISENGCFG_SHDLOAD0)
DPU_IRQ_HANDLER_DEFINE(disengcfg_framecomplete0, DISENGCFG_FRAMECOMPLETE0)
+DPU_IRQ_HANDLER_DEFINE(sig0_shdload, SIG0_SHDLOAD);
+DPU_IRQ_HANDLER_DEFINE(sig0_valid, SIG0_VALID);
DPU_IRQ_HANDLER_DEFINE(disengcfg_shdload1, DISENGCFG_SHDLOAD1)
DPU_IRQ_HANDLER_DEFINE(disengcfg_framecomplete1, DISENGCFG_FRAMECOMPLETE1)
+DPU_IRQ_HANDLER_DEFINE(sig1_shdload, SIG1_SHDLOAD);
+DPU_IRQ_HANDLER_DEFINE(sig1_valid, SIG1_VALID);
int dpu_map_irq(struct dpu_soc *dpu, int irq)
{
@@ -675,8 +697,12 @@ irq_set_chained_handler_and_data(dpu->irq_##name, dpu_##name##_irq_handler, dpu)
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(extdst5_shdload);
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(disengcfg_shdload0);
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(disengcfg_framecomplete0);
+ DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(sig0_shdload);
+ DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(sig0_valid);
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(disengcfg_shdload1);
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(disengcfg_framecomplete1);
+ DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(sig1_shdload);
+ DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA1(sig1_valid);
#define DPU_IRQ_CHIP_PM_GET(name) \
{ \
@@ -704,8 +730,12 @@ irq_set_chained_handler_and_data(dpu->irq_##name, dpu_##name##_irq_handler, dpu)
DPU_IRQ_CHIP_PM_GET(extdst5_shdload);
DPU_IRQ_CHIP_PM_GET(disengcfg_shdload0);
DPU_IRQ_CHIP_PM_GET(disengcfg_framecomplete0);
+ DPU_IRQ_CHIP_PM_GET(sig0_shdload);
+ DPU_IRQ_CHIP_PM_GET(sig0_valid);
DPU_IRQ_CHIP_PM_GET(disengcfg_shdload1);
DPU_IRQ_CHIP_PM_GET(disengcfg_framecomplete1);
+ DPU_IRQ_CHIP_PM_GET(sig1_shdload);
+ DPU_IRQ_CHIP_PM_GET(sig1_valid);
return 0;
@@ -716,8 +746,12 @@ pm_get_rollback:
DPU_IRQ_CHIP_PM_PUT_CHECK(extdst5_shdload);
DPU_IRQ_CHIP_PM_PUT_CHECK(disengcfg_shdload0);
DPU_IRQ_CHIP_PM_PUT_CHECK(disengcfg_framecomplete0);
+ DPU_IRQ_CHIP_PM_PUT_CHECK(sig0_shdload);
+ DPU_IRQ_CHIP_PM_PUT_CHECK(sig0_valid);
DPU_IRQ_CHIP_PM_PUT_CHECK(disengcfg_shdload1);
DPU_IRQ_CHIP_PM_PUT_CHECK(disengcfg_framecomplete1);
+ DPU_IRQ_CHIP_PM_PUT_CHECK(sig1_shdload);
+ DPU_IRQ_CHIP_PM_PUT_CHECK(sig1_valid);
return ret;
}
@@ -738,8 +772,12 @@ static void dpu_irq_exit(struct dpu_soc *dpu)
DPU_IRQ_CHIP_PM_PUT(extdst5_shdload);
DPU_IRQ_CHIP_PM_PUT(disengcfg_shdload0);
DPU_IRQ_CHIP_PM_PUT(disengcfg_framecomplete0);
+ DPU_IRQ_CHIP_PM_PUT(sig0_shdload);
+ DPU_IRQ_CHIP_PM_PUT(sig0_valid);
DPU_IRQ_CHIP_PM_PUT(disengcfg_shdload1);
DPU_IRQ_CHIP_PM_PUT(disengcfg_framecomplete1);
+ DPU_IRQ_CHIP_PM_PUT(sig1_shdload);
+ DPU_IRQ_CHIP_PM_PUT(sig1_valid);
#define DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(name) \
irq_set_chained_handler_and_data(dpu->irq_##name, NULL, NULL)
@@ -750,8 +788,12 @@ irq_set_chained_handler_and_data(dpu->irq_##name, NULL, NULL)
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(extdst5_shdload);
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(disengcfg_shdload0);
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(disengcfg_framecomplete0);
+ DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(sig0_shdload);
+ DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(sig0_valid);
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(disengcfg_shdload1);
DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(disengcfg_framecomplete1);
+ DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(sig1_shdload);
+ DPU_IRQ_SET_CHAINED_HANDLER_AND_DATA2(sig1_valid);
for (i = 0; i < dpu->irq_line_num; i++) {
irq = irq_linear_revmap(dpu->domain, i);
@@ -790,6 +832,7 @@ _dpu_submodules_init(struct dpu_soc *dpu, struct platform_device *pdev)
_DPU_UNITS_INIT(fw);
_DPU_UNITS_INIT(hs);
_DPU_UNITS_INIT(lb);
+ _DPU_UNITS_INIT(sig);
_DPU_UNITS_INIT(st);
_DPU_UNITS_INIT(tcon);
_DPU_UNITS_INIT(vs);
@@ -850,6 +893,7 @@ static int dpu_submodules_init(struct dpu_soc *dpu,
DPU_UNITS_INIT(fw);
DPU_UNITS_INIT(hs);
DPU_UNITS_INIT(lb);
+ DPU_UNITS_INIT(sig);
DPU_UNITS_INIT(st);
DPU_UNITS_INIT(tcon);
DPU_UNITS_INIT(vs);
diff --git a/drivers/gpu/imx/dpu/dpu-prv.h b/drivers/gpu/imx/dpu/dpu-prv.h
index 90a8447f33b1..2c1b5a39ac05 100644
--- a/drivers/gpu/imx/dpu/dpu-prv.h
+++ b/drivers/gpu/imx/dpu/dpu-prv.h
@@ -194,6 +194,7 @@ struct dpu_data {
const struct dpu_unit *fws;
const struct dpu_unit *hss;
const struct dpu_unit *lbs;
+ const struct dpu_unit *sigs;
const struct dpu_unit *sts;
const struct dpu_unit *tcons;
const struct dpu_unit *vss;
@@ -233,8 +234,12 @@ struct dpu_soc {
int irq_extdst5_shdload;
int irq_disengcfg_shdload0;
int irq_disengcfg_framecomplete0;
+ int irq_sig0_shdload;
+ int irq_sig0_valid;
int irq_disengcfg_shdload1;
int irq_disengcfg_framecomplete1;
+ int irq_sig1_shdload;
+ int irq_sig1_valid;
int irq_line_num;
bool irq_chip_pm_get_extdst0_shdload;
@@ -243,8 +248,12 @@ struct dpu_soc {
bool irq_chip_pm_get_extdst5_shdload;
bool irq_chip_pm_get_disengcfg_shdload0;
bool irq_chip_pm_get_disengcfg_framecomplete0;
+ bool irq_chip_pm_get_sig0_shdload;
+ bool irq_chip_pm_get_sig0_valid;
bool irq_chip_pm_get_disengcfg_shdload1;
bool irq_chip_pm_get_disengcfg_framecomplete1;
+ bool irq_chip_pm_get_sig1_shdload;
+ bool irq_chip_pm_get_sig1_valid;
struct irq_domain *domain;
@@ -260,6 +269,7 @@ struct dpu_soc {
struct dpu_fetchunit *fw_priv[1];
struct dpu_hscaler *hs_priv[3];
struct dpu_layerblend *lb_priv[4];
+ struct dpu_signature *sig_priv[2];
struct dpu_store *st_priv[1];
struct dpu_tcon *tcon_priv[2];
struct dpu_vscaler *vs_priv[3];
@@ -284,6 +294,7 @@ _DECLARE_DPU_UNIT_INIT_FUNC(fl);
_DECLARE_DPU_UNIT_INIT_FUNC(fw);
_DECLARE_DPU_UNIT_INIT_FUNC(hs);
_DECLARE_DPU_UNIT_INIT_FUNC(lb);
+_DECLARE_DPU_UNIT_INIT_FUNC(sig);
_DECLARE_DPU_UNIT_INIT_FUNC(st);
_DECLARE_DPU_UNIT_INIT_FUNC(tcon);
_DECLARE_DPU_UNIT_INIT_FUNC(vs);
@@ -302,6 +313,7 @@ DECLARE_DPU_UNIT_INIT_FUNC(fl);
DECLARE_DPU_UNIT_INIT_FUNC(fw);
DECLARE_DPU_UNIT_INIT_FUNC(hs);
DECLARE_DPU_UNIT_INIT_FUNC(lb);
+DECLARE_DPU_UNIT_INIT_FUNC(sig);
DECLARE_DPU_UNIT_INIT_FUNC(st);
DECLARE_DPU_UNIT_INIT_FUNC(tcon);
DECLARE_DPU_UNIT_INIT_FUNC(vs);
@@ -350,6 +362,7 @@ static const unsigned int fl_ids[] = {0};
static const unsigned int fw_ids[] = {2};
static const unsigned int hs_ids[] = {4, 5, 9};
static const unsigned int lb_ids[] = {0, 1, 2, 3};
+static const unsigned int sig_ids[] = {0, 1};
static const unsigned int st_ids[] = {9};
static const unsigned int tcon_ids[] = {0, 1};
static const unsigned int vs_ids[] = {4, 5, 9};
diff --git a/drivers/gpu/imx/dpu/dpu-signature.c b/drivers/gpu/imx/dpu/dpu-signature.c
new file mode 100644
index 000000000000..5fca7a1c4343
--- /dev/null
+++ b/drivers/gpu/imx/dpu/dpu-signature.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright 2019,2020 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 "dpu-prv.h"
+
+#define STATICCONTROL 0x8
+#define SHDLDSEL BIT(4)
+#define LOCAL 0
+#define GLOBAL BIT(4)
+#define PANICCOLOR 0xC
+#define EVALCONTRL(n) (0x10 + (n) * 0x24)
+#define ENGLOBALPANIC BIT(17)
+#define ENLOCALPANIC BIT(16)
+#define ALPHAINV BIT(9)
+#define ALPHAMASK BIT(8)
+#define ENCRC BIT(1)
+#define ENEVALWIN BIT(0)
+#define EVALUPPERLEFT(n) (0x14 + (n) * 0x24)
+#define EVALLOWERRIGHT(n) (0x18 + (n) * 0x24)
+#define YEVAL(y) (((y) & 0x3FFF) << 16)
+#define XEVAL(x) ((x) & 0x3FFF)
+#define SIGCRCREDREF(n) (0x1C + (n) * 0x24)
+#define SIGCRCGREENREF(n) (0x20 + (n) * 0x24)
+#define SIGCRCBLUEREF(n) (0x24 + (n) * 0x24)
+#define SIGCRCRED(n) (0x28 + (n) * 0x24)
+#define SIGCRCGREEN(n) (0x2C + (n) * 0x24)
+#define SIGCRCBLUE(n) (0x30 + (n) * 0x24)
+#define SHADOWLOAD 0x130
+#define SHDLDREQ(n) BIT(n)
+#define CONTINUOUSMODE 0x134
+#define ENCONT BIT(0)
+#define SOFTWAREKICK 0x138
+#define KICK BIT(0)
+#define STATUS 0x13C
+#define STSSIGIDLE BIT(20)
+#define STSSIGVALID BIT(16)
+#define STSSIGERROR(n) BIT(n)
+#define STSSIGERROR_MASK 0xFF
+
+struct dpu_signature {
+ void __iomem *base;
+ struct mutex mutex;
+ int id;
+ bool inuse;
+ struct dpu_soc *dpu;
+};
+
+static inline u32 dpu_sig_read(struct dpu_signature *sig, unsigned int offset)
+{
+ return readl(sig->base + offset);
+}
+
+static inline void dpu_sig_write(struct dpu_signature *sig,
+ unsigned int offset, u32 value)
+{
+ writel(value, sig->base + offset);
+}
+
+void signature_shden(struct dpu_signature *sig, bool enable)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, STATICCONTROL);
+ if (enable)
+ val |= SHDEN;
+ else
+ val &= ~SHDEN;
+ dpu_sig_write(sig, STATICCONTROL, val);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_shden);
+
+void signature_shdldsel_local(struct dpu_signature *sig)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, STATICCONTROL);
+ val &= ~GLOBAL;
+ dpu_sig_write(sig, STATICCONTROL, val);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_shdldsel_local);
+
+void signature_shdldsel_global(struct dpu_signature *sig)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, STATICCONTROL);
+ dpu_sig_write(sig, STATICCONTROL, val | GLOBAL);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_shdldsel_global);
+
+void
+signature_global_panic(struct dpu_signature *sig, unsigned int win, bool enable)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, EVALCONTRL(win));
+ if (enable)
+ val |= ENGLOBALPANIC;
+ else
+ val &= ~ENGLOBALPANIC;
+ dpu_sig_write(sig, EVALCONTRL(win), val);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_global_panic);
+
+void
+signature_local_panic(struct dpu_signature *sig, unsigned int win, bool enable)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, EVALCONTRL(win));
+ if (enable)
+ val |= ENLOCALPANIC;
+ else
+ val &= ~ENLOCALPANIC;
+ dpu_sig_write(sig, EVALCONTRL(win), val);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_local_panic);
+
+void
+signature_alpha_mask(struct dpu_signature *sig, unsigned int win, bool enable)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, EVALCONTRL(win));
+ if (enable)
+ val |= ALPHAMASK;
+ else
+ val &= ~ALPHAMASK;
+ dpu_sig_write(sig, EVALCONTRL(win), val);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_alpha_mask);
+
+void signature_crc(struct dpu_signature *sig, unsigned int win, bool enable)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, EVALCONTRL(win));
+ if (enable)
+ val |= ENCRC;
+ else
+ val &= ~ENCRC;
+ dpu_sig_write(sig, EVALCONTRL(win), val);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_crc);
+
+void
+signature_eval_win(struct dpu_signature *sig, unsigned int win, bool enable)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, EVALCONTRL(win));
+ if (enable)
+ val |= ENEVALWIN;
+ else
+ val &= ~ENEVALWIN;
+ dpu_sig_write(sig, EVALCONTRL(win), val);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_eval_win);
+
+void signature_win(struct dpu_signature *sig, unsigned int win,
+ int xul, int yul, int xlr, int ylr)
+{
+ mutex_lock(&sig->mutex);
+ dpu_sig_write(sig, EVALUPPERLEFT(win), XEVAL(xul) | YEVAL(yul));
+ dpu_sig_write(sig, EVALLOWERRIGHT(win), XEVAL(--xlr) | YEVAL(--ylr));
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_win);
+
+void signature_crc_value(struct dpu_signature *sig, unsigned int win,
+ u32 *red, u32 *green, u32 *blue)
+{
+ mutex_lock(&sig->mutex);
+ *red = dpu_sig_read(sig, SIGCRCRED(win));
+ *green = dpu_sig_read(sig, SIGCRCGREEN(win));
+ *blue = dpu_sig_read(sig, SIGCRCBLUE(win));
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_crc_value);
+
+void signature_shdldreq(struct dpu_signature *sig, u8 win_mask)
+{
+ mutex_lock(&sig->mutex);
+ dpu_sig_write(sig, SHADOWLOAD, win_mask);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_shdldreq);
+
+void signature_continuous_mode(struct dpu_signature *sig, bool enable)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, CONTINUOUSMODE);
+ if (enable)
+ val |= ENCONT;
+ else
+ val &= ~ENCONT;
+ dpu_sig_write(sig, CONTINUOUSMODE, val);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_continuous_mode);
+
+void signature_kick(struct dpu_signature *sig)
+{
+ mutex_lock(&sig->mutex);
+ dpu_sig_write(sig, SOFTWAREKICK, KICK);
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(signature_kick);
+
+bool signature_is_idle(struct dpu_signature *sig)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, STATUS);
+ mutex_unlock(&sig->mutex);
+
+ return !!(val & STSSIGIDLE);
+}
+EXPORT_SYMBOL_GPL(signature_is_idle);
+
+void signature_wait_for_idle(struct dpu_signature *sig)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(100);
+ bool idle;
+
+ do {
+ idle = signature_is_idle(sig);
+ } while (!idle && time_before(jiffies, timeout));
+
+ if (idle)
+ dev_dbg(sig->dpu->dev, "Signature%d is idle\n", sig->id);
+ else
+ dev_err(sig->dpu->dev,
+ "failed to wait for Signature%d idle\n", sig->id);
+}
+EXPORT_SYMBOL_GPL(signature_wait_for_idle);
+
+bool signature_is_valid(struct dpu_signature *sig)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, STATUS);
+ mutex_unlock(&sig->mutex);
+
+ return !!(val & STSSIGVALID);
+}
+EXPORT_SYMBOL_GPL(signature_is_valid);
+
+bool signature_is_error(struct dpu_signature *sig, u8 *err_win_mask)
+{
+ u32 val;
+
+ mutex_lock(&sig->mutex);
+ val = dpu_sig_read(sig, STATUS);
+ mutex_unlock(&sig->mutex);
+
+ *err_win_mask = val & STSSIGERROR_MASK;
+
+ return !!(*err_win_mask);
+}
+EXPORT_SYMBOL_GPL(signature_is_error);
+
+struct dpu_signature *dpu_sig_get(struct dpu_soc *dpu, int id)
+{
+ struct dpu_signature *sig;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sig_ids); i++)
+ if (sig_ids[i] == id)
+ break;
+
+ if (i == ARRAY_SIZE(sig_ids))
+ return ERR_PTR(-EINVAL);
+
+ sig = dpu->sig_priv[i];
+
+ mutex_lock(&sig->mutex);
+
+ if (sig->inuse) {
+ mutex_unlock(&sig->mutex);
+ return ERR_PTR(-EBUSY);
+ }
+
+ sig->inuse = true;
+
+ mutex_unlock(&sig->mutex);
+
+ return sig;
+}
+EXPORT_SYMBOL_GPL(dpu_sig_get);
+
+void dpu_sig_put(struct dpu_signature *sig)
+{
+ mutex_lock(&sig->mutex);
+
+ sig->inuse = false;
+
+ mutex_unlock(&sig->mutex);
+}
+EXPORT_SYMBOL_GPL(dpu_sig_put);
+
+struct dpu_signature *dpu_aux_sig_peek(struct dpu_signature *sig)
+{
+ return sig->dpu->sig_priv[sig->id ^ 1];
+}
+EXPORT_SYMBOL_GPL(dpu_aux_sig_peek);
+
+void _dpu_sig_init(struct dpu_soc *dpu, unsigned int id)
+{
+ struct dpu_signature *sig;
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(sig_ids); i++)
+ if (sig_ids[i] == id)
+ break;
+
+ if (WARN_ON(i == ARRAY_SIZE(sig_ids)))
+ return;
+
+ sig = dpu->sig_priv[i];
+
+ signature_shden(sig, true);
+ signature_shdldsel_local(sig);
+ for (j = 0; j < MAX_DPU_SIGNATURE_WIN_NUM; j++) {
+ signature_global_panic(sig, j, false);
+ signature_local_panic(sig, j, false);
+ signature_alpha_mask(sig, j, false);
+ signature_crc(sig, j, false);
+ signature_eval_win(sig, j, false);
+ signature_continuous_mode(sig, false);
+ }
+}
+
+int dpu_sig_init(struct dpu_soc *dpu, unsigned int id,
+ unsigned long unused, unsigned long base)
+{
+ struct dpu_signature *sig;
+
+ sig = devm_kzalloc(dpu->dev, sizeof(*sig), GFP_KERNEL);
+ if (!sig)
+ return -ENOMEM;
+
+ dpu->sig_priv[id] = sig;
+
+ sig->base = devm_ioremap(dpu->dev, base, SZ_512);
+ if (!sig->base)
+ return -ENOMEM;
+
+ sig->dpu = dpu;
+ sig->id = id;
+ mutex_init(&sig->mutex);
+
+ _dpu_sig_init(dpu, id);
+
+ return 0;
+}
diff --git a/include/video/dpu.h b/include/video/dpu.h
index 56989798184e..0155fbebf677 100644
--- a/include/video/dpu.h
+++ b/include/video/dpu.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
- * Copyright 2017-2019 NXP
+ * Copyright 2017-2020 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
@@ -325,6 +325,11 @@ enum {
FU_T_FW,
};
+enum dpu_crc_source {
+ DPU_CRC_SRC_NONE,
+ DPU_CRC_SRC_FRAMEGEN,
+};
+
struct dpu_fetchunit;
struct dpu_fetchunit_ops {
@@ -554,6 +559,36 @@ void layerblend_position(struct dpu_layerblend *lb, int x, int y);
struct dpu_layerblend *dpu_lb_get(struct dpu_soc *dpu, int id);
void dpu_lb_put(struct dpu_layerblend *lb);
+/* Signature Unit */
+#define MAX_DPU_SIGNATURE_WIN_NUM 8
+struct dpu_signature;
+void signature_shden(struct dpu_signature *sig, bool enable);
+void signature_shdldsel_local(struct dpu_signature *sig);
+void signature_shdldsel_global(struct dpu_signature *sig);
+void
+signature_global_panic(struct dpu_signature *sig, unsigned int win, bool enable);
+void
+signature_local_panic(struct dpu_signature *sig, unsigned int win, bool enable);
+void
+signature_alpha_mask(struct dpu_signature *sig, unsigned int win, bool enable);
+void signature_crc(struct dpu_signature *sig, unsigned int win, bool enable);
+void
+signature_eval_win(struct dpu_signature *sig, unsigned int win, bool enable);
+void signature_win(struct dpu_signature *sig, unsigned int win,
+ int xul, int yul, int xlr, int ylr);
+void signature_crc_value(struct dpu_signature *sig, unsigned int win,
+ u32 *red, u32 *green, u32 *blue);
+void signature_shdldreq(struct dpu_signature *sig, u8 win_mask);
+void signature_continuous_mode(struct dpu_signature *sig, bool enable);
+void signature_kick(struct dpu_signature *sig);
+bool signature_is_idle(struct dpu_signature *sig);
+void signature_wait_for_idle(struct dpu_signature *sig);
+bool signature_is_valid(struct dpu_signature *sig);
+bool signature_is_error(struct dpu_signature *sig, u8 *err_win_mask);
+struct dpu_signature *dpu_sig_get(struct dpu_soc *dpu, int id);
+void dpu_sig_put(struct dpu_signature *sig);
+struct dpu_signature *dpu_aux_sig_peek(struct dpu_signature *sig);
+
/* Store Unit */
struct dpu_store;
void store_pixengcfg_syncmode_fixup(struct dpu_store *st, bool enable);