diff options
Diffstat (limited to 'drivers/gpu/drm/meson/meson_viu.c')
-rw-r--r-- | drivers/gpu/drm/meson/meson_viu.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c index 68cf2c2eca5f..304f8ff1339c 100644 --- a/drivers/gpu/drm/meson/meson_viu.c +++ b/drivers/gpu/drm/meson/meson_viu.c @@ -7,6 +7,9 @@ */ #include <linux/export.h> +#include <linux/bitfield.h> + +#include <drm/drm_fourcc.h> #include "meson_drv.h" #include "meson_viu.h" @@ -335,6 +338,79 @@ void meson_viu_osd1_reset(struct meson_drm *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) { uint32_t val = (((length & 0x80) % 24) / 12); @@ -362,7 +438,7 @@ void meson_viu_init(struct meson_drm *priv) /* Initialize OSD1 fifo control register */ reg = VIU_OSD_DDR_PRIORITY_URGENT | - VIU_OSD_HOLD_FIFO_LINES(4) | + VIU_OSD_HOLD_FIFO_LINES(31) | VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ @@ -420,8 +496,13 @@ void meson_viu_init(struct meson_drm *priv) writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc), 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_commit = false; priv->viu.osd1_interlace = false; |