diff options
Diffstat (limited to 'drivers/gpu/drm/meson/meson_viu.c')
-rw-r--r-- | drivers/gpu/drm/meson/meson_viu.c | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c index 6bcfa527c180..e46e05f50bad 100644 --- a/drivers/gpu/drm/meson/meson_viu.c +++ b/drivers/gpu/drm/meson/meson_viu.c @@ -184,18 +184,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel, if (lut_sel == VIU_LUT_OSD_OETF) { writel(0, priv->io_base + _REG(addr_port)); - for (i = 0; i < 20; i++) + for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), priv->io_base + _REG(data_port)); writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16), priv->io_base + _REG(data_port)); - for (i = 0; i < 20; i++) + for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), priv->io_base + _REG(data_port)); - for (i = 0; i < 20; i++) + for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), priv->io_base + _REG(data_port)); @@ -211,18 +211,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel, } else if (lut_sel == VIU_LUT_OSD_EOTF) { writel(0, priv->io_base + _REG(addr_port)); - for (i = 0; i < 20; i++) + for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16), priv->io_base + _REG(data_port)); writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16), priv->io_base + _REG(data_port)); - for (i = 0; i < 20; i++) + for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), priv->io_base + _REG(data_port)); - for (i = 0; i < 20; i++) + for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16), priv->io_base + _REG(data_port)); @@ -296,6 +296,33 @@ static void meson_viu_load_matrix(struct meson_drm *priv) true); } +/* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */ +void meson_viu_osd1_reset(struct meson_drm *priv) +{ + uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2; + + /* Save these 2 registers state */ + osd1_fifo_ctrl_stat = readl_relaxed( + priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); + osd1_ctrl_stat2 = readl_relaxed( + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); + + /* Reset OSD1 */ + writel_bits_relaxed(BIT(0), BIT(0), + priv->io_base + _REG(VIU_SW_RESET)); + writel_bits_relaxed(BIT(0), 0, + priv->io_base + _REG(VIU_SW_RESET)); + + /* Rewrite these registers state lost in the reset */ + writel_relaxed(osd1_fifo_ctrl_stat, + priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); + writel_relaxed(osd1_ctrl_stat2, + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); + + /* Reload the conversion matrix */ + meson_viu_load_matrix(priv); +} + void meson_viu_init(struct meson_drm *priv) { uint32_t reg; @@ -329,6 +356,21 @@ void meson_viu_init(struct meson_drm *priv) 0xff << OSD_REPLACE_SHIFT, priv->io_base + _REG(VIU_OSD2_CTRL_STAT2)); + /* Disable VD1 AFBC */ + /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 */ + writel_bits_relaxed(0x7 << 16, 0, + priv->io_base + _REG(VIU_MISC_CTRL0)); + /* afbc vd1 set=0 */ + writel_bits_relaxed(BIT(20), 0, + priv->io_base + _REG(VIU_MISC_CTRL0)); + writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE)); + + writel_relaxed(0x00FF00C0, + priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE)); + writel_relaxed(0x00FF00C0, + priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE)); + + priv->viu.osd1_enabled = false; priv->viu.osd1_commit = false; priv->viu.osd1_interlace = false; |