aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/meson/meson_vpp.c
diff options
context:
space:
mode:
authorNeil Armstrong <narmstrong@baylibre.com>2016-11-10 09:29:37 -0500
committerNeil Armstrong <narmstrong@baylibre.com>2016-12-01 04:07:20 -0500
commitbbbe775ec5b5dace43a35886da9924837da09ddd (patch)
tree3b16dad9cc1b67dc2da301ffa16e847d4931d162 /drivers/gpu/drm/meson/meson_vpp.c
parentbc33b0ca11e3df467777a4fa7639ba488c9d4911 (diff)
drm: Add support for Amlogic Meson Graphic Controller
The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Diffstat (limited to 'drivers/gpu/drm/meson/meson_vpp.c')
-rw-r--r--drivers/gpu/drm/meson/meson_vpp.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c
new file mode 100644
index 000000000000..671909d8672e
--- /dev/null
+++ b/drivers/gpu/drm/meson/meson_vpp.c
@@ -0,0 +1,162 @@
1/*
2 * Copyright (C) 2016 BayLibre, SAS
3 * Author: Neil Armstrong <narmstrong@baylibre.com>
4 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
5 * Copyright (C) 2014 Endless Mobile
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <drm/drmP.h>
24#include "meson_drv.h"
25#include "meson_vpp.h"
26#include "meson_registers.h"
27
28/*
29 * VPP Handles all the Post Processing after the Scanout from the VIU
30 * We handle the following post processings :
31 * - Postblend : Blends the OSD1 only
32 * We exclude OSD2, VS1, VS1 and Preblend output
33 * - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and
34 * use it only for interlace scanout
35 * - Intermediate FIFO with default Amlogic values
36 *
37 * What is missing :
38 * - Preblend for video overlay pre-scaling
39 * - OSD2 support for cursor framebuffer
40 * - Video pre-scaling before postblend
41 * - Full Vertical/Horizontal OSD scaling to support TV overscan
42 * - HDR conversion
43 */
44
45void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux)
46{
47 writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
48}
49
50/*
51 * When the output is interlaced, the OSD must switch between
52 * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
53 * at each vsync.
54 * But the vertical scaler can provide such funtionnality if
55 * is configured for 2:1 scaling with interlace options enabled.
56 */
57void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
58 struct drm_rect *input)
59{
60 writel_relaxed(BIT(3) /* Enable scaler */ |
61 BIT(2), /* Select OSD1 */
62 priv->io_base + _REG(VPP_OSD_SC_CTRL0));
63
64 writel_relaxed(((drm_rect_width(input) - 1) << 16) |
65 (drm_rect_height(input) - 1),
66 priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
67 /* 2:1 scaling */
68 writel_relaxed(((input->x1) << 16) | (input->x2),
69 priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
70 writel_relaxed(((input->y1 >> 1) << 16) | (input->y2 >> 1),
71 priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
72
73 /* 2:1 scaling values */
74 writel_relaxed(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
75 writel_relaxed(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
76
77 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
78
79 writel_relaxed((4 << 0) /* osd_vsc_bank_length */ |
80 (4 << 3) /* osd_vsc_top_ini_rcv_num0 */ |
81 (1 << 8) /* osd_vsc_top_rpt_p0_num0 */ |
82 (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ |
83 (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ |
84 BIT(23) /* osd_prog_interlace */ |
85 BIT(24), /* Enable vertical scaler */
86 priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
87}
88
89void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv)
90{
91 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
92 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
93 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
94}
95
96static unsigned int vpp_filter_coefs_4point_bspline[] = {
97 0x15561500, 0x14561600, 0x13561700, 0x12561800,
98 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
99 0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
100 0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
101 0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
102 0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
103 0x05473301, 0x05463401, 0x04453601, 0x04433702,
104 0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
105 0x033d3d03
106};
107
108static void meson_vpp_write_scaling_filter_coefs(struct meson_drm *priv,
109 const unsigned int *coefs,
110 bool is_horizontal)
111{
112 int i;
113
114 writel_relaxed(is_horizontal ? BIT(8) : 0,
115 priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
116 for (i = 0; i < 33; i++)
117 writel_relaxed(coefs[i],
118 priv->io_base + _REG(VPP_OSD_SCALE_COEF));
119}
120
121void meson_vpp_init(struct meson_drm *priv)
122{
123 /* set dummy data default YUV black */
124 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
125 writel_relaxed(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
126 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu")) {
127 writel_bits_relaxed(0xff << 16, 0xff << 16,
128 priv->io_base + _REG(VIU_MISC_CTRL1));
129 writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
130 writel_relaxed(0x1020080,
131 priv->io_base + _REG(VPP_DUMMY_DATA1));
132 }
133
134 /* Initialize vpu fifo control registers */
135 writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
136 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
137 writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
138
139 /* Turn off preblend */
140 writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
141 priv->io_base + _REG(VPP_MISC));
142
143 /* Turn off POSTBLEND */
144 writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
145 priv->io_base + _REG(VPP_MISC));
146
147 /* Force all planes off */
148 writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
149 VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND, 0,
150 priv->io_base + _REG(VPP_MISC));
151
152 /* Disable Scalers */
153 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
154 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
155 writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
156
157 /* Write in the proper filter coefficients. */
158 meson_vpp_write_scaling_filter_coefs(priv,
159 vpp_filter_coefs_4point_bspline, false);
160 meson_vpp_write_scaling_filter_coefs(priv,
161 vpp_filter_coefs_4point_bspline, true);
162}