2019-03-25 14:21:07

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 00/11] drm/meson: Add G12A Support

The Amlogic G12A SoC offers very close Video Display
functionnalities with it's older GXBB, GXL & GXM predecessors.

The main differences are :
- G12A Support now 3 "real" OSD planes with a new Blender module
- Instead of having a single Scaler for OSD1, G12A has two scaler
that can be applied to 2 out of the 3 OSD planes or on the outputs
of the blender module.
- The HDMI PHY now support RX-SENSE, Dynamic HDR and it's registers are
now memory mapped instead of using an internal bus.
- The VPU now support a DSI interface to connect a display, using
the Synopsys DSI controller and a custom PHY

The complex Blender routing, HDMI RX-SENSE, Dynamic HDR and DSI support
are not handled in this patchset.

This patchset implements on-par support with the currently support
GXBB, GXL and GXM SoCs. There is no support delta with this patchset.

patch 10 & 11 implements the bindings found at [1].

[1] https://lkml.kernel.org/r/[email protected]

Neil Armstrong (11):
drm/meson: Switch PLL to 5.94GHz base for 297Mhz pixel clock
drm/meson: Add registers for G12A SoC
drm/meson: Add G12A Support for VPP setup
drm/meson: Add G12A Support for VIU setup
drm/meson: Add G12A support for OSD1 Plane
drm/meson: Add G12A Support for the Overlay video plane
drm/meson: Add G12A support for plane handling in CRTC driver
drm/meson: Add G12A support for CVBS Encoer
drm/meson: Add G12A Video Clock setup
drm/meson: Add G12A compatible
drm/meson: Add G12A support for the DW-HDMI Glue

drivers/gpu/drm/meson/meson_crtc.c | 269 +++++++++++++++++++-----
drivers/gpu/drm/meson/meson_drv.c | 1 +
drivers/gpu/drm/meson/meson_drv.h | 4 +
drivers/gpu/drm/meson/meson_dw_hdmi.c | 163 +++++++++++---
drivers/gpu/drm/meson/meson_dw_hdmi.h | 32 ++-
drivers/gpu/drm/meson/meson_overlay.c | 10 +-
drivers/gpu/drm/meson/meson_plane.c | 15 +-
drivers/gpu/drm/meson/meson_registers.h | 247 ++++++++++++++++++++++
drivers/gpu/drm/meson/meson_vclk.c | 123 +++++++++--
drivers/gpu/drm/meson/meson_venc.c | 11 +-
drivers/gpu/drm/meson/meson_venc_cvbs.c | 25 ++-
drivers/gpu/drm/meson/meson_viu.c | 72 ++++++-
drivers/gpu/drm/meson/meson_vpp.c | 51 +++--
13 files changed, 880 insertions(+), 143 deletions(-)

--
2.21.0



2019-03-25 14:19:47

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 11/11] drm/meson: Add G12A support for the DW-HDMI Glue

The Amlogic G12A embeds the same Synopsys DW-HDMI Controller,
but with :
- a "backport" of the HDR signaling registers from more recent
DW-HDMI controllers, this will need a tweak since it's not
normally present on this version of the DW-HDMI controller
- A direct mapping of TOP and DW-HDMI registers instead of an
internal bus accessed using read/write registers
- Support for RX-SENSE, but not yet implemented
- Support for HDMI 2.1 Dynamic HDR, but not yet implemented
- Different registers mapping for the HDMI PHY setup

This patchs adds support for these changes while providing exact
same support as the previous GXBB, GXL & GXM SoCs.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_dw_hdmi.c | 163 ++++++++++++++++++++------
drivers/gpu/drm/meson/meson_dw_hdmi.h | 32 ++++-
2 files changed, 157 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index 563953ec6ad0..779da21143b9 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/component.h>
+#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/reset.h>
#include <linux/clk.h>
@@ -105,6 +106,7 @@
#define HDMITX_TOP_ADDR_REG 0x0
#define HDMITX_TOP_DATA_REG 0x4
#define HDMITX_TOP_CTRL_REG 0x8
+#define HDMITX_TOP_G12A_OFFSET 0x8000

/* Controller Communication Channel */
#define HDMITX_DWC_ADDR_REG 0x10
@@ -118,6 +120,8 @@
#define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */
#define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */
#define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */
+#define HHI_HDMI_PHY_CNTL4 0x3b0 /* 0xec */
+#define HHI_HDMI_PHY_CNTL5 0x3b4 /* 0xed */

static DEFINE_SPINLOCK(reg_lock);

@@ -127,12 +131,26 @@ enum meson_venc_source {
MESON_VENC_SOURCE_ENCP = 2,
};

+struct meson_dw_hdmi;
+
+struct meson_dw_hdmi_data {
+ unsigned int (*top_read)(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr);
+ void (*top_write)(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr, unsigned int data);
+ unsigned int (*dwc_read)(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr);
+ void (*dwc_write)(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr, unsigned int data);
+};
+
struct meson_dw_hdmi {
struct drm_encoder encoder;
struct dw_hdmi_plat_data dw_plat_data;
struct meson_drm *priv;
struct device *dev;
void __iomem *hdmitx;
+ const struct meson_dw_hdmi_data *data;
struct reset_control *hdmitx_apb;
struct reset_control *hdmitx_ctrl;
struct reset_control *hdmitx_phy;
@@ -174,6 +192,12 @@ static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi,
return data;
}

+static unsigned int dw_hdmi_g12a_top_read(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr)
+{
+ return readl(dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
+}
+
static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
unsigned int addr, unsigned int data)
{
@@ -191,18 +215,24 @@ static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
spin_unlock_irqrestore(&reg_lock, flags);
}

+static inline void dw_hdmi_g12a_top_write(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr, unsigned int data)
+{
+ writel(data, dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
+}
+
/* Helper to change specific bits in PHY registers */
static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
unsigned int addr,
unsigned int mask,
unsigned int val)
{
- unsigned int data = dw_hdmi_top_read(dw_hdmi, addr);
+ unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr);

data &= ~mask;
data |= val;

- dw_hdmi_top_write(dw_hdmi, addr, data);
+ dw_hdmi->data->top_write(dw_hdmi, addr, data);
}

static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
@@ -226,6 +256,12 @@ static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
return data;
}

+static unsigned int dw_hdmi_g12a_dwc_read(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr)
+{
+ return readb(dw_hdmi->hdmitx + addr);
+}
+
static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
unsigned int addr, unsigned int data)
{
@@ -243,18 +279,24 @@ static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
spin_unlock_irqrestore(&reg_lock, flags);
}

+static inline void dw_hdmi_g12a_dwc_write(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr, unsigned int data)
+{
+ writeb(data, dw_hdmi->hdmitx + addr);
+}
+
/* Helper to change specific bits in controller registers */
static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
unsigned int addr,
unsigned int mask,
unsigned int val)
{
- unsigned int data = dw_hdmi_dwc_read(dw_hdmi, addr);
+ unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr);

data &= ~mask;
data |= val;

- dw_hdmi_dwc_write(dw_hdmi, addr, data);
+ dw_hdmi->data->dwc_write(dw_hdmi, addr, data);
}

/* Bridge */
@@ -300,6 +342,24 @@ static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
}
+ } else if (dw_hdmi_is_compatible(dw_hdmi,
+ "amlogic,meson-g12a-dw-hdmi")) {
+ if (pixel_clock >= 371250) {
+ /* 5.94Gbps, 3.7125Gbps */
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x0000080b);
+ } else if (pixel_clock >= 297000) {
+ /* 2.97Gbps */
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb6262);
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
+ } else {
+ /* 1.485Gbps, and below */
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb4242);
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
+ }
}
}

@@ -375,7 +435,7 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);

/* Bring out of reset */
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0);
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0);

/* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
@@ -384,24 +444,25 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
0x3 << 4, 0x3 << 4);

/* Enable normal output to PHY */
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));

/* TMDS pattern setup (TOFIX Handle the YUV420 case) */
if (mode->clock > 340000) {
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0);
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
+ 0);
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
0x03ff03ff);
} else {
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
0x001f001f);
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
0x001f001f);
}

/* Load TMDS pattern */
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
msleep(20);
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);

/* Setup PHY parameters */
meson_hdmi_phy_setup_mode(dw_hdmi, mode);
@@ -412,7 +473,8 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,

/* BIT_INVERT */
if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
- dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi"))
+ dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
+ dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
BIT(17), 0);
else
@@ -480,7 +542,7 @@ static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
{
struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;

- return !!dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
+ return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
connector_status_connected : connector_status_disconnected;
}

@@ -490,11 +552,11 @@ static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;

/* Setup HPD Filter */
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
(0xa << 12) | 0xa0);

/* Clear interrupts */
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);

/* Unmask interrupts */
@@ -515,8 +577,8 @@ static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
struct meson_dw_hdmi *dw_hdmi = dev_id;
u32 stat;

- stat = dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
+ stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);

/* HPD Events, handle in the threaded interrupt handler */
if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
@@ -686,7 +748,9 @@ static const struct drm_encoder_helper_funcs
static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
unsigned int *result)
{
- *result = dw_hdmi_dwc_read(context, reg);
+ struct meson_dw_hdmi *dw_hdmi = context;
+
+ *result = dw_hdmi->data->dwc_read(dw_hdmi, reg);

return 0;

@@ -695,7 +759,9 @@ static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
unsigned int val)
{
- dw_hdmi_dwc_write(context, reg, val);
+ struct meson_dw_hdmi *dw_hdmi = context;
+
+ dw_hdmi->data->dwc_write(dw_hdmi, reg, val);

return 0;
}
@@ -709,6 +775,20 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = {
.fast_io = true,
};

+static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
+ .top_read = dw_hdmi_top_read,
+ .top_write = dw_hdmi_top_write,
+ .dwc_read = dw_hdmi_dwc_read,
+ .dwc_write = dw_hdmi_dwc_write,
+};
+
+static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
+ .top_read = dw_hdmi_g12a_top_read,
+ .top_write = dw_hdmi_g12a_top_write,
+ .dwc_read = dw_hdmi_g12a_dwc_read,
+ .dwc_write = dw_hdmi_g12a_dwc_write,
+};
+
static bool meson_hdmi_connector_is_available(struct device *dev)
{
struct device_node *ep, *remote;
@@ -735,6 +815,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
void *data)
{
struct platform_device *pdev = to_platform_device(dev);
+ const struct meson_dw_hdmi_data *match;
struct meson_dw_hdmi *meson_dw_hdmi;
struct drm_device *drm = data;
struct meson_drm *priv = drm->dev_private;
@@ -751,6 +832,12 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
return -ENODEV;
}

+ match = of_device_get_match_data(&pdev->dev);
+ if (!match) {
+ dev_err(&pdev->dev, "failed to get match data\n");
+ return -ENODEV;
+ }
+
meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
GFP_KERNEL);
if (!meson_dw_hdmi)
@@ -758,6 +845,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,

meson_dw_hdmi->priv = priv;
meson_dw_hdmi->dev = dev;
+ meson_dw_hdmi->data = match;
dw_plat_data = &meson_dw_hdmi->dw_plat_data;
encoder = &meson_dw_hdmi->encoder;

@@ -858,24 +946,28 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
reset_control_reset(meson_dw_hdmi->hdmitx_phy);

/* Enable APB3 fail on error */
- writel_bits_relaxed(BIT(15), BIT(15),
- meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
- writel_bits_relaxed(BIT(15), BIT(15),
- meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
+ if (!meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ writel_bits_relaxed(BIT(15), BIT(15),
+ meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
+ writel_bits_relaxed(BIT(15), BIT(15),
+ meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
+ }

/* Bring out of reset */
- dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_SW_RESET, 0);
+ meson_dw_hdmi->data->top_write(meson_dw_hdmi,
+ HDMITX_TOP_SW_RESET, 0);

msleep(20);

- dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_CLK_CNTL, 0xff);
+ meson_dw_hdmi->data->top_write(meson_dw_hdmi,
+ HDMITX_TOP_CLK_CNTL, 0xff);

/* Enable HDMI-TX Interrupt */
- dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
- HDMITX_TOP_INTR_CORE);
+ meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
+ HDMITX_TOP_INTR_CORE);

- dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
- HDMITX_TOP_INTR_CORE);
+ meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
+ HDMITX_TOP_INTR_CORE);

/* Bridge / Connector */

@@ -924,9 +1016,14 @@ static int meson_dw_hdmi_remove(struct platform_device *pdev)
}

static const struct of_device_id meson_dw_hdmi_of_table[] = {
- { .compatible = "amlogic,meson-gxbb-dw-hdmi" },
- { .compatible = "amlogic,meson-gxl-dw-hdmi" },
- { .compatible = "amlogic,meson-gxm-dw-hdmi" },
+ { .compatible = "amlogic,meson-gxbb-dw-hdmi",
+ .data = &meson_dw_hdmi_gx_data },
+ { .compatible = "amlogic,meson-gxl-dw-hdmi",
+ .data = &meson_dw_hdmi_gx_data },
+ { .compatible = "amlogic,meson-gxm-dw-hdmi",
+ .data = &meson_dw_hdmi_gx_data },
+ { .compatible = "amlogic,meson-g12a-dw-hdmi",
+ .data = &meson_dw_hdmi_g12a_data },
{ }
};
MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.h b/drivers/gpu/drm/meson/meson_dw_hdmi.h
index 0b81183125e3..03e2f0c1a2d5 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.h
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.h
@@ -21,9 +21,12 @@
#define __MESON_DW_HDMI_H

/*
- * Bit 7 RW Reserved. Default 1.
- * Bit 6 RW Reserved. Default 1.
- * Bit 5 RW Reserved. Default 1.
+ * Bit 15-10: RW Reserved. Default 1 starting from G12A
+ * Bit 9 RW sw_reset_i2c starting from G12A
+ * Bit 8 RW sw_reset_axiarb starting from G12A
+ * Bit 7 RW Reserved. Default 1, sw_reset_emp starting from G12A
+ * Bit 6 RW Reserved. Default 1, sw_reset_flt starting from G12A
+ * Bit 5 RW Reserved. Default 1, sw_reset_hdcp22 starting from G12A
* Bit 4 RW sw_reset_phyif: PHY interface. 1=Apply reset; 0=Release from reset.
* Default 1.
* Bit 3 RW sw_reset_intr: interrupt module. 1=Apply reset;
@@ -39,12 +42,16 @@
#define HDMITX_TOP_SW_RESET (0x000)

/*
+ * Bit 31 RW free_clk_en: 0=Enable clock gating for power saving; 1= Disable
* Bit 12 RW i2s_ws_inv:1=Invert i2s_ws; 0=No invert. Default 0.
* Bit 11 RW i2s_clk_inv: 1=Invert i2s_clk; 0=No invert. Default 0.
* Bit 10 RW spdif_clk_inv: 1=Invert spdif_clk; 0=No invert. Default 0.
* Bit 9 RW tmds_clk_inv: 1=Invert tmds_clk; 0=No invert. Default 0.
* Bit 8 RW pixel_clk_inv: 1=Invert pixel_clk; 0=No invert. Default 0.
- * Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0.
+ * Bit 7 RW hdcp22_skpclk_en: starting from G12A, 1=enable; 0=disable
+ * Bit 6 RW hdcp22_esmclk_en: starting from G12A, 1=enable; 0=disable
+ * Bit 5 RW hdcp22_tmdsclk_en: starting from G12A, 1=enable; 0=disable
+ * Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0. Reserved for G12A
* Bit 3 RW i2s_clk_en: 1=enable i2s_clk; 0=disable. Default 0.
* Bit 2 RW spdif_clk_en: 1=enable spdif_clk; 0=disable. Default 0.
* Bit 1 RW tmds_clk_en: 1=enable tmds_clk; 0=disable. Default 0.
@@ -53,6 +60,8 @@
#define HDMITX_TOP_CLK_CNTL (0x001)

/*
+ * Bit 31:28 RW rxsense_glitch_width: starting from G12A
+ * Bit 27:16 RW rxsense_valid_width: starting from G12A
* Bit 11: 0 RW hpd_valid_width: filter out width <= M*1024. Default 0.
* Bit 15:12 RW hpd_glitch_width: filter out glitch <= N. Default 0.
*/
@@ -61,6 +70,9 @@
/*
* intr_maskn: MASK_N, one bit per interrupt source.
* 1=Enable interrupt source; 0=Disable interrupt source. Default 0.
+ * [ 7] rxsense_fall starting from G12A
+ * [ 6] rxsense_rise starting from G12A
+ * [ 5] err_i2c_timeout starting from G12A
* [ 4] hdcp22_rndnum_err
* [ 3] nonce_rfrsh_rise
* [ 2] hpd_fall_intr
@@ -73,6 +85,9 @@
* Bit 30: 0 RW intr_stat: For each bit, write 1 to manually set the interrupt
* bit, read back the interrupt status.
* Bit 31 R IP interrupt status
+ * Bit 7 RW rxsense_fall starting from G12A
+ * Bit 6 RW rxsense_rise starting from G12A
+ * Bit 5 RW err_i2c_timeout starting from G12A
* Bit 2 RW hpd_fall
* Bit 1 RW hpd_rise
* Bit 0 RW IP interrupt
@@ -80,6 +95,9 @@
#define HDMITX_TOP_INTR_STAT (0x004)

/*
+ * [7] rxsense_fall starting from G12A
+ * [6] rxsense_rise starting from G12A
+ * [5] err_i2c_timeout starting from G12A
* [4] hdcp22_rndnum_err
* [3] nonce_rfrsh_rise
* [2] hpd_fall
@@ -91,6 +109,8 @@
#define HDMITX_TOP_INTR_CORE BIT(0)
#define HDMITX_TOP_INTR_HPD_RISE BIT(1)
#define HDMITX_TOP_INTR_HPD_FALL BIT(2)
+#define HDMITX_TOP_INTR_RXSENSE_RISE BIT(6)
+#define HDMITX_TOP_INTR_RXSENSE_FALL BIT(7)

/* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data;
* 3'b010=Output PRBS data; 3'b100=Output shift pattern. Default 0.
@@ -140,7 +160,9 @@
*/
#define HDMITX_TOP_REVOCMEM_STAT (0x00D)

-/* Bit 0 R filtered HPD status. */
+/* Bit 1 R filtered RxSense status
+ * Bit 0 R filtered HPD status.
+ */
#define HDMITX_TOP_STAT0 (0x00E)

#endif /* __MESON_DW_HDMI_H */
--
2.21.0


2019-03-25 14:19:49

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 07/11] drm/meson: Add G12A support for plane handling in CRTC driver

This patch adds support for the new OSD+VD Plane blending module
in the CRTC code by adding the G12A code to manage the blending
module and setting the right OSD1 & VD1 plane registers.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_crtc.c | 269 +++++++++++++++++++++++------
drivers/gpu/drm/meson/meson_drv.h | 4 +
2 files changed, 221 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
index 6d9311e254ef..5579f8ac3e3f 100644
--- a/drivers/gpu/drm/meson/meson_crtc.c
+++ b/drivers/gpu/drm/meson/meson_crtc.c
@@ -39,12 +39,17 @@
#include "meson_viu.h"
#include "meson_registers.h"

+#define MESON_G12A_VIU_OFFSET 0x5ec0
+
/* CRTC definition */

struct meson_crtc {
struct drm_crtc base;
struct drm_pending_vblank_event *event;
struct meson_drm *priv;
+ void (*enable_osd1)(struct meson_drm *priv);
+ void (*enable_vd1)(struct meson_drm *priv);
+ unsigned int viu_offset;
};
#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)

@@ -80,6 +85,44 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {

};

+static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+ struct drm_crtc_state *crtc_state = crtc->state;
+ struct meson_drm *priv = meson_crtc->priv;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (!crtc_state) {
+ DRM_ERROR("Invalid crtc_state\n");
+ return;
+ }
+
+ /* VD1 Preblend vertical start/end */
+ writel(FIELD_PREP(GENMASK(11, 0), 2303),
+ priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
+
+ /* Setup Blender */
+ writel(crtc_state->mode.hdisplay |
+ crtc_state->mode.vdisplay << 16,
+ priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
+
+ writel_relaxed(0 << 16 |
+ (crtc_state->mode.hdisplay - 1),
+ priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
+ writel_relaxed(0 << 16 |
+ (crtc_state->mode.vdisplay - 1),
+ priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
+ writel_relaxed(crtc_state->mode.hdisplay << 16 |
+ crtc_state->mode.vdisplay,
+ priv->io_base + _REG(VPP_OUT_H_V_SIZE));
+
+ drm_crtc_vblank_on(crtc);
+
+ priv->viu.osd1_enabled = true;
+}
+
static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
@@ -110,6 +153,31 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
priv->viu.osd1_enabled = true;
}

+static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+ struct meson_drm *priv = meson_crtc->priv;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ drm_crtc_vblank_off(crtc);
+
+ priv->viu.osd1_enabled = false;
+ priv->viu.osd1_commit = false;
+
+ priv->viu.vd1_enabled = false;
+ priv->viu.vd1_commit = false;
+
+ if (crtc->state->event && !crtc->state->active) {
+ spin_lock_irq(&crtc->dev->event_lock);
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ spin_unlock_irq(&crtc->dev->event_lock);
+
+ crtc->state->event = NULL;
+ }
+}
+
static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
@@ -173,6 +241,53 @@ static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
.atomic_disable = meson_crtc_atomic_disable,
};

+static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
+ .atomic_begin = meson_crtc_atomic_begin,
+ .atomic_flush = meson_crtc_atomic_flush,
+ .atomic_enable = meson_g12a_crtc_atomic_enable,
+ .atomic_disable = meson_g12a_crtc_atomic_disable,
+};
+
+static void meson_crtc_enable_osd1(struct meson_drm *priv)
+{
+ writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
+ priv->io_base + _REG(VPP_MISC));
+}
+
+static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
+{
+ writel_relaxed(priv->viu.osd_blend_din0_scope_h,
+ priv->io_base +
+ _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
+ writel_relaxed(priv->viu.osd_blend_din0_scope_v,
+ priv->io_base +
+ _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
+ writel_relaxed(priv->viu.osb_blend0_size,
+ priv->io_base +
+ _REG(VIU_OSD_BLEND_BLEND0_SIZE));
+ writel_relaxed(priv->viu.osb_blend1_size,
+ priv->io_base +
+ _REG(VIU_OSD_BLEND_BLEND1_SIZE));
+}
+
+static void meson_crtc_enable_vd1(struct meson_drm *priv)
+{
+ writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
+ VPP_COLOR_MNG_ENABLE,
+ VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
+ VPP_COLOR_MNG_ENABLE,
+ priv->io_base + _REG(VPP_MISC));
+}
+
+static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
+{
+ writel_relaxed(((1 << 16) | /* post bld premult*/
+ (1 << 8) | /* post src */
+ (1 << 4) | /* pre bld premult*/
+ (1 << 0)),
+ priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
+}
+
void meson_crtc_irq(struct meson_drm *priv)
{
struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
@@ -219,8 +334,8 @@ void meson_crtc_irq(struct meson_drm *priv)
MESON_CANVAS_BLKMODE_LINEAR, 0);

/* Enable OSD1 */
- writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
- priv->io_base + _REG(VPP_MISC));
+ if (meson_crtc->enable_osd1)
+ meson_crtc->enable_osd1(priv);

priv->viu.osd1_commit = false;
}
@@ -261,89 +376,133 @@ void meson_crtc_irq(struct meson_drm *priv)
};

writel_relaxed(priv->viu.vd1_if0_gen_reg,
- priv->io_base + _REG(VD1_IF0_GEN_REG));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_GEN_REG));
writel_relaxed(priv->viu.vd1_if0_gen_reg,
- priv->io_base + _REG(VD2_IF0_GEN_REG));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_GEN_REG));
writel_relaxed(priv->viu.vd1_if0_gen_reg2,
- priv->io_base + _REG(VD1_IF0_GEN_REG2));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_GEN_REG2));
writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
- priv->io_base + _REG(VIU_VD1_FMT_CTRL));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VIU_VD1_FMT_CTRL));
writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
- priv->io_base + _REG(VIU_VD2_FMT_CTRL));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VIU_VD2_FMT_CTRL));
writel_relaxed(priv->viu.viu_vd1_fmt_w,
- priv->io_base + _REG(VIU_VD1_FMT_W));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VIU_VD1_FMT_W));
writel_relaxed(priv->viu.viu_vd1_fmt_w,
- priv->io_base + _REG(VIU_VD2_FMT_W));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VIU_VD2_FMT_W));
writel_relaxed(priv->viu.vd1_if0_canvas0,
- priv->io_base + _REG(VD1_IF0_CANVAS0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CANVAS0));
writel_relaxed(priv->viu.vd1_if0_canvas0,
- priv->io_base + _REG(VD1_IF0_CANVAS1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CANVAS1));
writel_relaxed(priv->viu.vd1_if0_canvas0,
- priv->io_base + _REG(VD2_IF0_CANVAS0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CANVAS0));
writel_relaxed(priv->viu.vd1_if0_canvas0,
- priv->io_base + _REG(VD2_IF0_CANVAS1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CANVAS1));
writel_relaxed(priv->viu.vd1_if0_luma_x0,
- priv->io_base + _REG(VD1_IF0_LUMA_X0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_LUMA_X0));
writel_relaxed(priv->viu.vd1_if0_luma_x0,
- priv->io_base + _REG(VD1_IF0_LUMA_X1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_LUMA_X1));
writel_relaxed(priv->viu.vd1_if0_luma_x0,
- priv->io_base + _REG(VD2_IF0_LUMA_X0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_LUMA_X0));
writel_relaxed(priv->viu.vd1_if0_luma_x0,
- priv->io_base + _REG(VD2_IF0_LUMA_X1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_LUMA_X1));
writel_relaxed(priv->viu.vd1_if0_luma_y0,
- priv->io_base + _REG(VD1_IF0_LUMA_Y0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_LUMA_Y0));
writel_relaxed(priv->viu.vd1_if0_luma_y0,
- priv->io_base + _REG(VD1_IF0_LUMA_Y1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_LUMA_Y1));
writel_relaxed(priv->viu.vd1_if0_luma_y0,
- priv->io_base + _REG(VD2_IF0_LUMA_Y0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_LUMA_Y0));
writel_relaxed(priv->viu.vd1_if0_luma_y0,
- priv->io_base + _REG(VD2_IF0_LUMA_Y1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_LUMA_Y1));
writel_relaxed(priv->viu.vd1_if0_chroma_x0,
- priv->io_base + _REG(VD1_IF0_CHROMA_X0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CHROMA_X0));
writel_relaxed(priv->viu.vd1_if0_chroma_x0,
- priv->io_base + _REG(VD1_IF0_CHROMA_X1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CHROMA_X1));
writel_relaxed(priv->viu.vd1_if0_chroma_x0,
- priv->io_base + _REG(VD2_IF0_CHROMA_X0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CHROMA_X0));
writel_relaxed(priv->viu.vd1_if0_chroma_x0,
- priv->io_base + _REG(VD2_IF0_CHROMA_X1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CHROMA_X1));
writel_relaxed(priv->viu.vd1_if0_chroma_y0,
- priv->io_base + _REG(VD1_IF0_CHROMA_Y0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CHROMA_Y0));
writel_relaxed(priv->viu.vd1_if0_chroma_y0,
- priv->io_base + _REG(VD1_IF0_CHROMA_Y1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CHROMA_Y1));
writel_relaxed(priv->viu.vd1_if0_chroma_y0,
- priv->io_base + _REG(VD2_IF0_CHROMA_Y0));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CHROMA_Y0));
writel_relaxed(priv->viu.vd1_if0_chroma_y0,
- priv->io_base + _REG(VD2_IF0_CHROMA_Y1));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CHROMA_Y1));
writel_relaxed(priv->viu.vd1_if0_repeat_loop,
- priv->io_base + _REG(VD1_IF0_RPT_LOOP));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_RPT_LOOP));
writel_relaxed(priv->viu.vd1_if0_repeat_loop,
- priv->io_base + _REG(VD2_IF0_RPT_LOOP));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_RPT_LOOP));
writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
- priv->io_base + _REG(VD1_IF0_LUMA0_RPT_PAT));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_LUMA0_RPT_PAT));
writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
- priv->io_base + _REG(VD2_IF0_LUMA0_RPT_PAT));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_LUMA0_RPT_PAT));
writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
- priv->io_base + _REG(VD1_IF0_LUMA1_RPT_PAT));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_LUMA1_RPT_PAT));
writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
- priv->io_base + _REG(VD2_IF0_LUMA1_RPT_PAT));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_LUMA1_RPT_PAT));
writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
- priv->io_base + _REG(VD1_IF0_CHROMA0_RPT_PAT));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CHROMA0_RPT_PAT));
writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
- priv->io_base + _REG(VD2_IF0_CHROMA0_RPT_PAT));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CHROMA0_RPT_PAT));
writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
- priv->io_base + _REG(VD1_IF0_CHROMA1_RPT_PAT));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CHROMA1_RPT_PAT));
writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
- priv->io_base + _REG(VD2_IF0_CHROMA1_RPT_PAT));
- writel_relaxed(0, priv->io_base + _REG(VD1_IF0_LUMA_PSEL));
- writel_relaxed(0, priv->io_base + _REG(VD1_IF0_CHROMA_PSEL));
- writel_relaxed(0, priv->io_base + _REG(VD2_IF0_LUMA_PSEL));
- writel_relaxed(0, priv->io_base + _REG(VD2_IF0_CHROMA_PSEL));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CHROMA1_RPT_PAT));
+ writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_LUMA_PSEL));
+ writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_CHROMA_PSEL));
+ writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_LUMA_PSEL));
+ writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
+ _REG(VD2_IF0_CHROMA_PSEL));
writel_relaxed(priv->viu.vd1_range_map_y,
- priv->io_base + _REG(VD1_IF0_RANGE_MAP_Y));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_RANGE_MAP_Y));
writel_relaxed(priv->viu.vd1_range_map_cb,
- priv->io_base + _REG(VD1_IF0_RANGE_MAP_CB));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_RANGE_MAP_CB));
writel_relaxed(priv->viu.vd1_range_map_cr,
- priv->io_base + _REG(VD1_IF0_RANGE_MAP_CR));
+ priv->io_base + meson_crtc->viu_offset +
+ _REG(VD1_IF0_RANGE_MAP_CR));
writel_relaxed(0x78404,
priv->io_base + _REG(VPP_SC_MISC));
writel_relaxed(priv->viu.vpp_pic_in_height,
@@ -389,11 +548,8 @@ void meson_crtc_irq(struct meson_drm *priv)
writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));

/* Enable VD1 */
- writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
- VPP_COLOR_MNG_ENABLE,
- VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
- VPP_COLOR_MNG_ENABLE,
- priv->io_base + _REG(VPP_MISC));
+ if (meson_crtc->enable_vd1)
+ meson_crtc->enable_vd1(priv);

priv->viu.vd1_commit = false;
}
@@ -430,7 +586,16 @@ int meson_crtc_create(struct meson_drm *priv)
return ret;
}

- drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
+ meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
+ meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
+ drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
+ } else {
+ meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
+ meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
+ drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
+ }

priv->crtc = crtc;

diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
index 214a7cb18ce2..9614baa836b9 100644
--- a/drivers/gpu/drm/meson/meson_drv.h
+++ b/drivers/gpu/drm/meson/meson_drv.h
@@ -62,6 +62,10 @@ struct meson_drm {
uint32_t osd_sc_h_phase_step;
uint32_t osd_sc_h_ctrl0;
uint32_t osd_sc_v_ctrl0;
+ uint32_t osd_blend_din0_scope_h;
+ uint32_t osd_blend_din0_scope_v;
+ uint32_t osb_blend0_size;
+ uint32_t osb_blend1_size;

bool vd1_enabled;
bool vd1_commit;
--
2.21.0


2019-03-25 14:19:52

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 10/11] drm/meson: Add G12A compatible

Finally add the Amlogic G12A SoC compatible for the VPU driver.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_drv.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 079d22299d78..faf1b1b0357c 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -447,6 +447,7 @@ static const struct of_device_id dt_match[] = {
{ .compatible = "amlogic,meson-gxbb-vpu" },
{ .compatible = "amlogic,meson-gxl-vpu" },
{ .compatible = "amlogic,meson-gxm-vpu" },
+ { .compatible = "amlogic,meson-g12a-vpu" },
{}
};
MODULE_DEVICE_TABLE(of, dt_match);
--
2.21.0


2019-03-25 14:20:04

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 09/11] drm/meson: Add G12A Video Clock setup

While switching to the Common Clock Framework is still Work In Progress,
this patch adds the corresponding G12A HDMI PLL setup to be on-par
with the other SoCs support.

The G12A has only a single tweak about the high frequency setup,
where the HDMI PLL needs a specific setup to handle correctly the
5.94GHz DCO frequency.

Apart that, it handle correctly all the other HDMI frequencies
and can achieve even better DMT clock frequency precision with
the larger fractional dividier width.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_vclk.c | 119 ++++++++++++++++++++++++++---
1 file changed, 108 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
index c15a5a5df633..b39034745444 100644
--- a/drivers/gpu/drm/meson/meson_vclk.c
+++ b/drivers/gpu/drm/meson/meson_vclk.c
@@ -113,9 +113,12 @@
#define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
#define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
#define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
+#define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */

#define HDMI_PLL_RESET BIT(28)
+#define HDMI_PLL_RESET_G12A BIT(29)
#define HDMI_PLL_LOCK BIT(31)
+#define HDMI_PLL_LOCK_G12A (3 << 30)

#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)

@@ -257,6 +260,10 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
+
+ /* Poll for lock bit */
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
+ (val & HDMI_PLL_LOCK), 10, 0);
} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
@@ -271,11 +278,26 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
HDMI_PLL_RESET, HDMI_PLL_RESET);
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
HDMI_PLL_RESET, 0);
- }

- /* Poll for lock bit */
- regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
- (val & HDMI_PLL_LOCK), 10, 0);
+ /* Poll for lock bit */
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
+ (val & HDMI_PLL_LOCK), 10, 0);
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00010000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x56540000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x3a0504f7);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
+
+ /* Poll for lock bit */
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
+ ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
+ 10, 0);
+ }

/* Disable VCLK2 */
regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
@@ -288,8 +310,13 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
VCLK2_DIV_MASK, (55 - 1));

/* select vid_pll for vclk2 */
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
- VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
+ else
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+
/* enable vclk2 gate */
regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);

@@ -476,32 +503,80 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
/* Poll for lock bit */
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
(val & HDMI_PLL_LOCK), 10, 0);
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
+
+ /* Enable and reset */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 0x3 << 28, 0x3 << 28);
+
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, frac);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
+
+ /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
+ if (m >= 0xf7) {
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0xea68dc00);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
+ } else {
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
+ }
+
+ do {
+ /* Reset PLL */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
+
+ /* UN-Reset PLL */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ HDMI_PLL_RESET_G12A, 0);
+
+ /* Poll for lock bits */
+ if (!regmap_read_poll_timeout(priv->hhi,
+ HHI_HDMI_PLL_CNTL, val,
+ ((val & HDMI_PLL_LOCK_G12A)
+ == HDMI_PLL_LOCK_G12A),
+ 10, 100))
+ break;
+ } while(1);
}

if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
3 << 16, pll_od_to_reg(od1) << 16);
else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
- meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
3 << 21, pll_od_to_reg(od1) << 21);
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 3 << 16, pll_od_to_reg(od1) << 16);

if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
3 << 22, pll_od_to_reg(od2) << 22);
else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
- meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
3 << 23, pll_od_to_reg(od2) << 23);
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 3 << 18, pll_od_to_reg(od2) << 18);

if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
3 << 18, pll_od_to_reg(od3) << 18);
else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
- meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
3 << 19, pll_od_to_reg(od3) << 19);
-
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 3 << 20, pll_od_to_reg(od3) << 20);
}

#define XTAL_FREQ 24000
@@ -518,6 +593,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,

#define HDMI_FRAC_MAX_GXBB 4096
#define HDMI_FRAC_MAX_GXL 1024
+#define HDMI_FRAC_MAX_G12A 131072

static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
unsigned int m,
@@ -534,6 +610,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
parent_freq *= 2;
}

+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ frac_max = HDMI_FRAC_MAX_G12A;
+
/* We can have a perfect match !*/
if (pll_freq / m == parent_freq &&
pll_freq % m == 0)
@@ -559,7 +638,8 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
if (frac >= HDMI_FRAC_MAX_GXBB)
return false;
} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
- meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu") ||
+ meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
/* Empiric supported min/max dividers */
if (m < 106 || m > 247)
return false;
@@ -713,6 +793,23 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
break;
}

+ meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ switch (pll_base_freq) {
+ case 2970000:
+ m = 0x7b;
+ frac = vic_alternate_clock ? 0x140b4 : 0x18000;
+ break;
+ case 4320000:
+ m = vic_alternate_clock ? 0xb3 : 0xb4;
+ frac = vic_alternate_clock ? 0x1a3ee : 0;
+ break;
+ case 5940000:
+ m = 0xf7;
+ frac = vic_alternate_clock ? 0x8148 : 0x10000;
+ break;
+ }
+
meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
}

--
2.21.0


2019-03-25 14:20:09

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 03/11] drm/meson: Add G12A Support for VPP setup

Amlogic G12A needs a different VPP setup code, handle it here.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_vpp.c | 51 ++++++++++++++++++-------------
1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c
index f9efb431e953..8c52a3455ef4 100644
--- a/drivers/gpu/drm/meson/meson_vpp.c
+++ b/drivers/gpu/drm/meson/meson_vpp.c
@@ -112,32 +112,39 @@ void meson_vpp_init(struct meson_drm *priv)
writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
writel_relaxed(0x1020080,
priv->io_base + _REG(VPP_DUMMY_DATA1));
- }
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ writel_relaxed(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));

/* Initialize vpu fifo control registers */
- writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
- 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ writel_relaxed(0xfff << 20 | 0x1000,
+ priv->io_base + _REG(VPP_OFIFO_SIZE));
+ else
+ writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
+ 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));

- /* Turn off preblend */
- writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
- priv->io_base + _REG(VPP_MISC));
-
- /* Turn off POSTBLEND */
- writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
- priv->io_base + _REG(VPP_MISC));
-
- /* Force all planes off */
- writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
- VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
- VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
- priv->io_base + _REG(VPP_MISC));
-
- /* Setup default VD settings */
- writel_relaxed(4096,
- priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
- writel_relaxed(4096,
- priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
+ if (!meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ /* Turn off preblend */
+ writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
+ priv->io_base + _REG(VPP_MISC));
+
+ /* Turn off POSTBLEND */
+ writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
+ priv->io_base + _REG(VPP_MISC));
+
+ /* Force all planes off */
+ writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
+ VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
+ VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
+ priv->io_base + _REG(VPP_MISC));
+
+ /* Setup default VD settings */
+ writel_relaxed(4096,
+ priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
+ writel_relaxed(4096,
+ priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
+ }

/* Disable Scalers */
writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
--
2.21.0


2019-03-25 14:20:13

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 08/11] drm/meson: Add G12A support for CVBS Encoer

The Meson G12A SoCs uses the exact same CVBS encoder except a simple
CVBS DAC register offset and settings delta.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_venc.c | 11 +++++++++--
drivers/gpu/drm/meson/meson_venc_cvbs.c | 25 ++++++++++++++++++-------
2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
index 66d73a932d19..6faca7313339 100644
--- a/drivers/gpu/drm/meson/meson_venc.c
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -73,7 +73,9 @@
/* HHI Registers */
#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */
#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
+#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */
#define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */

struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
@@ -1675,8 +1677,13 @@ void meson_venc_disable_vsync(struct meson_drm *priv)
void meson_venc_init(struct meson_drm *priv)
{
/* Disable CVBS VDAC */
- regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
- regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 8);
+ } else {
+ regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
+ }

/* Power Down Dacs */
writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
index d622d817b6df..2c5341c881c4 100644
--- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
@@ -37,7 +37,9 @@

/* HHI VDAC Registers */
#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
+#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */

struct meson_venc_cvbs {
struct drm_encoder encoder;
@@ -166,8 +168,13 @@ static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
struct meson_drm *priv = meson_venc_cvbs->priv;

/* Disable CVBS VDAC */
- regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
- regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
+ } else {
+ regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
+ }
}

static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
@@ -179,13 +186,17 @@ static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
/* VDAC0 source is not from ATV */
writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));

- if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
- else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
- meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
-
- regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0x906001);
+ regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
+ }
}

static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
--
2.21.0


2019-03-25 14:20:44

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 02/11] drm/meson: Add registers for G12A SoC

This patch adds the new VPU registers added since the
Amlogic GXM SoCs.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_registers.h | 247 ++++++++++++++++++++++++
1 file changed, 247 insertions(+)

diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
index 5c7e02c703bc..cfaf90501bb1 100644
--- a/drivers/gpu/drm/meson/meson_registers.h
+++ b/drivers/gpu/drm/meson/meson_registers.h
@@ -216,6 +216,29 @@
#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
#define VIU_OSD2_TEST_RDDATA 0x1a4c
#define VIU_OSD2_PROT_CTRL 0x1a4e
+#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd
+#define VIU_OSD2_DIMM_CTRL 0x1acf
+
+#define VIU_OSD3_CTRL_STAT 0x3d80
+#define VIU_OSD3_CTRL_STAT2 0x3d81
+#define VIU_OSD3_COLOR_ADDR 0x3d82
+#define VIU_OSD3_COLOR 0x3d83
+#define VIU_OSD3_TCOLOR_AG0 0x3d84
+#define VIU_OSD3_TCOLOR_AG1 0x3d85
+#define VIU_OSD3_TCOLOR_AG2 0x3d86
+#define VIU_OSD3_TCOLOR_AG3 0x3d87
+#define VIU_OSD3_BLK0_CFG_W0 0x3d88
+#define VIU_OSD3_BLK0_CFG_W1 0x3d8c
+#define VIU_OSD3_BLK0_CFG_W2 0x3d90
+#define VIU_OSD3_BLK0_CFG_W3 0x3d94
+#define VIU_OSD3_BLK0_CFG_W4 0x3d98
+#define VIU_OSD3_BLK1_CFG_W4 0x3d99
+#define VIU_OSD3_BLK2_CFG_W4 0x3d9a
+#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c
+#define VIU_OSD3_TEST_RDDATA 0x3d9d
+#define VIU_OSD3_PROT_CTRL 0x3d9e
+#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f
+#define VIU_OSD3_DIMM_CTRL 0x3da0

#define VD1_IF0_GEN_REG 0x1a50
#define VD1_IF0_CANVAS0 0x1a51
@@ -287,6 +310,27 @@
#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
#define VD1_IF0_GEN_REG3 0x1aa7
+
+#define VIU_OSD_BLENDO_H_START_END 0x1aa9
+#define VIU_OSD_BLENDO_V_START_END 0x1aaa
+#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab
+#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac
+#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad
+#define VIU_OSD_BLEND_CURRENT_XY 0x1aae
+
+#define VIU_OSD2_MATRIX_CTRL 0x1ab0
+#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1
+#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2
+#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3
+#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4
+#define VIU_OSD2_MATRIX_COEF22 0x1ab5
+#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6
+#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7
+#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8
+#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9
+#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba
+#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb
+#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc
#define VIU_OSD1_EOTF_CTL 0x1ad4
#define VIU_OSD1_EOTF_COEF00_01 0x1ad5
#define VIU_OSD1_EOTF_COEF02_10 0x1ad6
@@ -481,6 +525,82 @@
#define VPP_OSD_SCALE_COEF 0x1dcd
#define VPP_INT_LINE_NUM 0x1dce

+#define VPP_WRAP_OSD1_MATRIX_COEF00_01 0x3d60
+#define VPP_WRAP_OSD1_MATRIX_COEF02_10 0x3d61
+#define VPP_WRAP_OSD1_MATRIX_COEF11_12 0x3d62
+#define VPP_WRAP_OSD1_MATRIX_COEF20_21 0x3d63
+#define VPP_WRAP_OSD1_MATRIX_COEF22 0x3d64
+#define VPP_WRAP_OSD1_MATRIX_COEF13_14 0x3d65
+#define VPP_WRAP_OSD1_MATRIX_COEF23_24 0x3d66
+#define VPP_WRAP_OSD1_MATRIX_COEF15_25 0x3d67
+#define VPP_WRAP_OSD1_MATRIX_CLIP 0x3d68
+#define VPP_WRAP_OSD1_MATRIX_OFFSET0_1 0x3d69
+#define VPP_WRAP_OSD1_MATRIX_OFFSET2 0x3d6a
+#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1 0x3d6b
+#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2 0x3d6c
+#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d
+
+#define VPP_WRAP_OSD2_MATRIX_COEF00_01 0x3d70
+#define VPP_WRAP_OSD2_MATRIX_COEF02_10 0x3d71
+#define VPP_WRAP_OSD2_MATRIX_COEF11_12 0x3d72
+#define VPP_WRAP_OSD2_MATRIX_COEF20_21 0x3d73
+#define VPP_WRAP_OSD2_MATRIX_COEF22 0x3d74
+#define VPP_WRAP_OSD2_MATRIX_COEF13_14 0x3d75
+#define VPP_WRAP_OSD2_MATRIX_COEF23_24 0x3d76
+#define VPP_WRAP_OSD2_MATRIX_COEF15_25 0x3d77
+#define VPP_WRAP_OSD2_MATRIX_CLIP 0x3d78
+#define VPP_WRAP_OSD2_MATRIX_OFFSET0_1 0x3d79
+#define VPP_WRAP_OSD2_MATRIX_OFFSET2 0x3d7a
+#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1 0x3d7b
+#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2 0x3d7c
+#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d
+
+#define VPP_WRAP_OSD3_MATRIX_COEF00_01 0x3db0
+#define VPP_WRAP_OSD3_MATRIX_COEF02_10 0x3db1
+#define VPP_WRAP_OSD3_MATRIX_COEF11_12 0x3db2
+#define VPP_WRAP_OSD3_MATRIX_COEF20_21 0x3db3
+#define VPP_WRAP_OSD3_MATRIX_COEF22 0x3db4
+#define VPP_WRAP_OSD3_MATRIX_COEF13_14 0x3db5
+#define VPP_WRAP_OSD3_MATRIX_COEF23_24 0x3db6
+#define VPP_WRAP_OSD3_MATRIX_COEF15_25 0x3db7
+#define VPP_WRAP_OSD3_MATRIX_CLIP 0x3db8
+#define VPP_WRAP_OSD3_MATRIX_OFFSET0_1 0x3db9
+#define VPP_WRAP_OSD3_MATRIX_OFFSET2 0x3dba
+#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET0_1 0x3dbb
+#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
+#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
+
+/* osd2 scaler */
+#define OSD2_VSC_PHASE_STEP 0x3d00
+#define OSD2_VSC_INI_PHASE 0x3d01
+#define OSD2_VSC_CTRL0 0x3d02
+#define OSD2_HSC_PHASE_STEP 0x3d03
+#define OSD2_HSC_INI_PHASE 0x3d04
+#define OSD2_HSC_CTRL0 0x3d05
+#define OSD2_HSC_INI_PAT_CTRL 0x3d06
+#define OSD2_SC_DUMMY_DATA 0x3d07
+#define OSD2_SC_CTRL0 0x3d08
+#define OSD2_SCI_WH_M1 0x3d09
+#define OSD2_SCO_H_START_END 0x3d0a
+#define OSD2_SCO_V_START_END 0x3d0b
+#define OSD2_SCALE_COEF_IDX 0x3d18
+#define OSD2_SCALE_COEF 0x3d19
+
+/* osd34 scaler */
+#define OSD34_SCALE_COEF_IDX 0x3d1e
+#define OSD34_SCALE_COEF 0x3d1f
+#define OSD34_VSC_PHASE_STEP 0x3d20
+#define OSD34_VSC_INI_PHASE 0x3d21
+#define OSD34_VSC_CTRL0 0x3d22
+#define OSD34_HSC_PHASE_STEP 0x3d23
+#define OSD34_HSC_INI_PHASE 0x3d24
+#define OSD34_HSC_CTRL0 0x3d25
+#define OSD34_HSC_INI_PAT_CTRL 0x3d26
+#define OSD34_SC_DUMMY_DATA 0x3d27
+#define OSD34_SC_CTRL0 0x3d28
+#define OSD34_SCI_WH_M1 0x3d29
+#define OSD34_SCO_H_START_END 0x3d2a
+#define OSD34_SCO_V_START_END 0x3d2b
/* viu2 */
#define VIU2_ADDR_START 0x1e00
#define VIU2_ADDR_END 0x1eff
@@ -1400,4 +1520,131 @@
#define OSDSR_YBIC_VCOEF0 0x3149
#define OSDSR_CBIC_VCOEF0 0x314a

+/* osd afbcd on gxtvbb */
+#define OSD1_AFBCD_ENABLE 0x31a0
+#define OSD1_AFBCD_MODE 0x31a1
+#define OSD1_AFBCD_SIZE_IN 0x31a2
+#define OSD1_AFBCD_HDR_PTR 0x31a3
+#define OSD1_AFBCD_FRAME_PTR 0x31a4
+#define OSD1_AFBCD_CHROMA_PTR 0x31a5
+#define OSD1_AFBCD_CONV_CTRL 0x31a6
+#define OSD1_AFBCD_STATUS 0x31a8
+#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9
+#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa
+#define VIU_MISC_CTRL1 0x1a07
+
+/* add for gxm and 962e dv core2 */
+#define DOLBY_CORE2A_SWAP_CTRL1 0x3434
+#define DOLBY_CORE2A_SWAP_CTRL2 0x3435
+
+/* osd afbc on g12a */
+#define VPU_MAFBC_BLOCK_ID 0x3a00
+#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01
+#define VPU_MAFBC_IRQ_CLEAR 0x3a02
+#define VPU_MAFBC_IRQ_MASK 0x3a03
+#define VPU_MAFBC_IRQ_STATUS 0x3a04
+#define VPU_MAFBC_COMMAND 0x3a05
+#define VPU_MAFBC_STATUS 0x3a06
+#define VPU_MAFBC_SURFACE_CFG 0x3a07
+
+/* osd afbc on g12a */
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11
+#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12
+#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13
+#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b
+#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31
+#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32
+#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33
+#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b
+#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51
+#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52
+#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53
+#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b
+#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71
+#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72
+#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73
+#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b
+#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c
+
+#define DOLBY_PATH_CTRL 0x1a0c
+#define OSD_PATH_MISC_CTRL 0x1a0e
+#define MALI_AFBCD_TOP_CTRL 0x1a0f
+
+#define VIU_OSD_BLEND_CTRL 0x39b0
+#define VIU_OSD_BLEND_CTRL1 0x39c0
+#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1
+#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2
+#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3
+#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4
+#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5
+#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6
+#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7
+#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8
+#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9
+#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba
+#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb
+#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc
+#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf
+
+#define VPP_OUT_H_V_SIZE 0x1da5
+
+#define VPP_VD2_HDR_IN_SIZE 0x1df0
+#define VPP_OSD1_IN_SIZE 0x1df1
+#define VPP_GCLK_CTRL2 0x1df2
+#define VD2_PPS_DUMMY_DATA 0x1df4
+#define VPP_OSD1_BLD_H_SCOPE 0x1df5
+#define VPP_OSD1_BLD_V_SCOPE 0x1df6
+#define VPP_OSD2_BLD_H_SCOPE 0x1df7
+#define VPP_OSD2_BLD_V_SCOPE 0x1df8
+#define VPP_WRBAK_CTRL 0x1df9
+#define VPP_SLEEP_CTRL 0x1dfa
+#define VD1_BLEND_SRC_CTRL 0x1dfb
+#define VD2_BLEND_SRC_CTRL 0x1dfc
+#define OSD1_BLEND_SRC_CTRL 0x1dfd
+#define OSD2_BLEND_SRC_CTRL 0x1dfe
+
+#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968
+#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969
+#define VPP_RDARB_MODE 0x3978
+#define VPP_RDARB_REQEN_SLV 0x3979
+#define VPU_RDARB_MODE_L2C1 0x279d
+
#endif /* __MESON_REGISTERS_H */
--
2.21.0


2019-03-25 14:20:45

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 01/11] drm/meson: Switch PLL to 5.94GHz base for 297Mhz pixel clock

On Amlogic G12A SoC, the 2,97GHz PLL frequency is not stable enough
to provide a correct 297MHz pixel clock, so switch the PLL base
frequency with a /2 OD when the 297MHz pixel clock is requested.

This solves the issue on G12A and also works fine on GXBB, GXL & GXM.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_vclk.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
index f6ba35a405f8..c15a5a5df633 100644
--- a/drivers/gpu/drm/meson/meson_vclk.c
+++ b/drivers/gpu/drm/meson/meson_vclk.c
@@ -396,8 +396,8 @@ struct meson_vclk_params {
},
[MESON_VCLK_HDMI_297000] = {
.pixel_freq = 297000,
- .pll_base_freq = 2970000,
- .pll_od1 = 1,
+ .pll_base_freq = 5940000,
+ .pll_od1 = 2,
.pll_od2 = 1,
.pll_od3 = 1,
.vid_pll_div = VID_PLL_DIV_5,
--
2.21.0


2019-03-25 14:20:47

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 06/11] drm/meson: Add G12A Support for the Overlay video plane

Amlogic G12A SoC supports the same set of Video Planes, but now
are handled by the new OSD plane blender module.

This patch uses the same VD1 plane for G12A, using the exact same scaler
and VD11 setup registers, except using the new blender register to
disable the plane.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_overlay.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
index b54a22e483b9..bdbf925ff3e8 100644
--- a/drivers/gpu/drm/meson/meson_overlay.c
+++ b/drivers/gpu/drm/meson/meson_overlay.c
@@ -516,8 +516,14 @@ static void meson_overlay_atomic_disable(struct drm_plane *plane,
priv->viu.vd1_enabled = false;

/* Disable VD1 */
- writel_bits_relaxed(VPP_VD1_POSTBLEND | VPP_VD1_PREBLEND, 0,
- priv->io_base + _REG(VPP_MISC));
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
+ writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
+ writel_relaxed(0, priv->io_base + _REG(VD1_IF0_GEN_REG + 0x17b0));
+ writel_relaxed(0, priv->io_base + _REG(VD2_IF0_GEN_REG + 0x17b0));
+ } else
+ writel_bits_relaxed(VPP_VD1_POSTBLEND | VPP_VD1_PREBLEND, 0,
+ priv->io_base + _REG(VPP_MISC));

}

--
2.21.0


2019-03-25 14:20:55

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 04/11] drm/meson: Add G12A Support for VIU setup

Amlogic G12A SoC needs a different VIU setup code,
handle it.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_viu.c | 72 ++++++++++++++++++++++++++++---
1 file changed, 67 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
index ac0f3687e09a..0169c98b01c9 100644
--- a/drivers/gpu/drm/meson/meson_viu.c
+++ b/drivers/gpu/drm/meson/meson_viu.c
@@ -90,6 +90,34 @@ static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
EOTF_COEFF_RIGHTSHIFT /* right shift */
};

+void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv, int *m,
+ bool csc_on)
+{
+ /* VPP WRAP OSD1 matrix */
+ writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
+ writel(m[2] & 0xfff,
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
+ writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
+ writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
+ writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
+ writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
+ writel((m[11] & 0x1fff) << 16,
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
+
+ writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
+ writel(m[20] & 0xfff,
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
+
+ writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
+ priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
+}
+
void meson_viu_set_osd_matrix(struct meson_drm *priv,
enum viu_matrix_sel_e m_select,
int *m, bool csc_on)
@@ -336,14 +364,24 @@ void meson_viu_init(struct meson_drm *priv)
if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
meson_viu_load_matrix(priv);
+ else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
+ true);

/* Initialize OSD1 fifo control register */
reg = BIT(0) | /* Urgent DDR request priority */
- (4 << 5) | /* hold_fifo_lines */
- (3 << 10) | /* burst length 64 */
- (32 << 12) | /* fifo_depth_val: 32*8=256 */
- (2 << 22) | /* 4 words in 1 burst */
- (2 << 24);
+ (4 << 5); /* hold_fifo_lines */
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ reg |= (1 << 10) | /* burst length 32 */
+ (32 << 12) | /* fifo_depth_val: 32*8=256 */
+ (2 << 22) | /* 4 words in 1 burst */
+ (2 << 24) |
+ (1 << 31);
+ else
+ reg |= (3 << 10) | /* burst length 64 */
+ (32 << 12) | /* fifo_depth_val: 32*8=256 */
+ (2 << 22) | /* 4 words in 1 burst */
+ (2 << 24);
writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));

@@ -369,6 +407,30 @@ void meson_viu_init(struct meson_drm *priv)
writel_relaxed(0x00FF00C0,
priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));

+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ writel_relaxed(4 << 29 |
+ 1 << 27 |
+ 1 << 26 | /* blend_din0 input to blend0 */
+ 1 << 25 | /* blend1_dout to blend2 */
+ 1 << 24 | /* blend1_din3 input to blend1 */
+ 1 << 20 |
+ 0 << 16 |
+ 1,
+ priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
+ writel_relaxed(3 << 8 |
+ 1 << 20,
+ priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
+ writel_relaxed(1 << 20,
+ priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
+ writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
+ writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
+ writel_relaxed(0,
+ priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
+ writel_relaxed(0,
+ priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
+ writel_bits_relaxed(0x3 << 2, 0x3 << 2,
+ priv->io_base + _REG(DOLBY_PATH_CTRL));
+ }

priv->viu.osd1_enabled = false;
priv->viu.osd1_commit = false;
--
2.21.0


2019-03-25 14:21:00

by Neil Armstrong

[permalink] [raw]
Subject: [PATCH 05/11] drm/meson: Add G12A support for OSD1 Plane

Amlogic G12A SoC supports now up to 3 OSD planes (1 more than the
previous SoCs) and a brand new OSD plane blender module.

This patch uses the same OSD1 plane G12A, using the exact same scaler
and OSD1 setup registers, except using the new blender register to
disable the plane.

Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_plane.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index b7786218cb10..bf8f1fab63aa 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -294,6 +294,13 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;

+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
+ priv->viu.osd_blend_din0_scope_h = ((dest.x2 - 1) << 16) | dest.x1;
+ priv->viu.osd_blend_din0_scope_v = ((dest.y2 - 1) << 16) | dest.y1;
+ priv->viu.osb_blend0_size = dst_h << 16 | dst_w;
+ priv->viu.osb_blend1_size = dst_h << 16 | dst_w;
+ }
+
/* Update Canvas with buffer address */
gem = drm_fb_cma_get_gem_obj(fb, 0);

@@ -320,8 +327,12 @@ static void meson_plane_atomic_disable(struct drm_plane *plane,
struct meson_drm *priv = meson_plane->priv;

/* Disable OSD1 */
- writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
- priv->io_base + _REG(VPP_MISC));
+ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
+ writel_bits_relaxed(BIT(0) | BIT(21), 0,
+ priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
+ else
+ writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
+ priv->io_base + _REG(VPP_MISC));

meson_plane->enabled = false;

--
2.21.0


2019-04-09 08:43:54

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH 04/11] drm/meson: Add G12A Support for VIU setup

On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
> Amlogic G12A SoC needs a different VIU setup code,
> handle it.
>
> Signed-off-by: Neil Armstrong <[email protected]>
> ---
> drivers/gpu/drm/meson/meson_viu.c | 72 ++++++++++++++++++++++++++++---
> 1 file changed, 67 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
> index ac0f3687e09a..0169c98b01c9 100644
> --- a/drivers/gpu/drm/meson/meson_viu.c
> +++ b/drivers/gpu/drm/meson/meson_viu.c
> @@ -90,6 +90,34 @@ static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
> EOTF_COEFF_RIGHTSHIFT /* right shift */
> };
>
> +void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv, int *m,
> + bool csc_on)
> +{
> + /* VPP WRAP OSD1 matrix */
> + writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
> + writel(m[2] & 0xfff,
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
> + writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
> + writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
> + writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
> + writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
> + writel((m[11] & 0x1fff) << 16,
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
> +
> + writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));

Can you define some of the masks and shifts above ? possibly the same define
for all the registers I suppose ... maybe using FIELD_PREP ?

> + writel(m[20] & 0xfff,
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
> +
> + writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
> +}
> +
> void meson_viu_set_osd_matrix(struct meson_drm *priv,
> enum viu_matrix_sel_e m_select,
> int *m, bool csc_on)
> @@ -336,14 +364,24 @@ void meson_viu_init(struct meson_drm *priv)
> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> meson_viu_load_matrix(priv);
> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
> + true);
>
> /* Initialize OSD1 fifo control register */
> reg = BIT(0) | /* Urgent DDR request priority */
> - (4 << 5) | /* hold_fifo_lines */
> - (3 << 10) | /* burst length 64 */
> - (32 << 12) | /* fifo_depth_val: 32*8=256 */
> - (2 << 22) | /* 4 words in 1 burst */
> - (2 << 24);
> + (4 << 5); /* hold_fifo_lines */
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + reg |= (1 << 10) | /* burst length 32 */
> + (32 << 12) | /* fifo_depth_val: 32*8=256 */
> + (2 << 22) | /* 4 words in 1 burst */
> + (2 << 24) |
> + (1 << 31);
> + else
> + reg |= (3 << 10) | /* burst length 64 */
> + (32 << 12) | /* fifo_depth_val: 32*8=256 */
> + (2 << 22) | /* 4 words in 1 burst */
> + (2 << 24);

Could you use the BIT() macro and add some defines ?

> writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
> writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
>
> @@ -369,6 +407,30 @@ void meson_viu_init(struct meson_drm *priv)
> writel_relaxed(0x00FF00C0,
> priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
>
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + writel_relaxed(4 << 29 |
> + 1 << 27 |
> + 1 << 26 | /* blend_din0 input to blend0 */
> + 1 << 25 | /* blend1_dout to blend2 */
> + 1 << 24 | /* blend1_din3 input to blend1 */
> + 1 << 20 |
> + 0 << 16 |
> + 1,
> + priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
> + writel_relaxed(3 << 8 |
> + 1 << 20,
> + priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
> + writel_relaxed(1 << 20,
> + priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
> + writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
> + writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
> + writel_relaxed(0,
> + priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
> + writel_relaxed(0,
> + priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
> + writel_bits_relaxed(0x3 << 2, 0x3 << 2,
> + priv->io_base + _REG(DOLBY_PATH_CTRL));

Same for this hunk

> + }
>
> priv->viu.osd1_enabled = false;
> priv->viu.osd1_commit = false;


2019-04-09 08:44:02

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH 06/11] drm/meson: Add G12A Support for the Overlay video plane

On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
> Amlogic G12A SoC supports the same set of Video Planes, but now
> are handled by the new OSD plane blender module.
>
> This patch uses the same VD1 plane for G12A, using the exact same scaler
> and VD11 setup registers, except using the new blender register to
> disable the plane.
>
> Signed-off-by: Neil Armstrong <[email protected]>
> ---
> drivers/gpu/drm/meson/meson_overlay.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
> index b54a22e483b9..bdbf925ff3e8 100644
> --- a/drivers/gpu/drm/meson/meson_overlay.c
> +++ b/drivers/gpu/drm/meson/meson_overlay.c
> @@ -516,8 +516,14 @@ static void meson_overlay_atomic_disable(struct drm_plane *plane,
> priv->viu.vd1_enabled = false;
>
> /* Disable VD1 */
> - writel_bits_relaxed(VPP_VD1_POSTBLEND | VPP_VD1_PREBLEND, 0,
> - priv->io_base + _REG(VPP_MISC));
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
> + writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
> + writel_relaxed(0, priv->io_base + _REG(VD1_IF0_GEN_REG + 0x17b0));
> + writel_relaxed(0, priv->io_base + _REG(VD2_IF0_GEN_REG + 0x17b0));

Is it possible to add a comment explaining this 0x17b0 value ?

> + } else
> + writel_bits_relaxed(VPP_VD1_POSTBLEND | VPP_VD1_PREBLEND, 0,
> + priv->io_base + _REG(VPP_MISC));
>
> }
>


2019-04-09 08:44:18

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH 08/11] drm/meson: Add G12A support for CVBS Encoer

On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
> The Meson G12A SoCs uses the exact same CVBS encoder except a simple
> CVBS DAC register offset and settings delta.
>
> Signed-off-by: Neil Armstrong <[email protected]>
> ---
> drivers/gpu/drm/meson/meson_venc.c | 11 +++++++++--
> drivers/gpu/drm/meson/meson_venc_cvbs.c | 25 ++++++++++++++++++-------
> 2 files changed, 27 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
> index 66d73a932d19..6faca7313339 100644
> --- a/drivers/gpu/drm/meson/meson_venc.c
> +++ b/drivers/gpu/drm/meson/meson_venc.c
> @@ -73,7 +73,9 @@
> /* HHI Registers */
> #define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */
> #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
> +#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
> #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
> +#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */
> #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */
>
> struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
> @@ -1675,8 +1677,13 @@ void meson_venc_disable_vsync(struct meson_drm *priv)
> void meson_venc_init(struct meson_drm *priv)
> {
> /* Disable CVBS VDAC */
> - regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
> - regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 8);
> + } else {
> + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
> + }
>
> /* Power Down Dacs */
> writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
> diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
> index d622d817b6df..2c5341c881c4 100644
> --- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
> +++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
> @@ -37,7 +37,9 @@
>
> /* HHI VDAC Registers */
> #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
> +#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
> #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
> +#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */
>
> struct meson_venc_cvbs {
> struct drm_encoder encoder;
> @@ -166,8 +168,13 @@ static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
> struct meson_drm *priv = meson_venc_cvbs->priv;
>
> /* Disable CVBS VDAC */
> - regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
> - regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
> + } else {
> + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);

I imagine 8 stands for BIT(3) ? Could you add a define to explain (quickly)
what it is ?

> + }
> }
>
> static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
> @@ -179,13 +186,17 @@ static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
> /* VDAC0 source is not from ATV */
> writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
>
> - if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
> regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
> - else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
> regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
> -
> - regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0x906001);
> + regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
> + }

Maybe the values above are just magics taken from the vendor kernel, but if
you can, it would be nice to break them down to help us understand what is
controlled in these CTNL registers.

> }
>
> static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,


2019-04-09 08:44:47

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH 07/11] drm/meson: Add G12A support for plane handling in CRTC driver

On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
> This patch adds support for the new OSD+VD Plane blending module
> in the CRTC code by adding the G12A code to manage the blending
> module and setting the right OSD1 & VD1 plane registers.
>
> Signed-off-by: Neil Armstrong <[email protected]>
> ---
> drivers/gpu/drm/meson/meson_crtc.c | 269 +++++++++++++++++++++++------
> drivers/gpu/drm/meson/meson_drv.h | 4 +
> 2 files changed, 221 insertions(+), 52 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
> index 6d9311e254ef..5579f8ac3e3f 100644
> --- a/drivers/gpu/drm/meson/meson_crtc.c
> +++ b/drivers/gpu/drm/meson/meson_crtc.c
> @@ -39,12 +39,17 @@
> #include "meson_viu.h"
> #include "meson_registers.h"
>
> +#define MESON_G12A_VIU_OFFSET 0x5ec0
> +
> /* CRTC definition */
>
> struct meson_crtc {
> struct drm_crtc base;
> struct drm_pending_vblank_event *event;
> struct meson_drm *priv;
> + void (*enable_osd1)(struct meson_drm *priv);
> + void (*enable_vd1)(struct meson_drm *priv);
> + unsigned int viu_offset;
> };
> #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
>
> @@ -80,6 +85,44 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
>
> };
>
> +static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
> + struct drm_crtc_state *old_state)
> +{
> + struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
> + struct drm_crtc_state *crtc_state = crtc->state;
> + struct meson_drm *priv = meson_crtc->priv;
> +
> + DRM_DEBUG_DRIVER("\n");
> +
> + if (!crtc_state) {
> + DRM_ERROR("Invalid crtc_state\n");
> + return;
> + }
> +
> + /* VD1 Preblend vertical start/end */
> + writel(FIELD_PREP(GENMASK(11, 0), 2303),

Could could define this mask somewhere
I don't know if the 2303 can be explained. I'd nice if it could

> + priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
> +
> + /* Setup Blender */
> + writel(crtc_state->mode.hdisplay |
> + crtc_state->mode.vdisplay << 16,
> + priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
> +
> + writel_relaxed(0 << 16 |

this 16 shift seems to be used for hdisplay or something. Could
define/document it a bit

> + (crtc_state->mode.hdisplay - 1),
> + priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
> + writel_relaxed(0 << 16 |
> + (crtc_state->mode.vdisplay - 1),
> + priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
> + writel_relaxed(crtc_state->mode.hdisplay << 16 |
> + crtc_state->mode.vdisplay,
> + priv->io_base + _REG(VPP_OUT_H_V_SIZE));
> +
> + drm_crtc_vblank_on(crtc);
> +
> + priv->viu.osd1_enabled = true;
> +}
> +
> static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
> struct drm_crtc_state *old_state)
> {
> @@ -110,6 +153,31 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
> priv->viu.osd1_enabled = true;
> }
>
> +static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
> + struct drm_crtc_state *old_state)
> +{
> + struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
> + struct meson_drm *priv = meson_crtc->priv;
> +
> + DRM_DEBUG_DRIVER("\n");
> +
> + drm_crtc_vblank_off(crtc);
> +
> + priv->viu.osd1_enabled = false;
> + priv->viu.osd1_commit = false;
> +
> + priv->viu.vd1_enabled = false;
> + priv->viu.vd1_commit = false;
> +
> + if (crtc->state->event && !crtc->state->active) {
> + spin_lock_irq(&crtc->dev->event_lock);
> + drm_crtc_send_vblank_event(crtc, crtc->state->event);
> + spin_unlock_irq(&crtc->dev->event_lock);
> +
> + crtc->state->event = NULL;
> + }
> +}
> +
> static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
> struct drm_crtc_state *old_state)
> {
> @@ -173,6 +241,53 @@ static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
> .atomic_disable = meson_crtc_atomic_disable,
> };
>
> +static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
> + .atomic_begin = meson_crtc_atomic_begin,
> + .atomic_flush = meson_crtc_atomic_flush,
> + .atomic_enable = meson_g12a_crtc_atomic_enable,
> + .atomic_disable = meson_g12a_crtc_atomic_disable,
> +};
> +
> +static void meson_crtc_enable_osd1(struct meson_drm *priv)
> +{
> + writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
> + priv->io_base + _REG(VPP_MISC));
> +}
> +
> +static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
> +{
> + writel_relaxed(priv->viu.osd_blend_din0_scope_h,
> + priv->io_base +
> + _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
> + writel_relaxed(priv->viu.osd_blend_din0_scope_v,
> + priv->io_base +
> + _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
> + writel_relaxed(priv->viu.osb_blend0_size,
> + priv->io_base +
> + _REG(VIU_OSD_BLEND_BLEND0_SIZE));
> + writel_relaxed(priv->viu.osb_blend1_size,
> + priv->io_base +
> + _REG(VIU_OSD_BLEND_BLEND1_SIZE));
> +}
> +
> +static void meson_crtc_enable_vd1(struct meson_drm *priv)
> +{
> + writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
> + VPP_COLOR_MNG_ENABLE,
> + VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
> + VPP_COLOR_MNG_ENABLE,
> + priv->io_base + _REG(VPP_MISC));
> +}
> +
> +static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
> +{
> + writel_relaxed(((1 << 16) | /* post bld premult*/
> + (1 << 8) | /* post src */
> + (1 << 4) | /* pre bld premult*/
> + (1 << 0)),

Could you use the BIT() macro here and possibly some defines ?

> + priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
> +}
> +
> void meson_crtc_irq(struct meson_drm *priv)
> {
> struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
> @@ -219,8 +334,8 @@ void meson_crtc_irq(struct meson_drm *priv)
> MESON_CANVAS_BLKMODE_LINEAR, 0);
>
> /* Enable OSD1 */
> - writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
> - priv->io_base + _REG(VPP_MISC));
> + if (meson_crtc->enable_osd1)
> + meson_crtc->enable_osd1(priv);
>
> priv->viu.osd1_commit = false;
> }
> @@ -261,89 +376,133 @@ void meson_crtc_irq(struct meson_drm *priv)
> };
>
> writel_relaxed(priv->viu.vd1_if0_gen_reg,
> - priv->io_base + _REG(VD1_IF0_GEN_REG));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_GEN_REG));

Could you make a local variable for priv->io_base + meson_crtc->viu_offset ?
It would be a little easier to read

> writel_relaxed(priv->viu.vd1_if0_gen_reg,
> - priv->io_base + _REG(VD2_IF0_GEN_REG));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_GEN_REG));
> writel_relaxed(priv->viu.vd1_if0_gen_reg2,
> - priv->io_base + _REG(VD1_IF0_GEN_REG2));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_GEN_REG2));
> writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
> - priv->io_base + _REG(VIU_VD1_FMT_CTRL));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VIU_VD1_FMT_CTRL));
> writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
> - priv->io_base + _REG(VIU_VD2_FMT_CTRL));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VIU_VD2_FMT_CTRL));
> writel_relaxed(priv->viu.viu_vd1_fmt_w,
> - priv->io_base + _REG(VIU_VD1_FMT_W));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VIU_VD1_FMT_W));
> writel_relaxed(priv->viu.viu_vd1_fmt_w,
> - priv->io_base + _REG(VIU_VD2_FMT_W));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VIU_VD2_FMT_W));
> writel_relaxed(priv->viu.vd1_if0_canvas0,
> - priv->io_base + _REG(VD1_IF0_CANVAS0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CANVAS0));
> writel_relaxed(priv->viu.vd1_if0_canvas0,
> - priv->io_base + _REG(VD1_IF0_CANVAS1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CANVAS1));
> writel_relaxed(priv->viu.vd1_if0_canvas0,
> - priv->io_base + _REG(VD2_IF0_CANVAS0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CANVAS0));
> writel_relaxed(priv->viu.vd1_if0_canvas0,
> - priv->io_base + _REG(VD2_IF0_CANVAS1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CANVAS1));
> writel_relaxed(priv->viu.vd1_if0_luma_x0,
> - priv->io_base + _REG(VD1_IF0_LUMA_X0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_LUMA_X0));
> writel_relaxed(priv->viu.vd1_if0_luma_x0,
> - priv->io_base + _REG(VD1_IF0_LUMA_X1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_LUMA_X1));
> writel_relaxed(priv->viu.vd1_if0_luma_x0,
> - priv->io_base + _REG(VD2_IF0_LUMA_X0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_LUMA_X0));
> writel_relaxed(priv->viu.vd1_if0_luma_x0,
> - priv->io_base + _REG(VD2_IF0_LUMA_X1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_LUMA_X1));
> writel_relaxed(priv->viu.vd1_if0_luma_y0,
> - priv->io_base + _REG(VD1_IF0_LUMA_Y0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_LUMA_Y0));
> writel_relaxed(priv->viu.vd1_if0_luma_y0,
> - priv->io_base + _REG(VD1_IF0_LUMA_Y1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_LUMA_Y1));
> writel_relaxed(priv->viu.vd1_if0_luma_y0,
> - priv->io_base + _REG(VD2_IF0_LUMA_Y0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_LUMA_Y0));
> writel_relaxed(priv->viu.vd1_if0_luma_y0,
> - priv->io_base + _REG(VD2_IF0_LUMA_Y1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_LUMA_Y1));
> writel_relaxed(priv->viu.vd1_if0_chroma_x0,
> - priv->io_base + _REG(VD1_IF0_CHROMA_X0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CHROMA_X0));
> writel_relaxed(priv->viu.vd1_if0_chroma_x0,
> - priv->io_base + _REG(VD1_IF0_CHROMA_X1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CHROMA_X1));
> writel_relaxed(priv->viu.vd1_if0_chroma_x0,
> - priv->io_base + _REG(VD2_IF0_CHROMA_X0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CHROMA_X0));
> writel_relaxed(priv->viu.vd1_if0_chroma_x0,
> - priv->io_base + _REG(VD2_IF0_CHROMA_X1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CHROMA_X1));
> writel_relaxed(priv->viu.vd1_if0_chroma_y0,
> - priv->io_base + _REG(VD1_IF0_CHROMA_Y0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CHROMA_Y0));
> writel_relaxed(priv->viu.vd1_if0_chroma_y0,
> - priv->io_base + _REG(VD1_IF0_CHROMA_Y1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CHROMA_Y1));
> writel_relaxed(priv->viu.vd1_if0_chroma_y0,
> - priv->io_base + _REG(VD2_IF0_CHROMA_Y0));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CHROMA_Y0));
> writel_relaxed(priv->viu.vd1_if0_chroma_y0,
> - priv->io_base + _REG(VD2_IF0_CHROMA_Y1));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CHROMA_Y1));
> writel_relaxed(priv->viu.vd1_if0_repeat_loop,
> - priv->io_base + _REG(VD1_IF0_RPT_LOOP));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_RPT_LOOP));
> writel_relaxed(priv->viu.vd1_if0_repeat_loop,
> - priv->io_base + _REG(VD2_IF0_RPT_LOOP));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_RPT_LOOP));
> writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
> - priv->io_base + _REG(VD1_IF0_LUMA0_RPT_PAT));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_LUMA0_RPT_PAT));
> writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
> - priv->io_base + _REG(VD2_IF0_LUMA0_RPT_PAT));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_LUMA0_RPT_PAT));
> writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
> - priv->io_base + _REG(VD1_IF0_LUMA1_RPT_PAT));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_LUMA1_RPT_PAT));
> writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
> - priv->io_base + _REG(VD2_IF0_LUMA1_RPT_PAT));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_LUMA1_RPT_PAT));
> writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
> - priv->io_base + _REG(VD1_IF0_CHROMA0_RPT_PAT));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CHROMA0_RPT_PAT));
> writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
> - priv->io_base + _REG(VD2_IF0_CHROMA0_RPT_PAT));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CHROMA0_RPT_PAT));
> writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
> - priv->io_base + _REG(VD1_IF0_CHROMA1_RPT_PAT));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CHROMA1_RPT_PAT));
> writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
> - priv->io_base + _REG(VD2_IF0_CHROMA1_RPT_PAT));
> - writel_relaxed(0, priv->io_base + _REG(VD1_IF0_LUMA_PSEL));
> - writel_relaxed(0, priv->io_base + _REG(VD1_IF0_CHROMA_PSEL));
> - writel_relaxed(0, priv->io_base + _REG(VD2_IF0_LUMA_PSEL));
> - writel_relaxed(0, priv->io_base + _REG(VD2_IF0_CHROMA_PSEL));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CHROMA1_RPT_PAT));
> + writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_LUMA_PSEL));
> + writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_CHROMA_PSEL));
> + writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_LUMA_PSEL));
> + writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
> + _REG(VD2_IF0_CHROMA_PSEL));
> writel_relaxed(priv->viu.vd1_range_map_y,
> - priv->io_base + _REG(VD1_IF0_RANGE_MAP_Y));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_RANGE_MAP_Y));
> writel_relaxed(priv->viu.vd1_range_map_cb,
> - priv->io_base + _REG(VD1_IF0_RANGE_MAP_CB));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_RANGE_MAP_CB));
> writel_relaxed(priv->viu.vd1_range_map_cr,
> - priv->io_base + _REG(VD1_IF0_RANGE_MAP_CR));
> + priv->io_base + meson_crtc->viu_offset +
> + _REG(VD1_IF0_RANGE_MAP_CR));
> writel_relaxed(0x78404,
> priv->io_base + _REG(VPP_SC_MISC));
> writel_relaxed(priv->viu.vpp_pic_in_height,
> @@ -389,11 +548,8 @@ void meson_crtc_irq(struct meson_drm *priv)
> writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));
>
> /* Enable VD1 */
> - writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
> - VPP_COLOR_MNG_ENABLE,
> - VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
> - VPP_COLOR_MNG_ENABLE,
> - priv->io_base + _REG(VPP_MISC));
> + if (meson_crtc->enable_vd1)
> + meson_crtc->enable_vd1(priv);
>
> priv->viu.vd1_commit = false;
> }
> @@ -430,7 +586,16 @@ int meson_crtc_create(struct meson_drm *priv)
> return ret;
> }
>
> - drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
> + meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
> + meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
> + drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
> + } else {
> + meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
> + meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
> + drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
> + }
>
> priv->crtc = crtc;
>
> diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
> index 214a7cb18ce2..9614baa836b9 100644
> --- a/drivers/gpu/drm/meson/meson_drv.h
> +++ b/drivers/gpu/drm/meson/meson_drv.h
> @@ -62,6 +62,10 @@ struct meson_drm {
> uint32_t osd_sc_h_phase_step;
> uint32_t osd_sc_h_ctrl0;
> uint32_t osd_sc_v_ctrl0;
> + uint32_t osd_blend_din0_scope_h;
> + uint32_t osd_blend_din0_scope_v;
> + uint32_t osb_blend0_size;
> + uint32_t osb_blend1_size;
>
> bool vd1_enabled;
> bool vd1_commit;


2019-04-09 08:44:54

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH 00/11] drm/meson: Add G12A Support

On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
> The Amlogic G12A SoC offers very close Video Display
> functionnalities with it's older GXBB, GXL & GXM predecessors.
>
> The main differences are :
> - G12A Support now 3 "real" OSD planes with a new Blender module
> - Instead of having a single Scaler for OSD1, G12A has two scaler
> that can be applied to 2 out of the 3 OSD planes or on the outputs
> of the blender module.
> - The HDMI PHY now support RX-SENSE, Dynamic HDR and it's registers are
> now memory mapped instead of using an internal bus.
> - The VPU now support a DSI interface to connect a display, using
> the Synopsys DSI controller and a custom PHY
>
> The complex Blender routing, HDMI RX-SENSE, Dynamic HDR and DSI support
> are not handled in this patchset.
>
> This patchset implements on-par support with the currently support
> GXBB, GXL and GXM SoCs. There is no support delta with this patchset.
>
> patch 10 & 11 implements the bindings found at [1].
>
> [1] https://lkml.kernel.org/r/[email protected]
>
> Neil Armstrong (11):
> drm/meson: Switch PLL to 5.94GHz base for 297Mhz pixel clock
> drm/meson: Add registers for G12A SoC
> drm/meson: Add G12A Support for VPP setup
> drm/meson: Add G12A Support for VIU setup
> drm/meson: Add G12A support for OSD1 Plane
> drm/meson: Add G12A Support for the Overlay video plane
> drm/meson: Add G12A support for plane handling in CRTC driver
> drm/meson: Add G12A support for CVBS Encoer
> drm/meson: Add G12A Video Clock setup
> drm/meson: Add G12A compatible
> drm/meson: Add G12A support for the DW-HDMI Glue
>
> drivers/gpu/drm/meson/meson_crtc.c | 269 +++++++++++++++++++-----
> drivers/gpu/drm/meson/meson_drv.c | 1 +
> drivers/gpu/drm/meson/meson_drv.h | 4 +
> drivers/gpu/drm/meson/meson_dw_hdmi.c | 163 +++++++++++---
> drivers/gpu/drm/meson/meson_dw_hdmi.h | 32 ++-
> drivers/gpu/drm/meson/meson_overlay.c | 10 +-
> drivers/gpu/drm/meson/meson_plane.c | 15 +-
> drivers/gpu/drm/meson/meson_registers.h | 247 ++++++++++++++++++++++
> drivers/gpu/drm/meson/meson_vclk.c | 123 +++++++++--
> drivers/gpu/drm/meson/meson_venc.c | 11 +-
> drivers/gpu/drm/meson/meson_venc_cvbs.c | 25 ++-
> drivers/gpu/drm/meson/meson_viu.c | 72 ++++++-
> drivers/gpu/drm/meson/meson_vpp.c | 51 +++--
> 13 files changed, 880 insertions(+), 143 deletions(-)
>

on the u200 and sei510
Tested-by: Jerome Brunet <[email protected]>

I can't pretend to have a deep understanding of this subsystem, but as far as
I can tell, there is nothing crazy in there. With the comments around the use
of constants and defines fixed, you can add

Reviewed-by: Jerome Brunet <[email protected]>

As a possible future enhancement, it would be nice if you could trim the use
of *_is_compatible() functions. I think it would make the code easier to
follow and review.

2019-04-09 08:45:46

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH 08/11] drm/meson: Add G12A support for CVBS Encoer

On Tue, 2019-04-09 at 10:43 +0200, Jerome Brunet wrote:
> On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
> > The Meson G12A SoCs uses the exact same CVBS encoder except a simple
> > CVBS DAC register offset and settings delta.
> >
> > Signed-off-by: Neil Armstrong <[email protected]>
> > ---
> > drivers/gpu/drm/meson/meson_venc.c | 11 +++++++++--
> > drivers/gpu/drm/meson/meson_venc_cvbs.c | 25 ++++++++++++++++++-------
> > 2 files changed, 27 insertions(+), 9 deletions(-)

... and there is a typo in the patch title. s/Encoer/Encoder

2019-04-09 08:48:12

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH 09/11] drm/meson: Add G12A Video Clock setup

On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
> While switching to the Common Clock Framework is still Work In Progress,
> this patch adds the corresponding G12A HDMI PLL setup to be on-par
> with the other SoCs support.
>
> The G12A has only a single tweak about the high frequency setup,
> where the HDMI PLL needs a specific setup to handle correctly the
> 5.94GHz DCO frequency.
>
> Apart that, it handle correctly all the other HDMI frequencies
> and can achieve even better DMT clock frequency precision with
> the larger fractional dividier width.
>
> Signed-off-by: Neil Armstrong <[email protected]>
> ---
> drivers/gpu/drm/meson/meson_vclk.c | 119 ++++++++++++++++++++++++++---
> 1 file changed, 108 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
> index c15a5a5df633..b39034745444 100644
> --- a/drivers/gpu/drm/meson/meson_vclk.c
> +++ b/drivers/gpu/drm/meson/meson_vclk.c
> @@ -113,9 +113,12 @@
> #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
> #define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
> #define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
>
> #define HDMI_PLL_RESET BIT(28)
> +#define HDMI_PLL_RESET_G12A BIT(29)
> #define HDMI_PLL_LOCK BIT(31)
> +#define HDMI_PLL_LOCK_G12A (3 << 30)

GENMASK(31, 30) ?

>
> #define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
>
> @@ -257,6 +260,10 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
> +
> + /* Poll for lock bit */
> + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
> + (val & HDMI_PLL_LOCK), 10, 0);
> } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
> @@ -271,11 +278,26 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
> HDMI_PLL_RESET, HDMI_PLL_RESET);
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> HDMI_PLL_RESET, 0);
> - }
>
> - /* Poll for lock bit */
> - regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
> - (val & HDMI_PLL_LOCK), 10, 0);
> + /* Poll for lock bit */
> + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
> + (val & HDMI_PLL_LOCK), 10, 0);
> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00010000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x56540000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x3a0504f7);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
> +
> + /* Poll for lock bit */
> + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
> + ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
> + 10, 0);
> + }
>
> /* Disable VCLK2 */
> regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
> @@ -288,8 +310,13 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
> VCLK2_DIV_MASK, (55 - 1));
>
> /* select vid_pll for vclk2 */
> - regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
> - VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
> + VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
> + else
> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
> + VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
> +
> /* enable vclk2 gate */
> regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
>
> @@ -476,32 +503,80 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
> /* Poll for lock bit */
> regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
> (val & HDMI_PLL_LOCK), 10, 0);
> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
> +
> + /* Enable and reset */
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + 0x3 << 28, 0x3 << 28);

Could you use define of the enable and reset bit instead of 0x3 << 28 ?

> +
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, frac);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
> +
> + /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
> + if (m >= 0xf7) {
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0xea68dc00);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
> + } else {
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
> + }
> +
> + do {
> + /* Reset PLL */
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
> +
> + /* UN-Reset PLL */
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + HDMI_PLL_RESET_G12A, 0);
> +
> + /* Poll for lock bits */
> + if (!regmap_read_poll_timeout(priv->hhi,
> + HHI_HDMI_PLL_CNTL, val,
> + ((val & HDMI_PLL_LOCK_G12A)
> + == HDMI_PLL_LOCK_G12A),
> + 10, 100))
> + break;
> + } while(1);
> }
>
> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
> 3 << 16, pll_od_to_reg(od1) << 16);
> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
> 3 << 21, pll_od_to_reg(od1) << 21);
> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + 3 << 16, pll_od_to_reg(od1) << 16);
>
> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
> 3 << 22, pll_od_to_reg(od2) << 22);
> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
> 3 << 23, pll_od_to_reg(od2) << 23);
> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + 3 << 18, pll_od_to_reg(od2) << 18);
>
> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
> 3 << 18, pll_od_to_reg(od3) << 18);
> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
> 3 << 19, pll_od_to_reg(od3) << 19);
> -
> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + 3 << 20, pll_od_to_reg(od3) << 20);

Could you remove the constants above and define the shift and mask of the ODs
?

> }
>
> #define XTAL_FREQ 24000
> @@ -518,6 +593,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
>
> #define HDMI_FRAC_MAX_GXBB 4096
> #define HDMI_FRAC_MAX_GXL 1024
> +#define HDMI_FRAC_MAX_G12A 131072
>
> static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
> unsigned int m,
> @@ -534,6 +610,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
> parent_freq *= 2;
> }
>
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + frac_max = HDMI_FRAC_MAX_G12A;
> +
> /* We can have a perfect match !*/
> if (pll_freq / m == parent_freq &&
> pll_freq % m == 0)
> @@ -559,7 +638,8 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
> if (frac >= HDMI_FRAC_MAX_GXBB)
> return false;
> } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu") ||
> + meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> /* Empiric supported min/max dividers */
> if (m < 106 || m > 247)
> return false;
> @@ -713,6 +793,23 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
> break;
> }
>
> + meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> + switch (pll_base_freq) {
> + case 2970000:
> + m = 0x7b;
> + frac = vic_alternate_clock ? 0x140b4 : 0x18000;
> + break;
> + case 4320000:
> + m = vic_alternate_clock ? 0xb3 : 0xb4;
> + frac = vic_alternate_clock ? 0x1a3ee : 0;
> + break;
> + case 5940000:
> + m = 0xf7;
> + frac = vic_alternate_clock ? 0x8148 : 0x10000;
> + break;
> + }
> +
> meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
> }
>


2019-04-09 08:52:49

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 00/11] drm/meson: Add G12A Support

Hi,

On 09/04/2019 10:42, Jerome Brunet wrote:
> On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
>> The Amlogic G12A SoC offers very close Video Display
>> functionnalities with it's older GXBB, GXL & GXM predecessors.
>>
>> The main differences are :
>> - G12A Support now 3 "real" OSD planes with a new Blender module
>> - Instead of having a single Scaler for OSD1, G12A has two scaler
>> that can be applied to 2 out of the 3 OSD planes or on the outputs
>> of the blender module.
>> - The HDMI PHY now support RX-SENSE, Dynamic HDR and it's registers are
>> now memory mapped instead of using an internal bus.
>> - The VPU now support a DSI interface to connect a display, using
>> the Synopsys DSI controller and a custom PHY
>>
>> The complex Blender routing, HDMI RX-SENSE, Dynamic HDR and DSI support
>> are not handled in this patchset.
>>
>> This patchset implements on-par support with the currently support
>> GXBB, GXL and GXM SoCs. There is no support delta with this patchset.
>>
>> patch 10 & 11 implements the bindings found at [1].
>>
>> [1] https://lkml.kernel.org/r/[email protected]
>>
>> Neil Armstrong (11):
>> drm/meson: Switch PLL to 5.94GHz base for 297Mhz pixel clock
>> drm/meson: Add registers for G12A SoC
>> drm/meson: Add G12A Support for VPP setup
>> drm/meson: Add G12A Support for VIU setup
>> drm/meson: Add G12A support for OSD1 Plane
>> drm/meson: Add G12A Support for the Overlay video plane
>> drm/meson: Add G12A support for plane handling in CRTC driver
>> drm/meson: Add G12A support for CVBS Encoer
>> drm/meson: Add G12A Video Clock setup
>> drm/meson: Add G12A compatible
>> drm/meson: Add G12A support for the DW-HDMI Glue
>>
>> drivers/gpu/drm/meson/meson_crtc.c | 269 +++++++++++++++++++-----
>> drivers/gpu/drm/meson/meson_drv.c | 1 +
>> drivers/gpu/drm/meson/meson_drv.h | 4 +
>> drivers/gpu/drm/meson/meson_dw_hdmi.c | 163 +++++++++++---
>> drivers/gpu/drm/meson/meson_dw_hdmi.h | 32 ++-
>> drivers/gpu/drm/meson/meson_overlay.c | 10 +-
>> drivers/gpu/drm/meson/meson_plane.c | 15 +-
>> drivers/gpu/drm/meson/meson_registers.h | 247 ++++++++++++++++++++++
>> drivers/gpu/drm/meson/meson_vclk.c | 123 +++++++++--
>> drivers/gpu/drm/meson/meson_venc.c | 11 +-
>> drivers/gpu/drm/meson/meson_venc_cvbs.c | 25 ++-
>> drivers/gpu/drm/meson/meson_viu.c | 72 ++++++-
>> drivers/gpu/drm/meson/meson_vpp.c | 51 +++--
>> 13 files changed, 880 insertions(+), 143 deletions(-)
>>
>
> on the u200 and sei510
> Tested-by: Jerome Brunet <[email protected]>
>
> I can't pretend to have a deep understanding of this subsystem, but as far as
> I can tell, there is nothing crazy in there. With the comments around the use
> of constants and defines fixed, you can add
>
> Reviewed-by: Jerome Brunet <[email protected]>
>
> As a possible future enhancement, it would be nice if you could trim the use
> of *_is_compatible() functions. I think it would make the code easier to
> follow and review.
>

Thanks for the overall review,

I will do a complete fixup of the constants and defines in a follow-up patchset,
since the already-merged code also needs a good cleanup.

I'll do a more complete refactoring to get rid of the _is_compatible() stuff
in a second time, it needs much more work to handle correctly the 4 SoC families.

Neil

2019-04-09 09:18:53

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 07/11] drm/meson: Add G12A support for plane handling in CRTC driver

On 09/04/2019 10:43, Jerome Brunet wrote:
> On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
>> This patch adds support for the new OSD+VD Plane blending module
>> in the CRTC code by adding the G12A code to manage the blending
>> module and setting the right OSD1 & VD1 plane registers.
>>
>> Signed-off-by: Neil Armstrong <[email protected]>
>> ---
>> drivers/gpu/drm/meson/meson_crtc.c | 269 +++++++++++++++++++++++------
>> drivers/gpu/drm/meson/meson_drv.h | 4 +
>> 2 files changed, 221 insertions(+), 52 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
>> index 6d9311e254ef..5579f8ac3e3f 100644
>> --- a/drivers/gpu/drm/meson/meson_crtc.c
>> +++ b/drivers/gpu/drm/meson/meson_crtc.c
>> @@ -39,12 +39,17 @@
>> #include "meson_viu.h"
>> #include "meson_registers.h"
>>
>> +#define MESON_G12A_VIU_OFFSET 0x5ec0
>> +
>> /* CRTC definition */
>>
>> struct meson_crtc {
>> struct drm_crtc base;
>> struct drm_pending_vblank_event *event;
>> struct meson_drm *priv;
>> + void (*enable_osd1)(struct meson_drm *priv);
>> + void (*enable_vd1)(struct meson_drm *priv);
>> + unsigned int viu_offset;
>> };
>> #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
>>
>> @@ -80,6 +85,44 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
>>
>> };
>>
>> +static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
>> + struct drm_crtc_state *old_state)
>> +{
>> + struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
>> + struct drm_crtc_state *crtc_state = crtc->state;
>> + struct meson_drm *priv = meson_crtc->priv;
>> +
>> + DRM_DEBUG_DRIVER("\n");
>> +
>> + if (!crtc_state) {
>> + DRM_ERROR("Invalid crtc_state\n");
>> + return;
>> + }
>> +
>> + /* VD1 Preblend vertical start/end */
>> + writel(FIELD_PREP(GENMASK(11, 0), 2303),
>
> Could could define this mask somewhere
> I don't know if the 2303 can be explained. I'd nice if it could

It's a width, I'll add a comment.

>
>> + priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));
>> +
>> + /* Setup Blender */
>> + writel(crtc_state->mode.hdisplay |
>> + crtc_state->mode.vdisplay << 16,
>> + priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
>> +
>> + writel_relaxed(0 << 16 |
>
> this 16 shift seems to be used for hdisplay or something. Could
> define/document it a bit

Ack

>
>> + (crtc_state->mode.hdisplay - 1),
>> + priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
>> + writel_relaxed(0 << 16 |
>> + (crtc_state->mode.vdisplay - 1),
>> + priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
>> + writel_relaxed(crtc_state->mode.hdisplay << 16 |
>> + crtc_state->mode.vdisplay,
>> + priv->io_base + _REG(VPP_OUT_H_V_SIZE));
>> +
>> + drm_crtc_vblank_on(crtc);
>> +
>> + priv->viu.osd1_enabled = true;
>> +}
>> +
>> static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
>> struct drm_crtc_state *old_state)
>> {
>> @@ -110,6 +153,31 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
>> priv->viu.osd1_enabled = true;
>> }
>>
>> +static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
>> + struct drm_crtc_state *old_state)
>> +{
>> + struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
>> + struct meson_drm *priv = meson_crtc->priv;
>> +
>> + DRM_DEBUG_DRIVER("\n");
>> +
>> + drm_crtc_vblank_off(crtc);
>> +
>> + priv->viu.osd1_enabled = false;
>> + priv->viu.osd1_commit = false;
>> +
>> + priv->viu.vd1_enabled = false;
>> + priv->viu.vd1_commit = false;
>> +
>> + if (crtc->state->event && !crtc->state->active) {
>> + spin_lock_irq(&crtc->dev->event_lock);
>> + drm_crtc_send_vblank_event(crtc, crtc->state->event);
>> + spin_unlock_irq(&crtc->dev->event_lock);
>> +
>> + crtc->state->event = NULL;
>> + }
>> +}
>> +
>> static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
>> struct drm_crtc_state *old_state)
>> {
>> @@ -173,6 +241,53 @@ static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
>> .atomic_disable = meson_crtc_atomic_disable,
>> };
>>
>> +static const struct drm_crtc_helper_funcs meson_g12a_crtc_helper_funcs = {
>> + .atomic_begin = meson_crtc_atomic_begin,
>> + .atomic_flush = meson_crtc_atomic_flush,
>> + .atomic_enable = meson_g12a_crtc_atomic_enable,
>> + .atomic_disable = meson_g12a_crtc_atomic_disable,
>> +};
>> +
>> +static void meson_crtc_enable_osd1(struct meson_drm *priv)
>> +{
>> + writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
>> + priv->io_base + _REG(VPP_MISC));
>> +}
>> +
>> +static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
>> +{
>> + writel_relaxed(priv->viu.osd_blend_din0_scope_h,
>> + priv->io_base +
>> + _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
>> + writel_relaxed(priv->viu.osd_blend_din0_scope_v,
>> + priv->io_base +
>> + _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
>> + writel_relaxed(priv->viu.osb_blend0_size,
>> + priv->io_base +
>> + _REG(VIU_OSD_BLEND_BLEND0_SIZE));
>> + writel_relaxed(priv->viu.osb_blend1_size,
>> + priv->io_base +
>> + _REG(VIU_OSD_BLEND_BLEND1_SIZE));
>> +}
>> +
>> +static void meson_crtc_enable_vd1(struct meson_drm *priv)
>> +{
>> + writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
>> + VPP_COLOR_MNG_ENABLE,
>> + VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
>> + VPP_COLOR_MNG_ENABLE,
>> + priv->io_base + _REG(VPP_MISC));
>> +}
>> +
>> +static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
>> +{
>> + writel_relaxed(((1 << 16) | /* post bld premult*/
>> + (1 << 8) | /* post src */
>> + (1 << 4) | /* pre bld premult*/
>> + (1 << 0)),
>
> Could you use the BIT() macro here and possibly some defines ?

Ack

>
>> + priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
>> +}
>> +
>> void meson_crtc_irq(struct meson_drm *priv)
>> {
>> struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
>> @@ -219,8 +334,8 @@ void meson_crtc_irq(struct meson_drm *priv)
>> MESON_CANVAS_BLKMODE_LINEAR, 0);
>>
>> /* Enable OSD1 */
>> - writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
>> - priv->io_base + _REG(VPP_MISC));
>> + if (meson_crtc->enable_osd1)
>> + meson_crtc->enable_osd1(priv);
>>
>> priv->viu.osd1_commit = false;
>> }
>> @@ -261,89 +376,133 @@ void meson_crtc_irq(struct meson_drm *priv)
>> };
>>
>> writel_relaxed(priv->viu.vd1_if0_gen_reg,
>> - priv->io_base + _REG(VD1_IF0_GEN_REG));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_GEN_REG));
>
> Could you make a local variable for priv->io_base + meson_crtc->viu_offset ?
> It would be a little easier to read

Indeed

>
>> writel_relaxed(priv->viu.vd1_if0_gen_reg,
>> - priv->io_base + _REG(VD2_IF0_GEN_REG));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_GEN_REG));
>> writel_relaxed(priv->viu.vd1_if0_gen_reg2,
>> - priv->io_base + _REG(VD1_IF0_GEN_REG2));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_GEN_REG2));
>> writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
>> - priv->io_base + _REG(VIU_VD1_FMT_CTRL));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VIU_VD1_FMT_CTRL));
>> writel_relaxed(priv->viu.viu_vd1_fmt_ctrl,
>> - priv->io_base + _REG(VIU_VD2_FMT_CTRL));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VIU_VD2_FMT_CTRL));
>> writel_relaxed(priv->viu.viu_vd1_fmt_w,
>> - priv->io_base + _REG(VIU_VD1_FMT_W));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VIU_VD1_FMT_W));
>> writel_relaxed(priv->viu.viu_vd1_fmt_w,
>> - priv->io_base + _REG(VIU_VD2_FMT_W));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VIU_VD2_FMT_W));
>> writel_relaxed(priv->viu.vd1_if0_canvas0,
>> - priv->io_base + _REG(VD1_IF0_CANVAS0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CANVAS0));
>> writel_relaxed(priv->viu.vd1_if0_canvas0,
>> - priv->io_base + _REG(VD1_IF0_CANVAS1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CANVAS1));
>> writel_relaxed(priv->viu.vd1_if0_canvas0,
>> - priv->io_base + _REG(VD2_IF0_CANVAS0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CANVAS0));
>> writel_relaxed(priv->viu.vd1_if0_canvas0,
>> - priv->io_base + _REG(VD2_IF0_CANVAS1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CANVAS1));
>> writel_relaxed(priv->viu.vd1_if0_luma_x0,
>> - priv->io_base + _REG(VD1_IF0_LUMA_X0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_LUMA_X0));
>> writel_relaxed(priv->viu.vd1_if0_luma_x0,
>> - priv->io_base + _REG(VD1_IF0_LUMA_X1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_LUMA_X1));
>> writel_relaxed(priv->viu.vd1_if0_luma_x0,
>> - priv->io_base + _REG(VD2_IF0_LUMA_X0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_LUMA_X0));
>> writel_relaxed(priv->viu.vd1_if0_luma_x0,
>> - priv->io_base + _REG(VD2_IF0_LUMA_X1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_LUMA_X1));
>> writel_relaxed(priv->viu.vd1_if0_luma_y0,
>> - priv->io_base + _REG(VD1_IF0_LUMA_Y0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_LUMA_Y0));
>> writel_relaxed(priv->viu.vd1_if0_luma_y0,
>> - priv->io_base + _REG(VD1_IF0_LUMA_Y1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_LUMA_Y1));
>> writel_relaxed(priv->viu.vd1_if0_luma_y0,
>> - priv->io_base + _REG(VD2_IF0_LUMA_Y0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_LUMA_Y0));
>> writel_relaxed(priv->viu.vd1_if0_luma_y0,
>> - priv->io_base + _REG(VD2_IF0_LUMA_Y1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_LUMA_Y1));
>> writel_relaxed(priv->viu.vd1_if0_chroma_x0,
>> - priv->io_base + _REG(VD1_IF0_CHROMA_X0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CHROMA_X0));
>> writel_relaxed(priv->viu.vd1_if0_chroma_x0,
>> - priv->io_base + _REG(VD1_IF0_CHROMA_X1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CHROMA_X1));
>> writel_relaxed(priv->viu.vd1_if0_chroma_x0,
>> - priv->io_base + _REG(VD2_IF0_CHROMA_X0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CHROMA_X0));
>> writel_relaxed(priv->viu.vd1_if0_chroma_x0,
>> - priv->io_base + _REG(VD2_IF0_CHROMA_X1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CHROMA_X1));
>> writel_relaxed(priv->viu.vd1_if0_chroma_y0,
>> - priv->io_base + _REG(VD1_IF0_CHROMA_Y0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CHROMA_Y0));
>> writel_relaxed(priv->viu.vd1_if0_chroma_y0,
>> - priv->io_base + _REG(VD1_IF0_CHROMA_Y1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CHROMA_Y1));
>> writel_relaxed(priv->viu.vd1_if0_chroma_y0,
>> - priv->io_base + _REG(VD2_IF0_CHROMA_Y0));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CHROMA_Y0));
>> writel_relaxed(priv->viu.vd1_if0_chroma_y0,
>> - priv->io_base + _REG(VD2_IF0_CHROMA_Y1));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CHROMA_Y1));
>> writel_relaxed(priv->viu.vd1_if0_repeat_loop,
>> - priv->io_base + _REG(VD1_IF0_RPT_LOOP));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_RPT_LOOP));
>> writel_relaxed(priv->viu.vd1_if0_repeat_loop,
>> - priv->io_base + _REG(VD2_IF0_RPT_LOOP));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_RPT_LOOP));
>> writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
>> - priv->io_base + _REG(VD1_IF0_LUMA0_RPT_PAT));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_LUMA0_RPT_PAT));
>> writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
>> - priv->io_base + _REG(VD2_IF0_LUMA0_RPT_PAT));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_LUMA0_RPT_PAT));
>> writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
>> - priv->io_base + _REG(VD1_IF0_LUMA1_RPT_PAT));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_LUMA1_RPT_PAT));
>> writel_relaxed(priv->viu.vd1_if0_luma0_rpt_pat,
>> - priv->io_base + _REG(VD2_IF0_LUMA1_RPT_PAT));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_LUMA1_RPT_PAT));
>> writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
>> - priv->io_base + _REG(VD1_IF0_CHROMA0_RPT_PAT));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CHROMA0_RPT_PAT));
>> writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
>> - priv->io_base + _REG(VD2_IF0_CHROMA0_RPT_PAT));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CHROMA0_RPT_PAT));
>> writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
>> - priv->io_base + _REG(VD1_IF0_CHROMA1_RPT_PAT));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CHROMA1_RPT_PAT));
>> writel_relaxed(priv->viu.vd1_if0_chroma0_rpt_pat,
>> - priv->io_base + _REG(VD2_IF0_CHROMA1_RPT_PAT));
>> - writel_relaxed(0, priv->io_base + _REG(VD1_IF0_LUMA_PSEL));
>> - writel_relaxed(0, priv->io_base + _REG(VD1_IF0_CHROMA_PSEL));
>> - writel_relaxed(0, priv->io_base + _REG(VD2_IF0_LUMA_PSEL));
>> - writel_relaxed(0, priv->io_base + _REG(VD2_IF0_CHROMA_PSEL));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CHROMA1_RPT_PAT));
>> + writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_LUMA_PSEL));
>> + writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_CHROMA_PSEL));
>> + writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_LUMA_PSEL));
>> + writel_relaxed(0, priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD2_IF0_CHROMA_PSEL));
>> writel_relaxed(priv->viu.vd1_range_map_y,
>> - priv->io_base + _REG(VD1_IF0_RANGE_MAP_Y));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_RANGE_MAP_Y));
>> writel_relaxed(priv->viu.vd1_range_map_cb,
>> - priv->io_base + _REG(VD1_IF0_RANGE_MAP_CB));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_RANGE_MAP_CB));
>> writel_relaxed(priv->viu.vd1_range_map_cr,
>> - priv->io_base + _REG(VD1_IF0_RANGE_MAP_CR));
>> + priv->io_base + meson_crtc->viu_offset +
>> + _REG(VD1_IF0_RANGE_MAP_CR));
>> writel_relaxed(0x78404,
>> priv->io_base + _REG(VPP_SC_MISC));
>> writel_relaxed(priv->viu.vpp_pic_in_height,
>> @@ -389,11 +548,8 @@ void meson_crtc_irq(struct meson_drm *priv)
>> writel_relaxed(0x42, priv->io_base + _REG(VPP_SCALE_COEF_IDX));
>>
>> /* Enable VD1 */
>> - writel_bits_relaxed(VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
>> - VPP_COLOR_MNG_ENABLE,
>> - VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
>> - VPP_COLOR_MNG_ENABLE,
>> - priv->io_base + _REG(VPP_MISC));
>> + if (meson_crtc->enable_vd1)
>> + meson_crtc->enable_vd1(priv);
>>
>> priv->viu.vd1_commit = false;
>> }
>> @@ -430,7 +586,16 @@ int meson_crtc_create(struct meson_drm *priv)
>> return ret;
>> }
>>
>> - drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
>> + meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
>> + meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
>> + drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
>> + } else {
>> + meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
>> + meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
>> + drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
>> + }
>>
>> priv->crtc = crtc;
>>
>> diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
>> index 214a7cb18ce2..9614baa836b9 100644
>> --- a/drivers/gpu/drm/meson/meson_drv.h
>> +++ b/drivers/gpu/drm/meson/meson_drv.h
>> @@ -62,6 +62,10 @@ struct meson_drm {
>> uint32_t osd_sc_h_phase_step;
>> uint32_t osd_sc_h_ctrl0;
>> uint32_t osd_sc_v_ctrl0;
>> + uint32_t osd_blend_din0_scope_h;
>> + uint32_t osd_blend_din0_scope_v;
>> + uint32_t osb_blend0_size;
>> + uint32_t osb_blend1_size;
>>
>> bool vd1_enabled;
>> bool vd1_commit;
>
>


Will fix in a follow-up patch.

Neil

2019-04-09 09:20:46

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 09/11] drm/meson: Add G12A Video Clock setup

On 09/04/2019 10:46, Jerome Brunet wrote:
> On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
>> While switching to the Common Clock Framework is still Work In Progress,
>> this patch adds the corresponding G12A HDMI PLL setup to be on-par
>> with the other SoCs support.
>>
>> The G12A has only a single tweak about the high frequency setup,
>> where the HDMI PLL needs a specific setup to handle correctly the
>> 5.94GHz DCO frequency.
>>
>> Apart that, it handle correctly all the other HDMI frequencies
>> and can achieve even better DMT clock frequency precision with
>> the larger fractional dividier width.
>>
>> Signed-off-by: Neil Armstrong <[email protected]>
>> ---
>> drivers/gpu/drm/meson/meson_vclk.c | 119 ++++++++++++++++++++++++++---
>> 1 file changed, 108 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
>> index c15a5a5df633..b39034745444 100644
>> --- a/drivers/gpu/drm/meson/meson_vclk.c
>> +++ b/drivers/gpu/drm/meson/meson_vclk.c
>> @@ -113,9 +113,12 @@
>> #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
>> #define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
>> #define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
>> +#define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
>>
>> #define HDMI_PLL_RESET BIT(28)
>> +#define HDMI_PLL_RESET_G12A BIT(29)
>> #define HDMI_PLL_LOCK BIT(31)
>> +#define HDMI_PLL_LOCK_G12A (3 << 30)
>
> GENMASK(31, 30) ?

Ack

>
>>
>> #define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
>>
>> @@ -257,6 +260,10 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
>> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
>> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
>> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
>> +
>> + /* Poll for lock bit */
>> + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
>> + (val & HDMI_PLL_LOCK), 10, 0);
>> } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
>> meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
>> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
>> @@ -271,11 +278,26 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
>> HDMI_PLL_RESET, HDMI_PLL_RESET);
>> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
>> HDMI_PLL_RESET, 0);
>> - }
>>
>> - /* Poll for lock bit */
>> - regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
>> - (val & HDMI_PLL_LOCK), 10, 0);
>> + /* Poll for lock bit */
>> + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
>> + (val & HDMI_PLL_LOCK), 10, 0);
>> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00010000);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x56540000);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x3a0504f7);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
>> +
>> + /* Poll for lock bit */
>> + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
>> + ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
>> + 10, 0);
>> + }
>>
>> /* Disable VCLK2 */
>> regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
>> @@ -288,8 +310,13 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
>> VCLK2_DIV_MASK, (55 - 1));
>>
>> /* select vid_pll for vclk2 */
>> - regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
>> - VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
>> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
>> + VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
>> + else
>> + regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
>> + VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
>> +
>> /* enable vclk2 gate */
>> regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
>>
>> @@ -476,32 +503,80 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
>> /* Poll for lock bit */
>> regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
>> (val & HDMI_PLL_LOCK), 10, 0);
>> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
>> +
>> + /* Enable and reset */
>> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
>> + 0x3 << 28, 0x3 << 28);
>
> Could you use define of the enable and reset bit instead of 0x3 << 28 ?

Ack

>
>> +
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, frac);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
>> +
>> + /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
>> + if (m >= 0xf7) {
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0xea68dc00);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
>> + } else {
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
>> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
>> + }
>> +
>> + do {
>> + /* Reset PLL */
>> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
>> + HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
>> +
>> + /* UN-Reset PLL */
>> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
>> + HDMI_PLL_RESET_G12A, 0);
>> +
>> + /* Poll for lock bits */
>> + if (!regmap_read_poll_timeout(priv->hhi,
>> + HHI_HDMI_PLL_CNTL, val,
>> + ((val & HDMI_PLL_LOCK_G12A)
>> + == HDMI_PLL_LOCK_G12A),
>> + 10, 100))
>> + break;
>> + } while(1);
>> }
>>
>> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
>> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
>> 3 << 16, pll_od_to_reg(od1) << 16);
>> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
>> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
>> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
>> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
>> 3 << 21, pll_od_to_reg(od1) << 21);
>> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
>> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
>> + 3 << 16, pll_od_to_reg(od1) << 16);
>>
>> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
>> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
>> 3 << 22, pll_od_to_reg(od2) << 22);
>> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
>> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
>> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
>> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
>> 3 << 23, pll_od_to_reg(od2) << 23);
>> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
>> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
>> + 3 << 18, pll_od_to_reg(od2) << 18);
>>
>> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
>> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
>> 3 << 18, pll_od_to_reg(od3) << 18);
>> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
>> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
>> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
>> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
>> 3 << 19, pll_od_to_reg(od3) << 19);
>> -
>> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
>> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
>> + 3 << 20, pll_od_to_reg(od3) << 20);
>
> Could you remove the constants above and define the shift and mask of the ODs
> ?

Ack

>
>> }
>>
>> #define XTAL_FREQ 24000
>> @@ -518,6 +593,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
>>
>> #define HDMI_FRAC_MAX_GXBB 4096
>> #define HDMI_FRAC_MAX_GXL 1024
>> +#define HDMI_FRAC_MAX_G12A 131072
>>
>> static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
>> unsigned int m,
>> @@ -534,6 +610,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
>> parent_freq *= 2;
>> }
>>
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
>> + frac_max = HDMI_FRAC_MAX_G12A;
>> +
>> /* We can have a perfect match !*/
>> if (pll_freq / m == parent_freq &&
>> pll_freq % m == 0)
>> @@ -559,7 +638,8 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
>> if (frac >= HDMI_FRAC_MAX_GXBB)
>> return false;
>> } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
>> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
>> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu") ||
>> + meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> /* Empiric supported min/max dividers */
>> if (m < 106 || m > 247)
>> return false;
>> @@ -713,6 +793,23 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
>> break;
>> }
>>
>> + meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
>> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + switch (pll_base_freq) {
>> + case 2970000:
>> + m = 0x7b;
>> + frac = vic_alternate_clock ? 0x140b4 : 0x18000;
>> + break;
>> + case 4320000:
>> + m = vic_alternate_clock ? 0xb3 : 0xb4;
>> + frac = vic_alternate_clock ? 0x1a3ee : 0;
>> + break;
>> + case 5940000:
>> + m = 0xf7;
>> + frac = vic_alternate_clock ? 0x8148 : 0x10000;
>> + break;
>> + }
>> +
>> meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
>> }
>>
>
>

Will fix in a follow-up patch, including GXBB/GXL/GXM.

Neil

2019-04-09 09:20:52

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 04/11] drm/meson: Add G12A Support for VIU setup

On 09/04/2019 10:42, Jerome Brunet wrote:
> On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
>> Amlogic G12A SoC needs a different VIU setup code,
>> handle it.
>>
>> Signed-off-by: Neil Armstrong <[email protected]>
>> ---
>> drivers/gpu/drm/meson/meson_viu.c | 72 ++++++++++++++++++++++++++++---
>> 1 file changed, 67 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
>> index ac0f3687e09a..0169c98b01c9 100644
>> --- a/drivers/gpu/drm/meson/meson_viu.c
>> +++ b/drivers/gpu/drm/meson/meson_viu.c
>> @@ -90,6 +90,34 @@ static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
>> EOTF_COEFF_RIGHTSHIFT /* right shift */
>> };
>>
>> +void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv, int *m,
>> + bool csc_on)
>> +{
>> + /* VPP WRAP OSD1 matrix */
>> + writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
>> + writel(m[2] & 0xfff,
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
>> + writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
>> + writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
>> + writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
>> + writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
>> + writel((m[11] & 0x1fff) << 16,
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
>> +
>> + writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
>
> Can you define some of the masks and shifts above ? possibly the same define
> for all the registers I suppose ... maybe using FIELD_PREP ?

Ack

>
>> + writel(m[20] & 0xfff,
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
>> +
>> + writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
>> + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
>> +}
>> +
>> void meson_viu_set_osd_matrix(struct meson_drm *priv,
>> enum viu_matrix_sel_e m_select,
>> int *m, bool csc_on)
>> @@ -336,14 +364,24 @@ void meson_viu_init(struct meson_drm *priv)
>> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
>> meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
>> meson_viu_load_matrix(priv);
>> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
>> + meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
>> + true);
>>
>> /* Initialize OSD1 fifo control register */
>> reg = BIT(0) | /* Urgent DDR request priority */
>> - (4 << 5) | /* hold_fifo_lines */
>> - (3 << 10) | /* burst length 64 */
>> - (32 << 12) | /* fifo_depth_val: 32*8=256 */
>> - (2 << 22) | /* 4 words in 1 burst */
>> - (2 << 24);
>> + (4 << 5); /* hold_fifo_lines */
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
>> + reg |= (1 << 10) | /* burst length 32 */
>> + (32 << 12) | /* fifo_depth_val: 32*8=256 */
>> + (2 << 22) | /* 4 words in 1 burst */
>> + (2 << 24) |
>> + (1 << 31);
>> + else
>> + reg |= (3 << 10) | /* burst length 64 */
>> + (32 << 12) | /* fifo_depth_val: 32*8=256 */
>> + (2 << 22) | /* 4 words in 1 burst */
>> + (2 << 24);
>
> Could you use the BIT() macro and add some defines ?

Ack

>
>> writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
>> writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
>>
>> @@ -369,6 +407,30 @@ void meson_viu_init(struct meson_drm *priv)
>> writel_relaxed(0x00FF00C0,
>> priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
>>
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + writel_relaxed(4 << 29 |
>> + 1 << 27 |
>> + 1 << 26 | /* blend_din0 input to blend0 */
>> + 1 << 25 | /* blend1_dout to blend2 */
>> + 1 << 24 | /* blend1_din3 input to blend1 */
>> + 1 << 20 |
>> + 0 << 16 |
>> + 1,
>> + priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
>> + writel_relaxed(3 << 8 |
>> + 1 << 20,
>> + priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
>> + writel_relaxed(1 << 20,
>> + priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
>> + writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
>> + writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
>> + writel_relaxed(0,
>> + priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
>> + writel_relaxed(0,
>> + priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
>> + writel_bits_relaxed(0x3 << 2, 0x3 << 2,
>> + priv->io_base + _REG(DOLBY_PATH_CTRL));
>
> Same for this hunk

Ack

>
>> + }
>>
>> priv->viu.osd1_enabled = false;
>> priv->viu.osd1_commit = false;
>
>

Will fix in a follow-up patch, including GXBB/GXL/GXM.

Neil

2019-04-09 09:21:10

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 08/11] drm/meson: Add G12A support for CVBS Encoer

On 09/04/2019 10:43, Jerome Brunet wrote:
> On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
>> The Meson G12A SoCs uses the exact same CVBS encoder except a simple
>> CVBS DAC register offset and settings delta.
>>
>> Signed-off-by: Neil Armstrong <[email protected]>
>> ---
>> drivers/gpu/drm/meson/meson_venc.c | 11 +++++++++--
>> drivers/gpu/drm/meson/meson_venc_cvbs.c | 25 ++++++++++++++++++-------
>> 2 files changed, 27 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
>> index 66d73a932d19..6faca7313339 100644
>> --- a/drivers/gpu/drm/meson/meson_venc.c
>> +++ b/drivers/gpu/drm/meson/meson_venc.c
>> @@ -73,7 +73,9 @@
>> /* HHI Registers */
>> #define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */
>> #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
>> +#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
>> #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
>> +#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */
>> #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */
>>
>> struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
>> @@ -1675,8 +1677,13 @@ void meson_venc_disable_vsync(struct meson_drm *priv)
>> void meson_venc_init(struct meson_drm *priv)
>> {
>> /* Disable CVBS VDAC */
>> - regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
>> - regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 8);
>> + } else {
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
>> + }
>>
>> /* Power Down Dacs */
>> writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
>> diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
>> index d622d817b6df..2c5341c881c4 100644
>> --- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
>> +++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
>> @@ -37,7 +37,9 @@
>>
>> /* HHI VDAC Registers */
>> #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
>> +#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
>> #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
>> +#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */
>>
>> struct meson_venc_cvbs {
>> struct drm_encoder encoder;
>> @@ -166,8 +168,13 @@ static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
>> struct meson_drm *priv = meson_venc_cvbs->priv;
>>
>> /* Disable CVBS VDAC */
>> - regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
>> - regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
>> + } else {
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
>
> I imagine 8 stands for BIT(3) ? Could you add a define to explain (quickly)
> what it is ?

Ack

>
>> + }
>> }
>>
>> static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
>> @@ -179,13 +186,17 @@ static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
>> /* VDAC0 source is not from ATV */
>> writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
>>
>> - if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
>> regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
>> - else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
>> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
>> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
>> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
>> regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
>> -
>> - regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
>> + } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0x906001);
>> + regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
>> + }
>
> Maybe the values above are just magics taken from the vendor kernel, but if
> you can, it would be nice to break them down to help us understand what is
> controlled in these CTNL registers.

It's pretty magic values, but I'll do my best.

>
>> }
>>
>> static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
>
>
Will fix in a follow-up patch,

Neil

2019-04-09 09:21:33

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 08/11] drm/meson: Add G12A support for CVBS Encoer

On 09/04/2019 10:44, Jerome Brunet wrote:
> On Tue, 2019-04-09 at 10:43 +0200, Jerome Brunet wrote:
>> On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
>>> The Meson G12A SoCs uses the exact same CVBS encoder except a simple
>>> CVBS DAC register offset and settings delta.
>>>
>>> Signed-off-by: Neil Armstrong <[email protected]>
>>> ---
>>> drivers/gpu/drm/meson/meson_venc.c | 11 +++++++++--
>>> drivers/gpu/drm/meson/meson_venc_cvbs.c | 25 ++++++++++++++++++-------
>>> 2 files changed, 27 insertions(+), 9 deletions(-)
>
> ... and there is a typo in the patch title. s/Encoer/Encoder
>

Thanks for pointing this, I'll fix while applying.

Neil

2019-04-09 09:22:18

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 06/11] drm/meson: Add G12A Support for the Overlay video plane

On 09/04/2019 10:42, Jerome Brunet wrote:
> On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
>> Amlogic G12A SoC supports the same set of Video Planes, but now
>> are handled by the new OSD plane blender module.
>>
>> This patch uses the same VD1 plane for G12A, using the exact same scaler
>> and VD11 setup registers, except using the new blender register to
>> disable the plane.
>>
>> Signed-off-by: Neil Armstrong <[email protected]>
>> ---
>> drivers/gpu/drm/meson/meson_overlay.c | 10 ++++++++--
>> 1 file changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
>> index b54a22e483b9..bdbf925ff3e8 100644
>> --- a/drivers/gpu/drm/meson/meson_overlay.c
>> +++ b/drivers/gpu/drm/meson/meson_overlay.c
>> @@ -516,8 +516,14 @@ static void meson_overlay_atomic_disable(struct drm_plane *plane,
>> priv->viu.vd1_enabled = false;
>>
>> /* Disable VD1 */
>> - writel_bits_relaxed(VPP_VD1_POSTBLEND | VPP_VD1_PREBLEND, 0,
>> - priv->io_base + _REG(VPP_MISC));
>> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
>> + writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
>> + writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
>> + writel_relaxed(0, priv->io_base + _REG(VD1_IF0_GEN_REG + 0x17b0));
>> + writel_relaxed(0, priv->io_base + _REG(VD2_IF0_GEN_REG + 0x17b0));
>
> Is it possible to add a comment explaining this 0x17b0 value ?

It's the same register shift as in crtc, will add a define.

>
>> + } else
>> + writel_bits_relaxed(VPP_VD1_POSTBLEND | VPP_VD1_PREBLEND, 0,
>> + priv->io_base + _REG(VPP_MISC));
>>
>> }
>>
>
>

Will fix in a follow-up patch,

Neil