@@ -16,7 +16,8 @@ sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o
sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \
sun8i_vi_layer.o sun8i_ui_scaler.o \
- sun8i_vi_scaler.o sun8i_csc.o
+ sun8i_vi_scaler.o sun8i_csc.o \
+ sun50i_fmt.o
sun4i-tcon-y += sun4i_crtc.o
sun4i-tcon-y += sun4i_tcon_dclk.o
new file mode 100644
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@gmail.com>
+ */
+
+#include <uapi/linux/media-bus-format.h>
+
+#include "sun50i_fmt.h"
+
+static bool sun50i_fmt_is_10bit(u32 format)
+{
+ switch (format) {
+ case MEDIA_BUS_FMT_RGB101010_1X30:
+ case MEDIA_BUS_FMT_YUV10_1X30:
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+ case MEDIA_BUS_FMT_UYVY10_1X20:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static u32 sun50i_fmt_get_colorspace(u32 format)
+{
+ switch (format) {
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+ return SUN50I_FMT_CS_YUV420;
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ case MEDIA_BUS_FMT_UYVY10_1X20:
+ return SUN50I_FMT_CS_YUV422;
+ default:
+ return SUN50I_FMT_CS_YUV444RGB;
+ }
+}
+
+static void sun50i_fmt_de3_limits(u32 *limits, u32 colorspace, bool bit10)
+{
+ if (colorspace != SUN50I_FMT_CS_YUV444RGB) {
+ limits[0] = SUN50I_FMT_LIMIT(64, 940);
+ limits[1] = SUN50I_FMT_LIMIT(64, 960);
+ limits[2] = SUN50I_FMT_LIMIT(64, 960);
+ } else if (bit10) {
+ limits[0] = SUN50I_FMT_LIMIT(0, 1023);
+ limits[1] = SUN50I_FMT_LIMIT(0, 1023);
+ limits[2] = SUN50I_FMT_LIMIT(0, 1023);
+ } else {
+ limits[0] = SUN50I_FMT_LIMIT(0, 1021);
+ limits[1] = SUN50I_FMT_LIMIT(0, 1021);
+ limits[2] = SUN50I_FMT_LIMIT(0, 1021);
+ }
+}
+
+void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width,
+ u16 height, u32 format)
+{
+ u32 colorspace, limit[3], base;
+ struct regmap *regs;
+ bool bit10;
+
+ colorspace = sun50i_fmt_get_colorspace(format);
+ bit10 = sun50i_fmt_is_10bit(format);
+ base = SUN50I_FMT_DE3;
+ regs = sun8i_blender_regmap(mixer);
+
+ sun50i_fmt_de3_limits(limit, colorspace, bit10);
+
+ regmap_write(regs, SUN50I_FMT_CTRL(base), 0);
+
+ regmap_write(regs, SUN50I_FMT_SIZE(base),
+ SUN8I_MIXER_SIZE(width, height));
+ regmap_write(regs, SUN50I_FMT_SWAP(base), 0);
+ regmap_write(regs, SUN50I_FMT_DEPTH(base), bit10);
+ regmap_write(regs, SUN50I_FMT_FORMAT(base), colorspace);
+ regmap_write(regs, SUN50I_FMT_COEF(base), 0);
+
+ regmap_write(regs, SUN50I_FMT_LMT_Y(base), limit[0]);
+ regmap_write(regs, SUN50I_FMT_LMT_C0(base), limit[1]);
+ regmap_write(regs, SUN50I_FMT_LMT_C1(base), limit[2]);
+
+ regmap_write(regs, SUN50I_FMT_CTRL(base), 1);
+}
new file mode 100644
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@gmail.com>
+ */
+
+#ifndef _SUN50I_FMT_H_
+#define _SUN50I_FMT_H_
+
+#include "sun8i_mixer.h"
+
+#define SUN50I_FMT_DE3 0xa8000
+
+#define SUN50I_FMT_CTRL(base) ((base) + 0x00)
+#define SUN50I_FMT_SIZE(base) ((base) + 0x04)
+#define SUN50I_FMT_SWAP(base) ((base) + 0x08)
+#define SUN50I_FMT_DEPTH(base) ((base) + 0x0c)
+#define SUN50I_FMT_FORMAT(base) ((base) + 0x10)
+#define SUN50I_FMT_COEF(base) ((base) + 0x14)
+#define SUN50I_FMT_LMT_Y(base) ((base) + 0x20)
+#define SUN50I_FMT_LMT_C0(base) ((base) + 0x24)
+#define SUN50I_FMT_LMT_C1(base) ((base) + 0x28)
+
+#define SUN50I_FMT_LIMIT(low, high) (((high) << 16) | (low))
+
+#define SUN50I_FMT_CS_YUV444RGB 0
+#define SUN50I_FMT_CS_YUV422 1
+#define SUN50I_FMT_CS_YUV420 2
+
+void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width,
+ u16 height, u32 format);
+
+#endif