summaryrefslogtreecommitdiff
path: root/drivers/gpu/imx/dpu/dpu-fetchwarp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/imx/dpu/dpu-fetchwarp.c')
-rw-r--r--drivers/gpu/imx/dpu/dpu-fetchwarp.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/drivers/gpu/imx/dpu/dpu-fetchwarp.c b/drivers/gpu/imx/dpu/dpu-fetchwarp.c
new file mode 100644
index 000000000000..673c738da8a7
--- /dev/null
+++ b/drivers/gpu/imx/dpu/dpu-fetchwarp.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2018 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 WARPCONTROL 0x158
+#define ARBSTARTX 0x15c
+#define ARBSTARTY 0x160
+#define ARBDELTA 0x164
+#define FIRPOSITIONS 0x168
+#define FIRCOEFFICIENTS 0x16c
+#define CONTROL 0x170
+#define TRIGGERENABLE 0x174
+#define SHDLDREQ(lm) ((lm) & 0xFF)
+#define CONTROLTRIGGER 0x178
+#define START 0x17c
+#define FETCHTYPE 0x180
+#define BURSTBUFFERPROPERTIES 0x184
+#define STATUS 0x188
+#define HIDDENSTATUS 0x18c
+
+struct dpu_fetchwarp {
+ struct dpu_fetchunit fu;
+ fetchtype_t fetchtype;
+};
+
+static void
+fetchwarp_set_src_buf_dimensions(struct dpu_fetchunit *fu,
+ unsigned int w, unsigned int h,
+ u32 unused1, bool unused2)
+{
+ u32 val;
+
+ val = LINEWIDTH(w) | LINECOUNT(h);
+
+ mutex_lock(&fu->mutex);
+ dpu_fu_write(fu, val, SOURCEBUFFERDIMENSION(fu->sub_id));
+ mutex_unlock(&fu->mutex);
+}
+
+static void fetchwarp_set_fmt(struct dpu_fetchunit *fu,
+ u32 fmt, bool unused)
+{
+ u32 val, bits, shift;
+ int i, sub_id = fu->sub_id;
+
+ mutex_lock(&fu->mutex);
+ val = dpu_fu_read(fu, LAYERPROPERTY(sub_id));
+ val &= ~YUVCONVERSIONMODE_MASK;
+ dpu_fu_write(fu, val, LAYERPROPERTY(sub_id));
+ mutex_unlock(&fu->mutex);
+
+ for (i = 0; i < ARRAY_SIZE(dpu_pixel_format_matrix); i++) {
+ if (dpu_pixel_format_matrix[i].pixel_format == fmt) {
+ bits = dpu_pixel_format_matrix[i].bits;
+ shift = dpu_pixel_format_matrix[i].shift;
+
+ mutex_lock(&fu->mutex);
+ dpu_fu_write(fu, bits, COLORCOMPONENTBITS(sub_id));
+ dpu_fu_write(fu, shift, COLORCOMPONENTSHIFT(sub_id));
+ mutex_unlock(&fu->mutex);
+ return;
+ }
+ }
+
+ WARN_ON(1);
+}
+
+static void
+fetchwarp_set_framedimensions(struct dpu_fetchunit *fu,
+ unsigned int w, unsigned int h, bool unused)
+{
+ u32 val;
+
+ val = FRAMEWIDTH(w) | FRAMEHEIGHT(h);
+
+ mutex_lock(&fu->mutex);
+ dpu_fu_write(fu, val, FRAMEDIMENSIONS);
+ mutex_unlock(&fu->mutex);
+}
+
+void fetchwarp_rgb_constantcolor(struct dpu_fetchunit *fu,
+ u8 r, u8 g, u8 b, u8 a)
+{
+ u32 val;
+
+ val = rgb_color(r, g, b, a);
+
+ mutex_lock(&fu->mutex);
+ dpu_fu_write(fu, val, CONSTANTCOLOR(fu->id));
+ mutex_unlock(&fu->mutex);
+}
+EXPORT_SYMBOL_GPL(fetchwarp_rgb_constantcolor);
+
+void fetchwarp_yuv_constantcolor(struct dpu_fetchunit *fu, u8 y, u8 u, u8 v)
+{
+ u32 val;
+
+ val = yuv_color(y, u, v);
+
+ mutex_lock(&fu->mutex);
+ dpu_fu_write(fu, val, CONSTANTCOLOR(fu->id));
+ mutex_unlock(&fu->mutex);
+}
+EXPORT_SYMBOL_GPL(fetchwarp_yuv_constantcolor);
+
+static void fetchwarp_set_controltrigger(struct dpu_fetchunit *fu)
+{
+ mutex_lock(&fu->mutex);
+ dpu_fu_write(fu, SHDTOKGEN, CONTROLTRIGGER);
+ mutex_unlock(&fu->mutex);
+}
+
+int fetchwarp_fetchtype(struct dpu_fetchunit *fu, fetchtype_t *type)
+{
+ struct dpu_soc *dpu = fu->dpu;
+ u32 val;
+
+ mutex_lock(&fu->mutex);
+ val = dpu_fu_read(fu, FETCHTYPE);
+ val &= FETCHTYPE_MASK;
+ mutex_unlock(&fu->mutex);
+
+ switch (val) {
+ case FETCHTYPE__DECODE:
+ dev_dbg(dpu->dev, "FetchWarp%d with RL and RLAD decoder\n",
+ fu->id);
+ break;
+ case FETCHTYPE__LAYER:
+ dev_dbg(dpu->dev, "FetchWarp%d with fractional "
+ "plane(8 layers)\n", fu->id);
+ break;
+ case FETCHTYPE__WARP:
+ dev_dbg(dpu->dev, "FetchWarp%d with arbitrary warping and "
+ "fractional plane(8 layers)\n", fu->id);
+ break;
+ case FETCHTYPE__ECO:
+ dev_dbg(dpu->dev, "FetchWarp%d with minimum feature set for "
+ "alpha, chroma and coordinate planes\n",
+ fu->id);
+ break;
+ case FETCHTYPE__PERSP:
+ dev_dbg(dpu->dev, "FetchWarp%d with affine, perspective and "
+ "arbitrary warping\n", fu->id);
+ break;
+ case FETCHTYPE__ROT:
+ dev_dbg(dpu->dev, "FetchWarp%d with affine and arbitrary "
+ "warping\n", fu->id);
+ break;
+ case FETCHTYPE__DECODEL:
+ dev_dbg(dpu->dev, "FetchWarp%d with RL and RLAD decoder, "
+ "reduced feature set\n", fu->id);
+ break;
+ case FETCHTYPE__LAYERL:
+ dev_dbg(dpu->dev, "FetchWarp%d with fractional "
+ "plane(8 layers), reduced feature set\n",
+ fu->id);
+ break;
+ case FETCHTYPE__ROTL:
+ dev_dbg(dpu->dev, "FetchWarp%d with affine and arbitrary "
+ "warping, reduced feature set\n", fu->id);
+ break;
+ default:
+ dev_warn(dpu->dev, "Invalid fetch type %u for FetchWarp%d\n",
+ val, fu->id);
+ return -EINVAL;
+ }
+
+ *type = val;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fetchwarp_fetchtype);
+
+struct dpu_fetchunit *dpu_fw_get(struct dpu_soc *dpu, int id)
+{
+ struct dpu_fetchunit *fu;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fw_ids); i++)
+ if (fw_ids[i] == id)
+ break;
+
+ if (i == ARRAY_SIZE(fw_ids))
+ return ERR_PTR(-EINVAL);
+
+ fu = dpu->fw_priv[i];
+
+ mutex_lock(&fu->mutex);
+
+ if (fu->inuse) {
+ fu = ERR_PTR(-EBUSY);
+ goto out;
+ }
+
+ fu->inuse = true;
+out:
+ mutex_unlock(&fu->mutex);
+
+ return fu;
+}
+EXPORT_SYMBOL_GPL(dpu_fw_get);
+
+void dpu_fw_put(struct dpu_fetchunit *fu)
+{
+ mutex_lock(&fu->mutex);
+
+ fu->inuse = false;
+
+ mutex_unlock(&fu->mutex);
+}
+EXPORT_SYMBOL_GPL(dpu_fw_put);
+
+static const struct dpu_fetchunit_ops fw_ops = {
+ .set_burstlength = fetchunit_set_burstlength,
+ .set_baseaddress = fetchunit_set_baseaddress,
+ .set_src_bpp = fetchunit_set_src_bpp,
+ .set_src_stride = fetchunit_set_src_stride,
+ .set_src_buf_dimensions = fetchwarp_set_src_buf_dimensions,
+ .set_fmt = fetchwarp_set_fmt,
+ .enable_src_buf = fetchunit_enable_src_buf,
+ .disable_src_buf = fetchunit_disable_src_buf,
+ .is_enabled = fetchunit_is_enabled,
+ .set_framedimensions = fetchwarp_set_framedimensions,
+ .set_controltrigger = fetchwarp_set_controltrigger,
+ .get_stream_id = fetchunit_get_stream_id,
+ .set_stream_id = fetchunit_set_stream_id,
+ .pin_off = fetchunit_pin_off,
+ .unpin_off = fetchunit_unpin_off,
+ .is_pinned_off = fetchunit_is_pinned_off,
+};
+
+void _dpu_fw_init(struct dpu_soc *dpu, unsigned int id)
+{
+ struct dpu_fetchunit *fu;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fw_ids); i++)
+ if (fw_ids[i] == id)
+ break;
+
+ if (WARN_ON(i == ARRAY_SIZE(fw_ids)))
+ return;
+
+ fu = dpu->fw_priv[i];
+
+ fetchunit_baddr_autoupdate(fu, 0x0);
+ fetchunit_shden(fu, true);
+ fetchunit_shdldreq_sticky(fu, 0xFF);
+ fetchunit_disable_src_buf(fu);
+
+ mutex_lock(&fu->mutex);
+ dpu_fu_write(fu, SETNUMBUFFERS(16) | SETBURSTLENGTH(16),
+ BURSTBUFFERMANAGEMENT);
+ mutex_unlock(&fu->mutex);
+}
+
+int dpu_fw_init(struct dpu_soc *dpu, unsigned int id,
+ unsigned long pec_base, unsigned long base)
+{
+ struct dpu_fetchwarp *fw;
+ struct dpu_fetchunit *fu;
+ int i, ret;
+
+ fw = devm_kzalloc(dpu->dev, sizeof(*fw), GFP_KERNEL);
+ if (!fw)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(fw_ids); i++)
+ if (fw_ids[i] == id)
+ break;
+
+ fu = &fw->fu;
+ dpu->fw_priv[i] = fu;
+
+ fu->pec_base = devm_ioremap(dpu->dev, base, SZ_16);
+ if (!fu->pec_base)
+ return -ENOMEM;
+
+ fu->base = devm_ioremap(dpu->dev, base, SZ_512);
+ if (!fu->base)
+ return -ENOMEM;
+
+ fu->dpu = dpu;
+ fu->id = id;
+ fu->sub_id = 0;
+ fu->type = FU_T_FW;
+ fu->ops = &fw_ops;
+ fu->name = "fetchwarp";
+
+ mutex_init(&fu->mutex);
+
+ ret = fetchwarp_fetchtype(fu, &fw->fetchtype);
+ if (ret < 0)
+ return ret;
+
+ _dpu_fw_init(dpu, id);
+
+ return 0;
+}