diff options
Diffstat (limited to 'drivers/gpu/drm/exynos')
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_connector.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_core.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 26 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_encoder.c | 34 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_encoder.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 70 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 34 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 19 | 
10 files changed, 108 insertions, 105 deletions
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index d620b0784257..618bd4d87d28 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "drmP.h" | 28 | #include "drmP.h" | 
| 29 | #include "drm_crtc_helper.h" | 29 | #include "drm_crtc_helper.h" | 
| 30 | 30 | ||
| 31 | #include <drm/exynos_drm.h> | ||
| 31 | #include "exynos_drm_drv.h" | 32 | #include "exynos_drm_drv.h" | 
| 32 | #include "exynos_drm_encoder.h" | 33 | #include "exynos_drm_encoder.h" | 
| 33 | 34 | ||
| @@ -44,8 +45,9 @@ struct exynos_drm_connector { | |||
| 44 | /* convert exynos_video_timings to drm_display_mode */ | 45 | /* convert exynos_video_timings to drm_display_mode */ | 
| 45 | static inline void | 46 | static inline void | 
| 46 | convert_to_display_mode(struct drm_display_mode *mode, | 47 | convert_to_display_mode(struct drm_display_mode *mode, | 
| 47 | struct fb_videomode *timing) | 48 | struct exynos_drm_panel_info *panel) | 
| 48 | { | 49 | { | 
| 50 | struct fb_videomode *timing = &panel->timing; | ||
| 49 | DRM_DEBUG_KMS("%s\n", __FILE__); | 51 | DRM_DEBUG_KMS("%s\n", __FILE__); | 
| 50 | 52 | ||
| 51 | mode->clock = timing->pixclock / 1000; | 53 | mode->clock = timing->pixclock / 1000; | 
| @@ -60,6 +62,8 @@ convert_to_display_mode(struct drm_display_mode *mode, | |||
| 60 | mode->vsync_start = mode->vdisplay + timing->upper_margin; | 62 | mode->vsync_start = mode->vdisplay + timing->upper_margin; | 
| 61 | mode->vsync_end = mode->vsync_start + timing->vsync_len; | 63 | mode->vsync_end = mode->vsync_start + timing->vsync_len; | 
| 62 | mode->vtotal = mode->vsync_end + timing->lower_margin; | 64 | mode->vtotal = mode->vsync_end + timing->lower_margin; | 
| 65 | mode->width_mm = panel->width_mm; | ||
| 66 | mode->height_mm = panel->height_mm; | ||
| 63 | 67 | ||
| 64 | if (timing->vmode & FB_VMODE_INTERLACED) | 68 | if (timing->vmode & FB_VMODE_INTERLACED) | 
| 65 | mode->flags |= DRM_MODE_FLAG_INTERLACE; | 69 | mode->flags |= DRM_MODE_FLAG_INTERLACE; | 
| @@ -148,16 +152,18 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) | |||
| 148 | connector->display_info.raw_edid = edid; | 152 | connector->display_info.raw_edid = edid; | 
| 149 | } else { | 153 | } else { | 
| 150 | struct drm_display_mode *mode = drm_mode_create(connector->dev); | 154 | struct drm_display_mode *mode = drm_mode_create(connector->dev); | 
| 151 | struct fb_videomode *timing; | 155 | struct exynos_drm_panel_info *panel; | 
| 152 | 156 | ||
| 153 | if (display_ops->get_timing) | 157 | if (display_ops->get_panel) | 
| 154 | timing = display_ops->get_timing(manager->dev); | 158 | panel = display_ops->get_panel(manager->dev); | 
| 155 | else { | 159 | else { | 
| 156 | drm_mode_destroy(connector->dev, mode); | 160 | drm_mode_destroy(connector->dev, mode); | 
| 157 | return 0; | 161 | return 0; | 
| 158 | } | 162 | } | 
| 159 | 163 | ||
| 160 | convert_to_display_mode(mode, timing); | 164 | convert_to_display_mode(mode, panel); | 
| 165 | connector->display_info.width_mm = mode->width_mm; | ||
| 166 | connector->display_info.height_mm = mode->height_mm; | ||
| 161 | 167 | ||
| 162 | mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; | 168 | mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; | 
| 163 | drm_mode_set_name(mode); | 169 | drm_mode_set_name(mode); | 
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c index 661a03571d0c..d08a55896d50 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c | |||
| @@ -193,6 +193,9 @@ int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) | |||
| 193 | return err; | 193 | return err; | 
| 194 | } | 194 | } | 
| 195 | 195 | ||
| 196 | /* setup possible_clones. */ | ||
| 197 | exynos_drm_encoder_setup(drm_dev); | ||
| 198 | |||
| 196 | /* | 199 | /* | 
| 197 | * if any specific driver such as fimd or hdmi driver called | 200 | * if any specific driver such as fimd or hdmi driver called | 
| 198 | * exynos_drm_subdrv_register() later than drm_load(), | 201 | * exynos_drm_subdrv_register() later than drm_load(), | 
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index e3861ac49295..de818831a511 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
| @@ -307,9 +307,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, | |||
| 307 | */ | 307 | */ | 
| 308 | event->pipe = exynos_crtc->pipe; | 308 | event->pipe = exynos_crtc->pipe; | 
| 309 | 309 | ||
| 310 | list_add_tail(&event->base.link, | ||
| 311 | &dev_priv->pageflip_event_list); | ||
| 312 | |||
| 313 | ret = drm_vblank_get(dev, exynos_crtc->pipe); | 310 | ret = drm_vblank_get(dev, exynos_crtc->pipe); | 
| 314 | if (ret) { | 311 | if (ret) { | 
| 315 | DRM_DEBUG("failed to acquire vblank counter\n"); | 312 | DRM_DEBUG("failed to acquire vblank counter\n"); | 
| @@ -318,6 +315,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, | |||
| 318 | goto out; | 315 | goto out; | 
| 319 | } | 316 | } | 
| 320 | 317 | ||
| 318 | list_add_tail(&event->base.link, | ||
| 319 | &dev_priv->pageflip_event_list); | ||
| 320 | |||
| 321 | crtc->fb = fb; | 321 | crtc->fb = fb; | 
| 322 | ret = exynos_drm_crtc_update(crtc); | 322 | ret = exynos_drm_crtc_update(crtc); | 
| 323 | if (ret) { | 323 | if (ret) { | 
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 35889ca255e9..58820ebd3558 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | 33 | ||
| 34 | #include "exynos_drm_drv.h" | 34 | #include "exynos_drm_drv.h" | 
| 35 | #include "exynos_drm_crtc.h" | 35 | #include "exynos_drm_crtc.h" | 
| 36 | #include "exynos_drm_encoder.h" | ||
| 36 | #include "exynos_drm_fbdev.h" | 37 | #include "exynos_drm_fbdev.h" | 
| 37 | #include "exynos_drm_fb.h" | 38 | #include "exynos_drm_fb.h" | 
| 38 | #include "exynos_drm_gem.h" | 39 | #include "exynos_drm_gem.h" | 
| @@ -99,6 +100,9 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) | |||
| 99 | if (ret) | 100 | if (ret) | 
| 100 | goto err_vblank; | 101 | goto err_vblank; | 
| 101 | 102 | ||
| 103 | /* setup possible_clones. */ | ||
| 104 | exynos_drm_encoder_setup(dev); | ||
| 105 | |||
| 102 | /* | 106 | /* | 
| 103 | * create and configure fb helper and also exynos specific | 107 | * create and configure fb helper and also exynos specific | 
| 104 | * fbdev object. | 108 | * fbdev object. | 
| @@ -141,16 +145,21 @@ static int exynos_drm_unload(struct drm_device *dev) | |||
| 141 | } | 145 | } | 
| 142 | 146 | ||
| 143 | static void exynos_drm_preclose(struct drm_device *dev, | 147 | static void exynos_drm_preclose(struct drm_device *dev, | 
| 144 | struct drm_file *file_priv) | 148 | struct drm_file *file) | 
| 145 | { | 149 | { | 
| 146 | struct exynos_drm_private *dev_priv = dev->dev_private; | 150 | DRM_DEBUG_DRIVER("%s\n", __FILE__); | 
| 147 | 151 | ||
| 148 | /* | 152 | } | 
| 149 | * drm framework frees all events at release time, | 153 | |
| 150 | * so private event list should be cleared. | 154 | static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) | 
| 151 | */ | 155 | { | 
| 152 | if (!list_empty(&dev_priv->pageflip_event_list)) | 156 | DRM_DEBUG_DRIVER("%s\n", __FILE__); | 
| 153 | INIT_LIST_HEAD(&dev_priv->pageflip_event_list); | 157 | |
| 158 | if (!file->driver_priv) | ||
| 159 | return; | ||
| 160 | |||
| 161 | kfree(file->driver_priv); | ||
| 162 | file->driver_priv = NULL; | ||
| 154 | } | 163 | } | 
| 155 | 164 | ||
| 156 | static void exynos_drm_lastclose(struct drm_device *dev) | 165 | static void exynos_drm_lastclose(struct drm_device *dev) | 
| @@ -195,6 +204,7 @@ static struct drm_driver exynos_drm_driver = { | |||
| 195 | .unload = exynos_drm_unload, | 204 | .unload = exynos_drm_unload, | 
| 196 | .preclose = exynos_drm_preclose, | 205 | .preclose = exynos_drm_preclose, | 
| 197 | .lastclose = exynos_drm_lastclose, | 206 | .lastclose = exynos_drm_lastclose, | 
| 207 | .postclose = exynos_drm_postclose, | ||
| 198 | .get_vblank_counter = drm_vblank_count, | 208 | .get_vblank_counter = drm_vblank_count, | 
| 199 | .enable_vblank = exynos_drm_crtc_enable_vblank, | 209 | .enable_vblank = exynos_drm_crtc_enable_vblank, | 
| 200 | .disable_vblank = exynos_drm_crtc_disable_vblank, | 210 | .disable_vblank = exynos_drm_crtc_disable_vblank, | 
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index e685e1e33055..13540de90bfc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
| @@ -136,7 +136,7 @@ struct exynos_drm_overlay { | |||
| 136 | * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. | 136 | * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. | 
| 137 | * @is_connected: check for that display is connected or not. | 137 | * @is_connected: check for that display is connected or not. | 
| 138 | * @get_edid: get edid modes from display driver. | 138 | * @get_edid: get edid modes from display driver. | 
| 139 | * @get_timing: get timing object from display driver. | 139 | * @get_panel: get panel object from display driver. | 
| 140 | * @check_timing: check if timing is valid or not. | 140 | * @check_timing: check if timing is valid or not. | 
| 141 | * @power_on: display device on or off. | 141 | * @power_on: display device on or off. | 
| 142 | */ | 142 | */ | 
| @@ -145,7 +145,7 @@ struct exynos_drm_display_ops { | |||
| 145 | bool (*is_connected)(struct device *dev); | 145 | bool (*is_connected)(struct device *dev); | 
| 146 | int (*get_edid)(struct device *dev, struct drm_connector *connector, | 146 | int (*get_edid)(struct device *dev, struct drm_connector *connector, | 
| 147 | u8 *edid, int len); | 147 | u8 *edid, int len); | 
| 148 | void *(*get_timing)(struct device *dev); | 148 | void *(*get_panel)(struct device *dev); | 
| 149 | int (*check_timing)(struct device *dev, void *timing); | 149 | int (*check_timing)(struct device *dev, void *timing); | 
| 150 | int (*power_on)(struct device *dev, int mode); | 150 | int (*power_on)(struct device *dev, int mode); | 
| 151 | }; | 151 | }; | 
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 86b93dde219a..ef4754f1519b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c | |||
| @@ -195,6 +195,40 @@ static struct drm_encoder_funcs exynos_encoder_funcs = { | |||
| 195 | .destroy = exynos_drm_encoder_destroy, | 195 | .destroy = exynos_drm_encoder_destroy, | 
| 196 | }; | 196 | }; | 
| 197 | 197 | ||
| 198 | static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder) | ||
| 199 | { | ||
| 200 | struct drm_encoder *clone; | ||
| 201 | struct drm_device *dev = encoder->dev; | ||
| 202 | struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); | ||
| 203 | struct exynos_drm_display_ops *display_ops = | ||
| 204 | exynos_encoder->manager->display_ops; | ||
| 205 | unsigned int clone_mask = 0; | ||
| 206 | int cnt = 0; | ||
| 207 | |||
| 208 | list_for_each_entry(clone, &dev->mode_config.encoder_list, head) { | ||
| 209 | switch (display_ops->type) { | ||
| 210 | case EXYNOS_DISPLAY_TYPE_LCD: | ||
| 211 | case EXYNOS_DISPLAY_TYPE_HDMI: | ||
| 212 | clone_mask |= (1 << (cnt++)); | ||
| 213 | break; | ||
| 214 | default: | ||
| 215 | continue; | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | return clone_mask; | ||
| 220 | } | ||
| 221 | |||
| 222 | void exynos_drm_encoder_setup(struct drm_device *dev) | ||
| 223 | { | ||
| 224 | struct drm_encoder *encoder; | ||
| 225 | |||
| 226 | DRM_DEBUG_KMS("%s\n", __FILE__); | ||
| 227 | |||
| 228 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | ||
| 229 | encoder->possible_clones = exynos_drm_encoder_clones(encoder); | ||
| 230 | } | ||
| 231 | |||
| 198 | struct drm_encoder * | 232 | struct drm_encoder * | 
| 199 | exynos_drm_encoder_create(struct drm_device *dev, | 233 | exynos_drm_encoder_create(struct drm_device *dev, | 
| 200 | struct exynos_drm_manager *manager, | 234 | struct exynos_drm_manager *manager, | 
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h index 97b087a51cb6..eb7d2316847e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | struct exynos_drm_manager; | 31 | struct exynos_drm_manager; | 
| 32 | 32 | ||
| 33 | void exynos_drm_encoder_setup(struct drm_device *dev); | ||
| 33 | struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, | 34 | struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, | 
| 34 | struct exynos_drm_manager *mgr, | 35 | struct exynos_drm_manager *mgr, | 
| 35 | unsigned int possible_crtcs); | 36 | unsigned int possible_crtcs); | 
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index d7ae29d2f3d6..3508700e529b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c | |||
| @@ -195,66 +195,6 @@ out: | |||
| 195 | return ret; | 195 | return ret; | 
| 196 | } | 196 | } | 
| 197 | 197 | ||
| 198 | static bool | ||
| 199 | exynos_drm_fbdev_is_samefb(struct drm_framebuffer *fb, | ||
| 200 | struct drm_fb_helper_surface_size *sizes) | ||
| 201 | { | ||
| 202 | if (fb->width != sizes->surface_width) | ||
| 203 | return false; | ||
| 204 | if (fb->height != sizes->surface_height) | ||
| 205 | return false; | ||
| 206 | if (fb->bits_per_pixel != sizes->surface_bpp) | ||
| 207 | return false; | ||
| 208 | if (fb->depth != sizes->surface_depth) | ||
| 209 | return false; | ||
| 210 | |||
| 211 | return true; | ||
| 212 | } | ||
| 213 | |||
| 214 | static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper, | ||
| 215 | struct drm_fb_helper_surface_size *sizes) | ||
| 216 | { | ||
| 217 | struct drm_device *dev = helper->dev; | ||
| 218 | struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); | ||
| 219 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
| 220 | struct drm_framebuffer *fb = helper->fb; | ||
| 221 | struct drm_mode_fb_cmd2 mode_cmd = { 0 }; | ||
| 222 | unsigned long size; | ||
| 223 | |||
| 224 | DRM_DEBUG_KMS("%s\n", __FILE__); | ||
| 225 | |||
| 226 | if (exynos_drm_fbdev_is_samefb(fb, sizes)) | ||
| 227 | return 0; | ||
| 228 | |||
| 229 | mode_cmd.width = sizes->surface_width; | ||
| 230 | mode_cmd.height = sizes->surface_height; | ||
| 231 | mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3); | ||
| 232 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, | ||
| 233 | sizes->surface_depth); | ||
| 234 | |||
| 235 | if (exynos_fbdev->exynos_gem_obj) | ||
| 236 | exynos_drm_gem_destroy(exynos_fbdev->exynos_gem_obj); | ||
| 237 | |||
| 238 | if (fb->funcs->destroy) | ||
| 239 | fb->funcs->destroy(fb); | ||
| 240 | |||
| 241 | size = mode_cmd.pitches[0] * mode_cmd.height; | ||
| 242 | exynos_gem_obj = exynos_drm_gem_create(dev, size); | ||
| 243 | if (IS_ERR(exynos_gem_obj)) | ||
| 244 | return PTR_ERR(exynos_gem_obj); | ||
| 245 | |||
| 246 | exynos_fbdev->exynos_gem_obj = exynos_gem_obj; | ||
| 247 | |||
| 248 | helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, | ||
| 249 | &exynos_gem_obj->base); | ||
| 250 | if (IS_ERR_OR_NULL(helper->fb)) { | ||
| 251 | DRM_ERROR("failed to create drm framebuffer.\n"); | ||
| 252 | return PTR_ERR(helper->fb); | ||
| 253 | } | ||
| 254 | |||
| 255 | return exynos_drm_fbdev_update(helper, helper->fb); | ||
| 256 | } | ||
| 257 | |||
| 258 | static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, | 198 | static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, | 
| 259 | struct drm_fb_helper_surface_size *sizes) | 199 | struct drm_fb_helper_surface_size *sizes) | 
| 260 | { | 200 | { | 
| @@ -262,6 +202,10 @@ static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, | |||
| 262 | 202 | ||
| 263 | DRM_DEBUG_KMS("%s\n", __FILE__); | 203 | DRM_DEBUG_KMS("%s\n", __FILE__); | 
| 264 | 204 | ||
| 205 | /* | ||
| 206 | * with !helper->fb, it means that this funcion is called first time | ||
| 207 | * and after that, the helper->fb would be used as clone mode. | ||
| 208 | */ | ||
| 265 | if (!helper->fb) { | 209 | if (!helper->fb) { | 
| 266 | ret = exynos_drm_fbdev_create(helper, sizes); | 210 | ret = exynos_drm_fbdev_create(helper, sizes); | 
| 267 | if (ret < 0) { | 211 | if (ret < 0) { | 
| @@ -274,12 +218,6 @@ static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, | |||
| 274 | * because register_framebuffer() should be called. | 218 | * because register_framebuffer() should be called. | 
| 275 | */ | 219 | */ | 
| 276 | ret = 1; | 220 | ret = 1; | 
| 277 | } else { | ||
| 278 | ret = exynos_drm_fbdev_recreate(helper, sizes); | ||
| 279 | if (ret < 0) { | ||
| 280 | DRM_ERROR("failed to reconfigure fbdev\n"); | ||
| 281 | return ret; | ||
| 282 | } | ||
| 283 | } | 221 | } | 
| 284 | 222 | ||
| 285 | return ret; | 223 | return ret; | 
| diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index b6a737d196ae..360adf2bba04 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
| @@ -89,7 +89,7 @@ struct fimd_context { | |||
| 89 | bool suspended; | 89 | bool suspended; | 
| 90 | struct mutex lock; | 90 | struct mutex lock; | 
| 91 | 91 | ||
| 92 | struct fb_videomode *timing; | 92 | struct exynos_drm_panel_info *panel; | 
| 93 | }; | 93 | }; | 
| 94 | 94 | ||
| 95 | static bool fimd_display_is_connected(struct device *dev) | 95 | static bool fimd_display_is_connected(struct device *dev) | 
| @@ -101,13 +101,13 @@ static bool fimd_display_is_connected(struct device *dev) | |||
| 101 | return true; | 101 | return true; | 
| 102 | } | 102 | } | 
| 103 | 103 | ||
| 104 | static void *fimd_get_timing(struct device *dev) | 104 | static void *fimd_get_panel(struct device *dev) | 
| 105 | { | 105 | { | 
| 106 | struct fimd_context *ctx = get_fimd_context(dev); | 106 | struct fimd_context *ctx = get_fimd_context(dev); | 
| 107 | 107 | ||
| 108 | DRM_DEBUG_KMS("%s\n", __FILE__); | 108 | DRM_DEBUG_KMS("%s\n", __FILE__); | 
| 109 | 109 | ||
| 110 | return ctx->timing; | 110 | return ctx->panel; | 
| 111 | } | 111 | } | 
| 112 | 112 | ||
| 113 | static int fimd_check_timing(struct device *dev, void *timing) | 113 | static int fimd_check_timing(struct device *dev, void *timing) | 
| @@ -131,7 +131,7 @@ static int fimd_display_power_on(struct device *dev, int mode) | |||
| 131 | static struct exynos_drm_display_ops fimd_display_ops = { | 131 | static struct exynos_drm_display_ops fimd_display_ops = { | 
| 132 | .type = EXYNOS_DISPLAY_TYPE_LCD, | 132 | .type = EXYNOS_DISPLAY_TYPE_LCD, | 
| 133 | .is_connected = fimd_display_is_connected, | 133 | .is_connected = fimd_display_is_connected, | 
| 134 | .get_timing = fimd_get_timing, | 134 | .get_panel = fimd_get_panel, | 
| 135 | .check_timing = fimd_check_timing, | 135 | .check_timing = fimd_check_timing, | 
| 136 | .power_on = fimd_display_power_on, | 136 | .power_on = fimd_display_power_on, | 
| 137 | }; | 137 | }; | 
| @@ -193,7 +193,8 @@ static void fimd_apply(struct device *subdrv_dev) | |||
| 193 | static void fimd_commit(struct device *dev) | 193 | static void fimd_commit(struct device *dev) | 
| 194 | { | 194 | { | 
| 195 | struct fimd_context *ctx = get_fimd_context(dev); | 195 | struct fimd_context *ctx = get_fimd_context(dev); | 
| 196 | struct fb_videomode *timing = ctx->timing; | 196 | struct exynos_drm_panel_info *panel = ctx->panel; | 
| 197 | struct fb_videomode *timing = &panel->timing; | ||
| 197 | u32 val; | 198 | u32 val; | 
| 198 | 199 | ||
| 199 | if (ctx->suspended) | 200 | if (ctx->suspended) | 
| @@ -604,7 +605,12 @@ static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) | |||
| 604 | } | 605 | } | 
| 605 | 606 | ||
| 606 | if (is_checked) { | 607 | if (is_checked) { | 
| 607 | drm_vblank_put(drm_dev, crtc); | 608 | /* | 
| 609 | * call drm_vblank_put only in case that drm_vblank_get was | ||
| 610 | * called. | ||
| 611 | */ | ||
| 612 | if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0) | ||
| 613 | drm_vblank_put(drm_dev, crtc); | ||
| 608 | 614 | ||
| 609 | /* | 615 | /* | 
| 610 | * don't off vblank if vblank_disable_allowed is 1, | 616 | * don't off vblank if vblank_disable_allowed is 1, | 
| @@ -781,7 +787,7 @@ static int __devinit fimd_probe(struct platform_device *pdev) | |||
| 781 | struct fimd_context *ctx; | 787 | struct fimd_context *ctx; | 
| 782 | struct exynos_drm_subdrv *subdrv; | 788 | struct exynos_drm_subdrv *subdrv; | 
| 783 | struct exynos_drm_fimd_pdata *pdata; | 789 | struct exynos_drm_fimd_pdata *pdata; | 
| 784 | struct fb_videomode *timing; | 790 | struct exynos_drm_panel_info *panel; | 
| 785 | struct resource *res; | 791 | struct resource *res; | 
| 786 | int win; | 792 | int win; | 
| 787 | int ret = -EINVAL; | 793 | int ret = -EINVAL; | 
| @@ -794,9 +800,9 @@ static int __devinit fimd_probe(struct platform_device *pdev) | |||
| 794 | return -EINVAL; | 800 | return -EINVAL; | 
| 795 | } | 801 | } | 
| 796 | 802 | ||
| 797 | timing = &pdata->timing; | 803 | panel = &pdata->panel; | 
| 798 | if (!timing) { | 804 | if (!panel) { | 
| 799 | dev_err(dev, "timing is null.\n"); | 805 | dev_err(dev, "panel is null.\n"); | 
| 800 | return -EINVAL; | 806 | return -EINVAL; | 
| 801 | } | 807 | } | 
| 802 | 808 | ||
| @@ -858,16 +864,16 @@ static int __devinit fimd_probe(struct platform_device *pdev) | |||
| 858 | goto err_req_irq; | 864 | goto err_req_irq; | 
| 859 | } | 865 | } | 
| 860 | 866 | ||
| 861 | ctx->clkdiv = fimd_calc_clkdiv(ctx, timing); | 867 | ctx->clkdiv = fimd_calc_clkdiv(ctx, &panel->timing); | 
| 862 | ctx->vidcon0 = pdata->vidcon0; | 868 | ctx->vidcon0 = pdata->vidcon0; | 
| 863 | ctx->vidcon1 = pdata->vidcon1; | 869 | ctx->vidcon1 = pdata->vidcon1; | 
| 864 | ctx->default_win = pdata->default_win; | 870 | ctx->default_win = pdata->default_win; | 
| 865 | ctx->timing = timing; | 871 | ctx->panel = panel; | 
| 866 | 872 | ||
| 867 | timing->pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv; | 873 | panel->timing.pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv; | 
| 868 | 874 | ||
| 869 | DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n", | 875 | DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n", | 
| 870 | timing->pixclock, ctx->clkdiv); | 876 | panel->timing.pixclock, ctx->clkdiv); | 
| 871 | 877 | ||
| 872 | subdrv = &ctx->subdrv; | 878 | subdrv = &ctx->subdrv; | 
| 873 | 879 | ||
| diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index ac24cff39775..93846e810e38 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
| @@ -712,7 +712,12 @@ static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc) | |||
| 712 | } | 712 | } | 
| 713 | 713 | ||
| 714 | if (is_checked) | 714 | if (is_checked) | 
| 715 | drm_vblank_put(drm_dev, crtc); | 715 | /* | 
| 716 | * call drm_vblank_put only in case that drm_vblank_get was | ||
| 717 | * called. | ||
| 718 | */ | ||
| 719 | if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0) | ||
| 720 | drm_vblank_put(drm_dev, crtc); | ||
| 716 | 721 | ||
| 717 | spin_unlock_irqrestore(&drm_dev->event_lock, flags); | 722 | spin_unlock_irqrestore(&drm_dev->event_lock, flags); | 
| 718 | } | 723 | } | 
| @@ -779,15 +784,15 @@ static void mixer_win_reset(struct mixer_context *ctx) | |||
| 779 | mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST, | 784 | mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST, | 
| 780 | MXR_STATUS_BURST_MASK); | 785 | MXR_STATUS_BURST_MASK); | 
| 781 | 786 | ||
| 782 | /* setting default layer priority: layer1 > video > layer0 | 787 | /* setting default layer priority: layer1 > layer0 > video | 
| 783 | * because typical usage scenario would be | 788 | * because typical usage scenario would be | 
| 789 | * layer1 - OSD | ||
| 784 | * layer0 - framebuffer | 790 | * layer0 - framebuffer | 
| 785 | * video - video overlay | 791 | * video - video overlay | 
| 786 | * layer1 - OSD | ||
| 787 | */ | 792 | */ | 
| 788 | val = MXR_LAYER_CFG_GRP0_VAL(1); | 793 | val = MXR_LAYER_CFG_GRP1_VAL(3); | 
| 789 | val |= MXR_LAYER_CFG_VP_VAL(2); | 794 | val |= MXR_LAYER_CFG_GRP0_VAL(2); | 
| 790 | val |= MXR_LAYER_CFG_GRP1_VAL(3); | 795 | val |= MXR_LAYER_CFG_VP_VAL(1); | 
| 791 | mixer_reg_write(res, MXR_LAYER_CFG, val); | 796 | mixer_reg_write(res, MXR_LAYER_CFG, val); | 
| 792 | 797 | ||
| 793 | /* setting background color */ | 798 | /* setting background color */ | 
| @@ -1044,7 +1049,7 @@ static int mixer_remove(struct platform_device *pdev) | |||
| 1044 | platform_get_drvdata(pdev); | 1049 | platform_get_drvdata(pdev); | 
| 1045 | struct mixer_context *ctx = (struct mixer_context *)drm_hdmi_ctx->ctx; | 1050 | struct mixer_context *ctx = (struct mixer_context *)drm_hdmi_ctx->ctx; | 
| 1046 | 1051 | ||
| 1047 | dev_info(dev, "remove sucessful\n"); | 1052 | dev_info(dev, "remove successful\n"); | 
| 1048 | 1053 | ||
| 1049 | mixer_resource_poweroff(ctx); | 1054 | mixer_resource_poweroff(ctx); | 
| 1050 | mixer_resources_cleanup(ctx); | 1055 | mixer_resources_cleanup(ctx); | 
