diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-28 12:05:23 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-28 12:05:23 -0500 |
| commit | 4244cb482e8eab18142162a27c8829a04585863a (patch) | |
| tree | d13911f08bdf40ac17426c959ef9f76bb61c81ab /drivers | |
| parent | f02877ce3ca8f87a086e3fc98bb9e022bbec70ec (diff) | |
| parent | b7b996da27e6f8b518a7c7753fa5b6dff2df6899 (diff) | |
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
drm/exynos: fixed wrong err ptr usage and destroy call in exeception
drm/exynos: Add disable of manager
drm/exynos: include linux/module.h
drm/exynos: fix vblank bug.
drm/exynos: changed buffer structure.
drm/exynos: removed unnecessary variable.
drm/exynos: use gem create function generically
drm/exynos: checked for null pointer
drm/exynos: added crtc dpms for disable crtc
drm/exynos: removed meaningless parameter from fbdev update
drm/exynos: restored kernel_fb_list when reiniting fb_helper
drm/exynos: changed exynos_drm_display to exynos_drm_display_ops
drm/exynos: added manager object to connector
drm/exynos: fixed converting between display mode and timing
drm/exynos: fixed connector flag with hpd and interlace scan for hdmi
drm/exynos: added kms poll for handling hpd event
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_buf.c | 62 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_buf.h | 21 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_connector.c | 78 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 76 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.h | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_encoder.c | 83 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_encoder.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.c | 66 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 44 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 71 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 89 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.h | 28 |
14 files changed, 436 insertions, 226 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c index 6f8afea94fc9..2bb07bca511a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c | |||
| @@ -27,82 +27,84 @@ | |||
| 27 | #include "drm.h" | 27 | #include "drm.h" |
| 28 | 28 | ||
| 29 | #include "exynos_drm_drv.h" | 29 | #include "exynos_drm_drv.h" |
| 30 | #include "exynos_drm_gem.h" | ||
| 30 | #include "exynos_drm_buf.h" | 31 | #include "exynos_drm_buf.h" |
| 31 | 32 | ||
| 32 | static DEFINE_MUTEX(exynos_drm_buf_lock); | ||
| 33 | |||
| 34 | static int lowlevel_buffer_allocate(struct drm_device *dev, | 33 | static int lowlevel_buffer_allocate(struct drm_device *dev, |
| 35 | struct exynos_drm_buf_entry *entry) | 34 | struct exynos_drm_gem_buf *buffer) |
| 36 | { | 35 | { |
| 37 | DRM_DEBUG_KMS("%s\n", __FILE__); | 36 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 38 | 37 | ||
| 39 | entry->vaddr = dma_alloc_writecombine(dev->dev, entry->size, | 38 | buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size, |
| 40 | (dma_addr_t *)&entry->paddr, GFP_KERNEL); | 39 | &buffer->dma_addr, GFP_KERNEL); |
| 41 | if (!entry->paddr) { | 40 | if (!buffer->kvaddr) { |
| 42 | DRM_ERROR("failed to allocate buffer.\n"); | 41 | DRM_ERROR("failed to allocate buffer.\n"); |
| 43 | return -ENOMEM; | 42 | return -ENOMEM; |
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | DRM_DEBUG_KMS("allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n", | 45 | DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", |
| 47 | (unsigned int)entry->vaddr, entry->paddr, entry->size); | 46 | (unsigned long)buffer->kvaddr, |
| 47 | (unsigned long)buffer->dma_addr, | ||
| 48 | buffer->size); | ||
| 48 | 49 | ||
| 49 | return 0; | 50 | return 0; |
| 50 | } | 51 | } |
| 51 | 52 | ||
| 52 | static void lowlevel_buffer_deallocate(struct drm_device *dev, | 53 | static void lowlevel_buffer_deallocate(struct drm_device *dev, |
| 53 | struct exynos_drm_buf_entry *entry) | 54 | struct exynos_drm_gem_buf *buffer) |
| 54 | { | 55 | { |
| 55 | DRM_DEBUG_KMS("%s.\n", __FILE__); | 56 | DRM_DEBUG_KMS("%s.\n", __FILE__); |
| 56 | 57 | ||
| 57 | if (entry->paddr && entry->vaddr && entry->size) | 58 | if (buffer->dma_addr && buffer->size) |
| 58 | dma_free_writecombine(dev->dev, entry->size, entry->vaddr, | 59 | dma_free_writecombine(dev->dev, buffer->size, buffer->kvaddr, |
| 59 | entry->paddr); | 60 | (dma_addr_t)buffer->dma_addr); |
| 60 | else | 61 | else |
| 61 | DRM_DEBUG_KMS("entry data is null.\n"); | 62 | DRM_DEBUG_KMS("buffer data are invalid.\n"); |
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev, | 65 | struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev, |
| 65 | unsigned int size) | 66 | unsigned int size) |
| 66 | { | 67 | { |
| 67 | struct exynos_drm_buf_entry *entry; | 68 | struct exynos_drm_gem_buf *buffer; |
| 68 | 69 | ||
| 69 | DRM_DEBUG_KMS("%s.\n", __FILE__); | 70 | DRM_DEBUG_KMS("%s.\n", __FILE__); |
| 71 | DRM_DEBUG_KMS("desired size = 0x%x\n", size); | ||
| 70 | 72 | ||
| 71 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 73 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
| 72 | if (!entry) { | 74 | if (!buffer) { |
| 73 | DRM_ERROR("failed to allocate exynos_drm_buf_entry.\n"); | 75 | DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n"); |
| 74 | return ERR_PTR(-ENOMEM); | 76 | return ERR_PTR(-ENOMEM); |
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | entry->size = size; | 79 | buffer->size = size; |
| 78 | 80 | ||
| 79 | /* | 81 | /* |
| 80 | * allocate memory region with size and set the memory information | 82 | * allocate memory region with size and set the memory information |
| 81 | * to vaddr and paddr of a entry object. | 83 | * to vaddr and dma_addr of a buffer object. |
| 82 | */ | 84 | */ |
| 83 | if (lowlevel_buffer_allocate(dev, entry) < 0) { | 85 | if (lowlevel_buffer_allocate(dev, buffer) < 0) { |
| 84 | kfree(entry); | 86 | kfree(buffer); |
| 85 | entry = NULL; | 87 | buffer = NULL; |
| 86 | return ERR_PTR(-ENOMEM); | 88 | return ERR_PTR(-ENOMEM); |
| 87 | } | 89 | } |
| 88 | 90 | ||
| 89 | return entry; | 91 | return buffer; |
| 90 | } | 92 | } |
| 91 | 93 | ||
| 92 | void exynos_drm_buf_destroy(struct drm_device *dev, | 94 | void exynos_drm_buf_destroy(struct drm_device *dev, |
| 93 | struct exynos_drm_buf_entry *entry) | 95 | struct exynos_drm_gem_buf *buffer) |
| 94 | { | 96 | { |
| 95 | DRM_DEBUG_KMS("%s.\n", __FILE__); | 97 | DRM_DEBUG_KMS("%s.\n", __FILE__); |
| 96 | 98 | ||
| 97 | if (!entry) { | 99 | if (!buffer) { |
| 98 | DRM_DEBUG_KMS("entry is null.\n"); | 100 | DRM_DEBUG_KMS("buffer is null.\n"); |
| 99 | return; | 101 | return; |
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | lowlevel_buffer_deallocate(dev, entry); | 104 | lowlevel_buffer_deallocate(dev, buffer); |
| 103 | 105 | ||
| 104 | kfree(entry); | 106 | kfree(buffer); |
| 105 | entry = NULL; | 107 | buffer = NULL; |
| 106 | } | 108 | } |
| 107 | 109 | ||
| 108 | MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); | 110 | MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.h b/drivers/gpu/drm/exynos/exynos_drm_buf.h index 045d59eab01a..6e91f9caa5db 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.h +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.h | |||
| @@ -26,28 +26,15 @@ | |||
| 26 | #ifndef _EXYNOS_DRM_BUF_H_ | 26 | #ifndef _EXYNOS_DRM_BUF_H_ |
| 27 | #define _EXYNOS_DRM_BUF_H_ | 27 | #define _EXYNOS_DRM_BUF_H_ |
| 28 | 28 | ||
| 29 | /* | ||
| 30 | * exynos drm buffer entry structure. | ||
| 31 | * | ||
| 32 | * @paddr: physical address of allocated memory. | ||
| 33 | * @vaddr: kernel virtual address of allocated memory. | ||
| 34 | * @size: size of allocated memory. | ||
| 35 | */ | ||
| 36 | struct exynos_drm_buf_entry { | ||
| 37 | dma_addr_t paddr; | ||
| 38 | void __iomem *vaddr; | ||
| 39 | unsigned int size; | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* allocate physical memory. */ | 29 | /* allocate physical memory. */ |
| 43 | struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev, | 30 | struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev, |
| 44 | unsigned int size); | 31 | unsigned int size); |
| 45 | 32 | ||
| 46 | /* get physical memory information of a drm framebuffer. */ | 33 | /* get memory information of a drm framebuffer. */ |
| 47 | struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb); | 34 | struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb); |
| 48 | 35 | ||
| 49 | /* remove allocated physical memory. */ | 36 | /* remove allocated physical memory. */ |
| 50 | void exynos_drm_buf_destroy(struct drm_device *dev, | 37 | void exynos_drm_buf_destroy(struct drm_device *dev, |
| 51 | struct exynos_drm_buf_entry *entry); | 38 | struct exynos_drm_gem_buf *buffer); |
| 52 | 39 | ||
| 53 | #endif | 40 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 985d9e768728..d620b0784257 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c | |||
| @@ -37,6 +37,8 @@ | |||
| 37 | 37 | ||
| 38 | struct exynos_drm_connector { | 38 | struct exynos_drm_connector { |
| 39 | struct drm_connector drm_connector; | 39 | struct drm_connector drm_connector; |
| 40 | uint32_t encoder_id; | ||
| 41 | struct exynos_drm_manager *manager; | ||
| 40 | }; | 42 | }; |
| 41 | 43 | ||
| 42 | /* convert exynos_video_timings to drm_display_mode */ | 44 | /* convert exynos_video_timings to drm_display_mode */ |
| @@ -47,6 +49,7 @@ convert_to_display_mode(struct drm_display_mode *mode, | |||
| 47 | DRM_DEBUG_KMS("%s\n", __FILE__); | 49 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 48 | 50 | ||
| 49 | mode->clock = timing->pixclock / 1000; | 51 | mode->clock = timing->pixclock / 1000; |
| 52 | mode->vrefresh = timing->refresh; | ||
| 50 | 53 | ||
| 51 | mode->hdisplay = timing->xres; | 54 | mode->hdisplay = timing->xres; |
| 52 | mode->hsync_start = mode->hdisplay + timing->left_margin; | 55 | mode->hsync_start = mode->hdisplay + timing->left_margin; |
| @@ -57,6 +60,12 @@ convert_to_display_mode(struct drm_display_mode *mode, | |||
| 57 | mode->vsync_start = mode->vdisplay + timing->upper_margin; | 60 | mode->vsync_start = mode->vdisplay + timing->upper_margin; |
| 58 | mode->vsync_end = mode->vsync_start + timing->vsync_len; | 61 | mode->vsync_end = mode->vsync_start + timing->vsync_len; |
| 59 | mode->vtotal = mode->vsync_end + timing->lower_margin; | 62 | mode->vtotal = mode->vsync_end + timing->lower_margin; |
| 63 | |||
| 64 | if (timing->vmode & FB_VMODE_INTERLACED) | ||
| 65 | mode->flags |= DRM_MODE_FLAG_INTERLACE; | ||
| 66 | |||
| 67 | if (timing->vmode & FB_VMODE_DOUBLE) | ||
| 68 | mode->flags |= DRM_MODE_FLAG_DBLSCAN; | ||
| 60 | } | 69 | } |
| 61 | 70 | ||
| 62 | /* convert drm_display_mode to exynos_video_timings */ | 71 | /* convert drm_display_mode to exynos_video_timings */ |
| @@ -69,7 +78,7 @@ convert_to_video_timing(struct fb_videomode *timing, | |||
| 69 | memset(timing, 0, sizeof(*timing)); | 78 | memset(timing, 0, sizeof(*timing)); |
| 70 | 79 | ||
| 71 | timing->pixclock = mode->clock * 1000; | 80 | timing->pixclock = mode->clock * 1000; |
| 72 | timing->refresh = mode->vrefresh; | 81 | timing->refresh = drm_mode_vrefresh(mode); |
| 73 | 82 | ||
| 74 | timing->xres = mode->hdisplay; | 83 | timing->xres = mode->hdisplay; |
| 75 | timing->left_margin = mode->hsync_start - mode->hdisplay; | 84 | timing->left_margin = mode->hsync_start - mode->hdisplay; |
| @@ -92,15 +101,16 @@ convert_to_video_timing(struct fb_videomode *timing, | |||
| 92 | 101 | ||
| 93 | static int exynos_drm_connector_get_modes(struct drm_connector *connector) | 102 | static int exynos_drm_connector_get_modes(struct drm_connector *connector) |
| 94 | { | 103 | { |
| 95 | struct exynos_drm_manager *manager = | 104 | struct exynos_drm_connector *exynos_connector = |
| 96 | exynos_drm_get_manager(connector->encoder); | 105 | to_exynos_connector(connector); |
| 97 | struct exynos_drm_display *display = manager->display; | 106 | struct exynos_drm_manager *manager = exynos_connector->manager; |
| 107 | struct exynos_drm_display_ops *display_ops = manager->display_ops; | ||
| 98 | unsigned int count; | 108 | unsigned int count; |
| 99 | 109 | ||
| 100 | DRM_DEBUG_KMS("%s\n", __FILE__); | 110 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 101 | 111 | ||
| 102 | if (!display) { | 112 | if (!display_ops) { |
| 103 | DRM_DEBUG_KMS("display is null.\n"); | 113 | DRM_DEBUG_KMS("display_ops is null.\n"); |
| 104 | return 0; | 114 | return 0; |
| 105 | } | 115 | } |
| 106 | 116 | ||
| @@ -112,7 +122,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) | |||
| 112 | * P.S. in case of lcd panel, count is always 1 if success | 122 | * P.S. in case of lcd panel, count is always 1 if success |
| 113 | * because lcd panel has only one mode. | 123 | * because lcd panel has only one mode. |
| 114 | */ | 124 | */ |
| 115 | if (display->get_edid) { | 125 | if (display_ops->get_edid) { |
| 116 | int ret; | 126 | int ret; |
| 117 | void *edid; | 127 | void *edid; |
| 118 | 128 | ||
| @@ -122,7 +132,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) | |||
| 122 | return 0; | 132 | return 0; |
| 123 | } | 133 | } |
| 124 | 134 | ||
| 125 | ret = display->get_edid(manager->dev, connector, | 135 | ret = display_ops->get_edid(manager->dev, connector, |
| 126 | edid, MAX_EDID); | 136 | edid, MAX_EDID); |
| 127 | if (ret < 0) { | 137 | if (ret < 0) { |
| 128 | DRM_ERROR("failed to get edid data.\n"); | 138 | DRM_ERROR("failed to get edid data.\n"); |
| @@ -140,8 +150,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) | |||
| 140 | struct drm_display_mode *mode = drm_mode_create(connector->dev); | 150 | struct drm_display_mode *mode = drm_mode_create(connector->dev); |
| 141 | struct fb_videomode *timing; | 151 | struct fb_videomode *timing; |
| 142 | 152 | ||
| 143 | if (display->get_timing) | 153 | if (display_ops->get_timing) |
| 144 | timing = display->get_timing(manager->dev); | 154 | timing = display_ops->get_timing(manager->dev); |
| 145 | else { | 155 | else { |
| 146 | drm_mode_destroy(connector->dev, mode); | 156 | drm_mode_destroy(connector->dev, mode); |
| 147 | return 0; | 157 | return 0; |
| @@ -162,9 +172,10 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) | |||
| 162 | static int exynos_drm_connector_mode_valid(struct drm_connector *connector, | 172 | static int exynos_drm_connector_mode_valid(struct drm_connector *connector, |
| 163 | struct drm_display_mode *mode) | 173 | struct drm_display_mode *mode) |
| 164 | { | 174 | { |
| 165 | struct exynos_drm_manager *manager = | 175 | struct exynos_drm_connector *exynos_connector = |
| 166 | exynos_drm_get_manager(connector->encoder); | 176 | to_exynos_connector(connector); |
| 167 | struct exynos_drm_display *display = manager->display; | 177 | struct exynos_drm_manager *manager = exynos_connector->manager; |
| 178 | struct exynos_drm_display_ops *display_ops = manager->display_ops; | ||
| 168 | struct fb_videomode timing; | 179 | struct fb_videomode timing; |
| 169 | int ret = MODE_BAD; | 180 | int ret = MODE_BAD; |
| 170 | 181 | ||
| @@ -172,8 +183,8 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector, | |||
| 172 | 183 | ||
| 173 | convert_to_video_timing(&timing, mode); | 184 | convert_to_video_timing(&timing, mode); |
| 174 | 185 | ||
| 175 | if (display && display->check_timing) | 186 | if (display_ops && display_ops->check_timing) |
| 176 | if (!display->check_timing(manager->dev, (void *)&timing)) | 187 | if (!display_ops->check_timing(manager->dev, (void *)&timing)) |
| 177 | ret = MODE_OK; | 188 | ret = MODE_OK; |
| 178 | 189 | ||
| 179 | return ret; | 190 | return ret; |
| @@ -181,9 +192,25 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector, | |||
| 181 | 192 | ||
| 182 | struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector) | 193 | struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector) |
| 183 | { | 194 | { |
| 195 | struct drm_device *dev = connector->dev; | ||
| 196 | struct exynos_drm_connector *exynos_connector = | ||
| 197 | to_exynos_connector(connector); | ||
| 198 | struct drm_mode_object *obj; | ||
| 199 | struct drm_encoder *encoder; | ||
| 200 | |||
| 184 | DRM_DEBUG_KMS("%s\n", __FILE__); | 201 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 185 | 202 | ||
| 186 | return connector->encoder; | 203 | obj = drm_mode_object_find(dev, exynos_connector->encoder_id, |
| 204 | DRM_MODE_OBJECT_ENCODER); | ||
| 205 | if (!obj) { | ||
| 206 | DRM_DEBUG_KMS("Unknown ENCODER ID %d\n", | ||
| 207 | exynos_connector->encoder_id); | ||
| 208 | return NULL; | ||
| 209 | } | ||
| 210 | |||
| 211 | encoder = obj_to_encoder(obj); | ||
| 212 | |||
| 213 | return encoder; | ||
| 187 | } | 214 | } |
| 188 | 215 | ||
| 189 | static struct drm_connector_helper_funcs exynos_connector_helper_funcs = { | 216 | static struct drm_connector_helper_funcs exynos_connector_helper_funcs = { |
| @@ -196,15 +223,17 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = { | |||
| 196 | static enum drm_connector_status | 223 | static enum drm_connector_status |
| 197 | exynos_drm_connector_detect(struct drm_connector *connector, bool force) | 224 | exynos_drm_connector_detect(struct drm_connector *connector, bool force) |
| 198 | { | 225 | { |
| 199 | struct exynos_drm_manager *manager = | 226 | struct exynos_drm_connector *exynos_connector = |
| 200 | exynos_drm_get_manager(connector->encoder); | 227 | to_exynos_connector(connector); |
| 201 | struct exynos_drm_display *display = manager->display; | 228 | struct exynos_drm_manager *manager = exynos_connector->manager; |
| 229 | struct exynos_drm_display_ops *display_ops = | ||
| 230 | manager->display_ops; | ||
| 202 | enum drm_connector_status status = connector_status_disconnected; | 231 | enum drm_connector_status status = connector_status_disconnected; |
| 203 | 232 | ||
| 204 | DRM_DEBUG_KMS("%s\n", __FILE__); | 233 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 205 | 234 | ||
| 206 | if (display && display->is_connected) { | 235 | if (display_ops && display_ops->is_connected) { |
| 207 | if (display->is_connected(manager->dev)) | 236 | if (display_ops->is_connected(manager->dev)) |
| 208 | status = connector_status_connected; | 237 | status = connector_status_connected; |
| 209 | else | 238 | else |
| 210 | status = connector_status_disconnected; | 239 | status = connector_status_disconnected; |
| @@ -251,9 +280,11 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, | |||
| 251 | 280 | ||
| 252 | connector = &exynos_connector->drm_connector; | 281 | connector = &exynos_connector->drm_connector; |
| 253 | 282 | ||
| 254 | switch (manager->display->type) { | 283 | switch (manager->display_ops->type) { |
| 255 | case EXYNOS_DISPLAY_TYPE_HDMI: | 284 | case EXYNOS_DISPLAY_TYPE_HDMI: |
| 256 | type = DRM_MODE_CONNECTOR_HDMIA; | 285 | type = DRM_MODE_CONNECTOR_HDMIA; |
| 286 | connector->interlace_allowed = true; | ||
| 287 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
| 257 | break; | 288 | break; |
| 258 | default: | 289 | default: |
| 259 | type = DRM_MODE_CONNECTOR_Unknown; | 290 | type = DRM_MODE_CONNECTOR_Unknown; |
| @@ -267,7 +298,10 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, | |||
| 267 | if (err) | 298 | if (err) |
| 268 | goto err_connector; | 299 | goto err_connector; |
| 269 | 300 | ||
| 301 | exynos_connector->encoder_id = encoder->base.id; | ||
| 302 | exynos_connector->manager = manager; | ||
| 270 | connector->encoder = encoder; | 303 | connector->encoder = encoder; |
| 304 | |||
| 271 | err = drm_mode_connector_attach_encoder(connector, encoder); | 305 | err = drm_mode_connector_attach_encoder(connector, encoder); |
| 272 | if (err) { | 306 | if (err) { |
| 273 | DRM_ERROR("failed to attach a connector to a encoder\n"); | 307 | DRM_ERROR("failed to attach a connector to a encoder\n"); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 9337e5e2dbb6..ee43cc220853 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
| @@ -29,36 +29,17 @@ | |||
| 29 | #include "drmP.h" | 29 | #include "drmP.h" |
| 30 | #include "drm_crtc_helper.h" | 30 | #include "drm_crtc_helper.h" |
| 31 | 31 | ||
| 32 | #include "exynos_drm_crtc.h" | ||
| 32 | #include "exynos_drm_drv.h" | 33 | #include "exynos_drm_drv.h" |
| 33 | #include "exynos_drm_fb.h" | 34 | #include "exynos_drm_fb.h" |
| 34 | #include "exynos_drm_encoder.h" | 35 | #include "exynos_drm_encoder.h" |
| 36 | #include "exynos_drm_gem.h" | ||
| 35 | #include "exynos_drm_buf.h" | 37 | #include "exynos_drm_buf.h" |
| 36 | 38 | ||
| 37 | #define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ | 39 | #define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ |
| 38 | drm_crtc) | 40 | drm_crtc) |
| 39 | 41 | ||
| 40 | /* | 42 | /* |
| 41 | * Exynos specific crtc postion structure. | ||
| 42 | * | ||
| 43 | * @fb_x: offset x on a framebuffer to be displyed | ||
| 44 | * - the unit is screen coordinates. | ||
| 45 | * @fb_y: offset y on a framebuffer to be displayed | ||
| 46 | * - the unit is screen coordinates. | ||
| 47 | * @crtc_x: offset x on hardware screen. | ||
| 48 | * @crtc_y: offset y on hardware screen. | ||
| 49 | * @crtc_w: width of hardware screen. | ||
| 50 | * @crtc_h: height of hardware screen. | ||
| 51 | */ | ||
| 52 | struct exynos_drm_crtc_pos { | ||
| 53 | unsigned int fb_x; | ||
| 54 | unsigned int fb_y; | ||
| 55 | unsigned int crtc_x; | ||
| 56 | unsigned int crtc_y; | ||
| 57 | unsigned int crtc_w; | ||
| 58 | unsigned int crtc_h; | ||
| 59 | }; | ||
| 60 | |||
| 61 | /* | ||
| 62 | * Exynos specific crtc structure. | 43 | * Exynos specific crtc structure. |
| 63 | * | 44 | * |
| 64 | * @drm_crtc: crtc object. | 45 | * @drm_crtc: crtc object. |
| @@ -85,30 +66,31 @@ static void exynos_drm_crtc_apply(struct drm_crtc *crtc) | |||
| 85 | 66 | ||
| 86 | exynos_drm_fn_encoder(crtc, overlay, | 67 | exynos_drm_fn_encoder(crtc, overlay, |
| 87 | exynos_drm_encoder_crtc_mode_set); | 68 | exynos_drm_encoder_crtc_mode_set); |
| 88 | exynos_drm_fn_encoder(crtc, NULL, exynos_drm_encoder_crtc_commit); | 69 | exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, |
| 70 | exynos_drm_encoder_crtc_commit); | ||
| 89 | } | 71 | } |
| 90 | 72 | ||
| 91 | static int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, | 73 | int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, |
| 92 | struct drm_framebuffer *fb, | 74 | struct drm_framebuffer *fb, |
| 93 | struct drm_display_mode *mode, | 75 | struct drm_display_mode *mode, |
| 94 | struct exynos_drm_crtc_pos *pos) | 76 | struct exynos_drm_crtc_pos *pos) |
| 95 | { | 77 | { |
| 96 | struct exynos_drm_buf_entry *entry; | 78 | struct exynos_drm_gem_buf *buffer; |
| 97 | unsigned int actual_w; | 79 | unsigned int actual_w; |
| 98 | unsigned int actual_h; | 80 | unsigned int actual_h; |
| 99 | 81 | ||
| 100 | entry = exynos_drm_fb_get_buf(fb); | 82 | buffer = exynos_drm_fb_get_buf(fb); |
| 101 | if (!entry) { | 83 | if (!buffer) { |
| 102 | DRM_LOG_KMS("entry is null.\n"); | 84 | DRM_LOG_KMS("buffer is null.\n"); |
| 103 | return -EFAULT; | 85 | return -EFAULT; |
| 104 | } | 86 | } |
| 105 | 87 | ||
| 106 | overlay->paddr = entry->paddr; | 88 | overlay->dma_addr = buffer->dma_addr; |
| 107 | overlay->vaddr = entry->vaddr; | 89 | overlay->vaddr = buffer->kvaddr; |
| 108 | 90 | ||
| 109 | DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n", | 91 | DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", |
| 110 | (unsigned long)overlay->vaddr, | 92 | (unsigned long)overlay->vaddr, |
| 111 | (unsigned long)overlay->paddr); | 93 | (unsigned long)overlay->dma_addr); |
| 112 | 94 | ||
| 113 | actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w); | 95 | actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w); |
| 114 | actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h); | 96 | actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h); |
| @@ -171,9 +153,26 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc) | |||
| 171 | 153 | ||
| 172 | static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) | 154 | static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) |
| 173 | { | 155 | { |
| 174 | DRM_DEBUG_KMS("%s\n", __FILE__); | 156 | struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); |
| 175 | 157 | ||
| 176 | /* TODO */ | 158 | DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); |
| 159 | |||
| 160 | switch (mode) { | ||
| 161 | case DRM_MODE_DPMS_ON: | ||
| 162 | exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, | ||
| 163 | exynos_drm_encoder_crtc_commit); | ||
| 164 | break; | ||
| 165 | case DRM_MODE_DPMS_STANDBY: | ||
| 166 | case DRM_MODE_DPMS_SUSPEND: | ||
| 167 | case DRM_MODE_DPMS_OFF: | ||
| 168 | /* TODO */ | ||
| 169 | exynos_drm_fn_encoder(crtc, NULL, | ||
| 170 | exynos_drm_encoder_crtc_disable); | ||
| 171 | break; | ||
| 172 | default: | ||
| 173 | DRM_DEBUG_KMS("unspecified mode %d\n", mode); | ||
| 174 | break; | ||
| 175 | } | ||
| 177 | } | 176 | } |
| 178 | 177 | ||
| 179 | static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) | 178 | static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) |
| @@ -185,9 +184,12 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) | |||
| 185 | 184 | ||
| 186 | static void exynos_drm_crtc_commit(struct drm_crtc *crtc) | 185 | static void exynos_drm_crtc_commit(struct drm_crtc *crtc) |
| 187 | { | 186 | { |
| 187 | struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); | ||
| 188 | |||
| 188 | DRM_DEBUG_KMS("%s\n", __FILE__); | 189 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 189 | 190 | ||
| 190 | /* drm framework doesn't check NULL. */ | 191 | exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, |
| 192 | exynos_drm_encoder_crtc_commit); | ||
| 191 | } | 193 | } |
| 192 | 194 | ||
| 193 | static bool | 195 | static bool |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h index c584042d6d2c..25f72a62cb88 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h | |||
| @@ -35,4 +35,29 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr); | |||
| 35 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc); | 35 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc); |
| 36 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); | 36 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); |
| 37 | 37 | ||
| 38 | /* | ||
| 39 | * Exynos specific crtc postion structure. | ||
| 40 | * | ||
| 41 | * @fb_x: offset x on a framebuffer to be displyed | ||
| 42 | * - the unit is screen coordinates. | ||
| 43 | * @fb_y: offset y on a framebuffer to be displayed | ||
| 44 | * - the unit is screen coordinates. | ||
| 45 | * @crtc_x: offset x on hardware screen. | ||
| 46 | * @crtc_y: offset y on hardware screen. | ||
| 47 | * @crtc_w: width of hardware screen. | ||
| 48 | * @crtc_h: height of hardware screen. | ||
| 49 | */ | ||
| 50 | struct exynos_drm_crtc_pos { | ||
| 51 | unsigned int fb_x; | ||
| 52 | unsigned int fb_y; | ||
| 53 | unsigned int crtc_x; | ||
| 54 | unsigned int crtc_y; | ||
| 55 | unsigned int crtc_w; | ||
| 56 | unsigned int crtc_h; | ||
| 57 | }; | ||
| 58 | |||
| 59 | int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, | ||
| 60 | struct drm_framebuffer *fb, | ||
| 61 | struct drm_display_mode *mode, | ||
| 62 | struct exynos_drm_crtc_pos *pos); | ||
| 38 | #endif | 63 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 83810cbe3c17..53e2216de61d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | #include "drmP.h" | 28 | #include "drmP.h" |
| 29 | #include "drm.h" | 29 | #include "drm.h" |
| 30 | #include "drm_crtc_helper.h" | ||
| 30 | 31 | ||
| 31 | #include <drm/exynos_drm.h> | 32 | #include <drm/exynos_drm.h> |
| 32 | 33 | ||
| @@ -61,6 +62,9 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) | |||
| 61 | 62 | ||
| 62 | drm_mode_config_init(dev); | 63 | drm_mode_config_init(dev); |
| 63 | 64 | ||
| 65 | /* init kms poll for handling hpd */ | ||
| 66 | drm_kms_helper_poll_init(dev); | ||
| 67 | |||
| 64 | exynos_drm_mode_config_init(dev); | 68 | exynos_drm_mode_config_init(dev); |
| 65 | 69 | ||
| 66 | /* | 70 | /* |
| @@ -116,6 +120,7 @@ static int exynos_drm_unload(struct drm_device *dev) | |||
| 116 | exynos_drm_fbdev_fini(dev); | 120 | exynos_drm_fbdev_fini(dev); |
| 117 | exynos_drm_device_unregister(dev); | 121 | exynos_drm_device_unregister(dev); |
| 118 | drm_vblank_cleanup(dev); | 122 | drm_vblank_cleanup(dev); |
| 123 | drm_kms_helper_poll_fini(dev); | ||
| 119 | drm_mode_config_cleanup(dev); | 124 | drm_mode_config_cleanup(dev); |
| 120 | kfree(dev->dev_private); | 125 | kfree(dev->dev_private); |
| 121 | 126 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index c03683f2ae72..5e02e6ecc2e0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #ifndef _EXYNOS_DRM_DRV_H_ | 29 | #ifndef _EXYNOS_DRM_DRV_H_ |
| 30 | #define _EXYNOS_DRM_DRV_H_ | 30 | #define _EXYNOS_DRM_DRV_H_ |
| 31 | 31 | ||
| 32 | #include <linux/module.h> | ||
| 32 | #include "drm.h" | 33 | #include "drm.h" |
| 33 | 34 | ||
| 34 | #define MAX_CRTC 2 | 35 | #define MAX_CRTC 2 |
| @@ -79,8 +80,8 @@ struct exynos_drm_overlay_ops { | |||
| 79 | * @scan_flag: interlace or progressive way. | 80 | * @scan_flag: interlace or progressive way. |
| 80 | * (it could be DRM_MODE_FLAG_*) | 81 | * (it could be DRM_MODE_FLAG_*) |
| 81 | * @bpp: pixel size.(in bit) | 82 | * @bpp: pixel size.(in bit) |
| 82 | * @paddr: bus(accessed by dma) physical memory address to this overlay | 83 | * @dma_addr: bus(accessed by dma) address to the memory region allocated |
| 83 | * and this is physically continuous. | 84 | * for a overlay. |
| 84 | * @vaddr: virtual memory addresss to this overlay. | 85 | * @vaddr: virtual memory addresss to this overlay. |
| 85 | * @default_win: a window to be enabled. | 86 | * @default_win: a window to be enabled. |
| 86 | * @color_key: color key on or off. | 87 | * @color_key: color key on or off. |
| @@ -108,7 +109,7 @@ struct exynos_drm_overlay { | |||
| 108 | unsigned int scan_flag; | 109 | unsigned int scan_flag; |
| 109 | unsigned int bpp; | 110 | unsigned int bpp; |
| 110 | unsigned int pitch; | 111 | unsigned int pitch; |
| 111 | dma_addr_t paddr; | 112 | dma_addr_t dma_addr; |
| 112 | void __iomem *vaddr; | 113 | void __iomem *vaddr; |
| 113 | 114 | ||
| 114 | bool default_win; | 115 | bool default_win; |
| @@ -130,7 +131,7 @@ struct exynos_drm_overlay { | |||
| 130 | * @check_timing: check if timing is valid or not. | 131 | * @check_timing: check if timing is valid or not. |
| 131 | * @power_on: display device on or off. | 132 | * @power_on: display device on or off. |
| 132 | */ | 133 | */ |
| 133 | struct exynos_drm_display { | 134 | struct exynos_drm_display_ops { |
| 134 | enum exynos_drm_output_type type; | 135 | enum exynos_drm_output_type type; |
| 135 | bool (*is_connected)(struct device *dev); | 136 | bool (*is_connected)(struct device *dev); |
| 136 | int (*get_edid)(struct device *dev, struct drm_connector *connector, | 137 | int (*get_edid)(struct device *dev, struct drm_connector *connector, |
| @@ -146,12 +147,14 @@ struct exynos_drm_display { | |||
| 146 | * @mode_set: convert drm_display_mode to hw specific display mode and | 147 | * @mode_set: convert drm_display_mode to hw specific display mode and |
| 147 | * would be called by encoder->mode_set(). | 148 | * would be called by encoder->mode_set(). |
| 148 | * @commit: set current hw specific display mode to hw. | 149 | * @commit: set current hw specific display mode to hw. |
| 150 | * @disable: disable hardware specific display mode. | ||
| 149 | * @enable_vblank: specific driver callback for enabling vblank interrupt. | 151 | * @enable_vblank: specific driver callback for enabling vblank interrupt. |
| 150 | * @disable_vblank: specific driver callback for disabling vblank interrupt. | 152 | * @disable_vblank: specific driver callback for disabling vblank interrupt. |
| 151 | */ | 153 | */ |
| 152 | struct exynos_drm_manager_ops { | 154 | struct exynos_drm_manager_ops { |
| 153 | void (*mode_set)(struct device *subdrv_dev, void *mode); | 155 | void (*mode_set)(struct device *subdrv_dev, void *mode); |
| 154 | void (*commit)(struct device *subdrv_dev); | 156 | void (*commit)(struct device *subdrv_dev); |
| 157 | void (*disable)(struct device *subdrv_dev); | ||
| 155 | int (*enable_vblank)(struct device *subdrv_dev); | 158 | int (*enable_vblank)(struct device *subdrv_dev); |
| 156 | void (*disable_vblank)(struct device *subdrv_dev); | 159 | void (*disable_vblank)(struct device *subdrv_dev); |
| 157 | }; | 160 | }; |
| @@ -178,7 +181,7 @@ struct exynos_drm_manager { | |||
| 178 | int pipe; | 181 | int pipe; |
| 179 | struct exynos_drm_manager_ops *ops; | 182 | struct exynos_drm_manager_ops *ops; |
| 180 | struct exynos_drm_overlay_ops *overlay_ops; | 183 | struct exynos_drm_overlay_ops *overlay_ops; |
| 181 | struct exynos_drm_display *display; | 184 | struct exynos_drm_display_ops *display_ops; |
| 182 | }; | 185 | }; |
| 183 | 186 | ||
| 184 | /* | 187 | /* |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 7cf6fa86a67e..153061415baf 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c | |||
| @@ -53,15 +53,36 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
| 53 | struct drm_device *dev = encoder->dev; | 53 | struct drm_device *dev = encoder->dev; |
| 54 | struct drm_connector *connector; | 54 | struct drm_connector *connector; |
| 55 | struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); | 55 | struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); |
| 56 | struct exynos_drm_manager_ops *manager_ops = manager->ops; | ||
| 56 | 57 | ||
| 57 | DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode); | 58 | DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode); |
| 58 | 59 | ||
| 60 | switch (mode) { | ||
| 61 | case DRM_MODE_DPMS_ON: | ||
| 62 | if (manager_ops && manager_ops->commit) | ||
| 63 | manager_ops->commit(manager->dev); | ||
| 64 | break; | ||
| 65 | case DRM_MODE_DPMS_STANDBY: | ||
| 66 | case DRM_MODE_DPMS_SUSPEND: | ||
| 67 | case DRM_MODE_DPMS_OFF: | ||
| 68 | /* TODO */ | ||
| 69 | if (manager_ops && manager_ops->disable) | ||
| 70 | manager_ops->disable(manager->dev); | ||
| 71 | break; | ||
| 72 | default: | ||
| 73 | DRM_ERROR("unspecified mode %d\n", mode); | ||
| 74 | break; | ||
| 75 | } | ||
| 76 | |||
| 59 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 77 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 60 | if (connector->encoder == encoder) { | 78 | if (connector->encoder == encoder) { |
| 61 | struct exynos_drm_display *display = manager->display; | 79 | struct exynos_drm_display_ops *display_ops = |
| 80 | manager->display_ops; | ||
| 62 | 81 | ||
| 63 | if (display && display->power_on) | 82 | DRM_DEBUG_KMS("connector[%d] dpms[%d]\n", |
| 64 | display->power_on(manager->dev, mode); | 83 | connector->base.id, mode); |
| 84 | if (display_ops && display_ops->power_on) | ||
| 85 | display_ops->power_on(manager->dev, mode); | ||
| 65 | } | 86 | } |
| 66 | } | 87 | } |
| 67 | } | 88 | } |
| @@ -116,15 +137,11 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder) | |||
| 116 | { | 137 | { |
| 117 | struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); | 138 | struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); |
| 118 | struct exynos_drm_manager_ops *manager_ops = manager->ops; | 139 | struct exynos_drm_manager_ops *manager_ops = manager->ops; |
| 119 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; | ||
| 120 | 140 | ||
| 121 | DRM_DEBUG_KMS("%s\n", __FILE__); | 141 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 122 | 142 | ||
| 123 | if (manager_ops && manager_ops->commit) | 143 | if (manager_ops && manager_ops->commit) |
| 124 | manager_ops->commit(manager->dev); | 144 | manager_ops->commit(manager->dev); |
| 125 | |||
| 126 | if (overlay_ops && overlay_ops->commit) | ||
| 127 | overlay_ops->commit(manager->dev); | ||
| 128 | } | 145 | } |
| 129 | 146 | ||
| 130 | static struct drm_crtc * | 147 | static struct drm_crtc * |
| @@ -208,10 +225,23 @@ void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, | |||
| 208 | { | 225 | { |
| 209 | struct drm_device *dev = crtc->dev; | 226 | struct drm_device *dev = crtc->dev; |
| 210 | struct drm_encoder *encoder; | 227 | struct drm_encoder *encoder; |
| 228 | struct exynos_drm_private *private = dev->dev_private; | ||
| 229 | struct exynos_drm_manager *manager; | ||
| 211 | 230 | ||
| 212 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 231 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
| 213 | if (encoder->crtc != crtc) | 232 | /* |
| 214 | continue; | 233 | * if crtc is detached from encoder, check pipe, |
| 234 | * otherwise check crtc attached to encoder | ||
| 235 | */ | ||
| 236 | if (!encoder->crtc) { | ||
| 237 | manager = to_exynos_encoder(encoder)->manager; | ||
| 238 | if (manager->pipe < 0 || | ||
| 239 | private->crtc[manager->pipe] != crtc) | ||
| 240 | continue; | ||
| 241 | } else { | ||
| 242 | if (encoder->crtc != crtc) | ||
| 243 | continue; | ||
| 244 | } | ||
| 215 | 245 | ||
| 216 | fn(encoder, data); | 246 | fn(encoder, data); |
| 217 | } | 247 | } |
| @@ -250,8 +280,18 @@ void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) | |||
| 250 | struct exynos_drm_manager *manager = | 280 | struct exynos_drm_manager *manager = |
| 251 | to_exynos_encoder(encoder)->manager; | 281 | to_exynos_encoder(encoder)->manager; |
| 252 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; | 282 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; |
| 283 | int crtc = *(int *)data; | ||
| 284 | |||
| 285 | DRM_DEBUG_KMS("%s\n", __FILE__); | ||
| 286 | |||
| 287 | /* | ||
| 288 | * when crtc is detached from encoder, this pipe is used | ||
| 289 | * to select manager operation | ||
| 290 | */ | ||
| 291 | manager->pipe = crtc; | ||
| 253 | 292 | ||
| 254 | overlay_ops->commit(manager->dev); | 293 | if (overlay_ops && overlay_ops->commit) |
| 294 | overlay_ops->commit(manager->dev); | ||
| 255 | } | 295 | } |
| 256 | 296 | ||
| 257 | void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data) | 297 | void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data) |
| @@ -261,7 +301,28 @@ void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data) | |||
| 261 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; | 301 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; |
| 262 | struct exynos_drm_overlay *overlay = data; | 302 | struct exynos_drm_overlay *overlay = data; |
| 263 | 303 | ||
| 264 | overlay_ops->mode_set(manager->dev, overlay); | 304 | if (overlay_ops && overlay_ops->mode_set) |
| 305 | overlay_ops->mode_set(manager->dev, overlay); | ||
| 306 | } | ||
| 307 | |||
| 308 | void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data) | ||
| 309 | { | ||
| 310 | struct exynos_drm_manager *manager = | ||
| 311 | to_exynos_encoder(encoder)->manager; | ||
| 312 | struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; | ||
| 313 | |||
| 314 | DRM_DEBUG_KMS("\n"); | ||
| 315 | |||
| 316 | if (overlay_ops && overlay_ops->disable) | ||
| 317 | overlay_ops->disable(manager->dev); | ||
| 318 | |||
| 319 | /* | ||
| 320 | * crtc is already detached from encoder and last | ||
| 321 | * function for detaching is properly done, so | ||
| 322 | * clear pipe from manager to prevent repeated call | ||
| 323 | */ | ||
| 324 | if (!encoder->crtc) | ||
| 325 | manager->pipe = -1; | ||
| 265 | } | 326 | } |
| 266 | 327 | ||
| 267 | MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); | 328 | MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h index 5ecd645d06a9..a22acfbf0e4e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h | |||
| @@ -41,5 +41,6 @@ void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); | |||
| 41 | void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); | 41 | void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); |
| 42 | void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data); | 42 | void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data); |
| 43 | void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data); | 43 | void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data); |
| 44 | void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data); | ||
| 44 | 45 | ||
| 45 | #endif | 46 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 48d29cfd5240..5bf4a1ac7f82 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c | |||
| @@ -29,7 +29,9 @@ | |||
| 29 | #include "drmP.h" | 29 | #include "drmP.h" |
| 30 | #include "drm_crtc.h" | 30 | #include "drm_crtc.h" |
| 31 | #include "drm_crtc_helper.h" | 31 | #include "drm_crtc_helper.h" |
| 32 | #include "drm_fb_helper.h" | ||
| 32 | 33 | ||
| 34 | #include "exynos_drm_drv.h" | ||
| 33 | #include "exynos_drm_fb.h" | 35 | #include "exynos_drm_fb.h" |
| 34 | #include "exynos_drm_buf.h" | 36 | #include "exynos_drm_buf.h" |
| 35 | #include "exynos_drm_gem.h" | 37 | #include "exynos_drm_gem.h" |
| @@ -41,14 +43,14 @@ | |||
| 41 | * | 43 | * |
| 42 | * @fb: drm framebuffer obejct. | 44 | * @fb: drm framebuffer obejct. |
| 43 | * @exynos_gem_obj: exynos specific gem object containing a gem object. | 45 | * @exynos_gem_obj: exynos specific gem object containing a gem object. |
| 44 | * @entry: pointer to exynos drm buffer entry object. | 46 | * @buffer: pointer to exynos_drm_gem_buffer object. |
| 45 | * - containing only the information to physically continuous memory | 47 | * - contain the memory information to memory region allocated |
| 46 | * region allocated at default framebuffer creation. | 48 | * at default framebuffer creation. |
| 47 | */ | 49 | */ |
| 48 | struct exynos_drm_fb { | 50 | struct exynos_drm_fb { |
| 49 | struct drm_framebuffer fb; | 51 | struct drm_framebuffer fb; |
| 50 | struct exynos_drm_gem_obj *exynos_gem_obj; | 52 | struct exynos_drm_gem_obj *exynos_gem_obj; |
| 51 | struct exynos_drm_buf_entry *entry; | 53 | struct exynos_drm_gem_buf *buffer; |
| 52 | }; | 54 | }; |
| 53 | 55 | ||
| 54 | static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) | 56 | static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) |
| @@ -63,8 +65,8 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) | |||
| 63 | * default framebuffer has no gem object so | 65 | * default framebuffer has no gem object so |
| 64 | * a buffer of the default framebuffer should be released at here. | 66 | * a buffer of the default framebuffer should be released at here. |
| 65 | */ | 67 | */ |
| 66 | if (!exynos_fb->exynos_gem_obj && exynos_fb->entry) | 68 | if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer) |
| 67 | exynos_drm_buf_destroy(fb->dev, exynos_fb->entry); | 69 | exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer); |
| 68 | 70 | ||
| 69 | kfree(exynos_fb); | 71 | kfree(exynos_fb); |
| 70 | exynos_fb = NULL; | 72 | exynos_fb = NULL; |
| @@ -143,29 +145,29 @@ exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev, | |||
| 143 | */ | 145 | */ |
| 144 | if (!mode_cmd->handle) { | 146 | if (!mode_cmd->handle) { |
| 145 | if (!file_priv) { | 147 | if (!file_priv) { |
| 146 | struct exynos_drm_buf_entry *entry; | 148 | struct exynos_drm_gem_buf *buffer; |
| 147 | 149 | ||
| 148 | /* | 150 | /* |
| 149 | * in case that file_priv is NULL, it allocates | 151 | * in case that file_priv is NULL, it allocates |
| 150 | * only buffer and this buffer would be used | 152 | * only buffer and this buffer would be used |
| 151 | * for default framebuffer. | 153 | * for default framebuffer. |
| 152 | */ | 154 | */ |
| 153 | entry = exynos_drm_buf_create(dev, size); | 155 | buffer = exynos_drm_buf_create(dev, size); |
| 154 | if (IS_ERR(entry)) { | 156 | if (IS_ERR(buffer)) { |
| 155 | ret = PTR_ERR(entry); | 157 | ret = PTR_ERR(buffer); |
| 156 | goto err_buffer; | 158 | goto err_buffer; |
| 157 | } | 159 | } |
| 158 | 160 | ||
| 159 | exynos_fb->entry = entry; | 161 | exynos_fb->buffer = buffer; |
| 160 | 162 | ||
| 161 | DRM_LOG_KMS("default fb: paddr = 0x%lx, size = 0x%x\n", | 163 | DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n", |
| 162 | (unsigned long)entry->paddr, size); | 164 | (unsigned long)buffer->dma_addr, size); |
| 163 | 165 | ||
| 164 | goto out; | 166 | goto out; |
| 165 | } else { | 167 | } else { |
| 166 | exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, | 168 | exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, |
| 167 | size, | 169 | &mode_cmd->handle, |
| 168 | &mode_cmd->handle); | 170 | size); |
| 169 | if (IS_ERR(exynos_gem_obj)) { | 171 | if (IS_ERR(exynos_gem_obj)) { |
| 170 | ret = PTR_ERR(exynos_gem_obj); | 172 | ret = PTR_ERR(exynos_gem_obj); |
| 171 | goto err_buffer; | 173 | goto err_buffer; |
| @@ -189,10 +191,10 @@ exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev, | |||
| 189 | * so that default framebuffer has no its own gem object, | 191 | * so that default framebuffer has no its own gem object, |
| 190 | * only its own buffer object. | 192 | * only its own buffer object. |
| 191 | */ | 193 | */ |
| 192 | exynos_fb->entry = exynos_gem_obj->entry; | 194 | exynos_fb->buffer = exynos_gem_obj->buffer; |
| 193 | 195 | ||
| 194 | DRM_LOG_KMS("paddr = 0x%lx, size = 0x%x, gem object = 0x%x\n", | 196 | DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n", |
| 195 | (unsigned long)exynos_fb->entry->paddr, size, | 197 | (unsigned long)exynos_fb->buffer->dma_addr, size, |
| 196 | (unsigned int)&exynos_gem_obj->base); | 198 | (unsigned int)&exynos_gem_obj->base); |
| 197 | 199 | ||
| 198 | out: | 200 | out: |
| @@ -220,26 +222,36 @@ struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev, | |||
| 220 | return exynos_drm_fb_init(file_priv, dev, mode_cmd); | 222 | return exynos_drm_fb_init(file_priv, dev, mode_cmd); |
| 221 | } | 223 | } |
| 222 | 224 | ||
| 223 | struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb) | 225 | struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb) |
| 224 | { | 226 | { |
| 225 | struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); | 227 | struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); |
| 226 | struct exynos_drm_buf_entry *entry; | 228 | struct exynos_drm_gem_buf *buffer; |
| 227 | 229 | ||
| 228 | DRM_DEBUG_KMS("%s\n", __FILE__); | 230 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 229 | 231 | ||
| 230 | entry = exynos_fb->entry; | 232 | buffer = exynos_fb->buffer; |
| 231 | if (!entry) | 233 | if (!buffer) |
| 232 | return NULL; | 234 | return NULL; |
| 233 | 235 | ||
| 234 | DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n", | 236 | DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", |
| 235 | (unsigned long)entry->vaddr, | 237 | (unsigned long)buffer->kvaddr, |
| 236 | (unsigned long)entry->paddr); | 238 | (unsigned long)buffer->dma_addr); |
| 237 | 239 | ||
| 238 | return entry; | 240 | return buffer; |
| 241 | } | ||
| 242 | |||
| 243 | static void exynos_drm_output_poll_changed(struct drm_device *dev) | ||
| 244 | { | ||
| 245 | struct exynos_drm_private *private = dev->dev_private; | ||
| 246 | struct drm_fb_helper *fb_helper = private->fb_helper; | ||
| 247 | |||
| 248 | if (fb_helper) | ||
| 249 | drm_fb_helper_hotplug_event(fb_helper); | ||
| 239 | } | 250 | } |
| 240 | 251 | ||
| 241 | static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { | 252 | static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { |
| 242 | .fb_create = exynos_drm_fb_create, | 253 | .fb_create = exynos_drm_fb_create, |
| 254 | .output_poll_changed = exynos_drm_output_poll_changed, | ||
| 243 | }; | 255 | }; |
| 244 | 256 | ||
| 245 | void exynos_drm_mode_config_init(struct drm_device *dev) | 257 | void exynos_drm_mode_config_init(struct drm_device *dev) |
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"); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 4659c88cdd9b..db3b3d9e731d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
| @@ -64,7 +64,7 @@ struct fimd_win_data { | |||
| 64 | unsigned int fb_width; | 64 | unsigned int fb_width; |
| 65 | unsigned int fb_height; | 65 | unsigned int fb_height; |
| 66 | unsigned int bpp; | 66 | unsigned int bpp; |
| 67 | dma_addr_t paddr; | 67 | dma_addr_t dma_addr; |
| 68 | void __iomem *vaddr; | 68 | void __iomem *vaddr; |
| 69 | unsigned int buf_offsize; | 69 | unsigned int buf_offsize; |
| 70 | unsigned int line_size; /* bytes */ | 70 | unsigned int line_size; /* bytes */ |
| @@ -124,7 +124,7 @@ static int fimd_display_power_on(struct device *dev, int mode) | |||
| 124 | return 0; | 124 | return 0; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static struct exynos_drm_display fimd_display = { | 127 | static struct exynos_drm_display_ops fimd_display_ops = { |
| 128 | .type = EXYNOS_DISPLAY_TYPE_LCD, | 128 | .type = EXYNOS_DISPLAY_TYPE_LCD, |
| 129 | .is_connected = fimd_display_is_connected, | 129 | .is_connected = fimd_display_is_connected, |
| 130 | .get_timing = fimd_get_timing, | 130 | .get_timing = fimd_get_timing, |
| @@ -177,6 +177,40 @@ static void fimd_commit(struct device *dev) | |||
| 177 | writel(val, ctx->regs + VIDCON0); | 177 | writel(val, ctx->regs + VIDCON0); |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | static void fimd_disable(struct device *dev) | ||
| 181 | { | ||
| 182 | struct fimd_context *ctx = get_fimd_context(dev); | ||
| 183 | struct exynos_drm_subdrv *subdrv = &ctx->subdrv; | ||
| 184 | struct drm_device *drm_dev = subdrv->drm_dev; | ||
| 185 | struct exynos_drm_manager *manager = &subdrv->manager; | ||
| 186 | u32 val; | ||
| 187 | |||
| 188 | DRM_DEBUG_KMS("%s\n", __FILE__); | ||
| 189 | |||
| 190 | /* fimd dma off */ | ||
| 191 | val = readl(ctx->regs + VIDCON0); | ||
| 192 | val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F); | ||
| 193 | writel(val, ctx->regs + VIDCON0); | ||
| 194 | |||
| 195 | /* | ||
| 196 | * if vblank is enabled status with dma off then | ||
| 197 | * it disables vsync interrupt. | ||
| 198 | */ | ||
| 199 | if (drm_dev->vblank_enabled[manager->pipe] && | ||
| 200 | atomic_read(&drm_dev->vblank_refcount[manager->pipe])) { | ||
| 201 | drm_vblank_put(drm_dev, manager->pipe); | ||
| 202 | |||
| 203 | /* | ||
| 204 | * if vblank_disable_allowed is 0 then disable | ||
| 205 | * vsync interrupt right now else the vsync interrupt | ||
| 206 | * would be disabled by drm timer once a current process | ||
| 207 | * gives up ownershop of vblank event. | ||
| 208 | */ | ||
| 209 | if (!drm_dev->vblank_disable_allowed) | ||
| 210 | drm_vblank_off(drm_dev, manager->pipe); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 180 | static int fimd_enable_vblank(struct device *dev) | 214 | static int fimd_enable_vblank(struct device *dev) |
| 181 | { | 215 | { |
| 182 | struct fimd_context *ctx = get_fimd_context(dev); | 216 | struct fimd_context *ctx = get_fimd_context(dev); |
| @@ -220,6 +254,7 @@ static void fimd_disable_vblank(struct device *dev) | |||
| 220 | 254 | ||
| 221 | static struct exynos_drm_manager_ops fimd_manager_ops = { | 255 | static struct exynos_drm_manager_ops fimd_manager_ops = { |
| 222 | .commit = fimd_commit, | 256 | .commit = fimd_commit, |
| 257 | .disable = fimd_disable, | ||
| 223 | .enable_vblank = fimd_enable_vblank, | 258 | .enable_vblank = fimd_enable_vblank, |
| 224 | .disable_vblank = fimd_disable_vblank, | 259 | .disable_vblank = fimd_disable_vblank, |
| 225 | }; | 260 | }; |
| @@ -251,7 +286,7 @@ static void fimd_win_mode_set(struct device *dev, | |||
| 251 | win_data->ovl_height = overlay->crtc_height; | 286 | win_data->ovl_height = overlay->crtc_height; |
| 252 | win_data->fb_width = overlay->fb_width; | 287 | win_data->fb_width = overlay->fb_width; |
| 253 | win_data->fb_height = overlay->fb_height; | 288 | win_data->fb_height = overlay->fb_height; |
| 254 | win_data->paddr = overlay->paddr + offset; | 289 | win_data->dma_addr = overlay->dma_addr + offset; |
| 255 | win_data->vaddr = overlay->vaddr + offset; | 290 | win_data->vaddr = overlay->vaddr + offset; |
| 256 | win_data->bpp = overlay->bpp; | 291 | win_data->bpp = overlay->bpp; |
| 257 | win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * | 292 | win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * |
| @@ -263,7 +298,7 @@ static void fimd_win_mode_set(struct device *dev, | |||
| 263 | DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", | 298 | DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", |
| 264 | win_data->ovl_width, win_data->ovl_height); | 299 | win_data->ovl_width, win_data->ovl_height); |
| 265 | DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n", | 300 | DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n", |
| 266 | (unsigned long)win_data->paddr, | 301 | (unsigned long)win_data->dma_addr, |
| 267 | (unsigned long)win_data->vaddr); | 302 | (unsigned long)win_data->vaddr); |
| 268 | DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", | 303 | DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", |
| 269 | overlay->fb_width, overlay->crtc_width); | 304 | overlay->fb_width, overlay->crtc_width); |
| @@ -376,16 +411,16 @@ static void fimd_win_commit(struct device *dev) | |||
| 376 | writel(val, ctx->regs + SHADOWCON); | 411 | writel(val, ctx->regs + SHADOWCON); |
| 377 | 412 | ||
| 378 | /* buffer start address */ | 413 | /* buffer start address */ |
| 379 | val = win_data->paddr; | 414 | val = (unsigned long)win_data->dma_addr; |
| 380 | writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); | 415 | writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); |
| 381 | 416 | ||
| 382 | /* buffer end address */ | 417 | /* buffer end address */ |
| 383 | size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3); | 418 | size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3); |
| 384 | val = win_data->paddr + size; | 419 | val = (unsigned long)(win_data->dma_addr + size); |
| 385 | writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); | 420 | writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); |
| 386 | 421 | ||
| 387 | DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", | 422 | DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", |
| 388 | (unsigned long)win_data->paddr, val, size); | 423 | (unsigned long)win_data->dma_addr, val, size); |
| 389 | DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", | 424 | DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", |
| 390 | win_data->ovl_width, win_data->ovl_height); | 425 | win_data->ovl_width, win_data->ovl_height); |
| 391 | 426 | ||
| @@ -447,7 +482,6 @@ static void fimd_win_commit(struct device *dev) | |||
| 447 | static void fimd_win_disable(struct device *dev) | 482 | static void fimd_win_disable(struct device *dev) |
| 448 | { | 483 | { |
| 449 | struct fimd_context *ctx = get_fimd_context(dev); | 484 | struct fimd_context *ctx = get_fimd_context(dev); |
| 450 | struct fimd_win_data *win_data; | ||
| 451 | int win = ctx->default_win; | 485 | int win = ctx->default_win; |
| 452 | u32 val; | 486 | u32 val; |
| 453 | 487 | ||
| @@ -456,8 +490,6 @@ static void fimd_win_disable(struct device *dev) | |||
| 456 | if (win < 0 || win > WINDOWS_NR) | 490 | if (win < 0 || win > WINDOWS_NR) |
| 457 | return; | 491 | return; |
| 458 | 492 | ||
| 459 | win_data = &ctx->win_data[win]; | ||
| 460 | |||
| 461 | /* protect windows */ | 493 | /* protect windows */ |
| 462 | val = readl(ctx->regs + SHADOWCON); | 494 | val = readl(ctx->regs + SHADOWCON); |
| 463 | val |= SHADOWCON_WINx_PROTECT(win); | 495 | val |= SHADOWCON_WINx_PROTECT(win); |
| @@ -528,6 +560,16 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) | |||
| 528 | /* VSYNC interrupt */ | 560 | /* VSYNC interrupt */ |
| 529 | writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); | 561 | writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); |
| 530 | 562 | ||
| 563 | /* | ||
| 564 | * in case that vblank_disable_allowed is 1, it could induce | ||
| 565 | * the problem that manager->pipe could be -1 because with | ||
| 566 | * disable callback, vsync interrupt isn't disabled and at this moment, | ||
| 567 | * vsync interrupt could occur. the vsync interrupt would be disabled | ||
| 568 | * by timer handler later. | ||
| 569 | */ | ||
| 570 | if (manager->pipe == -1) | ||
| 571 | return IRQ_HANDLED; | ||
| 572 | |||
| 531 | drm_handle_vblank(drm_dev, manager->pipe); | 573 | drm_handle_vblank(drm_dev, manager->pipe); |
| 532 | fimd_finish_pageflip(drm_dev, manager->pipe); | 574 | fimd_finish_pageflip(drm_dev, manager->pipe); |
| 533 | 575 | ||
| @@ -548,13 +590,6 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev) | |||
| 548 | */ | 590 | */ |
| 549 | drm_dev->irq_enabled = 1; | 591 | drm_dev->irq_enabled = 1; |
| 550 | 592 | ||
| 551 | /* | ||
| 552 | * with vblank_disable_allowed = 1, vblank interrupt will be disabled | ||
| 553 | * by drm timer once a current process gives up ownership of | ||
| 554 | * vblank event.(drm_vblank_put function was called) | ||
| 555 | */ | ||
| 556 | drm_dev->vblank_disable_allowed = 1; | ||
| 557 | |||
| 558 | return 0; | 593 | return 0; |
| 559 | } | 594 | } |
| 560 | 595 | ||
| @@ -731,7 +766,7 @@ static int __devinit fimd_probe(struct platform_device *pdev) | |||
| 731 | subdrv->manager.pipe = -1; | 766 | subdrv->manager.pipe = -1; |
| 732 | subdrv->manager.ops = &fimd_manager_ops; | 767 | subdrv->manager.ops = &fimd_manager_ops; |
| 733 | subdrv->manager.overlay_ops = &fimd_overlay_ops; | 768 | subdrv->manager.overlay_ops = &fimd_overlay_ops; |
| 734 | subdrv->manager.display = &fimd_display; | 769 | subdrv->manager.display_ops = &fimd_display_ops; |
| 735 | subdrv->manager.dev = dev; | 770 | subdrv->manager.dev = dev; |
| 736 | 771 | ||
| 737 | platform_set_drvdata(pdev, ctx); | 772 | platform_set_drvdata(pdev, ctx); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index a8e7a88906ed..aba0fe47f7ea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
| @@ -62,40 +62,28 @@ static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) | |||
| 62 | return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; | 62 | return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv, | 65 | static struct exynos_drm_gem_obj |
| 66 | struct drm_device *dev, unsigned int size, | 66 | *exynos_drm_gem_init(struct drm_device *drm_dev, |
| 67 | unsigned int *handle) | 67 | struct drm_file *file_priv, unsigned int *handle, |
| 68 | unsigned int size) | ||
| 68 | { | 69 | { |
| 69 | struct exynos_drm_gem_obj *exynos_gem_obj; | 70 | struct exynos_drm_gem_obj *exynos_gem_obj; |
| 70 | struct exynos_drm_buf_entry *entry; | ||
| 71 | struct drm_gem_object *obj; | 71 | struct drm_gem_object *obj; |
| 72 | int ret; | 72 | int ret; |
| 73 | 73 | ||
| 74 | DRM_DEBUG_KMS("%s\n", __FILE__); | ||
| 75 | |||
| 76 | size = roundup(size, PAGE_SIZE); | ||
| 77 | |||
| 78 | exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); | 74 | exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); |
| 79 | if (!exynos_gem_obj) { | 75 | if (!exynos_gem_obj) { |
| 80 | DRM_ERROR("failed to allocate exynos gem object.\n"); | 76 | DRM_ERROR("failed to allocate exynos gem object.\n"); |
| 81 | return ERR_PTR(-ENOMEM); | 77 | return ERR_PTR(-ENOMEM); |
| 82 | } | 78 | } |
| 83 | 79 | ||
| 84 | /* allocate the new buffer object and memory region. */ | ||
| 85 | entry = exynos_drm_buf_create(dev, size); | ||
| 86 | if (!entry) { | ||
| 87 | kfree(exynos_gem_obj); | ||
| 88 | return ERR_PTR(-ENOMEM); | ||
| 89 | } | ||
| 90 | |||
| 91 | exynos_gem_obj->entry = entry; | ||
| 92 | |||
| 93 | obj = &exynos_gem_obj->base; | 80 | obj = &exynos_gem_obj->base; |
| 94 | 81 | ||
| 95 | ret = drm_gem_object_init(dev, obj, size); | 82 | ret = drm_gem_object_init(drm_dev, obj, size); |
| 96 | if (ret < 0) { | 83 | if (ret < 0) { |
| 97 | DRM_ERROR("failed to initailize gem object.\n"); | 84 | DRM_ERROR("failed to initialize gem object.\n"); |
| 98 | goto err_obj_init; | 85 | ret = -EINVAL; |
| 86 | goto err_object_init; | ||
| 99 | } | 87 | } |
| 100 | 88 | ||
| 101 | DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); | 89 | DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); |
| @@ -127,24 +115,50 @@ err_handle_create: | |||
| 127 | err_create_mmap_offset: | 115 | err_create_mmap_offset: |
| 128 | drm_gem_object_release(obj); | 116 | drm_gem_object_release(obj); |
| 129 | 117 | ||
| 130 | err_obj_init: | 118 | err_object_init: |
| 131 | exynos_drm_buf_destroy(dev, exynos_gem_obj->entry); | ||
| 132 | |||
| 133 | kfree(exynos_gem_obj); | 119 | kfree(exynos_gem_obj); |
| 134 | 120 | ||
| 135 | return ERR_PTR(ret); | 121 | return ERR_PTR(ret); |
| 136 | } | 122 | } |
| 137 | 123 | ||
| 124 | struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, | ||
| 125 | struct drm_file *file_priv, | ||
| 126 | unsigned int *handle, unsigned long size) | ||
| 127 | { | ||
| 128 | |||
| 129 | struct exynos_drm_gem_obj *exynos_gem_obj = NULL; | ||
| 130 | struct exynos_drm_gem_buf *buffer; | ||
| 131 | |||
| 132 | size = roundup(size, PAGE_SIZE); | ||
| 133 | |||
| 134 | DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size); | ||
| 135 | |||
| 136 | buffer = exynos_drm_buf_create(dev, size); | ||
| 137 | if (IS_ERR(buffer)) { | ||
| 138 | return ERR_CAST(buffer); | ||
| 139 | } | ||
| 140 | |||
| 141 | exynos_gem_obj = exynos_drm_gem_init(dev, file_priv, handle, size); | ||
| 142 | if (IS_ERR(exynos_gem_obj)) { | ||
| 143 | exynos_drm_buf_destroy(dev, buffer); | ||
| 144 | return exynos_gem_obj; | ||
| 145 | } | ||
| 146 | |||
| 147 | exynos_gem_obj->buffer = buffer; | ||
| 148 | |||
| 149 | return exynos_gem_obj; | ||
| 150 | } | ||
| 151 | |||
| 138 | int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, | 152 | int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, |
| 139 | struct drm_file *file_priv) | 153 | struct drm_file *file_priv) |
| 140 | { | 154 | { |
| 141 | struct drm_exynos_gem_create *args = data; | 155 | struct drm_exynos_gem_create *args = data; |
| 142 | struct exynos_drm_gem_obj *exynos_gem_obj; | 156 | struct exynos_drm_gem_obj *exynos_gem_obj = NULL; |
| 143 | 157 | ||
| 144 | DRM_DEBUG_KMS("%s : size = 0x%x\n", __FILE__, args->size); | 158 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| 145 | 159 | ||
| 146 | exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size, | 160 | exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, |
| 147 | &args->handle); | 161 | &args->handle, args->size); |
| 148 | if (IS_ERR(exynos_gem_obj)) | 162 | if (IS_ERR(exynos_gem_obj)) |
| 149 | return PTR_ERR(exynos_gem_obj); | 163 | return PTR_ERR(exynos_gem_obj); |
| 150 | 164 | ||
| @@ -175,7 +189,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp, | |||
| 175 | { | 189 | { |
| 176 | struct drm_gem_object *obj = filp->private_data; | 190 | struct drm_gem_object *obj = filp->private_data; |
| 177 | struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); | 191 | struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); |
| 178 | struct exynos_drm_buf_entry *entry; | 192 | struct exynos_drm_gem_buf *buffer; |
| 179 | unsigned long pfn, vm_size; | 193 | unsigned long pfn, vm_size; |
| 180 | 194 | ||
| 181 | DRM_DEBUG_KMS("%s\n", __FILE__); | 195 | DRM_DEBUG_KMS("%s\n", __FILE__); |
| @@ -187,20 +201,20 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp, | |||
| 187 | 201 | ||
| 188 | vm_size = vma->vm_end - vma->vm_start; | 202 | vm_size = vma->vm_end - vma->vm_start; |
| 189 | /* | 203 | /* |
| 190 | * a entry contains information to physically continuous memory | 204 | * a buffer contains information to physically continuous memory |
| 191 | * allocated by user request or at framebuffer creation. | 205 | * allocated by user request or at framebuffer creation. |
| 192 | */ | 206 | */ |
| 193 | entry = exynos_gem_obj->entry; | 207 | buffer = exynos_gem_obj->buffer; |
| 194 | 208 | ||
| 195 | /* check if user-requested size is valid. */ | 209 | /* check if user-requested size is valid. */ |
| 196 | if (vm_size > entry->size) | 210 | if (vm_size > buffer->size) |
| 197 | return -EINVAL; | 211 | return -EINVAL; |
| 198 | 212 | ||
| 199 | /* | 213 | /* |
| 200 | * get page frame number to physical memory to be mapped | 214 | * get page frame number to physical memory to be mapped |
| 201 | * to user space. | 215 | * to user space. |
| 202 | */ | 216 | */ |
| 203 | pfn = exynos_gem_obj->entry->paddr >> PAGE_SHIFT; | 217 | pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >> PAGE_SHIFT; |
| 204 | 218 | ||
| 205 | DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn); | 219 | DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn); |
| 206 | 220 | ||
| @@ -281,7 +295,7 @@ void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj) | |||
| 281 | 295 | ||
| 282 | exynos_gem_obj = to_exynos_gem_obj(gem_obj); | 296 | exynos_gem_obj = to_exynos_gem_obj(gem_obj); |
| 283 | 297 | ||
| 284 | exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->entry); | 298 | exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->buffer); |
| 285 | 299 | ||
| 286 | kfree(exynos_gem_obj); | 300 | kfree(exynos_gem_obj); |
| 287 | } | 301 | } |
| @@ -302,8 +316,8 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, | |||
| 302 | args->pitch = args->width * args->bpp >> 3; | 316 | args->pitch = args->width * args->bpp >> 3; |
| 303 | args->size = args->pitch * args->height; | 317 | args->size = args->pitch * args->height; |
| 304 | 318 | ||
| 305 | exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size, | 319 | exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, &args->handle, |
| 306 | &args->handle); | 320 | args->size); |
| 307 | if (IS_ERR(exynos_gem_obj)) | 321 | if (IS_ERR(exynos_gem_obj)) |
| 308 | return PTR_ERR(exynos_gem_obj); | 322 | return PTR_ERR(exynos_gem_obj); |
| 309 | 323 | ||
| @@ -360,7 +374,8 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 360 | 374 | ||
| 361 | mutex_lock(&dev->struct_mutex); | 375 | mutex_lock(&dev->struct_mutex); |
| 362 | 376 | ||
| 363 | pfn = (exynos_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset; | 377 | pfn = (((unsigned long)exynos_gem_obj->buffer->dma_addr) >> |
| 378 | PAGE_SHIFT) + page_offset; | ||
| 364 | 379 | ||
| 365 | ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); | 380 | ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); |
| 366 | 381 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index e5fc0148277b..ef8797334e6d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h | |||
| @@ -30,13 +30,29 @@ | |||
| 30 | struct exynos_drm_gem_obj, base) | 30 | struct exynos_drm_gem_obj, base) |
| 31 | 31 | ||
| 32 | /* | 32 | /* |
| 33 | * exynos drm gem buffer structure. | ||
| 34 | * | ||
| 35 | * @kvaddr: kernel virtual address to allocated memory region. | ||
| 36 | * @dma_addr: bus address(accessed by dma) to allocated memory region. | ||
| 37 | * - this address could be physical address without IOMMU and | ||
| 38 | * device address with IOMMU. | ||
| 39 | * @size: size of allocated memory region. | ||
| 40 | */ | ||
| 41 | struct exynos_drm_gem_buf { | ||
| 42 | void __iomem *kvaddr; | ||
| 43 | dma_addr_t dma_addr; | ||
| 44 | unsigned long size; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* | ||
| 33 | * exynos drm buffer structure. | 48 | * exynos drm buffer structure. |
| 34 | * | 49 | * |
| 35 | * @base: a gem object. | 50 | * @base: a gem object. |
| 36 | * - a new handle to this gem object would be created | 51 | * - a new handle to this gem object would be created |
| 37 | * by drm_gem_handle_create(). | 52 | * by drm_gem_handle_create(). |
| 38 | * @entry: pointer to exynos drm buffer entry object. | 53 | * @buffer: a pointer to exynos_drm_gem_buffer object. |
| 39 | * - containing the information to physically | 54 | * - contain the information to memory region allocated |
| 55 | * by user request or at framebuffer creation. | ||
| 40 | * continuous memory region allocated by user request | 56 | * continuous memory region allocated by user request |
| 41 | * or at framebuffer creation. | 57 | * or at framebuffer creation. |
| 42 | * | 58 | * |
| @@ -45,13 +61,13 @@ | |||
| 45 | */ | 61 | */ |
| 46 | struct exynos_drm_gem_obj { | 62 | struct exynos_drm_gem_obj { |
| 47 | struct drm_gem_object base; | 63 | struct drm_gem_object base; |
| 48 | struct exynos_drm_buf_entry *entry; | 64 | struct exynos_drm_gem_buf *buffer; |
| 49 | }; | 65 | }; |
| 50 | 66 | ||
| 51 | /* create a new buffer and get a new gem handle. */ | 67 | /* create a new buffer and get a new gem handle. */ |
| 52 | struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv, | 68 | struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, |
| 53 | struct drm_device *dev, unsigned int size, | 69 | struct drm_file *file_priv, |
| 54 | unsigned int *handle); | 70 | unsigned int *handle, unsigned long size); |
| 55 | 71 | ||
| 56 | /* | 72 | /* |
| 57 | * request gem object creation and buffer allocation as the size | 73 | * request gem object creation and buffer allocation as the size |
