diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_fbdev.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 1f4b3d1a7713..836f41008187 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include "exynos_drm_drv.h" | 34 | #include "exynos_drm_drv.h" |
35 | #include "exynos_drm_fb.h" | 35 | #include "exynos_drm_fb.h" |
36 | #include "exynos_drm_gem.h" | ||
36 | #include "exynos_drm_buf.h" | 37 | #include "exynos_drm_buf.h" |
37 | 38 | ||
38 | #define MAX_CONNECTOR 4 | 39 | #define MAX_CONNECTOR 4 |
@@ -85,15 +86,13 @@ static struct fb_ops exynos_drm_fb_ops = { | |||
85 | }; | 86 | }; |
86 | 87 | ||
87 | static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, | 88 | static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, |
88 | struct drm_framebuffer *fb, | 89 | struct drm_framebuffer *fb) |
89 | unsigned int fb_width, | ||
90 | unsigned int fb_height) | ||
91 | { | 90 | { |
92 | struct fb_info *fbi = helper->fbdev; | 91 | struct fb_info *fbi = helper->fbdev; |
93 | struct drm_device *dev = helper->dev; | 92 | struct drm_device *dev = helper->dev; |
94 | struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper); | 93 | struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper); |
95 | struct exynos_drm_buf_entry *entry; | 94 | struct exynos_drm_gem_buf *buffer; |
96 | unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3); | 95 | unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); |
97 | unsigned long offset; | 96 | unsigned long offset; |
98 | 97 | ||
99 | DRM_DEBUG_KMS("%s\n", __FILE__); | 98 | DRM_DEBUG_KMS("%s\n", __FILE__); |
@@ -101,20 +100,20 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, | |||
101 | exynos_fb->fb = fb; | 100 | exynos_fb->fb = fb; |
102 | 101 | ||
103 | drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth); | 102 | drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth); |
104 | drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height); | 103 | drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); |
105 | 104 | ||
106 | entry = exynos_drm_fb_get_buf(fb); | 105 | buffer = exynos_drm_fb_get_buf(fb); |
107 | if (!entry) { | 106 | if (!buffer) { |
108 | DRM_LOG_KMS("entry is null.\n"); | 107 | DRM_LOG_KMS("buffer is null.\n"); |
109 | return -EFAULT; | 108 | return -EFAULT; |
110 | } | 109 | } |
111 | 110 | ||
112 | offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); | 111 | offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); |
113 | offset += fbi->var.yoffset * fb->pitch; | 112 | offset += fbi->var.yoffset * fb->pitch; |
114 | 113 | ||
115 | dev->mode_config.fb_base = entry->paddr; | 114 | dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr; |
116 | fbi->screen_base = entry->vaddr + offset; | 115 | fbi->screen_base = buffer->kvaddr + offset; |
117 | fbi->fix.smem_start = entry->paddr + offset; | 116 | fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset); |
118 | fbi->screen_size = size; | 117 | fbi->screen_size = size; |
119 | fbi->fix.smem_len = size; | 118 | fbi->fix.smem_len = size; |
120 | 119 | ||
@@ -171,8 +170,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, | |||
171 | goto out; | 170 | goto out; |
172 | } | 171 | } |
173 | 172 | ||
174 | ret = exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width, | 173 | ret = exynos_drm_fbdev_update(helper, helper->fb); |
175 | sizes->fb_height); | ||
176 | if (ret < 0) | 174 | if (ret < 0) |
177 | fb_dealloc_cmap(&fbi->cmap); | 175 | fb_dealloc_cmap(&fbi->cmap); |
178 | 176 | ||
@@ -235,8 +233,7 @@ static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper, | |||
235 | } | 233 | } |
236 | 234 | ||
237 | helper->fb = exynos_fbdev->fb; | 235 | helper->fb = exynos_fbdev->fb; |
238 | return exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width, | 236 | return exynos_drm_fbdev_update(helper, helper->fb); |
239 | sizes->fb_height); | ||
240 | } | 237 | } |
241 | 238 | ||
242 | static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, | 239 | static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, |
@@ -405,6 +402,18 @@ int exynos_drm_fbdev_reinit(struct drm_device *dev) | |||
405 | fb_helper = private->fb_helper; | 402 | fb_helper = private->fb_helper; |
406 | 403 | ||
407 | if (fb_helper) { | 404 | if (fb_helper) { |
405 | struct list_head temp_list; | ||
406 | |||
407 | INIT_LIST_HEAD(&temp_list); | ||
408 | |||
409 | /* | ||
410 | * fb_helper is reintialized but kernel fb is reused | ||
411 | * so kernel_fb_list need to be backuped and restored | ||
412 | */ | ||
413 | if (!list_empty(&fb_helper->kernel_fb_list)) | ||
414 | list_replace_init(&fb_helper->kernel_fb_list, | ||
415 | &temp_list); | ||
416 | |||
408 | drm_fb_helper_fini(fb_helper); | 417 | drm_fb_helper_fini(fb_helper); |
409 | 418 | ||
410 | ret = drm_fb_helper_init(dev, fb_helper, | 419 | ret = drm_fb_helper_init(dev, fb_helper, |
@@ -414,6 +423,9 @@ int exynos_drm_fbdev_reinit(struct drm_device *dev) | |||
414 | return ret; | 423 | return ret; |
415 | } | 424 | } |
416 | 425 | ||
426 | if (!list_empty(&temp_list)) | ||
427 | list_replace(&temp_list, &fb_helper->kernel_fb_list); | ||
428 | |||
417 | ret = drm_fb_helper_single_add_all_connectors(fb_helper); | 429 | ret = drm_fb_helper_single_add_all_connectors(fb_helper); |
418 | if (ret < 0) { | 430 | if (ret < 0) { |
419 | DRM_ERROR("failed to add fb helper to connectors\n"); | 431 | DRM_ERROR("failed to add fb helper to connectors\n"); |