Commit ea0fe672 authored by Hans de Goede's avatar Hans de Goede
Browse files

drm/i915/dsi: Move poking of panel-enable GPIO to intel_dsi_vbt.c



On some older devices (BYT, CHT) which may use v2 VBT MIPI-sequences,
we need to manually control the panel enable GPIO as v2 sequences do
not do this.

So far we have been carrying the code to do this on BYT/CHT devices
with a Crystal Cove PMIC in vlv_dsi.c, but as this really is a shortcoming
of the VBT MIPI-sequences, intel_dsi_vbt.c is a better place for this,
so move it there.

This is a preparation patch for adding panel-enable and backlight-enable
GPIO support for BYT devices where instead of the PMIC the SoC is used
for backlight control.

Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191216205122.1850923-3-hdegoede@redhat.com
parent cdd280b1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -203,6 +203,8 @@ void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port);

/* intel_dsi_vbt.c */
bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id);
void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi);
void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi);
void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
				 enum mipi_seq seq_id);
void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec);
+44 −2
Original line number Diff line number Diff line
@@ -453,7 +453,7 @@ static const char *sequence_name(enum mipi_seq seq_id)
		return "(unknown)";
}

void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi,
			       enum mipi_seq seq_id)
{
	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
@@ -519,6 +519,18 @@ void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
	}
}

void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
				 enum mipi_seq seq_id)
{
	if (seq_id == MIPI_SEQ_POWER_ON && intel_dsi->gpio_panel)
		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);

	intel_dsi_vbt_exec(intel_dsi, seq_id);

	if (seq_id == MIPI_SEQ_POWER_OFF && intel_dsi->gpio_panel)
		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);
}

void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec)
{
	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
@@ -671,3 +683,33 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)

	return true;
}

/*
 * On some BYT/CHT devs some sequences are incomplete and we need to manually
 * control some GPIOs.
 */
void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi)
{
	struct drm_device *dev = intel_dsi->base.base.dev;
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;

	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
	    mipi_config->pwm_blc == PPS_BLC_PMIC) {
		intel_dsi->gpio_panel =
			gpiod_get(dev->dev, "panel", GPIOD_OUT_HIGH);

		if (IS_ERR(intel_dsi->gpio_panel)) {
			DRM_ERROR("Failed to own gpio for panel control\n");
			intel_dsi->gpio_panel = NULL;
		}
	}
}

void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi)
{
	if (intel_dsi->gpio_panel) {
		gpiod_put(intel_dsi->gpio_panel);
		intel_dsi->gpio_panel = NULL;
	}
}
+2 −25
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@
 * Author: Jani Nikula <jani.nikula@intel.com>
 */

#include <linux/gpio/consumer.h>
#include <linux/slab.h>

#include <drm/drm_atomic_helper.h>
@@ -793,9 +792,6 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder,
	if (!IS_GEMINILAKE(dev_priv))
		intel_dsi_prepare(encoder, pipe_config);

	/* Power on, try both CRC pmic gpio and VBT */
	if (intel_dsi->gpio_panel)
		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_ON);
	intel_dsi_msleep(intel_dsi, intel_dsi->panel_on_delay);

@@ -945,11 +941,8 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder,
	/* Assert reset */
	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_ASSERT_RESET);

	/* Power off, try both CRC pmic gpio and VBT */
	intel_dsi_msleep(intel_dsi, intel_dsi->panel_off_delay);
	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_OFF);
	if (intel_dsi->gpio_panel)
		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);

	/*
	 * FIXME As we do with eDP, just make a note of the time here
@@ -1541,10 +1534,7 @@ static void intel_dsi_encoder_destroy(struct drm_encoder *encoder)
{
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);

	/* dispose of the gpios */
	if (intel_dsi->gpio_panel)
		gpiod_put(intel_dsi->gpio_panel);

	intel_dsi_vbt_gpio_cleanup(intel_dsi);
	intel_encoder_destroy(encoder);
}

@@ -1923,20 +1913,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)

	vlv_dphy_param_init(intel_dsi);

	/*
	 * In case of BYT with CRC PMIC, we need to use GPIO for
	 * Panel control.
	 */
	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
	    (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC)) {
		intel_dsi->gpio_panel =
			gpiod_get(dev->dev, "panel", GPIOD_OUT_HIGH);

		if (IS_ERR(intel_dsi->gpio_panel)) {
			DRM_ERROR("Failed to own gpio for panel control\n");
			intel_dsi->gpio_panel = NULL;
		}
	}
	intel_dsi_vbt_gpio_init(intel_dsi);

	drm_connector_init(dev, connector, &intel_dsi_connector_funcs,
			   DRM_MODE_CONNECTOR_DSI);