diff options
author | Liu Ying <victor.liu@nxp.com> | 2019-04-08 16:11:53 +0800 |
---|---|---|
committer | Liu Ying <victor.liu@nxp.com> | 2020-07-09 09:42:03 +0800 |
commit | c30b395e8d940691440fd0b042c23af85298b8d7 (patch) | |
tree | 4a9d3a7f7986b88b8d5df83838a2260cd6cf3548 | |
parent | 97b5de8b94ffab07c6a2bd42884d0fd13d42b3a1 (diff) |
MLK-21509-1 gpu: imx: dpu: common: Add signature unit support
This patch adds signature unit support in the dpu common driver.
Signed-off-by: Liu Ying <victor.liu@nxp.com>
Reviewed-by: Robby Cai <robby.cai@nxp.com>
-rw-r--r-- | drivers/gpu/imx/dpu/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-common.c | 44 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-prv.h | 13 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-signature.c | 392 | ||||
-rw-r--r-- | include/video/dpu.h | 37 |
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); |