Unverified Commit 1cbc91eb authored by Maxime Ripard's avatar Maxime Ripard
Browse files

drm/vc4: Consolidate Hardware Revision Check



A new generation of controller has been introduced with the
BCM2711/RaspberryPi4. This generation needs a bunch of quirks, and over
time we've piled on a number of checks in most parts of the drivers.

All these checks are performed several times, and are not always
consistent. Let's create a single, global, variable to hold it and use
it everywhere.

Reviewed-by: default avatarMelissa Wen <mwen@igalia.com>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220610115149.964394-3-maxime@cerno.tech
parent cb468c7d
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -256,7 +256,7 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
		 * Removing 1 from the FIFO full level however
		 * seems to completely remove that issue.
		 */
		if (!vc4->hvs->hvs5)
		if (!vc4->is_vc5)
			return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX - 1;

		return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX;
@@ -389,7 +389,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
	if (is_dsi)
		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);

	if (vc4->hvs->hvs5)
	if (vc4->is_vc5)
		CRTC_WRITE(PV_MUX_CFG,
			   VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP,
					 PV_MUX_CFG_RGB_PIXEL_MUX_MODE));
@@ -1149,7 +1149,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
				  crtc_funcs, NULL);
	drm_crtc_helper_add(crtc, crtc_helper_funcs);

	if (!vc4->hvs->hvs5) {
	if (!vc4->is_vc5) {
		drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));

		drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
+4 −0
Original line number Diff line number Diff line
@@ -217,10 +217,13 @@ static int vc4_drm_bind(struct device *dev)
	struct vc4_dev *vc4;
	struct device_node *node;
	struct drm_crtc *crtc;
	bool is_vc5;
	int ret = 0;

	dev->coherent_dma_mask = DMA_BIT_MASK(32);

	is_vc5 = of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5");

	/* If VC4 V3D is missing, don't advertise render nodes. */
	node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL);
	if (!node || !of_device_is_available(node))
@@ -230,6 +233,7 @@ static int vc4_drm_bind(struct device *dev)
	vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base);
	if (IS_ERR(vc4))
		return PTR_ERR(vc4);
	vc4->is_vc5 = is_vc5;

	drm = &vc4->base;
	platform_set_drvdata(pdev, drm);
+3 −3
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ struct vc4_perfmon {
struct vc4_dev {
	struct drm_device base;

	bool is_vc5;

	unsigned int irq;

	struct vc4_hvs *hvs;
@@ -316,6 +318,7 @@ struct vc4_v3d {
};

struct vc4_hvs {
	struct vc4_dev *vc4;
	struct platform_device *pdev;
	void __iomem *regs;
	u32 __iomem *dlist;
@@ -333,9 +336,6 @@ struct vc4_hvs {
	struct drm_mm_node mitchell_netravali_filter;

	struct debugfs_regset32 regset;

	/* HVS version 5 flag, therefore requires updated dlist structures */
	bool hvs5;
};

struct vc4_plane {
+9 −9
Original line number Diff line number Diff line
@@ -220,10 +220,11 @@ u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)

int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output)
{
	struct vc4_dev *vc4 = hvs->vc4;
	u32 reg;
	int ret;

	if (!hvs->hvs5)
	if (!vc4->is_vc5)
		return output;

	switch (output) {
@@ -273,6 +274,7 @@ int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output)
static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
				struct drm_display_mode *mode, bool oneshot)
{
	struct vc4_dev *vc4 = hvs->vc4;
	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
	unsigned int chan = vc4_crtc_state->assigned_channel;
@@ -291,7 +293,7 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
	 */
	dispctrl = SCALER_DISPCTRLX_ENABLE;

	if (!hvs->hvs5)
	if (!vc4->is_vc5)
		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
					  SCALER_DISPCTRLX_WIDTH) |
			    VC4_SET_FIELD(mode->vdisplay,
@@ -312,7 +314,7 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,

	HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
		  SCALER_DISPBKGND_AUTOHS |
		  ((!hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
		  ((!vc4->is_vc5) ? SCALER_DISPBKGND_GAMMA : 0) |
		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));

	/* Reload the LUT, since the SRAMs would have been disabled if
@@ -617,11 +619,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
	if (!hvs)
		return -ENOMEM;

	hvs->vc4 = vc4;
	hvs->pdev = pdev;

	if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm2711-hvs"))
		hvs->hvs5 = true;

	hvs->regs = vc4_ioremap_regs(pdev, 0);
	if (IS_ERR(hvs->regs))
		return PTR_ERR(hvs->regs);
@@ -630,7 +630,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
	hvs->regset.regs = hvs_regs;
	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);

	if (hvs->hvs5) {
	if (vc4->is_vc5) {
		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
		if (IS_ERR(hvs->core_clk)) {
			dev_err(&pdev->dev, "Couldn't get core clock\n");
@@ -644,7 +644,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
		}
	}

	if (!hvs->hvs5)
	if (!vc4->is_vc5)
		hvs->dlist = hvs->regs + SCALER_DLIST_START;
	else
		hvs->dlist = hvs->regs + SCALER5_DLIST_START;
@@ -665,7 +665,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
	 * between planes when they don't overlap on the screen, but
	 * for now we just allocate globally.
	 */
	if (!hvs->hvs5)
	if (!vc4->is_vc5)
		/* 48k words of 2x12-bit pixels */
		drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024);
	else
+5 −7
Original line number Diff line number Diff line
@@ -393,7 +393,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
		old_hvs_state->fifo_state[channel].pending_commit = NULL;
	}

	if (vc4->hvs->hvs5) {
	if (vc4->is_vc5) {
		unsigned long state_rate = max(old_hvs_state->core_clock_rate,
					       new_hvs_state->core_clock_rate);
		unsigned long core_rate = max_t(unsigned long,
@@ -412,7 +412,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)

	vc4_ctm_commit(vc4, state);

	if (vc4->hvs->hvs5)
	if (vc4->is_vc5)
		vc5_hvs_pv_muxing_commit(vc4, state);
	else
		vc4_hvs_pv_muxing_commit(vc4, state);
@@ -430,7 +430,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)

	drm_atomic_helper_cleanup_planes(dev, state);

	if (vc4->hvs->hvs5) {
	if (vc4->is_vc5) {
		drm_dbg(dev, "Running the core clock at %lu Hz\n",
			new_hvs_state->core_clock_rate);

@@ -1000,8 +1000,6 @@ static const struct drm_mode_config_funcs vc4_mode_funcs = {
int vc4_kms_load(struct drm_device *dev)
{
	struct vc4_dev *vc4 = to_vc4_dev(dev);
	bool is_vc5 = of_device_is_compatible(dev->dev->of_node,
					      "brcm,bcm2711-vc5");
	int ret;

	/*
@@ -1009,7 +1007,7 @@ int vc4_kms_load(struct drm_device *dev)
	 * the BCM2711, but the load tracker computations are used for
	 * the core clock rate calculation.
	 */
	if (!is_vc5) {
	if (!vc4->is_vc5) {
		/* Start with the load tracker enabled. Can be
		 * disabled through the debugfs load_tracker file.
		 */
@@ -1025,7 +1023,7 @@ int vc4_kms_load(struct drm_device *dev)
		return ret;
	}

	if (is_vc5) {
	if (vc4->is_vc5) {
		dev->mode_config.max_width = 7680;
		dev->mode_config.max_height = 7680;
	} else {
Loading