Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec9ed197 authored by Vandana Kannan's avatar Vandana Kannan Committed by Daniel Vetter
Browse files

drm/i915: Make downclock deduction common for all panels



If one mode of a internal panel has more than one refresh rate, then a reduced
clock is found for the LFP (LVDS/eDP). This enables switching between low
and high frequency dynamically. Moving downclock calculation to intel_panel
so that it is common for LVDS and eDP.

Signed-off-by: default avatarVandana Kannan <vandana.kannan@intel.com>
Signed-off-by: default avatarPradeep Bhat <pradeep.bhat@intel.com>
Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent c461562e
Loading
Loading
Loading
Loading
+5 −1
Original line number Original line Diff line number Diff line
@@ -155,6 +155,7 @@ struct intel_encoder {


struct intel_panel {
struct intel_panel {
	struct drm_display_mode *fixed_mode;
	struct drm_display_mode *fixed_mode;
	struct drm_display_mode *downclock_mode;
	int fitting_mode;
	int fitting_mode;


	/* backlight */
	/* backlight */
@@ -823,7 +824,10 @@ void intel_panel_disable_backlight(struct intel_connector *connector);
void intel_panel_destroy_backlight(struct drm_connector *connector);
void intel_panel_destroy_backlight(struct drm_connector *connector);
void intel_panel_init_backlight_funcs(struct drm_device *dev);
void intel_panel_init_backlight_funcs(struct drm_device *dev);
enum drm_connector_status intel_panel_detect(struct drm_device *dev);
enum drm_connector_status intel_panel_detect(struct drm_device *dev);

extern struct drm_display_mode *intel_find_panel_downclock(
				struct drm_device *dev,
				struct drm_display_mode *fixed_mode,
				struct drm_connector *connector);


/* intel_pm.c */
/* intel_pm.c */
void intel_init_clock_gating(struct drm_device *dev);
void intel_init_clock_gating(struct drm_device *dev);
+16 −53
Original line number Original line Diff line number Diff line
@@ -755,57 +755,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
	{ }	/* terminating entry */
	{ }	/* terminating entry */
};
};


/**
 * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
 * @dev: drm device
 * @connector: LVDS connector
 *
 * Find the reduced downclock for LVDS in EDID.
 */
static void intel_find_lvds_downclock(struct drm_device *dev,
				      struct drm_display_mode *fixed_mode,
				      struct drm_connector *connector)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_display_mode *scan;
	int temp_downclock;

	temp_downclock = fixed_mode->clock;
	list_for_each_entry(scan, &connector->probed_modes, head) {
		/*
		 * If one mode has the same resolution with the fixed_panel
		 * mode while they have the different refresh rate, it means
		 * that the reduced downclock is found for the LVDS. In such
		 * case we can set the different FPx0/1 to dynamically select
		 * between low and high frequency.
		 */
		if (scan->hdisplay == fixed_mode->hdisplay &&
		    scan->hsync_start == fixed_mode->hsync_start &&
		    scan->hsync_end == fixed_mode->hsync_end &&
		    scan->htotal == fixed_mode->htotal &&
		    scan->vdisplay == fixed_mode->vdisplay &&
		    scan->vsync_start == fixed_mode->vsync_start &&
		    scan->vsync_end == fixed_mode->vsync_end &&
		    scan->vtotal == fixed_mode->vtotal) {
			if (scan->clock < temp_downclock) {
				/*
				 * The downclock is already found. But we
				 * expect to find the lower downclock.
				 */
				temp_downclock = scan->clock;
			}
		}
	}
	if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) {
		/* We found the downclock for LVDS. */
		dev_priv->lvds_downclock_avail = 1;
		dev_priv->lvds_downclock = temp_downclock;
		DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
			      "Normal clock %dKhz, downclock %dKhz\n",
			      fixed_mode->clock, temp_downclock);
	}
}

/*
/*
 * Enumerate the child dev array parsed from VBT to check whether
 * Enumerate the child dev array parsed from VBT to check whether
 * the LVDS is present.
 * the LVDS is present.
@@ -1083,8 +1032,22 @@ void intel_lvds_init(struct drm_device *dev)


			fixed_mode = drm_mode_duplicate(dev, scan);
			fixed_mode = drm_mode_duplicate(dev, scan);
			if (fixed_mode) {
			if (fixed_mode) {
				intel_find_lvds_downclock(dev, fixed_mode,
				intel_connector->panel.downclock_mode =
							  connector);
					intel_find_panel_downclock(dev,
					fixed_mode, connector);
				if (intel_connector->panel.downclock_mode !=
					NULL &&	i915_lvds_downclock) {
					/* We found the downclock for LVDS. */
					dev_priv->lvds_downclock_avail = true;
					dev_priv->lvds_downclock =
						intel_connector->panel.
						downclock_mode->clock;
					DRM_DEBUG_KMS("LVDS downclock is found"
					" in EDID. Normal clock %dKhz, "
					"downclock %dKhz\n",
					fixed_mode->clock,
					dev_priv->lvds_downclock);
				}
				goto out;
				goto out;
			}
			}
		}
		}
+57 −0
Original line number Original line Diff line number Diff line
@@ -1104,6 +1104,59 @@ void intel_panel_destroy_backlight(struct drm_connector *connector)
	intel_backlight_device_unregister(intel_connector);
	intel_backlight_device_unregister(intel_connector);
}
}


/**
 * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
 * @dev: drm device
 * @fixed_mode : panel native mode
 * @connector: LVDS/eDP connector
 *
 * Return downclock_avail
 * Find the reduced downclock for LVDS/eDP in EDID.
 */
struct drm_display_mode *
intel_find_panel_downclock(struct drm_device *dev,
			struct drm_display_mode *fixed_mode,
			struct drm_connector *connector)
{
	struct drm_display_mode *scan, *tmp_mode;
	int temp_downclock;

	temp_downclock = fixed_mode->clock;
	tmp_mode = NULL;

	list_for_each_entry(scan, &connector->probed_modes, head) {
		/*
		 * If one mode has the same resolution with the fixed_panel
		 * mode while they have the different refresh rate, it means
		 * that the reduced downclock is found. In such
		 * case we can set the different FPx0/1 to dynamically select
		 * between low and high frequency.
		 */
		if (scan->hdisplay == fixed_mode->hdisplay &&
		    scan->hsync_start == fixed_mode->hsync_start &&
		    scan->hsync_end == fixed_mode->hsync_end &&
		    scan->htotal == fixed_mode->htotal &&
		    scan->vdisplay == fixed_mode->vdisplay &&
		    scan->vsync_start == fixed_mode->vsync_start &&
		    scan->vsync_end == fixed_mode->vsync_end &&
		    scan->vtotal == fixed_mode->vtotal) {
			if (scan->clock < temp_downclock) {
				/*
				 * The downclock is already found. But we
				 * expect to find the lower downclock.
				 */
				temp_downclock = scan->clock;
				tmp_mode = scan;
			}
		}
	}

	if (temp_downclock < fixed_mode->clock)
		return drm_mode_duplicate(dev, tmp_mode);
	else
		return NULL;
}

/* Set up chip specific backlight functions */
/* Set up chip specific backlight functions */
void intel_panel_init_backlight_funcs(struct drm_device *dev)
void intel_panel_init_backlight_funcs(struct drm_device *dev)
{
{
@@ -1157,4 +1210,8 @@ void intel_panel_fini(struct intel_panel *panel)


	if (panel->fixed_mode)
	if (panel->fixed_mode)
		drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
		drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);

	if (panel->downclock_mode)
		drm_mode_destroy(intel_connector->base.dev,
				panel->downclock_mode);
}
}