Skip to content

Commit bbbe775

Browse files
committed
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 <[email protected]> Signed-off-by: Neil Armstrong <[email protected]>
1 parent bc33b0c commit bbbe775

23 files changed

+3876
-0
lines changed

drivers/gpu/drm/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ source "drivers/gpu/drm/hisilicon/Kconfig"
223223

224224
source "drivers/gpu/drm/mediatek/Kconfig"
225225

226+
source "drivers/gpu/drm/meson/Kconfig"
227+
226228
# Keep legacy drivers last
227229

228230
menuconfig DRM_LEGACY

drivers/gpu/drm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ obj-$(CONFIG_DRM_TEGRA) += tegra/
7979
obj-$(CONFIG_DRM_STI) += sti/
8080
obj-$(CONFIG_DRM_IMX) += imx/
8181
obj-$(CONFIG_DRM_MEDIATEK) += mediatek/
82+
obj-$(CONFIG_DRM_MESON) += meson/
8283
obj-y += i2c/
8384
obj-y += panel/
8485
obj-y += bridge/

drivers/gpu/drm/meson/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
config DRM_MESON
2+
tristate "DRM Support for Amlogic Meson Display Controller"
3+
depends on DRM && OF && (ARM || ARM64)
4+
depends on ARCH_MESON || COMPILE_TEST
5+
select DRM_KMS_HELPER
6+
select DRM_KMS_CMA_HELPER
7+
select DRM_GEM_CMA_HELPER
8+
select VIDEOMODE_HELPERS
9+
select REGMAP_MMIO

drivers/gpu/drm/meson/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
meson-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
2+
meson-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
3+
4+
obj-$(CONFIG_DRM_MESON) += meson.o

drivers/gpu/drm/meson/meson_canvas.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (C) 2016 BayLibre, SAS
3+
* Author: Neil Armstrong <[email protected]>
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 "meson_drv.h"
24+
#include "meson_canvas.h"
25+
#include "meson_registers.h"
26+
27+
/*
28+
* CANVAS is a memory zone where physical memory frames information
29+
* are stored for the VIU to scanout.
30+
*/
31+
32+
/* DMC Registers */
33+
#define DMC_CAV_LUT_DATAL 0x48 /* 0x12 offset in data sheet */
34+
#define CANVAS_WIDTH_LBIT 29
35+
#define CANVAS_WIDTH_LWID 3
36+
#define DMC_CAV_LUT_DATAH 0x4c /* 0x13 offset in data sheet */
37+
#define CANVAS_WIDTH_HBIT 0
38+
#define CANVAS_HEIGHT_BIT 9
39+
#define CANVAS_BLKMODE_BIT 24
40+
#define DMC_CAV_LUT_ADDR 0x50 /* 0x14 offset in data sheet */
41+
#define CANVAS_LUT_WR_EN (0x2 << 8)
42+
#define CANVAS_LUT_RD_EN (0x1 << 8)
43+
44+
void meson_canvas_setup(struct meson_drm *priv,
45+
uint32_t canvas_index, uint32_t addr,
46+
uint32_t stride, uint32_t height,
47+
unsigned int wrap,
48+
unsigned int blkmode)
49+
{
50+
unsigned int val;
51+
52+
regmap_write(priv->dmc, DMC_CAV_LUT_DATAL,
53+
(((addr + 7) >> 3)) |
54+
(((stride + 7) >> 3) << CANVAS_WIDTH_LBIT));
55+
56+
regmap_write(priv->dmc, DMC_CAV_LUT_DATAH,
57+
((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) <<
58+
CANVAS_WIDTH_HBIT) |
59+
(height << CANVAS_HEIGHT_BIT) |
60+
(wrap << 22) |
61+
(blkmode << CANVAS_BLKMODE_BIT));
62+
63+
regmap_write(priv->dmc, DMC_CAV_LUT_ADDR,
64+
CANVAS_LUT_WR_EN | canvas_index);
65+
66+
/* Force a read-back to make sure everything is flushed. */
67+
regmap_read(priv->dmc, DMC_CAV_LUT_DATAH, &val);
68+
}

drivers/gpu/drm/meson/meson_canvas.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (C) 2016 BayLibre, SAS
3+
* Author: Neil Armstrong <[email protected]>
4+
* Copyright (C) 2014 Endless Mobile
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License as
8+
* published by the Free Software Foundation; either version 2 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but
12+
* WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
/* Canvas LUT Memory */
21+
22+
#ifndef __MESON_CANVAS_H
23+
#define __MESON_CANVAS_H
24+
25+
#define MESON_CANVAS_ID_OSD1 0x4e
26+
27+
/* Canvas configuration. */
28+
#define MESON_CANVAS_WRAP_NONE 0x00
29+
#define MESON_CANVAS_WRAP_X 0x01
30+
#define MESON_CANVAS_WRAP_Y 0x02
31+
32+
#define MESON_CANVAS_BLKMODE_LINEAR 0x00
33+
#define MESON_CANVAS_BLKMODE_32x32 0x01
34+
#define MESON_CANVAS_BLKMODE_64x64 0x02
35+
36+
void meson_canvas_setup(struct meson_drm *priv,
37+
uint32_t canvas_index, uint32_t addr,
38+
uint32_t stride, uint32_t height,
39+
unsigned int wrap,
40+
unsigned int blkmode);
41+
42+
#endif /* __MESON_CANVAS_H */

drivers/gpu/drm/meson/meson_crtc.c

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
* Copyright (C) 2016 BayLibre, SAS
3+
* Author: Neil Armstrong <[email protected]>
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+
* Written by:
21+
* Jasper St. Pierre <[email protected]>
22+
*/
23+
24+
#include <linux/kernel.h>
25+
#include <linux/module.h>
26+
#include <linux/mutex.h>
27+
#include <linux/platform_device.h>
28+
#include <drm/drmP.h>
29+
#include <drm/drm_atomic.h>
30+
#include <drm/drm_atomic_helper.h>
31+
#include <drm/drm_flip_work.h>
32+
#include <drm/drm_crtc_helper.h>
33+
34+
#include "meson_crtc.h"
35+
#include "meson_plane.h"
36+
#include "meson_vpp.h"
37+
#include "meson_viu.h"
38+
#include "meson_registers.h"
39+
40+
/* CRTC definition */
41+
42+
struct meson_crtc {
43+
struct drm_crtc base;
44+
struct drm_pending_vblank_event *event;
45+
struct meson_drm *priv;
46+
};
47+
#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
48+
49+
/* CRTC */
50+
51+
static const struct drm_crtc_funcs meson_crtc_funcs = {
52+
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
53+
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
54+
.destroy = drm_crtc_cleanup,
55+
.page_flip = drm_atomic_helper_page_flip,
56+
.reset = drm_atomic_helper_crtc_reset,
57+
.set_config = drm_atomic_helper_set_config,
58+
};
59+
60+
static void meson_crtc_enable(struct drm_crtc *crtc)
61+
{
62+
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
63+
struct drm_plane *plane = meson_crtc->priv->primary_plane;
64+
struct meson_drm *priv = meson_crtc->priv;
65+
66+
/* Enable VPP Postblend */
67+
writel(plane->state->crtc_w,
68+
priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
69+
70+
writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
71+
priv->io_base + _REG(VPP_MISC));
72+
73+
priv->viu.osd1_enabled = true;
74+
}
75+
76+
static void meson_crtc_disable(struct drm_crtc *crtc)
77+
{
78+
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
79+
struct meson_drm *priv = meson_crtc->priv;
80+
81+
priv->viu.osd1_enabled = false;
82+
83+
/* Disable VPP Postblend */
84+
writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
85+
priv->io_base + _REG(VPP_MISC));
86+
87+
if (crtc->state->event && !crtc->state->active) {
88+
spin_lock_irq(&crtc->dev->event_lock);
89+
drm_crtc_send_vblank_event(crtc, crtc->state->event);
90+
spin_unlock_irq(&crtc->dev->event_lock);
91+
92+
crtc->state->event = NULL;
93+
}
94+
}
95+
96+
static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
97+
struct drm_crtc_state *state)
98+
{
99+
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
100+
unsigned long flags;
101+
102+
if (crtc->state->event) {
103+
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
104+
105+
spin_lock_irqsave(&crtc->dev->event_lock, flags);
106+
meson_crtc->event = crtc->state->event;
107+
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
108+
crtc->state->event = NULL;
109+
}
110+
}
111+
112+
static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
113+
struct drm_crtc_state *old_crtc_state)
114+
{
115+
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
116+
struct meson_drm *priv = meson_crtc->priv;
117+
118+
if (priv->viu.osd1_enabled)
119+
priv->viu.osd1_commit = true;
120+
}
121+
122+
static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
123+
.enable = meson_crtc_enable,
124+
.disable = meson_crtc_disable,
125+
.atomic_begin = meson_crtc_atomic_begin,
126+
.atomic_flush = meson_crtc_atomic_flush,
127+
};
128+
129+
void meson_crtc_irq(struct meson_drm *priv)
130+
{
131+
struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
132+
unsigned long flags;
133+
134+
/* Update the OSD registers */
135+
if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
136+
writel_relaxed(priv->viu.osd1_ctrl_stat,
137+
priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
138+
writel_relaxed(priv->viu.osd1_blk0_cfg[0],
139+
priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
140+
writel_relaxed(priv->viu.osd1_blk0_cfg[1],
141+
priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
142+
writel_relaxed(priv->viu.osd1_blk0_cfg[2],
143+
priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
144+
writel_relaxed(priv->viu.osd1_blk0_cfg[3],
145+
priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
146+
writel_relaxed(priv->viu.osd1_blk0_cfg[4],
147+
priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
148+
149+
/* If output is interlace, make use of the Scaler */
150+
if (priv->viu.osd1_interlace) {
151+
struct drm_plane *plane = priv->primary_plane;
152+
struct drm_plane_state *state = plane->state;
153+
struct drm_rect dest = {
154+
.x1 = state->crtc_x,
155+
.y1 = state->crtc_y,
156+
.x2 = state->crtc_x + state->crtc_w,
157+
.y2 = state->crtc_y + state->crtc_h,
158+
};
159+
160+
meson_vpp_setup_interlace_vscaler_osd1(priv, &dest);
161+
} else
162+
meson_vpp_disable_interlace_vscaler_osd1(priv);
163+
164+
/* Enable OSD1 */
165+
writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
166+
priv->io_base + _REG(VPP_MISC));
167+
168+
priv->viu.osd1_commit = false;
169+
}
170+
171+
drm_crtc_handle_vblank(priv->crtc);
172+
173+
spin_lock_irqsave(&priv->drm->event_lock, flags);
174+
if (meson_crtc->event) {
175+
drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event);
176+
drm_crtc_vblank_put(priv->crtc);
177+
meson_crtc->event = NULL;
178+
}
179+
spin_unlock_irqrestore(&priv->drm->event_lock, flags);
180+
}
181+
182+
int meson_crtc_create(struct meson_drm *priv)
183+
{
184+
struct meson_crtc *meson_crtc;
185+
struct drm_crtc *crtc;
186+
int ret;
187+
188+
meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
189+
GFP_KERNEL);
190+
if (!meson_crtc)
191+
return -ENOMEM;
192+
193+
meson_crtc->priv = priv;
194+
crtc = &meson_crtc->base;
195+
ret = drm_crtc_init_with_planes(priv->drm, crtc,
196+
priv->primary_plane, NULL,
197+
&meson_crtc_funcs, "meson_crtc");
198+
if (ret) {
199+
dev_err(priv->drm->dev, "Failed to init CRTC\n");
200+
return ret;
201+
}
202+
203+
drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
204+
205+
priv->crtc = crtc;
206+
207+
return 0;
208+
}

drivers/gpu/drm/meson/meson_crtc.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (C) 2016 BayLibre, SAS
3+
* Author: Neil Armstrong <[email protected]>
4+
* Copyright (C) 2014 Endless Mobile
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License as
8+
* published by the Free Software Foundation; either version 2 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but
12+
* WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, see <http://www.gnu.org/licenses/>.
18+
*
19+
* Written by:
20+
* Jasper St. Pierre <[email protected]>
21+
*/
22+
23+
#ifndef __MESON_CRTC_H
24+
#define __MESON_CRTC_H
25+
26+
#include "meson_drv.h"
27+
28+
int meson_crtc_create(struct meson_drm *priv);
29+
30+
void meson_crtc_irq(struct meson_drm *priv);
31+
32+
#endif /* __MESON_CRTC_H */

0 commit comments

Comments
 (0)