diff options
Diffstat (limited to 'drivers/gpu/imx/dpu/dpu-store.c')
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-store.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/gpu/imx/dpu/dpu-store.c b/drivers/gpu/imx/dpu/dpu-store.c new file mode 100644 index 000000000000..cbd06b83581b --- /dev/null +++ b/drivers/gpu/imx/dpu/dpu-store.c @@ -0,0 +1,157 @@ +/* + * Copyright 2018-2019 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 PIXENGCFG_STATIC 0x8 +#define DIV(n) (((n) & 0xFF) << 16) +#define DIV_RESET 0x80 + +struct dpu_store { + void __iomem *pec_base; + void __iomem *base; + struct mutex mutex; + int id; + bool inuse; + struct dpu_soc *dpu; +}; + +static inline u32 dpu_pec_st_read(struct dpu_store *st, unsigned int offset) +{ + return readl(st->pec_base + offset); +} + +static inline void dpu_pec_st_write(struct dpu_store *st, + unsigned int offset, u32 value) +{ + writel(value, st->pec_base + offset); +} + +void store_pixengcfg_syncmode_fixup(struct dpu_store *st, bool enable) +{ + struct dpu_soc *dpu; + u32 val; + + if (!st) + return; + + dpu = st->dpu; + + mutex_lock(&st->mutex); + val = dpu_pec_st_read(st, PIXENGCFG_STATIC); + if (enable) + val |= BIT(16); + else + val &= ~BIT(16); + dpu_pec_st_write(st, PIXENGCFG_STATIC, val); + mutex_unlock(&st->mutex); +} +EXPORT_SYMBOL_GPL(store_pixengcfg_syncmode_fixup); + +struct dpu_store *dpu_st_get(struct dpu_soc *dpu, int id) +{ + struct dpu_store *st; + int i; + + for (i = 0; i < ARRAY_SIZE(st_ids); i++) + if (st_ids[i] == id) + break; + + if (i == ARRAY_SIZE(st_ids)) + return ERR_PTR(-EINVAL); + + st = dpu->st_priv[i]; + + mutex_lock(&st->mutex); + + if (st->inuse) { + mutex_unlock(&st->mutex); + return ERR_PTR(-EBUSY); + } + + st->inuse = true; + + mutex_unlock(&st->mutex); + + return st; +} +EXPORT_SYMBOL_GPL(dpu_st_get); + +void dpu_st_put(struct dpu_store *st) +{ + mutex_lock(&st->mutex); + + st->inuse = false; + + mutex_unlock(&st->mutex); +} +EXPORT_SYMBOL_GPL(dpu_st_put); + +void _dpu_st_init(struct dpu_soc *dpu, unsigned int id) +{ + struct dpu_store *st; + int i; + + for (i = 0; i < ARRAY_SIZE(st_ids); i++) + if (st_ids[i] == id) + break; + + if (WARN_ON(i == ARRAY_SIZE(st_ids))) + return; + + st = dpu->st_priv[i]; + + dpu_pec_st_write(st, PIXENGCFG_STATIC, SHDEN | DIV(DIV_RESET)); +} + +int dpu_st_init(struct dpu_soc *dpu, unsigned int id, + unsigned long pec_base, unsigned long base) +{ + struct dpu_store *st; + int i; + + st = devm_kzalloc(dpu->dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(st_ids); i++) + if (st_ids[i] == id) + break; + + if (i == ARRAY_SIZE(st_ids)) + return -EINVAL; + + dpu->st_priv[i] = st; + + st->pec_base = devm_ioremap(dpu->dev, pec_base, SZ_32); + if (!st->pec_base) + return -ENOMEM; + + st->base = devm_ioremap(dpu->dev, base, SZ_256); + if (!st->base) + return -ENOMEM; + + st->dpu = dpu; + st->id = id; + mutex_init(&st->mutex); + + _dpu_st_init(dpu, id); + + return 0; +} |