Unverified Commit 83239891 authored by Maxime Ripard's avatar Maxime Ripard
Browse files

drm/vc4: hdmi: Support the BCM2711 HDMI controllers

parent 37387429
Loading
Loading
Loading
Loading
+284 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
#include <linux/rational.h>
#include <linux/reset.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_drm_eld.h>
#include <sound/pcm_params.h>
@@ -53,6 +54,31 @@
#include "vc4_hdmi_regs.h"
#include "vc4_regs.h"

#define VC5_HDMI_HORZA_HFP_SHIFT		16
#define VC5_HDMI_HORZA_HFP_MASK			VC4_MASK(28, 16)
#define VC5_HDMI_HORZA_VPOS			BIT(15)
#define VC5_HDMI_HORZA_HPOS			BIT(14)
#define VC5_HDMI_HORZA_HAP_SHIFT		0
#define VC5_HDMI_HORZA_HAP_MASK			VC4_MASK(13, 0)

#define VC5_HDMI_HORZB_HBP_SHIFT		16
#define VC5_HDMI_HORZB_HBP_MASK			VC4_MASK(26, 16)
#define VC5_HDMI_HORZB_HSP_SHIFT		0
#define VC5_HDMI_HORZB_HSP_MASK			VC4_MASK(10, 0)

#define VC5_HDMI_VERTA_VSP_SHIFT		24
#define VC5_HDMI_VERTA_VSP_MASK			VC4_MASK(28, 24)
#define VC5_HDMI_VERTA_VFP_SHIFT		16
#define VC5_HDMI_VERTA_VFP_MASK			VC4_MASK(22, 16)
#define VC5_HDMI_VERTA_VAL_SHIFT		0
#define VC5_HDMI_VERTA_VAL_MASK			VC4_MASK(12, 0)

#define VC5_HDMI_VERTB_VSPO_SHIFT		16
#define VC5_HDMI_VERTB_VSPO_MASK		VC4_MASK(29, 16)

# define VC4_HD_M_SW_RST			BIT(2)
# define VC4_HD_M_ENABLE			BIT(0)

#define CEC_CLOCK_FREQ 40000
#define VC4_HSM_MID_CLOCK 149985000

@@ -83,6 +109,16 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
}

static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
{
	reset_control_reset(vc4_hdmi->reset);

	HDMI_WRITE(HDMI_DVP_CTL, 0);

	HDMI_WRITE(HDMI_CLOCK_STOP,
		   HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
}

static enum drm_connector_status
vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
@@ -393,6 +429,45 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
}

static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
{
	u32 csc_ctl;

	csc_ctl = 0x07;	/* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */

	if (enable) {
		/* CEA VICs other than #1 requre limited range RGB
		 * output unless overridden by an AVI infoframe.
		 * Apply a colorspace conversion to squash 0-255 down
		 * to 16-235.  The matrix here is:
		 *
		 * [ 0.8594 0      0      16]
		 * [ 0      0.8594 0      16]
		 * [ 0      0      0.8594 16]
		 * [ 0      0      0       1]
		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
		 */
		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
		HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
		HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
		HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
		HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
	} else {
		/* Still use the matrix for full range, but make it unity.
		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
		 */
		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
		HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
		HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
		HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
		HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
	}

	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
}

static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
				 struct drm_display_mode *mode)
{
@@ -437,6 +512,53 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
	HDMI_WRITE(HDMI_VERTB0, vertb_even);
	HDMI_WRITE(HDMI_VERTB1, vertb);
}
static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
				 struct drm_display_mode *mode)
{
	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
	u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
	u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
				   VC5_HDMI_VERTA_VSP) |
		     VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
				   VC5_HDMI_VERTA_VFP) |
		     VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
	u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
		     VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
				   VC4_HDMI_VERTB_VBP));
	u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
			  VC4_SET_FIELD(mode->crtc_vtotal -
					mode->crtc_vsync_end -
					interlaced,
					VC4_HDMI_VERTB_VBP));

	HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
	HDMI_WRITE(HDMI_HORZA,
		   (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
		   (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
				 VC5_HDMI_HORZA_HAP) |
		   VC4_SET_FIELD((mode->hsync_start -
				  mode->hdisplay) * pixel_rep,
				 VC5_HDMI_HORZA_HFP));

	HDMI_WRITE(HDMI_HORZB,
		   VC4_SET_FIELD((mode->htotal -
				  mode->hsync_end) * pixel_rep,
				 VC5_HDMI_HORZB_HBP) |
		   VC4_SET_FIELD((mode->hsync_end -
				  mode->hsync_start) * pixel_rep,
				 VC5_HDMI_HORZB_HSP));

	HDMI_WRITE(HDMI_VERTA0, verta);
	HDMI_WRITE(HDMI_VERTA1, verta);

	HDMI_WRITE(HDMI_VERTB0, vertb_even);
	HDMI_WRITE(HDMI_VERTB1, vertb);

	HDMI_WRITE(HDMI_CLOCK_STOP, 0);
}

static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
{
@@ -668,6 +790,18 @@ static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
	return channel_map;
}

static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
{
	int i;
	u32 channel_map = 0;

	for (i = 0; i < 8; i++) {
		if (channel_mask & BIT(i))
			channel_map |= i << (4 * i);
	}
	return channel_map;
}

/* HDMI audio codec callbacks */
static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
{
@@ -1399,6 +1533,104 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
	return 0;
}

static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
{
	struct platform_device *pdev = vc4_hdmi->pdev;
	struct device *dev = &pdev->dev;
	struct resource *res;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
	if (!res)
		return -ENODEV;

	vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
					       resource_size(res));
	if (IS_ERR(vc4_hdmi->hdmicore_regs))
		return PTR_ERR(vc4_hdmi->hdmicore_regs);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
	if (!res)
		return -ENODEV;

	vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
	if (IS_ERR(vc4_hdmi->hd_regs))
		return PTR_ERR(vc4_hdmi->hd_regs);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
	if (!res)
		return -ENODEV;

	vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
	if (IS_ERR(vc4_hdmi->cec_regs))
		return PTR_ERR(vc4_hdmi->cec_regs);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
	if (!res)
		return -ENODEV;

	vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
	if (IS_ERR(vc4_hdmi->csc_regs))
		return PTR_ERR(vc4_hdmi->csc_regs);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
	if (!res)
		return -ENODEV;

	vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
	if (IS_ERR(vc4_hdmi->dvp_regs))
		return PTR_ERR(vc4_hdmi->dvp_regs);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
	if (!res)
		return -ENODEV;

	vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
	if (IS_ERR(vc4_hdmi->phy_regs))
		return PTR_ERR(vc4_hdmi->phy_regs);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
	if (!res)
		return -ENODEV;

	vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
	if (IS_ERR(vc4_hdmi->ram_regs))
		return PTR_ERR(vc4_hdmi->ram_regs);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
	if (!res)
		return -ENODEV;

	vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
	if (IS_ERR(vc4_hdmi->rm_regs))
		return PTR_ERR(vc4_hdmi->rm_regs);

	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
	if (IS_ERR(vc4_hdmi->hsm_clock)) {
		DRM_ERROR("Failed to get HDMI state machine clock\n");
		return PTR_ERR(vc4_hdmi->hsm_clock);
	}

	vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");
	if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {
		DRM_ERROR("Failed to get pixel bvb clock\n");
		return PTR_ERR(vc4_hdmi->pixel_bvb_clock);
	}

	vc4_hdmi->audio_clock = devm_clk_get(dev, "audio");
	if (IS_ERR(vc4_hdmi->audio_clock)) {
		DRM_ERROR("Failed to get audio clock\n");
		return PTR_ERR(vc4_hdmi->audio_clock);
	}

	vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
	if (IS_ERR(vc4_hdmi->reset)) {
		DRM_ERROR("Failed to get HDMI reset line\n");
		return PTR_ERR(vc4_hdmi->reset);
	}

	return 0;
}

static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
{
	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
@@ -1569,8 +1801,60 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
	.channel_map		= vc4_hdmi_channel_map,
};

static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
	.debugfs_name		= "hdmi0_regs",
	.card_name		= "vc4-hdmi-0",
	.max_pixel_clock	= 297000000,
	.registers		= vc5_hdmi_hdmi0_fields,
	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
	.phy_lane_mapping	= {
		PHY_LANE_0,
		PHY_LANE_1,
		PHY_LANE_2,
		PHY_LANE_CK,
	},

	.init_resources		= vc5_hdmi_init_resources,
	.csc_setup		= vc5_hdmi_csc_setup,
	.reset			= vc5_hdmi_reset,
	.set_timings		= vc5_hdmi_set_timings,
	.phy_init		= vc5_hdmi_phy_init,
	.phy_disable		= vc5_hdmi_phy_disable,
	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
	.channel_map		= vc5_hdmi_channel_map,
};

static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
	.encoder_type		= VC4_ENCODER_TYPE_HDMI1,
	.debugfs_name		= "hdmi1_regs",
	.card_name		= "vc4-hdmi-1",
	.max_pixel_clock	= 297000000,
	.registers		= vc5_hdmi_hdmi1_fields,
	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
	.phy_lane_mapping	= {
		PHY_LANE_1,
		PHY_LANE_0,
		PHY_LANE_CK,
		PHY_LANE_2,
	},

	.init_resources		= vc5_hdmi_init_resources,
	.csc_setup		= vc5_hdmi_csc_setup,
	.reset			= vc5_hdmi_reset,
	.set_timings		= vc5_hdmi_set_timings,
	.phy_init		= vc5_hdmi_phy_init,
	.phy_disable		= vc5_hdmi_phy_disable,
	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
	.channel_map		= vc5_hdmi_channel_map,
};

static const struct of_device_id vc4_hdmi_dt_match[] = {
	{ .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
	{ .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
	{ .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
	{}
};

+36 −0
Original line number Diff line number Diff line
@@ -26,6 +26,13 @@ struct drm_display_mode;
struct vc4_hdmi;
struct vc4_hdmi_register;

enum vc4_hdmi_phy_channel {
	PHY_LANE_0 = 0,
	PHY_LANE_1,
	PHY_LANE_2,
	PHY_LANE_CK,
};

struct vc4_hdmi_variant {
	/* Encoder Type for that controller */
	enum vc4_encoder_type encoder_type;
@@ -48,6 +55,13 @@ struct vc4_hdmi_variant {
	/* Number of registers on that variant */
	unsigned int num_registers;

	/* BCM2711 Only.
	 * The variants don't map the lane in the same order in the
	 * PHY, so this is an array mapping the HDMI channel (index)
	 * to the PHY lane (value).
	 */
	enum vc4_hdmi_phy_channel phy_lane_mapping[4];

	/* Callback to get the resources (memory region, interrupts,
	 * clocks, etc) for that variant.
	 */
@@ -108,6 +122,20 @@ struct vc4_hdmi {
	struct i2c_adapter *ddc;
	void __iomem *hdmicore_regs;
	void __iomem *hd_regs;

	/* VC5 Only */
	void __iomem *cec_regs;
	/* VC5 Only */
	void __iomem *csc_regs;
	/* VC5 Only */
	void __iomem *dvp_regs;
	/* VC5 Only */
	void __iomem *phy_regs;
	/* VC5 Only */
	void __iomem *ram_regs;
	/* VC5 Only */
	void __iomem *rm_regs;

	int hpd_gpio;
	bool hpd_active_low;

@@ -121,6 +149,8 @@ struct vc4_hdmi {
	struct clk *audio_clock;
	struct clk *pixel_bvb_clock;

	struct reset_control *reset;

	struct debugfs_regset32 hdmi_regset;
	struct debugfs_regset32 hd_regset;
};
@@ -145,4 +175,10 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);

void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
		       struct drm_display_mode *mode);
void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);

#endif /* _VC4_HDMI_H_ */
+481 −0

File changed.

Preview size limit exceeded, changes collapsed.

+201 −0
Original line number Diff line number Diff line
@@ -9,6 +9,12 @@ enum vc4_hdmi_regs {
	VC4_INVALID = 0,
	VC4_HDMI,
	VC4_HD,
	VC5_CEC,
	VC5_CSC,
	VC5_DVP,
	VC5_PHY,
	VC5_RAM,
	VC5_RM,
};

enum vc4_hdmi_field {
@@ -36,6 +42,7 @@ enum vc4_hdmi_field {
	HDMI_CEC_TX_DATA_2,
	HDMI_CEC_TX_DATA_3,
	HDMI_CEC_TX_DATA_4,
	HDMI_CLOCK_STOP,
	HDMI_CORE_REV,
	HDMI_CRP_CFG,
	HDMI_CSC_12_11,
@@ -52,6 +59,7 @@ enum vc4_hdmi_field {
	 */
	HDMI_CTS_0,
	HDMI_CTS_1,
	HDMI_DVP_CTL,
	HDMI_FIFO_CTL,
	HDMI_FRAME_COUNT,
	HDMI_HORZA,
@@ -84,10 +92,27 @@ enum vc4_hdmi_field {
	HDMI_RAM_PACKET_CONFIG,
	HDMI_RAM_PACKET_START,
	HDMI_RAM_PACKET_STATUS,
	HDMI_RM_CONTROL,
	HDMI_RM_FORMAT,
	HDMI_RM_OFFSET,
	HDMI_SCHEDULER_CONTROL,
	HDMI_SW_RESET_CONTROL,
	HDMI_TX_PHY_CHANNEL_SWAP,
	HDMI_TX_PHY_CLK_DIV,
	HDMI_TX_PHY_CTL_0,
	HDMI_TX_PHY_CTL_1,
	HDMI_TX_PHY_CTL_2,
	HDMI_TX_PHY_CTL_3,
	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
	HDMI_TX_PHY_PLL_CFG,
	HDMI_TX_PHY_PLL_CTL_0,
	HDMI_TX_PHY_PLL_CTL_1,
	HDMI_TX_PHY_POWERDOWN_CTL,
	HDMI_TX_PHY_RESET_CTL,
	HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
	HDMI_VEC_INTERFACE_XBAR,
	HDMI_VERTA0,
	HDMI_VERTA1,
	HDMI_VERTB0,
@@ -110,6 +135,12 @@ struct vc4_hdmi_register {

#define VC4_HD_REG(reg, offset)		_VC4_REG(VC4_HD, reg, offset)
#define VC4_HDMI_REG(reg, offset)	_VC4_REG(VC4_HDMI, reg, offset)
#define VC5_CEC_REG(reg, offset)	_VC4_REG(VC5_CEC, reg, offset)
#define VC5_CSC_REG(reg, offset)	_VC4_REG(VC5_CSC, reg, offset)
#define VC5_DVP_REG(reg, offset)	_VC4_REG(VC5_DVP, reg, offset)
#define VC5_PHY_REG(reg, offset)	_VC4_REG(VC5_PHY, reg, offset)
#define VC5_RAM_REG(reg, offset)	_VC4_REG(VC5_RAM, reg, offset)
#define VC5_RM_REG(reg, offset)		_VC4_REG(VC5_RM, reg, offset)

static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
	VC4_HD_REG(HDMI_M_CTL, 0x000c),
@@ -172,6 +203,158 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
	VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
};

static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
	VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
	VC4_HD_REG(HDMI_MAI_CTL, 0x0010),
	VC4_HD_REG(HDMI_MAI_THR, 0x0014),
	VC4_HD_REG(HDMI_MAI_FMT, 0x0018),
	VC4_HD_REG(HDMI_MAI_DATA, 0x001c),
	VC4_HD_REG(HDMI_MAI_SMP, 0x0020),
	VC4_HD_REG(HDMI_VID_CTL, 0x0044),
	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060),

	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
	VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
	VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
	VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
	VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
	VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
	VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
	VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
	VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),

	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
	VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),

	VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
	VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
	VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
	VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
	VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
	VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
	VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
	VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
	VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),

	VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
	VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
	VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),

	VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),

	VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
	VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
	VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
	VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
	VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
	VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
	VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
	VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
	VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
	VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
	VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
	VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
	VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),

	VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
	VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
	VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
	VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
	VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
	VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
	VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
};

static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
	VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
	VC4_HD_REG(HDMI_MAI_CTL, 0x0030),
	VC4_HD_REG(HDMI_MAI_THR, 0x0034),
	VC4_HD_REG(HDMI_MAI_FMT, 0x0038),
	VC4_HD_REG(HDMI_MAI_DATA, 0x003c),
	VC4_HD_REG(HDMI_MAI_SMP, 0x0040),
	VC4_HD_REG(HDMI_VID_CTL, 0x0048),
	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064),

	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
	VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
	VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
	VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
	VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
	VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
	VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
	VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
	VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),

	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
	VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),

	VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
	VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
	VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
	VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
	VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
	VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
	VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
	VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
	VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),

	VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
	VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
	VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),

	VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),

	VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
	VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
	VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
	VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
	VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
	VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
	VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
	VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
	VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
	VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
	VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
	VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
	VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),

	VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
	VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
	VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
	VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
	VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
	VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
	VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
};

static inline
void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
					enum vc4_hdmi_regs reg)
@@ -183,6 +366,24 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
	case VC4_HDMI:
		return hdmi->hdmicore_regs;

	case VC5_CSC:
		return hdmi->csc_regs;

	case VC5_CEC:
		return hdmi->cec_regs;

	case VC5_DVP:
		return hdmi->dvp_regs;

	case VC5_PHY:
		return hdmi->phy_regs;

	case VC5_RAM:
		return hdmi->ram_regs;

	case VC5_RM:
		return hdmi->rm_regs;

	default:
		return NULL;
	}
+2 −0
Original line number Diff line number Diff line
@@ -744,6 +744,8 @@
# define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)
# define VC4_HD_CSC_CTL_ENABLE			BIT(0)

# define VC4_DVP_HT_CLOCK_STOP_PIXEL		BIT(1)

/* HVS display list information. */
#define HVS_BOOTLOADER_DLIST_END                32