Commit 1de425b0 authored by Inki Dae's avatar Inki Dae Committed by Dave Airlie
Browse files

drm/exynos: added mode_fixup feature and code clean.



this patch adds mode_fixup feature for hdmi module that
specific driver changes current mode to driver desired mode
properly.

Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 3ecd70b1
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -225,6 +225,29 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
	.best_encoder	= exynos_drm_best_encoder,
};

static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
				unsigned int max_width, unsigned int max_height)
{
	struct exynos_drm_connector *exynos_connector =
					to_exynos_connector(connector);
	struct exynos_drm_manager *manager = exynos_connector->manager;
	struct exynos_drm_manager_ops *ops = manager->ops;
	unsigned int width, height;

	width = max_width;
	height = max_height;

	/*
	 * if specific driver want to find desired_mode using maxmum
	 * resolution then get max width and height from that driver.
	 */
	if (ops && ops->get_max_resol)
		ops->get_max_resol(manager->dev, &width, &height);

	return drm_helper_probe_single_connector_modes(connector, width,
							height);
}

/* get detection status of display device. */
static enum drm_connector_status
exynos_drm_connector_detect(struct drm_connector *connector, bool force)
@@ -262,7 +285,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)

static struct drm_connector_funcs exynos_connector_funcs = {
	.dpms		= drm_helper_connector_dpms,
	.fill_modes	= drm_helper_probe_single_connector_modes,
	.fill_modes	= exynos_drm_connector_fill_modes,
	.detect		= exynos_drm_connector_detect,
	.destroy	= exynos_drm_connector_destroy,
};
+5 −1
Original line number Diff line number Diff line
@@ -249,7 +249,11 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
{
	DRM_DEBUG_KMS("%s\n", __FILE__);

	mode = adjusted_mode;
	/*
	 * copy the mode data adjusted by mode_fixup() into crtc->mode
	 * so that hardware can be seet to proper mode.
	 */
	memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));

	return exynos_drm_crtc_update(crtc);
}
+8 −0
Original line number Diff line number Diff line
@@ -155,8 +155,10 @@ struct exynos_drm_display_ops {
 *
 * @dpms: control device power.
 * @apply: set timing, vblank and overlay data to registers.
 * @mode_fixup: fix mode data comparing to hw specific display mode.
 * @mode_set: convert drm_display_mode to hw specific display mode and
 *	      would be called by encoder->mode_set().
 * @get_max_resol: get maximum resolution to specific hardware.
 * @commit: set current hw specific display mode to hw.
 * @enable_vblank: specific driver callback for enabling vblank interrupt.
 * @disable_vblank: specific driver callback for disabling vblank interrupt.
@@ -164,7 +166,13 @@ struct exynos_drm_display_ops {
struct exynos_drm_manager_ops {
	void (*dpms)(struct device *subdrv_dev, int mode);
	void (*apply)(struct device *subdrv_dev);
	void (*mode_fixup)(struct device *subdrv_dev,
				struct drm_connector *connector,
				struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_mode);
	void (*mode_set)(struct device *subdrv_dev, void *mode);
	void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width,
				unsigned int *height);
	void (*commit)(struct device *subdrv_dev);
	int (*enable_vblank)(struct device *subdrv_dev);
	void (*disable_vblank)(struct device *subdrv_dev);
+13 −4
Original line number Diff line number Diff line
@@ -111,9 +111,19 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
			       struct drm_display_mode *mode,
			       struct drm_display_mode *adjusted_mode)
{
	struct drm_device *dev = encoder->dev;
	struct drm_connector *connector;
	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
	struct exynos_drm_manager_ops *manager_ops = manager->ops;

	DRM_DEBUG_KMS("%s\n", __FILE__);

	/* drm framework doesn't check NULL. */
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
		if (connector->encoder == encoder)
			if (manager_ops && manager_ops->mode_fixup)
				manager_ops->mode_fixup(manager->dev, connector,
							mode, adjusted_mode);
	}

	return true;
}
@@ -132,12 +142,11 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,

	DRM_DEBUG_KMS("%s\n", __FILE__);

	mode = adjusted_mode;

	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
		if (connector->encoder == encoder) {
			if (manager_ops && manager_ops->mode_set)
				manager_ops->mode_set(manager->dev, mode);
				manager_ops->mode_set(manager->dev,
							adjusted_mode);

			if (overlay_ops && overlay_ops->mode_set)
				overlay_ops->mode_set(manager->dev, overlay);
+28 −0
Original line number Diff line number Diff line
@@ -155,6 +155,20 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
		return hdmi_overlay_ops->disable_vblank(ctx->mixer_ctx->ctx);
}

static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
				struct drm_connector *connector,
				struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_mode)
{
	struct drm_hdmi_context *ctx = to_context(subdrv_dev);

	DRM_DEBUG_KMS("%s\n", __FILE__);

	if (hdmi_manager_ops && hdmi_manager_ops->mode_fixup)
		hdmi_manager_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector,
						mode, adjusted_mode);
}

static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
{
	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
@@ -165,6 +179,18 @@ static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
		hdmi_manager_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
}

static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
				unsigned int *width, unsigned int *height)
{
	struct drm_hdmi_context *ctx = to_context(subdrv_dev);

	DRM_DEBUG_KMS("%s\n", __FILE__);

	if (hdmi_manager_ops && hdmi_manager_ops->get_max_resol)
		hdmi_manager_ops->get_max_resol(ctx->hdmi_ctx->ctx, width,
							height);
}

static void drm_hdmi_commit(struct device *subdrv_dev)
{
	struct drm_hdmi_context *ctx = to_context(subdrv_dev);
@@ -200,7 +226,9 @@ static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
	.dpms = drm_hdmi_dpms,
	.enable_vblank = drm_hdmi_enable_vblank,
	.disable_vblank = drm_hdmi_disable_vblank,
	.mode_fixup = drm_hdmi_mode_fixup,
	.mode_set = drm_hdmi_mode_set,
	.get_max_resol = drm_hdmi_get_max_resol,
	.commit = drm_hdmi_commit,
};

Loading