Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2016 BayLibre, SAS
0004  * Author: Neil Armstrong <narmstrong@baylibre.com>
0005  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
0006  * Copyright (C) 2014 Endless Mobile
0007  */
0008 
0009 #include <linux/export.h>
0010 
0011 #include "meson_drv.h"
0012 #include "meson_registers.h"
0013 #include "meson_vpp.h"
0014 
0015 /**
0016  * DOC: Video Post Processing
0017  *
0018  * VPP Handles all the Post Processing after the Scanout from the VIU
0019  * We handle the following post processings :
0020  *
0021  * - Postblend, Blends the OSD1 only
0022  *  We exclude OSD2, VS1, VS1 and Preblend output
0023  * - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and
0024  *  use it only for interlace scanout
0025  * - Intermediate FIFO with default Amlogic values
0026  *
0027  * What is missing :
0028  *
0029  * - Preblend for video overlay pre-scaling
0030  * - OSD2 support for cursor framebuffer
0031  * - Video pre-scaling before postblend
0032  * - Full Vertical/Horizontal OSD scaling to support TV overscan
0033  * - HDR conversion
0034  */
0035 
0036 void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux)
0037 {
0038     writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
0039 }
0040 
0041 static unsigned int vpp_filter_coefs_4point_bspline[] = {
0042     0x15561500, 0x14561600, 0x13561700, 0x12561800,
0043     0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
0044     0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
0045     0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
0046     0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
0047     0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
0048     0x05473301, 0x05463401, 0x04453601, 0x04433702,
0049     0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
0050     0x033d3d03
0051 };
0052 
0053 static void meson_vpp_write_scaling_filter_coefs(struct meson_drm *priv,
0054                          const unsigned int *coefs,
0055                          bool is_horizontal)
0056 {
0057     int i;
0058 
0059     writel_relaxed(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
0060             priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
0061     for (i = 0; i < 33; i++)
0062         writel_relaxed(coefs[i],
0063                 priv->io_base + _REG(VPP_OSD_SCALE_COEF));
0064 }
0065 
0066 static const uint32_t vpp_filter_coefs_bicubic[] = {
0067     0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300,
0068     0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
0069     0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
0070     0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
0071     0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
0072     0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
0073     0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
0074     0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
0075     0xf84848f8
0076 };
0077 
0078 static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_drm *priv,
0079                             const unsigned int *coefs,
0080                             bool is_horizontal)
0081 {
0082     int i;
0083 
0084     writel_relaxed(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
0085             priv->io_base + _REG(VPP_SCALE_COEF_IDX));
0086     for (i = 0; i < 33; i++)
0087         writel_relaxed(coefs[i],
0088                 priv->io_base + _REG(VPP_SCALE_COEF));
0089 }
0090 
0091 void meson_vpp_init(struct meson_drm *priv)
0092 {
0093     /* set dummy data default YUV black */
0094     if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
0095         writel_relaxed(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
0096     else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
0097         writel_bits_relaxed(0xff << 16, 0xff << 16,
0098                     priv->io_base + _REG(VIU_MISC_CTRL1));
0099         writel_relaxed(VPP_PPS_DUMMY_DATA_MODE,
0100                    priv->io_base + _REG(VPP_DOLBY_CTRL));
0101         writel_relaxed(0x1020080,
0102                 priv->io_base + _REG(VPP_DUMMY_DATA1));
0103     } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
0104         writel_relaxed(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
0105 
0106     /* Initialize vpu fifo control registers */
0107     if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
0108         writel_relaxed(VPP_OFIFO_SIZE_DEFAULT,
0109                    priv->io_base + _REG(VPP_OFIFO_SIZE));
0110     else
0111         writel_bits_relaxed(VPP_OFIFO_SIZE_MASK, 0x77f,
0112                     priv->io_base + _REG(VPP_OFIFO_SIZE));
0113     writel_relaxed(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4),
0114                priv->io_base + _REG(VPP_HOLD_LINES));
0115 
0116     if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
0117         /* Turn off preblend */
0118         writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
0119                     priv->io_base + _REG(VPP_MISC));
0120 
0121         /* Turn off POSTBLEND */
0122         writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
0123                     priv->io_base + _REG(VPP_MISC));
0124 
0125         /* Force all planes off */
0126         writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
0127                     VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
0128                     VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
0129                     priv->io_base + _REG(VPP_MISC));
0130 
0131         /* Setup default VD settings */
0132         writel_relaxed(4096,
0133                 priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
0134         writel_relaxed(4096,
0135                 priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
0136     }
0137 
0138     /* Disable Scalers */
0139     writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
0140     writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
0141     writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
0142 
0143     /* Set horizontal/vertical bank length and enable video scale out */
0144     writel_relaxed(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) |
0145                VPP_SC_VD_EN_ENABLE,
0146                priv->io_base + _REG(VPP_SC_MISC));
0147 
0148     /* Enable minus black level for vadj1 */
0149     writel_relaxed(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE,
0150                priv->io_base + _REG(VPP_VADJ_CTRL));
0151 
0152     /* Write in the proper filter coefficients. */
0153     meson_vpp_write_scaling_filter_coefs(priv,
0154                 vpp_filter_coefs_4point_bspline, false);
0155     meson_vpp_write_scaling_filter_coefs(priv,
0156                 vpp_filter_coefs_4point_bspline, true);
0157 
0158     /* Write the VD proper filter coefficients. */
0159     meson_vpp_write_vd_scaling_filter_coefs(priv, vpp_filter_coefs_bicubic,
0160                         false);
0161     meson_vpp_write_vd_scaling_filter_coefs(priv, vpp_filter_coefs_bicubic,
0162                         true);
0163 }