8163715
From 9db79f3a51c97e0cfcde1b25299e8db9ee3d64ab Mon Sep 17 00:00:00 2001
8163715
From: Eric Anholt <eric@anholt.net>
8163715
Date: Wed, 14 Sep 2016 19:21:29 +0100
8163715
Subject: [PATCH 1/4] drm/vc4: Fall back to using an EDID probe in the absence
8163715
 of a GPIO.
8163715
8163715
On Pi0/1/2, we use an external GPIO line for hotplug detection, since
8163715
the HDMI_HOTPLUG register isn't connected to anything.  However, with
8163715
the Pi3 the HPD GPIO line has moved off to a GPIO expander that will
8163715
be tricky to get to (the firmware is constantly polling the expander
8163715
using i2c0, so we'll need to coordinate with it).
8163715
8163715
As a stop-gap, if we don't have a GPIO line, use an EDID probe to
8163715
detect connection.  Fixes HDMI display on the pi3.
8163715
8163715
Signed-off-by: Eric Anholt <eric@anholt.net>
8163715
---
8163715
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +++
8163715
 1 file changed, 3 insertions(+)
8163715
8163715
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
index 4452f36..5adc0c7 100644
8163715
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
@@ -174,6 +174,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
8163715
 			return connector_status_disconnected;
8163715
 	}
8163715
 
8163715
+	if (drm_probe_ddc(vc4->hdmi->ddc))
8163715
+		return connector_status_connected;
8163715
+
8163715
 	if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
8163715
 		return connector_status_connected;
8163715
 	else
8163715
-- 
8163715
2.9.3
8163715
8163715
From 7b4c39f34fbbdfe0cd0e626686ee01ab96601598 Mon Sep 17 00:00:00 2001
8163715
From: Eric Anholt <eric@anholt.net>
8163715
Date: Fri, 16 Sep 2016 10:59:45 +0100
8163715
Subject: [PATCH 2/4] drm/vc4: Enable limited range RGB output on HDMI with CEA
8163715
 modes.
8163715
8163715
Fixes broken grayscale ramps on many HDMI monitors, where large areas
8163715
at the ends of the ramp would all appear as black or white.
8163715
8163715
Signed-off-by: Eric Anholt <eric@anholt.net>
8163715
---
8163715
 drivers/gpu/drm/vc4/vc4_hdmi.c | 31 +++++++++++++++++++++++++++++--
8163715
 drivers/gpu/drm/vc4/vc4_regs.h |  9 ++++++++-
8163715
 2 files changed, 37 insertions(+), 3 deletions(-)
8163715
8163715
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
index 5adc0c7..5df4e74 100644
8163715
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
@@ -276,6 +276,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
8163715
 				      struct drm_display_mode *unadjusted_mode,
8163715
 				      struct drm_display_mode *mode)
8163715
 {
8163715
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
8163715
 	struct drm_device *dev = encoder->dev;
8163715
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
8163715
 	bool debug_dump_regs = false;
8163715
@@ -291,6 +292,7 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
8163715
 	u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
8163715
 		     VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
8163715
 				   VC4_HDMI_VERTB_VBP));
8163715
+	u32 csc_ctl;
8163715
 
8163715
 	if (debug_dump_regs) {
8163715
 		DRM_INFO("HDMI regs before:\n");
8163715
@@ -329,9 +331,34 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
8163715
 		 (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
8163715
 		 (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
8163715
 
8163715
+	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
8163715
+				VC4_HD_CSC_CTL_ORDER);
8163715
+
8163715
+	if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) {
8163715
+		/* CEA VICs other than #1 requre limited range RGB
8163715
+		 * output.  Apply a colorspace conversion to squash
8163715
+		 * 0-255 down to 16-235.  The matrix here is:
8163715
+		 *
8163715
+		 * [ 0      0      0.8594 16]
8163715
+		 * [ 0      0.8594 0      16]
8163715
+		 * [ 0.8594 0      0      16]
8163715
+		 * [ 0      0      0       1]
8163715
+		 */
8163715
+		csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
8163715
+		csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
8163715
+		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
8163715
+					 VC4_HD_CSC_CTL_MODE);
8163715
+
8163715
+		HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
8163715
+		HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
8163715
+		HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
8163715
+		HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
8163715
+		HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
8163715
+		HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
8163715
+	}
8163715
+
8163715
 	/* The RGB order applies even when CSC is disabled. */
8163715
-	HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
8163715
-					       VC4_HD_CSC_CTL_ORDER));
8163715
+	HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
8163715
 
8163715
 	HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
8163715
 
8163715
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
8163715
index 160942a..9ecd6ff 100644
8163715
--- a/drivers/gpu/drm/vc4/vc4_regs.h
8163715
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
8163715
@@ -528,10 +528,17 @@
8163715
 # define VC4_HD_CSC_CTL_MODE_SHIFT		2
8163715
 # define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB	0
8163715
 # define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB	1
8163715
-# define VC4_HD_CSC_CTL_MODE_CUSTOM		2
8163715
+# define VC4_HD_CSC_CTL_MODE_CUSTOM		3
8163715
 # define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)
8163715
 # define VC4_HD_CSC_CTL_ENABLE			BIT(0)
8163715
 
8163715
+#define VC4_HD_CSC_12_11			0x044
8163715
+#define VC4_HD_CSC_14_13			0x048
8163715
+#define VC4_HD_CSC_22_21			0x04c
8163715
+#define VC4_HD_CSC_24_23			0x050
8163715
+#define VC4_HD_CSC_32_31			0x054
8163715
+#define VC4_HD_CSC_34_33			0x058
8163715
+
8163715
 #define VC4_HD_FRAME_COUNT			0x068
8163715
 
8163715
 /* HVS display list information. */
8163715
-- 
8163715
2.9.3
8163715
8163715
From f379f5432e4b74e3d1d894ce2fefbe1b8a3c24fd Mon Sep 17 00:00:00 2001
8163715
From: Eric Anholt <eric@anholt.net>
8163715
Date: Wed, 28 Sep 2016 19:20:44 -0700
8163715
Subject: [PATCH 4/4] drm/vc4: Increase timeout for HDMI_SCHEDULER_CONTROL
8163715
 changes.
8163715
8163715
Fixes occasional debug spew at boot when connected directly through
8163715
HDMI, and probably confusing the HDMI state machine when we go trying
8163715
to poke registers for the enable sequence too soon.
8163715
8163715
Signed-off-by: Eric Anholt <eric@anholt.net>
8163715
---
8163715
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++--
8163715
 1 file changed, 2 insertions(+), 2 deletions(-)
8163715
8163715
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
index 5df4e74..9a6883d 100644
8163715
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
@@ -399,7 +399,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
8163715
 			   VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
8163715
 
8163715
 		ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
8163715
-			       VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1);
8163715
+			       VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
8163715
 		WARN_ONCE(ret, "Timeout waiting for "
8163715
 			  "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
8163715
 	} else {
8163715
@@ -411,7 +411,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
8163715
 			   ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
8163715
 
8163715
 		ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
8163715
-				 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1);
8163715
+				 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
8163715
 		WARN_ONCE(ret, "Timeout waiting for "
8163715
 			  "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
8163715
 	}
8163715
-- 
8163715
2.9.3
8163715
8163715
From bd712d14886c37eb804036b2ac3036df79d33476 Mon Sep 17 00:00:00 2001
8163715
From: Eric Anholt <eric@anholt.net>
8163715
Date: Thu, 29 Sep 2016 15:34:43 -0700
8163715
Subject: [PATCH] drm/vc4: Set up the AVI and SPD infoframes.
8163715
8163715
Fixes a purple bar on the left side of the screen with my Dell
8163715
2408WFP.  It will also be required for supporting the double-clocked
8163715
video modes.
8163715
8163715
Signed-off-by: Eric Anholt <eric@anholt.net>
8163715
---
8163715
 drivers/gpu/drm/vc4/vc4_hdmi.c | 136 +++++++++++++++++++++++++++++++++++++++--
8163715
 drivers/gpu/drm/vc4/vc4_regs.h |   5 ++
8163715
 2 files changed, 136 insertions(+), 5 deletions(-)
8163715
8163715
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
index 9a6883d..f722334 100644
8163715
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
8163715
@@ -62,6 +62,8 @@ struct vc4_hdmi {
8163715
 struct vc4_hdmi_encoder {
8163715
 	struct vc4_encoder base;
8163715
 	bool hdmi_monitor;
8163715
+	bool limited_rgb_range;
8163715
+	bool rgb_range_selectable;
8163715
 };
8163715
 
8163715
 static inline struct vc4_hdmi_encoder *
8163715
@@ -205,6 +207,12 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
8163715
 		return -ENODEV;
8163715
 
8163715
 	vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
8163715
+
8163715
+	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
8163715
+		vc4_encoder->rgb_range_selectable =
8163715
+			drm_rgb_quant_range_selectable(edid);
8163715
+	}
8163715
+
8163715
 	drm_mode_connector_update_edid_property(connector, edid);
8163715
 	ret = drm_add_edid_modes(connector, edid);
8163715
 
8163715
@@ -272,6 +280,117 @@ static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = {
8163715
 	.destroy = vc4_hdmi_encoder_destroy,
8163715
 };
8163715
 
8163715
+static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
8163715
+				enum hdmi_infoframe_type type)
8163715
+{
8163715
+	struct drm_device *dev = encoder->dev;
8163715
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
8163715
+	u32 packet_id = type - 0x80;
8163715
+
8163715
+	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
8163715
+		   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
8163715
+
8163715
+	return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
8163715
+			  BIT(packet_id)), 100);
8163715
+}
8163715
+
8163715
+static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
8163715
+				     union hdmi_infoframe *frame)
8163715
+{
8163715
+	struct drm_device *dev = encoder->dev;
8163715
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
8163715
+	u32 packet_id = frame->any.type - 0x80;
8163715
+	u32 packet_reg = VC4_HDMI_GCP_0 + VC4_HDMI_PACKET_STRIDE * packet_id;
8163715
+	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
8163715
+	ssize_t len, i;
8163715
+	int ret;
8163715
+
8163715
+	WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
8163715
+		    VC4_HDMI_RAM_PACKET_ENABLE),
8163715
+		  "Packet RAM has to be on to store the packet.");
8163715
+
8163715
+	len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
8163715
+	if (len < 0)
8163715
+		return;
8163715
+
8163715
+	ret = vc4_hdmi_stop_packet(encoder, frame->any.type);
8163715
+	if (ret) {
8163715
+		DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret);
8163715
+		return;
8163715
+	}
8163715
+
8163715
+	for (i = 0; i < len; i += 7) {
8163715
+		HDMI_WRITE(packet_reg,
8163715
+			   buffer[i + 0] << 0 |
8163715
+			   buffer[i + 1] << 8 |
8163715
+			   buffer[i + 2] << 16);
8163715
+		packet_reg += 4;
8163715
+
8163715
+		HDMI_WRITE(packet_reg,
8163715
+			   buffer[i + 3] << 0 |
8163715
+			   buffer[i + 4] << 8 |
8163715
+			   buffer[i + 5] << 16 |
8163715
+			   buffer[i + 6] << 24);
8163715
+		packet_reg += 4;
8163715
+	}
8163715
+
8163715
+	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
8163715
+		   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
8163715
+	ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
8163715
+			BIT(packet_id)), 100);
8163715
+	if (ret)
8163715
+		DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
8163715
+}
8163715
+
8163715
+static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
8163715
+{
8163715
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
8163715
+	struct drm_crtc *crtc = encoder->crtc;
8163715
+	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
8163715
+	union hdmi_infoframe frame;
8163715
+	int ret;
8163715
+
8163715
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
8163715
+	if (ret < 0) {
8163715
+		DRM_ERROR("couldn't fill AVI infoframe\n");
8163715
+		return;
8163715
+	}
8163715
+
8163715
+	if (vc4_encoder->rgb_range_selectable) {
8163715
+		if (vc4_encoder->limited_rgb_range) {
8163715
+			frame.avi.quantization_range =
8163715
+				HDMI_QUANTIZATION_RANGE_LIMITED;
8163715
+		} else {
8163715
+			frame.avi.quantization_range =
8163715
+				HDMI_QUANTIZATION_RANGE_FULL;
8163715
+		}
8163715
+	}
8163715
+
8163715
+	vc4_hdmi_write_infoframe(encoder, &frame);
8163715
+}
8163715
+
8163715
+static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
8163715
+{
8163715
+	union hdmi_infoframe frame;
8163715
+	int ret;
8163715
+
8163715
+	ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore");
8163715
+	if (ret < 0) {
8163715
+		DRM_ERROR("couldn't fill SPD infoframe\n");
8163715
+		return;
8163715
+	}
8163715
+
8163715
+	frame.spd.sdi = HDMI_SPD_SDI_PC;
8163715
+
8163715
+	vc4_hdmi_write_infoframe(encoder, &frame);
8163715
+}
8163715
+
8163715
+static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
8163715
+{
8163715
+	vc4_hdmi_set_avi_infoframe(encoder);
8163715
+	vc4_hdmi_set_spd_infoframe(encoder);
8163715
+}
8163715
+
8163715
 static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
8163715
 				      struct drm_display_mode *unadjusted_mode,
8163715
 				      struct drm_display_mode *mode)
8163715
@@ -336,8 +455,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
8163715
 
8163715
 	if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) {
8163715
 		/* CEA VICs other than #1 requre limited range RGB
8163715
-		 * output.  Apply a colorspace conversion to squash
8163715
-		 * 0-255 down to 16-235.  The matrix here is:
8163715
+		 * output unless overridden by an AVI infoframe.
8163715
+		 * Apply a colorspace conversion to squash 0-255 down
8163715
+		 * to 16-235.  The matrix here is:
8163715
 		 *
8163715
 		 * [ 0      0      0.8594 16]
8163715
 		 * [ 0      0.8594 0      16]
8163715
@@ -355,6 +475,9 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder,
8163715
 		HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
8163715
 		HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
8163715
 		HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
8163715
+		vc4_encoder->limited_rgb_range = true;
8163715
+	} else {
8163715
+		vc4_encoder->limited_rgb_range = false;
8163715
 	}
8163715
 
8163715
 	/* The RGB order applies even when CSC is disabled. */
8163715
@@ -373,6 +496,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
8163715
 	struct drm_device *dev = encoder->dev;
8163715
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
8163715
 
8163715
+	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
8163715
+
8163715
 	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
8163715
 	HD_WRITE(VC4_HD_VID_CTL,
8163715
 		 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
8163715
@@ -425,9 +550,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
8163715
 			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
8163715
 			   VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
8163715
 
8163715
-		/* XXX: Set HDMI_RAM_PACKET_CONFIG (1 << 16) and set
8163715
-		 * up the infoframe.
8163715
-		 */
8163715
+		HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
8163715
+			   VC4_HDMI_RAM_PACKET_ENABLE);
8163715
+
8163715
+		vc4_hdmi_set_infoframes(encoder);
8163715
 
8163715
 		drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
8163715
 		drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
8163715
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
8163715
index 9ecd6ff..a4b5370 100644
8163715
--- a/drivers/gpu/drm/vc4/vc4_regs.h
8163715
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
8163715
@@ -438,6 +438,8 @@
8163715
 #define VC4_HDMI_RAM_PACKET_CONFIG		0x0a0
8163715
 # define VC4_HDMI_RAM_PACKET_ENABLE		BIT(16)
8163715
 
8163715
+#define VC4_HDMI_RAM_PACKET_STATUS		0x0a4
8163715
+
8163715
 #define VC4_HDMI_HORZA				0x0c4
8163715
 # define VC4_HDMI_HORZA_VPOS			BIT(14)
8163715
 # define VC4_HDMI_HORZA_HPOS			BIT(13)
8163715
@@ -499,6 +501,9 @@
8163715
 
8163715
 #define VC4_HDMI_TX_PHY_RESET_CTL		0x2c0
8163715
 
8163715
+#define VC4_HDMI_GCP_0				0x400
8163715
+#define VC4_HDMI_PACKET_STRIDE			0x24
8163715
+
8163715
 #define VC4_HD_M_CTL				0x00c
8163715
 # define VC4_HD_M_REGISTER_FILE_STANDBY		(3 << 6)
8163715
 # define VC4_HD_M_RAM_STANDBY			(3 << 4)
8163715
-- 
8163715
2.9.3
8163715
8163715
From c4e634ce412d97f0e61223b2a5b3f8f9600cd4dc Mon Sep 17 00:00:00 2001
8163715
From: Eric Anholt <eric@anholt.net>
8163715
Date: Fri, 30 Sep 2016 10:07:27 -0700
8163715
Subject: clk: bcm2835: Clamp the PLL's requested rate to the hardware limits.
8163715
8163715
Fixes setting low-resolution video modes on HDMI.  Now the PLLH_PIX
8163715
divider adjusts itself until the PLLH is within bounds.
8163715
8163715
Signed-off-by: Eric Anholt <eric@anholt.net>
8163715
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
8163715
---
8163715
 drivers/clk/bcm/clk-bcm2835.c | 11 ++++-------
8163715
 1 file changed, 4 insertions(+), 7 deletions(-)
8163715
8163715
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
8163715
index b68bf57..8c7763f 100644
8163715
--- a/drivers/clk/bcm/clk-bcm2835.c
8163715
+++ b/drivers/clk/bcm/clk-bcm2835.c
8163715
@@ -502,8 +502,12 @@ static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate,
8163715
 static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate,
8163715
 				   unsigned long *parent_rate)
8163715
 {
8163715
+	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
8163715
+	const struct bcm2835_pll_data *data = pll->data;
8163715
 	u32 ndiv, fdiv;
8163715
 
8163715
+	rate = clamp(rate, data->min_rate, data->max_rate);
8163715
+
8163715
 	bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv);
8163715
 
8163715
 	return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1);
8163715
@@ -608,13 +612,6 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
8163715
 	u32 ana[4];
8163715
 	int i;
8163715
 
8163715
-	if (rate < data->min_rate || rate > data->max_rate) {
8163715
-		dev_err(cprman->dev, "%s: rate out of spec: %lu vs (%lu, %lu)\n",
8163715
-			clk_hw_get_name(hw), rate,
8163715
-			data->min_rate, data->max_rate);
8163715
-		return -EINVAL;
8163715
-	}
8163715
-
8163715
 	if (rate > data->max_fb_rate) {
8163715
 		use_fb_prediv = true;
8163715
 		rate /= 2;
8163715
-- 
8163715
cgit v0.12
8163715
8163715
From e69fdcca836f0b81a2260b69429c8622a80ea891 Mon Sep 17 00:00:00 2001
8163715
From: Eric Anholt <eric@anholt.net>
8163715
Date: Wed, 1 Jun 2016 12:05:33 -0700
8163715
Subject: clk: bcm2835: Mark the VPU clock as critical
8163715
8163715
The VPU clock is also the clock for our AXI bus, so we really can't
8163715
disable it.  This might have happened during boot if, for example,
8163715
uart1 (aux_uart clock) probed and was then disabled before the other
8163715
consumers of the VPU clock had probed.
8163715
8163715
Signed-off-by: Eric Anholt <eric@anholt.net>
8163715
Acked-by: Martin Sperl <kernel@martin.sperl.org>
8163715
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
8163715
---
8163715
 drivers/clk/bcm/clk-bcm2835.c | 5 ++++-
8163715
 1 file changed, 4 insertions(+), 1 deletion(-)
8163715
8163715
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
8163715
index 7a79708..d9db03c 100644
8163715
--- a/drivers/clk/bcm/clk-bcm2835.c
8163715
+++ b/drivers/clk/bcm/clk-bcm2835.c
8163715
@@ -443,6 +443,8 @@ struct bcm2835_clock_data {
8163715
 	/* Number of fractional bits in the divider */
8163715
 	u32 frac_bits;
8163715
 
8163715
+	u32 flags;
8163715
+
8163715
 	bool is_vpu_clock;
8163715
 	bool is_mash_clock;
8163715
 };
8163715
@@ -1230,7 +1232,7 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
8163715
 	init.parent_names = parents;
8163715
 	init.num_parents = data->num_mux_parents;
8163715
 	init.name = data->name;
8163715
-	init.flags = CLK_IGNORE_UNUSED;
8163715
+	init.flags = data->flags | CLK_IGNORE_UNUSED;
8163715
 
8163715
 	if (data->is_vpu_clock) {
8163715
 		init.ops = &bcm2835_vpu_clock_clk_ops;
8163715
@@ -1649,6 +1651,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
8163715
 		.div_reg = CM_VPUDIV,
8163715
 		.int_bits = 12,
8163715
 		.frac_bits = 8,
8163715
+		.flags = CLK_IS_CRITICAL,
8163715
 		.is_vpu_clock = true),
8163715
 
8163715
 	/* clocks with per parent mux */
8163715
-- 
8163715
cgit v0.12
8163715
8163715
From eddcbe8398fc7103fccd22aa6df6917caf0123bf Mon Sep 17 00:00:00 2001
8163715
From: Eric Anholt <eric@anholt.net>
8163715
Date: Wed, 1 Jun 2016 12:05:34 -0700
8163715
Subject: clk: bcm2835: Mark GPIO clocks enabled at boot as critical
8163715
8163715
These divide off of PLLD_PER and are used for the ethernet and wifi
8163715
PHYs source PLLs.  Neither of them is currently represented by a phy
8163715
device that would grab the clock for us.
8163715
8163715
This keeps other drivers from killing the networking PHYs when they
8163715
disable their own clocks and trigger PLLD_PER's refcount going to 0.
8163715
8163715
Signed-off-by: Eric Anholt <eric@anholt.net>
8163715
Acked-by: Martin Sperl <kernel@martin.sperl.org>
8163715
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
8163715
---
8163715
 drivers/clk/bcm/clk-bcm2835.c | 10 +++++++++-
8163715
 1 file changed, 9 insertions(+), 1 deletion(-)
8163715
8163715
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
8163715
index d9db03c..400615b 100644
8163715
--- a/drivers/clk/bcm/clk-bcm2835.c
8163715
+++ b/drivers/clk/bcm/clk-bcm2835.c
8163715
@@ -1239,6 +1239,12 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
8163715
 	} else {
8163715
 		init.ops = &bcm2835_clock_clk_ops;
8163715
 		init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
8163715
+
8163715
+		/* If the clock wasn't actually enabled at boot, it's not
8163715
+		 * critical.
8163715
+		 */
8163715
+		if (!(cprman_read(cprman, data->ctl_reg) & CM_ENABLE))
8163715
+			init.flags &= ~CLK_IS_CRITICAL;
8163715
 	}
8163715
 
8163715
 	clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL);
8163715
@@ -1708,13 +1714,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
8163715
 		.div_reg = CM_GP1DIV,
8163715
 		.int_bits = 12,
8163715
 		.frac_bits = 12,
8163715
+		.flags = CLK_IS_CRITICAL,
8163715
 		.is_mash_clock = true),
8163715
 	[BCM2835_CLOCK_GP2]	= REGISTER_PER_CLK(
8163715
 		.name = "gp2",
8163715
 		.ctl_reg = CM_GP2CTL,
8163715
 		.div_reg = CM_GP2DIV,
8163715
 		.int_bits = 12,
8163715
-		.frac_bits = 12),
8163715
+		.frac_bits = 12,
8163715
+		.flags = CLK_IS_CRITICAL),
8163715
 
8163715
 	/* HDMI state machine */
8163715
 	[BCM2835_CLOCK_HSM]	= REGISTER_PER_CLK(
8163715
-- 
8163715
cgit v0.12
8163715
8163715
From 9e400c5cc5c105e35216ac59a346f20cdd7613be Mon Sep 17 00:00:00 2001
8163715
From: Eric Anholt <eric@anholt.net>
8163715
Date: Wed, 1 Jun 2016 12:05:35 -0700
8163715
Subject: clk: bcm2835: Mark the CM SDRAM clock's parent as critical
8163715
8163715
While the SDRAM is being driven by its dedicated PLL most of the time,
8163715
there is a little loop running in the firmware that periodically turns
8163715
on the CM SDRAM clock (using its pre-initialized parent) and switches
8163715
SDRAM to using the CM clock to do PVT recalibration.
8163715
8163715
This avoids system hangs if we choose SDRAM's parent for some other
8163715
clock, then disable that clock.
8163715
8163715
Signed-off-by: Eric Anholt <eric@anholt.net>
8163715
Acked-by: Martin Sperl <kernel@martin.sperl.org>
8163715
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
8163715
---
8163715
 drivers/clk/bcm/clk-bcm2835.c | 25 +++++++++++++++++++++++++
8163715
 1 file changed, 25 insertions(+)
8163715
8163715
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
8163715
index 400615b..c6420b3 100644
8163715
--- a/drivers/clk/bcm/clk-bcm2835.c
8163715
+++ b/drivers/clk/bcm/clk-bcm2835.c
8163715
@@ -36,6 +36,7 @@
8163715
 
8163715
 #include <linux/clk-provider.h>
8163715
 #include <linux/clkdev.h>
8163715
+#include <linux/clk.h>
8163715
 #include <linux/clk/bcm2835.h>
8163715
 #include <linux/debugfs.h>
8163715
 #include <linux/module.h>
8163715
@@ -1801,6 +1802,25 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
8163715
 		.ctl_reg = CM_PERIICTL),
8163715
 };
8163715
 
8163715
+/*
8163715
+ * Permanently take a reference on the parent of the SDRAM clock.
8163715
+ *
8163715
+ * While the SDRAM is being driven by its dedicated PLL most of the
8163715
+ * time, there is a little loop running in the firmware that
8163715
+ * periodically switches the SDRAM to using our CM clock to do PVT
8163715
+ * recalibration, with the assumption that the previously configured
8163715
+ * SDRAM parent is still enabled and running.
8163715
+ */
8163715
+static int bcm2835_mark_sdc_parent_critical(struct clk *sdc)
8163715
+{
8163715
+	struct clk *parent = clk_get_parent(sdc);
8163715
+
8163715
+	if (IS_ERR(parent))
8163715
+		return PTR_ERR(parent);
8163715
+
8163715
+	return clk_prepare_enable(parent);
8163715
+}
8163715
+
8163715
 static int bcm2835_clk_probe(struct platform_device *pdev)
8163715
 {
8163715
 	struct device *dev = &pdev->dev;
8163715
@@ -1810,6 +1830,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
8163715
 	const struct bcm2835_clk_desc *desc;
8163715
 	const size_t asize = ARRAY_SIZE(clk_desc_array);
8163715
 	size_t i;
8163715
+	int ret;
8163715
 
8163715
 	cprman = devm_kzalloc(dev,
8163715
 			      sizeof(*cprman) + asize * sizeof(*clks),
8163715
@@ -1840,6 +1861,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
8163715
 			clks[i] = desc->clk_register(cprman, desc->data);
8163715
 	}
8163715
 
8163715
+	ret = bcm2835_mark_sdc_parent_critical(clks[BCM2835_CLOCK_SDRAM]);
8163715
+	if (ret)
8163715
+		return ret;
8163715
+
8163715
 	return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
8163715
 				   &cprman->onecell);
8163715
 }
8163715
-- 
8163715
cgit v0.12
8163715
8163715
From 30772942cc1095c3129eecfa182e2c568e566b9d Mon Sep 17 00:00:00 2001
8163715
From: Dan Carpenter <dan.carpenter@oracle.com>
8163715
Date: Thu, 13 Oct 2016 11:54:31 +0300
8163715
Subject: [PATCH] drm/vc4: Fix a couple error codes in vc4_cl_lookup_bos()
8163715
8163715
If the allocation fails the current code returns success.  If
8163715
copy_from_user() fails it returns the number of bytes remaining instead
8163715
of -EFAULT.
8163715
8163715
Fixes: d5b1a78a772f ("drm/vc4: Add support for drawing 3D frames.")
8163715
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
8163715
Reviewed-by: Eric Anholt <eric@anholt.net>
8163715
---
8163715
 drivers/gpu/drm/vc4/vc4_gem.c | 9 +++++----
8163715
 1 file changed, 5 insertions(+), 4 deletions(-)
8163715
8163715
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
8163715
index ae1609e..4050540 100644
8163715
--- a/drivers/gpu/drm/vc4/vc4_gem.c
8163715
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
8163715
@@ -548,14 +548,15 @@ vc4_cl_lookup_bos(struct drm_device *dev,
8163715
 
8163715
 	handles = drm_malloc_ab(exec->bo_count, sizeof(uint32_t));
8163715
 	if (!handles) {
8163715
+		ret = -ENOMEM;
8163715
 		DRM_ERROR("Failed to allocate incoming GEM handles\n");
8163715
 		goto fail;
8163715
 	}
8163715
 
8163715
-	ret = copy_from_user(handles,
8163715
-			     (void __user *)(uintptr_t)args->bo_handles,
8163715
-			     exec->bo_count * sizeof(uint32_t));
8163715
-	if (ret) {
8163715
+	if (copy_from_user(handles,
8163715
+			   (void __user *)(uintptr_t)args->bo_handles,
8163715
+			   exec->bo_count * sizeof(uint32_t))) {
8163715
+		ret = -EFAULT;
8163715
 		DRM_ERROR("Failed to copy in GEM handles\n");
8163715
 		goto fail;
8163715
 	}
8163715
-- 
8163715
2.9.3
8163715