aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_connector.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_connector.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.c67
1 files changed, 47 insertions, 20 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index d620b0784257..bf791fa0e50d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -28,6 +28,7 @@
#include "drmP.h"
#include "drm_crtc_helper.h"
+#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_encoder.h"
@@ -44,22 +45,25 @@ struct exynos_drm_connector {
/* convert exynos_video_timings to drm_display_mode */
static inline void
convert_to_display_mode(struct drm_display_mode *mode,
- struct fb_videomode *timing)
+ struct exynos_drm_panel_info *panel)
{
+ struct fb_videomode *timing = &panel->timing;
DRM_DEBUG_KMS("%s\n", __FILE__);
mode->clock = timing->pixclock / 1000;
mode->vrefresh = timing->refresh;
mode->hdisplay = timing->xres;
- mode->hsync_start = mode->hdisplay + timing->left_margin;
+ mode->hsync_start = mode->hdisplay + timing->right_margin;
mode->hsync_end = mode->hsync_start + timing->hsync_len;
- mode->htotal = mode->hsync_end + timing->right_margin;
+ mode->htotal = mode->hsync_end + timing->left_margin;
mode->vdisplay = timing->yres;
- mode->vsync_start = mode->vdisplay + timing->upper_margin;
+ mode->vsync_start = mode->vdisplay + timing->lower_margin;
mode->vsync_end = mode->vsync_start + timing->vsync_len;
- mode->vtotal = mode->vsync_end + timing->lower_margin;
+ mode->vtotal = mode->vsync_end + timing->upper_margin;
+ mode->width_mm = panel->width_mm;
+ mode->height_mm = panel->height_mm;
if (timing->vmode & FB_VMODE_INTERLACED)
mode->flags |= DRM_MODE_FLAG_INTERLACE;
@@ -81,14 +85,14 @@ convert_to_video_timing(struct fb_videomode *timing,
timing->refresh = drm_mode_vrefresh(mode);
timing->xres = mode->hdisplay;
- timing->left_margin = mode->hsync_start - mode->hdisplay;
+ timing->right_margin = mode->hsync_start - mode->hdisplay;
timing->hsync_len = mode->hsync_end - mode->hsync_start;
- timing->right_margin = mode->htotal - mode->hsync_end;
+ timing->left_margin = mode->htotal - mode->hsync_end;
timing->yres = mode->vdisplay;
- timing->upper_margin = mode->vsync_start - mode->vdisplay;
+ timing->lower_margin = mode->vsync_start - mode->vdisplay;
timing->vsync_len = mode->vsync_end - mode->vsync_start;
- timing->lower_margin = mode->vtotal - mode->vsync_end;
+ timing->upper_margin = mode->vtotal - mode->vsync_end;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
timing->vmode = FB_VMODE_INTERLACED;
@@ -148,16 +152,18 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
connector->display_info.raw_edid = edid;
} else {
struct drm_display_mode *mode = drm_mode_create(connector->dev);
- struct fb_videomode *timing;
+ struct exynos_drm_panel_info *panel;
- if (display_ops->get_timing)
- timing = display_ops->get_timing(manager->dev);
+ if (display_ops->get_panel)
+ panel = display_ops->get_panel(manager->dev);
else {
drm_mode_destroy(connector->dev, mode);
return 0;
}
- convert_to_display_mode(mode, timing);
+ convert_to_display_mode(mode, panel);
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_set_name(mode);
@@ -219,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)
@@ -256,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,
};
@@ -286,6 +315,10 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
connector->interlace_allowed = true;
connector->polled = DRM_CONNECTOR_POLL_HPD;
break;
+ case EXYNOS_DISPLAY_TYPE_VIDI:
+ type = DRM_MODE_CONNECTOR_VIRTUAL;
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+ break;
default:
type = DRM_MODE_CONNECTOR_Unknown;
break;
@@ -319,9 +352,3 @@ err_connector:
kfree(exynos_connector);
return NULL;
}
-
-MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
-MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
-MODULE_AUTHOR("Seung-Woo Kim <sw0312.kim@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DRM Connector Driver");
-MODULE_LICENSE("GPL");