Commit 1b85270f authored by Neil Armstrong's avatar Neil Armstrong

drm/meson: viu: add AFBC modules routing functions

The Amlogic G12A AFBC Decoder pixel input need to be routed diferently
than the Amlogic GXM AFBC decoder, this adds support for routing the
VIU OSD1 pixel source to the AFBC "Mali Unpack" module.

This "Mali Unpack" module is also configured with a static RGBA mapping
for now until we support more pixel formats.
Signed-off-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Reviewed-by: default avatarKevin Hilman <khilman@baylibre.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191021091509.3864-8-narmstrong@baylibre.com
parent 68e2f64e
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
*/ */
#include <linux/export.h> #include <linux/export.h>
#include <linux/bitfield.h>
#include <drm/drm_fourcc.h>
#include "meson_drv.h" #include "meson_drv.h"
#include "meson_viu.h" #include "meson_viu.h"
...@@ -335,6 +338,79 @@ void meson_viu_osd1_reset(struct meson_drm *priv) ...@@ -335,6 +338,79 @@ void meson_viu_osd1_reset(struct meson_drm *priv)
meson_viu_load_matrix(priv); meson_viu_load_matrix(priv);
} }
#define OSD1_MALI_ORDER_ABGR \
(FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER, \
VIU_OSD1_MALI_REORDER_A) | \
FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER, \
VIU_OSD1_MALI_REORDER_B) | \
FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER, \
VIU_OSD1_MALI_REORDER_G) | \
FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER, \
VIU_OSD1_MALI_REORDER_R))
#define OSD1_MALI_ORDER_ARGB \
(FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER, \
VIU_OSD1_MALI_REORDER_A) | \
FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER, \
VIU_OSD1_MALI_REORDER_R) | \
FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER, \
VIU_OSD1_MALI_REORDER_G) | \
FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER, \
VIU_OSD1_MALI_REORDER_B))
void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv)
{
u32 afbc_order = OSD1_MALI_ORDER_ARGB;
/* Enable Mali AFBC Unpack */
writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN,
VIU_OSD1_MALI_UNPACK_EN,
priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
switch (priv->afbcd.format) {
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
afbc_order = OSD1_MALI_ORDER_ABGR;
break;
}
/* Setup RGBA Reordering */
writel_bits_relaxed(VIU_OSD1_MALI_AFBCD_A_REORDER |
VIU_OSD1_MALI_AFBCD_B_REORDER |
VIU_OSD1_MALI_AFBCD_G_REORDER |
VIU_OSD1_MALI_AFBCD_R_REORDER,
afbc_order,
priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
/* Select AFBCD path for OSD1 */
writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
priv->io_base + _REG(OSD_PATH_MISC_CTRL));
}
void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv)
{
/* Disable AFBCD path for OSD1 */
writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 0,
priv->io_base + _REG(OSD_PATH_MISC_CTRL));
/* Disable AFBCD unpack */
writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 0,
priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
}
void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv)
{
writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x90),
priv->io_base + _REG(VIU_MISC_CTRL1));
}
void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv)
{
writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x00),
priv->io_base + _REG(VIU_MISC_CTRL1));
}
static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length) static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length)
{ {
uint32_t val = (((length & 0x80) % 24) / 12); uint32_t val = (((length & 0x80) % 24) / 12);
...@@ -420,8 +496,13 @@ void meson_viu_init(struct meson_drm *priv) ...@@ -420,8 +496,13 @@ void meson_viu_init(struct meson_drm *priv)
writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc), writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
priv->io_base + _REG(DOLBY_PATH_CTRL)); priv->io_base + _REG(DOLBY_PATH_CTRL));
meson_viu_g12a_disable_osd1_afbc(priv);
} }
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
meson_viu_gxm_disable_osd1_afbc(priv);
priv->viu.osd1_enabled = false; priv->viu.osd1_enabled = false;
priv->viu.osd1_commit = false; priv->viu.osd1_commit = false;
priv->viu.osd1_interlace = false; priv->viu.osd1_interlace = false;
......
...@@ -63,6 +63,10 @@ ...@@ -63,6 +63,10 @@
#define OSD_PENDING_STAT_CLEAN BIT(1) #define OSD_PENDING_STAT_CLEAN BIT(1)
void meson_viu_osd1_reset(struct meson_drm *priv); void meson_viu_osd1_reset(struct meson_drm *priv);
void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv);
void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv);
void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv);
void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv);
void meson_viu_init(struct meson_drm *priv); void meson_viu_init(struct meson_drm *priv);
#endif /* __MESON_VIU_H */ #endif /* __MESON_VIU_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment