diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_connector.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_connector.c | 67 |
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"); |