diff options
Diffstat (limited to 'drivers/gpu/drm')
31 files changed, 248 insertions, 141 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); |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c3afb783cb9d..03c53fcf8653 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -3028,6 +3028,20 @@ | |||
| 3028 | #define DISP_TILE_SURFACE_SWIZZLING (1<<13) | 3028 | #define DISP_TILE_SURFACE_SWIZZLING (1<<13) |
| 3029 | #define DISP_FBC_WM_DIS (1<<15) | 3029 | #define DISP_FBC_WM_DIS (1<<15) |
| 3030 | 3030 | ||
| 3031 | /* GEN7 chicken */ | ||
| 3032 | #define GEN7_COMMON_SLICE_CHICKEN1 0x7010 | ||
| 3033 | # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26)) | ||
| 3034 | |||
| 3035 | #define GEN7_L3CNTLREG1 0xB01C | ||
| 3036 | #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C4FFF8C | ||
| 3037 | |||
| 3038 | #define GEN7_L3_CHICKEN_MODE_REGISTER 0xB030 | ||
| 3039 | #define GEN7_WA_L3_CHICKEN_MODE 0x20000000 | ||
| 3040 | |||
| 3041 | /* WaCatErrorRejectionIssue */ | ||
| 3042 | #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030 | ||
| 3043 | #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) | ||
| 3044 | |||
| 3031 | /* PCH */ | 3045 | /* PCH */ |
| 3032 | 3046 | ||
| 3033 | /* south display engine interrupt */ | 3047 | /* south display engine interrupt */ |
| @@ -3618,6 +3632,7 @@ | |||
| 3618 | #define GT_FIFO_NUM_RESERVED_ENTRIES 20 | 3632 | #define GT_FIFO_NUM_RESERVED_ENTRIES 20 |
| 3619 | 3633 | ||
| 3620 | #define GEN6_UCGCTL2 0x9404 | 3634 | #define GEN6_UCGCTL2 0x9404 |
| 3635 | # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) | ||
| 3621 | # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) | 3636 | # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) |
| 3622 | # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) | 3637 | # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) |
| 3623 | 3638 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 00fbff5ddd81..f851db7be2cc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -4680,8 +4680,17 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, | |||
| 4680 | 4680 | ||
| 4681 | crtc = intel_get_crtc_for_plane(dev, plane); | 4681 | crtc = intel_get_crtc_for_plane(dev, plane); |
| 4682 | clock = crtc->mode.clock; | 4682 | clock = crtc->mode.clock; |
| 4683 | if (!clock) { | ||
| 4684 | *sprite_wm = 0; | ||
| 4685 | return false; | ||
| 4686 | } | ||
| 4683 | 4687 | ||
| 4684 | line_time_us = (sprite_width * 1000) / clock; | 4688 | line_time_us = (sprite_width * 1000) / clock; |
| 4689 | if (!line_time_us) { | ||
| 4690 | *sprite_wm = 0; | ||
| 4691 | return false; | ||
| 4692 | } | ||
| 4693 | |||
| 4685 | line_count = (latency_ns / line_time_us + 1000) / 1000; | 4694 | line_count = (latency_ns / line_time_us + 1000) / 1000; |
| 4686 | line_size = sprite_width * pixel_size; | 4695 | line_size = sprite_width * pixel_size; |
| 4687 | 4696 | ||
| @@ -6175,7 +6184,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) | |||
| 6175 | int i; | 6184 | int i; |
| 6176 | 6185 | ||
| 6177 | /* The clocks have to be on to load the palette. */ | 6186 | /* The clocks have to be on to load the palette. */ |
| 6178 | if (!crtc->enabled) | 6187 | if (!crtc->enabled || !intel_crtc->active) |
| 6179 | return; | 6188 | return; |
| 6180 | 6189 | ||
| 6181 | /* use legacy palette for Ironlake */ | 6190 | /* use legacy palette for Ironlake */ |
| @@ -6561,7 +6570,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, | |||
| 6561 | mode_cmd.height = mode->vdisplay; | 6570 | mode_cmd.height = mode->vdisplay; |
| 6562 | mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width, | 6571 | mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width, |
| 6563 | bpp); | 6572 | bpp); |
| 6564 | mode_cmd.pixel_format = 0; | 6573 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); |
| 6565 | 6574 | ||
| 6566 | return intel_framebuffer_create(dev, &mode_cmd, obj); | 6575 | return intel_framebuffer_create(dev, &mode_cmd, obj); |
| 6567 | } | 6576 | } |
| @@ -8184,8 +8193,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 8184 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ | 8193 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ |
| 8185 | 8194 | ||
| 8186 | if (intel_enable_rc6(dev_priv->dev)) | 8195 | if (intel_enable_rc6(dev_priv->dev)) |
| 8187 | rc6_mask = GEN6_RC_CTL_RC6p_ENABLE | | 8196 | rc6_mask = GEN6_RC_CTL_RC6_ENABLE | |
| 8188 | GEN6_RC_CTL_RC6_ENABLE; | 8197 | ((IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0); |
| 8189 | 8198 | ||
| 8190 | I915_WRITE(GEN6_RC_CONTROL, | 8199 | I915_WRITE(GEN6_RC_CONTROL, |
| 8191 | rc6_mask | | 8200 | rc6_mask | |
| @@ -8463,12 +8472,32 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) | |||
| 8463 | I915_WRITE(WM2_LP_ILK, 0); | 8472 | I915_WRITE(WM2_LP_ILK, 0); |
| 8464 | I915_WRITE(WM1_LP_ILK, 0); | 8473 | I915_WRITE(WM1_LP_ILK, 0); |
| 8465 | 8474 | ||
| 8475 | /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. | ||
| 8476 | * This implements the WaDisableRCZUnitClockGating workaround. | ||
| 8477 | */ | ||
| 8478 | I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); | ||
| 8479 | |||
| 8466 | I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); | 8480 | I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); |
| 8467 | 8481 | ||
| 8468 | I915_WRITE(IVB_CHICKEN3, | 8482 | I915_WRITE(IVB_CHICKEN3, |
| 8469 | CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | | 8483 | CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | |
| 8470 | CHICKEN3_DGMG_DONE_FIX_DISABLE); | 8484 | CHICKEN3_DGMG_DONE_FIX_DISABLE); |
| 8471 | 8485 | ||
| 8486 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ | ||
| 8487 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, | ||
| 8488 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); | ||
| 8489 | |||
| 8490 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ | ||
| 8491 | I915_WRITE(GEN7_L3CNTLREG1, | ||
| 8492 | GEN7_WA_FOR_GEN7_L3_CONTROL); | ||
| 8493 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, | ||
| 8494 | GEN7_WA_L3_CHICKEN_MODE); | ||
| 8495 | |||
| 8496 | /* This is required by WaCatErrorRejectionIssue */ | ||
| 8497 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, | ||
| 8498 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | ||
| 8499 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); | ||
| 8500 | |||
| 8472 | for_each_pipe(pipe) { | 8501 | for_each_pipe(pipe) { |
| 8473 | I915_WRITE(DSPCNTR(pipe), | 8502 | I915_WRITE(DSPCNTR(pipe), |
| 8474 | I915_READ(DSPCNTR(pipe)) | | 8503 | I915_READ(DSPCNTR(pipe)) | |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 1ab842c6032e..536191540b03 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -301,7 +301,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) | |||
| 301 | 301 | ||
| 302 | I915_WRITE_CTL(ring, | 302 | I915_WRITE_CTL(ring, |
| 303 | ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | 303 | ((ring->size - PAGE_SIZE) & RING_NR_PAGES) |
| 304 | | RING_REPORT_64K | RING_VALID); | 304 | | RING_VALID); |
| 305 | 305 | ||
| 306 | /* If the head is still not zero, the ring is dead */ | 306 | /* If the head is still not zero, the ring is dead */ |
| 307 | if ((I915_READ_CTL(ring) & RING_VALID) == 0 || | 307 | if ((I915_READ_CTL(ring) & RING_VALID) == 0 || |
| @@ -1132,18 +1132,6 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) | |||
| 1132 | struct drm_device *dev = ring->dev; | 1132 | struct drm_device *dev = ring->dev; |
| 1133 | struct drm_i915_private *dev_priv = dev->dev_private; | 1133 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1134 | unsigned long end; | 1134 | unsigned long end; |
| 1135 | u32 head; | ||
| 1136 | |||
| 1137 | /* If the reported head position has wrapped or hasn't advanced, | ||
| 1138 | * fallback to the slow and accurate path. | ||
| 1139 | */ | ||
| 1140 | head = intel_read_status_page(ring, 4); | ||
| 1141 | if (head > ring->head) { | ||
| 1142 | ring->head = head; | ||
| 1143 | ring->space = ring_space(ring); | ||
| 1144 | if (ring->space >= n) | ||
| 1145 | return 0; | ||
| 1146 | } | ||
| 1147 | 1135 | ||
| 1148 | trace_i915_ring_wait_begin(ring); | 1136 | trace_i915_ring_wait_begin(ring); |
| 1149 | if (drm_core_check_feature(dev, DRIVER_GEM)) | 1137 | if (drm_core_check_feature(dev, DRIVER_GEM)) |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 9be353b894cc..f58254a3fb01 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -3223,6 +3223,7 @@ int evergreen_resume(struct radeon_device *rdev) | |||
| 3223 | r = evergreen_startup(rdev); | 3223 | r = evergreen_startup(rdev); |
| 3224 | if (r) { | 3224 | if (r) { |
| 3225 | DRM_ERROR("evergreen startup failed on resume\n"); | 3225 | DRM_ERROR("evergreen startup failed on resume\n"); |
| 3226 | rdev->accel_working = false; | ||
| 3226 | return r; | 3227 | return r; |
| 3227 | } | 3228 | } |
| 3228 | 3229 | ||
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index db09065e68fd..2509c505acb8 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -1547,6 +1547,7 @@ int cayman_resume(struct radeon_device *rdev) | |||
| 1547 | r = cayman_startup(rdev); | 1547 | r = cayman_startup(rdev); |
| 1548 | if (r) { | 1548 | if (r) { |
| 1549 | DRM_ERROR("cayman startup failed on resume\n"); | 1549 | DRM_ERROR("cayman startup failed on resume\n"); |
| 1550 | rdev->accel_working = false; | ||
| 1550 | return r; | 1551 | return r; |
| 1551 | } | 1552 | } |
| 1552 | return r; | 1553 | return r; |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 18cd84fae99c..333cde9d4e7b 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -3928,6 +3928,8 @@ static int r100_startup(struct radeon_device *rdev) | |||
| 3928 | 3928 | ||
| 3929 | int r100_resume(struct radeon_device *rdev) | 3929 | int r100_resume(struct radeon_device *rdev) |
| 3930 | { | 3930 | { |
| 3931 | int r; | ||
| 3932 | |||
| 3931 | /* Make sur GART are not working */ | 3933 | /* Make sur GART are not working */ |
| 3932 | if (rdev->flags & RADEON_IS_PCI) | 3934 | if (rdev->flags & RADEON_IS_PCI) |
| 3933 | r100_pci_gart_disable(rdev); | 3935 | r100_pci_gart_disable(rdev); |
| @@ -3947,7 +3949,11 @@ int r100_resume(struct radeon_device *rdev) | |||
| 3947 | radeon_surface_init(rdev); | 3949 | radeon_surface_init(rdev); |
| 3948 | 3950 | ||
| 3949 | rdev->accel_working = true; | 3951 | rdev->accel_working = true; |
| 3950 | return r100_startup(rdev); | 3952 | r = r100_startup(rdev); |
| 3953 | if (r) { | ||
| 3954 | rdev->accel_working = false; | ||
| 3955 | } | ||
| 3956 | return r; | ||
| 3951 | } | 3957 | } |
| 3952 | 3958 | ||
| 3953 | int r100_suspend(struct radeon_device *rdev) | 3959 | int r100_suspend(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 3fc0d29a5f39..6829638cca40 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c | |||
| @@ -1431,6 +1431,8 @@ static int r300_startup(struct radeon_device *rdev) | |||
| 1431 | 1431 | ||
| 1432 | int r300_resume(struct radeon_device *rdev) | 1432 | int r300_resume(struct radeon_device *rdev) |
| 1433 | { | 1433 | { |
| 1434 | int r; | ||
| 1435 | |||
| 1434 | /* Make sur GART are not working */ | 1436 | /* Make sur GART are not working */ |
| 1435 | if (rdev->flags & RADEON_IS_PCIE) | 1437 | if (rdev->flags & RADEON_IS_PCIE) |
| 1436 | rv370_pcie_gart_disable(rdev); | 1438 | rv370_pcie_gart_disable(rdev); |
| @@ -1452,7 +1454,11 @@ int r300_resume(struct radeon_device *rdev) | |||
| 1452 | radeon_surface_init(rdev); | 1454 | radeon_surface_init(rdev); |
| 1453 | 1455 | ||
| 1454 | rdev->accel_working = true; | 1456 | rdev->accel_working = true; |
| 1455 | return r300_startup(rdev); | 1457 | r = r300_startup(rdev); |
| 1458 | if (r) { | ||
| 1459 | rdev->accel_working = false; | ||
| 1460 | } | ||
| 1461 | return r; | ||
| 1456 | } | 1462 | } |
| 1457 | 1463 | ||
| 1458 | int r300_suspend(struct radeon_device *rdev) | 1464 | int r300_suspend(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 666e28fe509c..b14323053bad 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
| @@ -291,6 +291,8 @@ static int r420_startup(struct radeon_device *rdev) | |||
| 291 | 291 | ||
| 292 | int r420_resume(struct radeon_device *rdev) | 292 | int r420_resume(struct radeon_device *rdev) |
| 293 | { | 293 | { |
| 294 | int r; | ||
| 295 | |||
| 294 | /* Make sur GART are not working */ | 296 | /* Make sur GART are not working */ |
| 295 | if (rdev->flags & RADEON_IS_PCIE) | 297 | if (rdev->flags & RADEON_IS_PCIE) |
| 296 | rv370_pcie_gart_disable(rdev); | 298 | rv370_pcie_gart_disable(rdev); |
| @@ -316,7 +318,11 @@ int r420_resume(struct radeon_device *rdev) | |||
| 316 | radeon_surface_init(rdev); | 318 | radeon_surface_init(rdev); |
| 317 | 319 | ||
| 318 | rdev->accel_working = true; | 320 | rdev->accel_working = true; |
| 319 | return r420_startup(rdev); | 321 | r = r420_startup(rdev); |
| 322 | if (r) { | ||
| 323 | rdev->accel_working = false; | ||
| 324 | } | ||
| 325 | return r; | ||
| 320 | } | 326 | } |
| 321 | 327 | ||
| 322 | int r420_suspend(struct radeon_device *rdev) | 328 | int r420_suspend(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 4ae1615e752f..25084e824dbc 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c | |||
| @@ -218,6 +218,8 @@ static int r520_startup(struct radeon_device *rdev) | |||
| 218 | 218 | ||
| 219 | int r520_resume(struct radeon_device *rdev) | 219 | int r520_resume(struct radeon_device *rdev) |
| 220 | { | 220 | { |
| 221 | int r; | ||
| 222 | |||
| 221 | /* Make sur GART are not working */ | 223 | /* Make sur GART are not working */ |
| 222 | if (rdev->flags & RADEON_IS_PCIE) | 224 | if (rdev->flags & RADEON_IS_PCIE) |
| 223 | rv370_pcie_gart_disable(rdev); | 225 | rv370_pcie_gart_disable(rdev); |
| @@ -237,7 +239,11 @@ int r520_resume(struct radeon_device *rdev) | |||
| 237 | radeon_surface_init(rdev); | 239 | radeon_surface_init(rdev); |
| 238 | 240 | ||
| 239 | rdev->accel_working = true; | 241 | rdev->accel_working = true; |
| 240 | return r520_startup(rdev); | 242 | r = r520_startup(rdev); |
| 243 | if (r) { | ||
| 244 | rdev->accel_working = false; | ||
| 245 | } | ||
| 246 | return r; | ||
| 241 | } | 247 | } |
| 242 | 248 | ||
| 243 | int r520_init(struct radeon_device *rdev) | 249 | int r520_init(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 4f08e5e6ee9d..fbcd84803b60 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -2529,6 +2529,7 @@ int r600_resume(struct radeon_device *rdev) | |||
| 2529 | r = r600_startup(rdev); | 2529 | r = r600_startup(rdev); |
| 2530 | if (r) { | 2530 | if (r) { |
| 2531 | DRM_ERROR("r600 startup failed on resume\n"); | 2531 | DRM_ERROR("r600 startup failed on resume\n"); |
| 2532 | rdev->accel_working = false; | ||
| 2532 | return r; | 2533 | return r; |
| 2533 | } | 2534 | } |
| 2534 | 2535 | ||
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0427e3..387fcc9f03ef 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
| @@ -1304,6 +1304,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, | |||
| 1304 | h0 = G_038004_TEX_HEIGHT(word1) + 1; | 1304 | h0 = G_038004_TEX_HEIGHT(word1) + 1; |
| 1305 | d0 = G_038004_TEX_DEPTH(word1); | 1305 | d0 = G_038004_TEX_DEPTH(word1); |
| 1306 | nfaces = 1; | 1306 | nfaces = 1; |
| 1307 | array = 0; | ||
| 1307 | switch (G_038000_DIM(word0)) { | 1308 | switch (G_038000_DIM(word0)) { |
| 1308 | case V_038000_SQ_TEX_DIM_1D: | 1309 | case V_038000_SQ_TEX_DIM_1D: |
| 1309 | case V_038000_SQ_TEX_DIM_2D: | 1310 | case V_038000_SQ_TEX_DIM_2D: |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 9e72daeeddc6..1f53ae74ada1 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
| @@ -3020,6 +3020,9 @@ radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on) | |||
| 3020 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 3020 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| 3021 | uint32_t bios_2_scratch; | 3021 | uint32_t bios_2_scratch; |
| 3022 | 3022 | ||
| 3023 | if (ASIC_IS_DCE4(rdev)) | ||
| 3024 | return; | ||
| 3025 | |||
| 3023 | if (rdev->family >= CHIP_R600) | 3026 | if (rdev->family >= CHIP_R600) |
| 3024 | bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); | 3027 | bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); |
| 3025 | else | 3028 | else |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index e7cb3ab09243..8b3d8ed52ff6 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -1117,13 +1117,23 @@ static int radeon_dp_get_modes(struct drm_connector *connector) | |||
| 1117 | (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { | 1117 | (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) { |
| 1118 | struct drm_display_mode *mode; | 1118 | struct drm_display_mode *mode; |
| 1119 | 1119 | ||
| 1120 | if (!radeon_dig_connector->edp_on) | 1120 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
| 1121 | atombios_set_edp_panel_power(connector, | 1121 | if (!radeon_dig_connector->edp_on) |
| 1122 | ATOM_TRANSMITTER_ACTION_POWER_ON); | 1122 | atombios_set_edp_panel_power(connector, |
| 1123 | ret = radeon_ddc_get_modes(radeon_connector); | 1123 | ATOM_TRANSMITTER_ACTION_POWER_ON); |
| 1124 | if (!radeon_dig_connector->edp_on) | 1124 | ret = radeon_ddc_get_modes(radeon_connector); |
| 1125 | atombios_set_edp_panel_power(connector, | 1125 | if (!radeon_dig_connector->edp_on) |
| 1126 | ATOM_TRANSMITTER_ACTION_POWER_OFF); | 1126 | atombios_set_edp_panel_power(connector, |
| 1127 | ATOM_TRANSMITTER_ACTION_POWER_OFF); | ||
| 1128 | } else { | ||
| 1129 | /* need to setup ddc on the bridge */ | ||
| 1130 | if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) != | ||
| 1131 | ENCODER_OBJECT_ID_NONE) { | ||
| 1132 | if (encoder) | ||
| 1133 | radeon_atom_ext_encoder_setup_ddc(encoder); | ||
| 1134 | } | ||
| 1135 | ret = radeon_ddc_get_modes(radeon_connector); | ||
| 1136 | } | ||
| 1127 | 1137 | ||
| 1128 | if (ret > 0) { | 1138 | if (ret > 0) { |
| 1129 | if (encoder) { | 1139 | if (encoder) { |
| @@ -1134,7 +1144,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector) | |||
| 1134 | return ret; | 1144 | return ret; |
| 1135 | } | 1145 | } |
| 1136 | 1146 | ||
| 1137 | encoder = radeon_best_single_encoder(connector); | ||
| 1138 | if (!encoder) | 1147 | if (!encoder) |
| 1139 | return 0; | 1148 | return 0; |
| 1140 | 1149 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 435a3d970ab8..e64bec488ed8 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
| @@ -453,6 +453,10 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 453 | int r; | 453 | int r; |
| 454 | 454 | ||
| 455 | radeon_mutex_lock(&rdev->cs_mutex); | 455 | radeon_mutex_lock(&rdev->cs_mutex); |
| 456 | if (!rdev->accel_working) { | ||
| 457 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 458 | return -EBUSY; | ||
| 459 | } | ||
| 456 | /* initialize parser */ | 460 | /* initialize parser */ |
| 457 | memset(&parser, 0, sizeof(struct radeon_cs_parser)); | 461 | memset(&parser, 0, sizeof(struct radeon_cs_parser)); |
| 458 | parser.filp = filp; | 462 | parser.filp = filp; |
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 010dad8b66ae..c58a036233fb 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
| @@ -597,13 +597,13 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, | |||
| 597 | if (bo_va == NULL) | 597 | if (bo_va == NULL) |
| 598 | return 0; | 598 | return 0; |
| 599 | 599 | ||
| 600 | list_del(&bo_va->bo_list); | ||
| 601 | mutex_lock(&vm->mutex); | 600 | mutex_lock(&vm->mutex); |
| 602 | radeon_mutex_lock(&rdev->cs_mutex); | 601 | radeon_mutex_lock(&rdev->cs_mutex); |
| 603 | radeon_vm_bo_update_pte(rdev, vm, bo, NULL); | 602 | radeon_vm_bo_update_pte(rdev, vm, bo, NULL); |
| 604 | radeon_mutex_unlock(&rdev->cs_mutex); | 603 | radeon_mutex_unlock(&rdev->cs_mutex); |
| 605 | list_del(&bo_va->vm_list); | 604 | list_del(&bo_va->vm_list); |
| 606 | mutex_unlock(&vm->mutex); | 605 | mutex_unlock(&vm->mutex); |
| 606 | list_del(&bo_va->bo_list); | ||
| 607 | 607 | ||
| 608 | kfree(bo_va); | 608 | kfree(bo_va); |
| 609 | return 0; | 609 | return 0; |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 30a4c5014c8b..92c9ea4751fb 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
| @@ -500,8 +500,11 @@ static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32]; | |||
| 500 | int radeon_debugfs_ring_init(struct radeon_device *rdev) | 500 | int radeon_debugfs_ring_init(struct radeon_device *rdev) |
| 501 | { | 501 | { |
| 502 | #if defined(CONFIG_DEBUG_FS) | 502 | #if defined(CONFIG_DEBUG_FS) |
| 503 | return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, | 503 | if (rdev->family >= CHIP_CAYMAN) |
| 504 | ARRAY_SIZE(radeon_debugfs_ring_info_list)); | 504 | return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, |
| 505 | ARRAY_SIZE(radeon_debugfs_ring_info_list)); | ||
| 506 | else | ||
| 507 | return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, 1); | ||
| 505 | #else | 508 | #else |
| 506 | return 0; | 509 | return 0; |
| 507 | #endif | 510 | #endif |
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index b0ce84a20a68..866a05be75f2 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c | |||
| @@ -442,6 +442,8 @@ static int rs400_startup(struct radeon_device *rdev) | |||
| 442 | 442 | ||
| 443 | int rs400_resume(struct radeon_device *rdev) | 443 | int rs400_resume(struct radeon_device *rdev) |
| 444 | { | 444 | { |
| 445 | int r; | ||
| 446 | |||
| 445 | /* Make sur GART are not working */ | 447 | /* Make sur GART are not working */ |
| 446 | rs400_gart_disable(rdev); | 448 | rs400_gart_disable(rdev); |
| 447 | /* Resume clock before doing reset */ | 449 | /* Resume clock before doing reset */ |
| @@ -462,7 +464,11 @@ int rs400_resume(struct radeon_device *rdev) | |||
| 462 | radeon_surface_init(rdev); | 464 | radeon_surface_init(rdev); |
| 463 | 465 | ||
| 464 | rdev->accel_working = true; | 466 | rdev->accel_working = true; |
| 465 | return rs400_startup(rdev); | 467 | r = rs400_startup(rdev); |
| 468 | if (r) { | ||
| 469 | rdev->accel_working = false; | ||
| 470 | } | ||
| 471 | return r; | ||
| 466 | } | 472 | } |
| 467 | 473 | ||
| 468 | int rs400_suspend(struct radeon_device *rdev) | 474 | int rs400_suspend(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index c05865e5521f..4fc700684dcd 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
| @@ -876,6 +876,8 @@ static int rs600_startup(struct radeon_device *rdev) | |||
| 876 | 876 | ||
| 877 | int rs600_resume(struct radeon_device *rdev) | 877 | int rs600_resume(struct radeon_device *rdev) |
| 878 | { | 878 | { |
| 879 | int r; | ||
| 880 | |||
| 879 | /* Make sur GART are not working */ | 881 | /* Make sur GART are not working */ |
| 880 | rs600_gart_disable(rdev); | 882 | rs600_gart_disable(rdev); |
| 881 | /* Resume clock before doing reset */ | 883 | /* Resume clock before doing reset */ |
| @@ -894,7 +896,11 @@ int rs600_resume(struct radeon_device *rdev) | |||
| 894 | radeon_surface_init(rdev); | 896 | radeon_surface_init(rdev); |
| 895 | 897 | ||
| 896 | rdev->accel_working = true; | 898 | rdev->accel_working = true; |
| 897 | return rs600_startup(rdev); | 899 | r = rs600_startup(rdev); |
| 900 | if (r) { | ||
| 901 | rdev->accel_working = false; | ||
| 902 | } | ||
| 903 | return r; | ||
| 898 | } | 904 | } |
| 899 | 905 | ||
| 900 | int rs600_suspend(struct radeon_device *rdev) | 906 | int rs600_suspend(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 4f24a0fa8c82..f68dff2fadcb 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
| @@ -659,6 +659,8 @@ static int rs690_startup(struct radeon_device *rdev) | |||
| 659 | 659 | ||
| 660 | int rs690_resume(struct radeon_device *rdev) | 660 | int rs690_resume(struct radeon_device *rdev) |
| 661 | { | 661 | { |
| 662 | int r; | ||
| 663 | |||
| 662 | /* Make sur GART are not working */ | 664 | /* Make sur GART are not working */ |
| 663 | rs400_gart_disable(rdev); | 665 | rs400_gart_disable(rdev); |
| 664 | /* Resume clock before doing reset */ | 666 | /* Resume clock before doing reset */ |
| @@ -677,7 +679,11 @@ int rs690_resume(struct radeon_device *rdev) | |||
| 677 | radeon_surface_init(rdev); | 679 | radeon_surface_init(rdev); |
| 678 | 680 | ||
| 679 | rdev->accel_working = true; | 681 | rdev->accel_working = true; |
| 680 | return rs690_startup(rdev); | 682 | r = rs690_startup(rdev); |
| 683 | if (r) { | ||
| 684 | rdev->accel_working = false; | ||
| 685 | } | ||
| 686 | return r; | ||
| 681 | } | 687 | } |
| 682 | 688 | ||
| 683 | int rs690_suspend(struct radeon_device *rdev) | 689 | int rs690_suspend(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 880637fd1946..959bf4483bea 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c | |||
| @@ -424,6 +424,8 @@ static int rv515_startup(struct radeon_device *rdev) | |||
| 424 | 424 | ||
| 425 | int rv515_resume(struct radeon_device *rdev) | 425 | int rv515_resume(struct radeon_device *rdev) |
| 426 | { | 426 | { |
| 427 | int r; | ||
| 428 | |||
| 427 | /* Make sur GART are not working */ | 429 | /* Make sur GART are not working */ |
| 428 | if (rdev->flags & RADEON_IS_PCIE) | 430 | if (rdev->flags & RADEON_IS_PCIE) |
| 429 | rv370_pcie_gart_disable(rdev); | 431 | rv370_pcie_gart_disable(rdev); |
| @@ -443,7 +445,11 @@ int rv515_resume(struct radeon_device *rdev) | |||
| 443 | radeon_surface_init(rdev); | 445 | radeon_surface_init(rdev); |
| 444 | 446 | ||
| 445 | rdev->accel_working = true; | 447 | rdev->accel_working = true; |
| 446 | return rv515_startup(rdev); | 448 | r = rv515_startup(rdev); |
| 449 | if (r) { | ||
| 450 | rdev->accel_working = false; | ||
| 451 | } | ||
| 452 | return r; | ||
| 447 | } | 453 | } |
| 448 | 454 | ||
| 449 | int rv515_suspend(struct radeon_device *rdev) | 455 | int rv515_suspend(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index a1668b659ddd..c049c0c51841 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
| @@ -1139,6 +1139,7 @@ int rv770_resume(struct radeon_device *rdev) | |||
| 1139 | r = rv770_startup(rdev); | 1139 | r = rv770_startup(rdev); |
| 1140 | if (r) { | 1140 | if (r) { |
| 1141 | DRM_ERROR("r600 startup failed on resume\n"); | 1141 | DRM_ERROR("r600 startup failed on resume\n"); |
| 1142 | rdev->accel_working = false; | ||
| 1142 | return r; | 1143 | return r; |
| 1143 | } | 1144 | } |
| 1144 | 1145 | ||
