diff options
Diffstat (limited to 'drivers/gpu/drm')
| -rw-r--r-- | drivers/gpu/drm/drm_drv.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dispc.c | 27 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dsi.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/dss/omapdss.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_connector.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 154 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 216 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.h | 51 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_encoder.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_fb.c | 164 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_irq.c | 242 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_plane.c | 24 |
16 files changed, 440 insertions, 479 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 1b11ab628da7..72116978ec06 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
| @@ -598,6 +598,8 @@ static void drm_dev_release(struct kref *ref) | |||
| 598 | { | 598 | { |
| 599 | struct drm_device *dev = container_of(ref, struct drm_device, ref); | 599 | struct drm_device *dev = container_of(ref, struct drm_device, ref); |
| 600 | 600 | ||
| 601 | drm_vblank_cleanup(dev); | ||
| 602 | |||
| 601 | if (drm_core_check_feature(dev, DRIVER_GEM)) | 603 | if (drm_core_check_feature(dev, DRIVER_GEM)) |
| 602 | drm_gem_destroy(dev); | 604 | drm_gem_destroy(dev); |
| 603 | 605 | ||
| @@ -805,8 +807,6 @@ void drm_dev_unregister(struct drm_device *dev) | |||
| 805 | if (dev->agp) | 807 | if (dev->agp) |
| 806 | drm_pci_agp_destroy(dev); | 808 | drm_pci_agp_destroy(dev); |
| 807 | 809 | ||
| 808 | drm_vblank_cleanup(dev); | ||
| 809 | |||
| 810 | list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) | 810 | list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) |
| 811 | drm_legacy_rmmap(dev, r_list->map); | 811 | drm_legacy_rmmap(dev, r_list->map); |
| 812 | 812 | ||
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c index dc026a843712..a2bb855a2851 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | |||
| @@ -1253,7 +1253,7 @@ static int dsicm_probe(struct platform_device *pdev) | |||
| 1253 | dsicm_hw_reset(ddata); | 1253 | dsicm_hw_reset(ddata); |
| 1254 | 1254 | ||
| 1255 | if (ddata->use_dsi_backlight) { | 1255 | if (ddata->use_dsi_backlight) { |
| 1256 | memset(&props, 0, sizeof(struct backlight_properties)); | 1256 | memset(&props, 0, sizeof(props)); |
| 1257 | props.max_brightness = 255; | 1257 | props.max_brightness = 255; |
| 1258 | 1258 | ||
| 1259 | props.type = BACKLIGHT_RAW; | 1259 | props.type = BACKLIGHT_RAW; |
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c index 746cb8d9cba1..5ab39e0060f2 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c | |||
| @@ -909,6 +909,7 @@ static struct spi_driver acx565akm_driver = { | |||
| 909 | 909 | ||
| 910 | module_spi_driver(acx565akm_driver); | 910 | module_spi_driver(acx565akm_driver); |
| 911 | 911 | ||
| 912 | MODULE_ALIAS("spi:sony,acx565akm"); | ||
| 912 | MODULE_AUTHOR("Nokia Corporation"); | 913 | MODULE_AUTHOR("Nokia Corporation"); |
| 913 | MODULE_DESCRIPTION("acx565akm LCD Driver"); | 914 | MODULE_DESCRIPTION("acx565akm LCD Driver"); |
| 914 | MODULE_LICENSE("GPL"); | 915 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index c839f6456db2..5554b72cf56a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c | |||
| @@ -620,6 +620,19 @@ u32 dispc_wb_get_framedone_irq(void) | |||
| 620 | return DISPC_IRQ_FRAMEDONEWB; | 620 | return DISPC_IRQ_FRAMEDONEWB; |
| 621 | } | 621 | } |
| 622 | 622 | ||
| 623 | void dispc_mgr_enable(enum omap_channel channel, bool enable) | ||
| 624 | { | ||
| 625 | mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); | ||
| 626 | /* flush posted write */ | ||
| 627 | mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); | ||
| 628 | } | ||
| 629 | EXPORT_SYMBOL(dispc_mgr_enable); | ||
| 630 | |||
| 631 | static bool dispc_mgr_is_enabled(enum omap_channel channel) | ||
| 632 | { | ||
| 633 | return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); | ||
| 634 | } | ||
| 635 | |||
| 623 | bool dispc_mgr_go_busy(enum omap_channel channel) | 636 | bool dispc_mgr_go_busy(enum omap_channel channel) |
| 624 | { | 637 | { |
| 625 | return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; | 638 | return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; |
| @@ -2901,20 +2914,6 @@ enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channe | |||
| 2901 | } | 2914 | } |
| 2902 | EXPORT_SYMBOL(dispc_mgr_get_supported_outputs); | 2915 | EXPORT_SYMBOL(dispc_mgr_get_supported_outputs); |
| 2903 | 2916 | ||
| 2904 | void dispc_mgr_enable(enum omap_channel channel, bool enable) | ||
| 2905 | { | ||
| 2906 | mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); | ||
| 2907 | /* flush posted write */ | ||
| 2908 | mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); | ||
| 2909 | } | ||
| 2910 | EXPORT_SYMBOL(dispc_mgr_enable); | ||
| 2911 | |||
| 2912 | bool dispc_mgr_is_enabled(enum omap_channel channel) | ||
| 2913 | { | ||
| 2914 | return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); | ||
| 2915 | } | ||
| 2916 | EXPORT_SYMBOL(dispc_mgr_is_enabled); | ||
| 2917 | |||
| 2918 | void dispc_wb_enable(bool enable) | 2917 | void dispc_wb_enable(bool enable) |
| 2919 | { | 2918 | { |
| 2920 | dispc_ovl_enable(OMAP_DSS_WB, enable); | 2919 | dispc_ovl_enable(OMAP_DSS_WB, enable); |
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index f060bda31235..f74615d005a8 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c | |||
| @@ -4336,7 +4336,7 @@ static void print_dsi_vm(const char *str, | |||
| 4336 | 4336 | ||
| 4337 | wc = DIV_ROUND_UP(t->hact * t->bitspp, 8); | 4337 | wc = DIV_ROUND_UP(t->hact * t->bitspp, 8); |
| 4338 | pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */ | 4338 | pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */ |
| 4339 | bl = t->hss + t->hsa + t->hse + t->hbp + t->hfront_porch; | 4339 | bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp; |
| 4340 | tot = bl + pps; | 4340 | tot = bl + pps; |
| 4341 | 4341 | ||
| 4342 | #define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk)) | 4342 | #define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk)) |
| @@ -4345,14 +4345,14 @@ static void print_dsi_vm(const char *str, | |||
| 4345 | "%u/%u/%u/%u/%u/%u = %u + %u = %u\n", | 4345 | "%u/%u/%u/%u/%u/%u = %u + %u = %u\n", |
| 4346 | str, | 4346 | str, |
| 4347 | byteclk, | 4347 | byteclk, |
| 4348 | t->hss, t->hsa, t->hse, t->hbp, pps, t->hfront_porch, | 4348 | t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp, |
| 4349 | bl, pps, tot, | 4349 | bl, pps, tot, |
| 4350 | TO_DSI_T(t->hss), | 4350 | TO_DSI_T(t->hss), |
| 4351 | TO_DSI_T(t->hsa), | 4351 | TO_DSI_T(t->hsa), |
| 4352 | TO_DSI_T(t->hse), | 4352 | TO_DSI_T(t->hse), |
| 4353 | TO_DSI_T(t->hbp), | 4353 | TO_DSI_T(t->hbp), |
| 4354 | TO_DSI_T(pps), | 4354 | TO_DSI_T(pps), |
| 4355 | TO_DSI_T(t->hfront_porch), | 4355 | TO_DSI_T(t->hfp), |
| 4356 | 4356 | ||
| 4357 | TO_DSI_T(bl), | 4357 | TO_DSI_T(bl), |
| 4358 | TO_DSI_T(pps), | 4358 | TO_DSI_T(pps), |
| @@ -4367,7 +4367,7 @@ static void print_dispc_vm(const char *str, const struct videomode *vm) | |||
| 4367 | int hact, bl, tot; | 4367 | int hact, bl, tot; |
| 4368 | 4368 | ||
| 4369 | hact = vm->hactive; | 4369 | hact = vm->hactive; |
| 4370 | bl = vm->hsync_len + vm->hbp + vm->hfront_porch; | 4370 | bl = vm->hsync_len + vm->hback_porch + vm->hfront_porch; |
| 4371 | tot = hact + bl; | 4371 | tot = hact + bl; |
| 4372 | 4372 | ||
| 4373 | #define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck)) | 4373 | #define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck)) |
| @@ -4376,10 +4376,10 @@ static void print_dispc_vm(const char *str, const struct videomode *vm) | |||
| 4376 | "%u/%u/%u/%u = %u + %u = %u\n", | 4376 | "%u/%u/%u/%u = %u + %u = %u\n", |
| 4377 | str, | 4377 | str, |
| 4378 | pck, | 4378 | pck, |
| 4379 | vm->hsync_len, vm->hbp, hact, vm->hfront_porch, | 4379 | vm->hsync_len, vm->hback_porch, hact, vm->hfront_porch, |
| 4380 | bl, hact, tot, | 4380 | bl, hact, tot, |
| 4381 | TO_DISPC_T(vm->hsync_len), | 4381 | TO_DISPC_T(vm->hsync_len), |
| 4382 | TO_DISPC_T(vm->hbp), | 4382 | TO_DISPC_T(vm->hback_porch), |
| 4383 | TO_DISPC_T(hact), | 4383 | TO_DISPC_T(hact), |
| 4384 | TO_DISPC_T(vm->hfront_porch), | 4384 | TO_DISPC_T(vm->hfront_porch), |
| 4385 | TO_DISPC_T(bl), | 4385 | TO_DISPC_T(bl), |
| @@ -4401,12 +4401,12 @@ static void print_dsi_dispc_vm(const char *str, | |||
| 4401 | dsi_tput = (u64)byteclk * t->ndl * 8; | 4401 | dsi_tput = (u64)byteclk * t->ndl * 8; |
| 4402 | pck = (u32)div64_u64(dsi_tput, t->bitspp); | 4402 | pck = (u32)div64_u64(dsi_tput, t->bitspp); |
| 4403 | dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl); | 4403 | dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl); |
| 4404 | dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfront_porch; | 4404 | dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp; |
| 4405 | 4405 | ||
| 4406 | vm.pixelclock = pck; | 4406 | vm.pixelclock = pck; |
| 4407 | vm.hsync_len = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); | 4407 | vm.hsync_len = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); |
| 4408 | vm.hbp = div64_u64((u64)t->hbp * pck, byteclk); | 4408 | vm.hback_porch = div64_u64((u64)t->hbp * pck, byteclk); |
| 4409 | vm.hfront_porch = div64_u64((u64)t->hfront_porch * pck, byteclk); | 4409 | vm.hfront_porch = div64_u64((u64)t->hfp * pck, byteclk); |
| 4410 | vm.hactive = t->hact; | 4410 | vm.hactive = t->hact; |
| 4411 | 4411 | ||
| 4412 | print_dispc_vm(str, &vm); | 4412 | print_dispc_vm(str, &vm); |
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c index 136d30484d02..bf626acae271 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c +++ b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c | |||
| @@ -119,8 +119,7 @@ static void __init omapdss_omapify_node(struct device_node *node) | |||
| 119 | 119 | ||
| 120 | static void __init omapdss_add_to_list(struct device_node *node, bool root) | 120 | static void __init omapdss_add_to_list(struct device_node *node, bool root) |
| 121 | { | 121 | { |
| 122 | struct dss_conv_node *n = kmalloc(sizeof(struct dss_conv_node), | 122 | struct dss_conv_node *n = kmalloc(sizeof(*n), GFP_KERNEL); |
| 123 | GFP_KERNEL); | ||
| 124 | if (n) { | 123 | if (n) { |
| 125 | n->node = node; | 124 | n->node = node; |
| 126 | n->root = root; | 125 | n->root = root; |
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index b420dde8c0fb..5b3b961127bd 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h | |||
| @@ -856,7 +856,6 @@ int dispc_runtime_get(void); | |||
| 856 | void dispc_runtime_put(void); | 856 | void dispc_runtime_put(void); |
| 857 | 857 | ||
| 858 | void dispc_mgr_enable(enum omap_channel channel, bool enable); | 858 | void dispc_mgr_enable(enum omap_channel channel, bool enable); |
| 859 | bool dispc_mgr_is_enabled(enum omap_channel channel); | ||
| 860 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); | 859 | u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); |
| 861 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); | 860 | u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); |
| 862 | u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel); | 861 | u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel); |
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 2580e8673908..f90e2d22c5ec 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c | |||
| @@ -162,7 +162,7 @@ static int omap_connector_mode_valid(struct drm_connector *connector, | |||
| 162 | 162 | ||
| 163 | dssdrv->get_timings(dssdev, &t); | 163 | dssdrv->get_timings(dssdev, &t); |
| 164 | 164 | ||
| 165 | if (memcmp(&vm, &t, sizeof(struct videomode))) | 165 | if (memcmp(&vm, &t, sizeof(vm))) |
| 166 | r = -EINVAL; | 166 | r = -EINVAL; |
| 167 | else | 167 | else |
| 168 | r = 0; | 168 | r = 0; |
| @@ -217,7 +217,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, | |||
| 217 | 217 | ||
| 218 | omap_dss_get_device(dssdev); | 218 | omap_dss_get_device(dssdev); |
| 219 | 219 | ||
| 220 | omap_connector = kzalloc(sizeof(struct omap_connector), GFP_KERNEL); | 220 | omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL); |
| 221 | if (!omap_connector) | 221 | if (!omap_connector) |
| 222 | goto fail; | 222 | goto fail; |
| 223 | 223 | ||
| @@ -240,8 +240,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, | |||
| 240 | connector->interlace_allowed = 1; | 240 | connector->interlace_allowed = 1; |
| 241 | connector->doublescan_allowed = 0; | 241 | connector->doublescan_allowed = 0; |
| 242 | 242 | ||
| 243 | drm_connector_register(connector); | ||
| 244 | |||
| 245 | return connector; | 243 | return connector; |
| 246 | 244 | ||
| 247 | fail: | 245 | fail: |
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 8dea89030e66..dd47dc191e6b 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
| @@ -36,26 +36,18 @@ struct omap_crtc { | |||
| 36 | 36 | ||
| 37 | struct videomode vm; | 37 | struct videomode vm; |
| 38 | 38 | ||
| 39 | struct omap_drm_irq vblank_irq; | ||
| 40 | struct omap_drm_irq error_irq; | ||
| 41 | |||
| 42 | bool ignore_digit_sync_lost; | 39 | bool ignore_digit_sync_lost; |
| 43 | 40 | ||
| 41 | bool enabled; | ||
| 44 | bool pending; | 42 | bool pending; |
| 45 | wait_queue_head_t pending_wait; | 43 | wait_queue_head_t pending_wait; |
| 44 | struct drm_pending_vblank_event *event; | ||
| 46 | }; | 45 | }; |
| 47 | 46 | ||
| 48 | /* ----------------------------------------------------------------------------- | 47 | /* ----------------------------------------------------------------------------- |
| 49 | * Helper Functions | 48 | * Helper Functions |
| 50 | */ | 49 | */ |
| 51 | 50 | ||
| 52 | uint32_t pipe2vbl(struct drm_crtc *crtc) | ||
| 53 | { | ||
| 54 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
| 55 | |||
| 56 | return dispc_mgr_get_vsync_irq(omap_crtc->channel); | ||
| 57 | } | ||
| 58 | |||
| 59 | struct videomode *omap_crtc_timings(struct drm_crtc *crtc) | 51 | struct videomode *omap_crtc_timings(struct drm_crtc *crtc) |
| 60 | { | 52 | { |
| 61 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 53 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| @@ -68,6 +60,19 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc) | |||
| 68 | return omap_crtc->channel; | 60 | return omap_crtc->channel; |
| 69 | } | 61 | } |
| 70 | 62 | ||
| 63 | static bool omap_crtc_is_pending(struct drm_crtc *crtc) | ||
| 64 | { | ||
| 65 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
| 66 | unsigned long flags; | ||
| 67 | bool pending; | ||
| 68 | |||
| 69 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
| 70 | pending = omap_crtc->pending; | ||
| 71 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
| 72 | |||
| 73 | return pending; | ||
| 74 | } | ||
| 75 | |||
| 71 | int omap_crtc_wait_pending(struct drm_crtc *crtc) | 76 | int omap_crtc_wait_pending(struct drm_crtc *crtc) |
| 72 | { | 77 | { |
| 73 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 78 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| @@ -77,7 +82,7 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc) | |||
| 77 | * a single frame refresh even on slower displays. | 82 | * a single frame refresh even on slower displays. |
| 78 | */ | 83 | */ |
| 79 | return wait_event_timeout(omap_crtc->pending_wait, | 84 | return wait_event_timeout(omap_crtc->pending_wait, |
| 80 | !omap_crtc->pending, | 85 | !omap_crtc_is_pending(crtc), |
| 81 | msecs_to_jiffies(250)); | 86 | msecs_to_jiffies(250)); |
| 82 | } | 87 | } |
| 83 | 88 | ||
| @@ -135,14 +140,15 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) | |||
| 135 | u32 framedone_irq, vsync_irq; | 140 | u32 framedone_irq, vsync_irq; |
| 136 | int ret; | 141 | int ret; |
| 137 | 142 | ||
| 143 | if (WARN_ON(omap_crtc->enabled == enable)) | ||
| 144 | return; | ||
| 145 | |||
| 138 | if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) { | 146 | if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) { |
| 139 | dispc_mgr_enable(channel, enable); | 147 | dispc_mgr_enable(channel, enable); |
| 148 | omap_crtc->enabled = enable; | ||
| 140 | return; | 149 | return; |
| 141 | } | 150 | } |
| 142 | 151 | ||
| 143 | if (dispc_mgr_is_enabled(channel) == enable) | ||
| 144 | return; | ||
| 145 | |||
| 146 | if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) { | 152 | if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) { |
| 147 | /* | 153 | /* |
| 148 | * Digit output produces some sync lost interrupts during the | 154 | * Digit output produces some sync lost interrupts during the |
| @@ -173,6 +179,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) | |||
| 173 | } | 179 | } |
| 174 | 180 | ||
| 175 | dispc_mgr_enable(channel, enable); | 181 | dispc_mgr_enable(channel, enable); |
| 182 | omap_crtc->enabled = enable; | ||
| 176 | 183 | ||
| 177 | ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); | 184 | ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); |
| 178 | if (ret) { | 185 | if (ret) { |
| @@ -259,26 +266,9 @@ static const struct dss_mgr_ops mgr_ops = { | |||
| 259 | * Setup, Flush and Page Flip | 266 | * Setup, Flush and Page Flip |
| 260 | */ | 267 | */ |
| 261 | 268 | ||
| 262 | static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) | 269 | void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus) |
| 263 | { | 270 | { |
| 264 | struct drm_pending_vblank_event *event; | 271 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| 265 | struct drm_device *dev = crtc->dev; | ||
| 266 | unsigned long flags; | ||
| 267 | |||
| 268 | event = crtc->state->event; | ||
| 269 | |||
| 270 | if (!event) | ||
| 271 | return; | ||
| 272 | |||
| 273 | spin_lock_irqsave(&dev->event_lock, flags); | ||
| 274 | drm_crtc_send_vblank_event(crtc, event); | ||
| 275 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 276 | } | ||
| 277 | |||
| 278 | static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
| 279 | { | ||
| 280 | struct omap_crtc *omap_crtc = | ||
| 281 | container_of(irq, struct omap_crtc, error_irq); | ||
| 282 | 272 | ||
| 283 | if (omap_crtc->ignore_digit_sync_lost) { | 273 | if (omap_crtc->ignore_digit_sync_lost) { |
| 284 | irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT; | 274 | irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT; |
| @@ -289,29 +279,38 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | |||
| 289 | DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus); | 279 | DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus); |
| 290 | } | 280 | } |
| 291 | 281 | ||
| 292 | static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | 282 | void omap_crtc_vblank_irq(struct drm_crtc *crtc) |
| 293 | { | 283 | { |
| 294 | struct omap_crtc *omap_crtc = | 284 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| 295 | container_of(irq, struct omap_crtc, vblank_irq); | 285 | bool pending; |
| 296 | struct drm_device *dev = omap_crtc->base.dev; | ||
| 297 | 286 | ||
| 298 | if (dispc_mgr_go_busy(omap_crtc->channel)) | 287 | spin_lock(&crtc->dev->event_lock); |
| 288 | /* | ||
| 289 | * If the dispc is busy we're racing the flush operation. Try again on | ||
| 290 | * the next vblank interrupt. | ||
| 291 | */ | ||
| 292 | if (dispc_mgr_go_busy(omap_crtc->channel)) { | ||
| 293 | spin_unlock(&crtc->dev->event_lock); | ||
| 299 | return; | 294 | return; |
| 295 | } | ||
| 300 | 296 | ||
| 301 | DBG("%s: apply done", omap_crtc->name); | 297 | /* Send the vblank event if one has been requested. */ |
| 302 | 298 | if (omap_crtc->event) { | |
| 303 | __omap_irq_unregister(dev, &omap_crtc->vblank_irq); | 299 | drm_crtc_send_vblank_event(crtc, omap_crtc->event); |
| 300 | omap_crtc->event = NULL; | ||
| 301 | } | ||
| 304 | 302 | ||
| 305 | rmb(); | 303 | pending = omap_crtc->pending; |
| 306 | WARN_ON(!omap_crtc->pending); | ||
| 307 | omap_crtc->pending = false; | 304 | omap_crtc->pending = false; |
| 308 | wmb(); | 305 | spin_unlock(&crtc->dev->event_lock); |
| 309 | 306 | ||
| 310 | /* wake up userspace */ | 307 | if (pending) |
| 311 | omap_crtc_complete_page_flip(&omap_crtc->base); | 308 | drm_crtc_vblank_put(crtc); |
| 312 | 309 | ||
| 313 | /* wake up omap_atomic_complete */ | 310 | /* Wake up omap_atomic_complete. */ |
| 314 | wake_up(&omap_crtc->pending_wait); | 311 | wake_up(&omap_crtc->pending_wait); |
| 312 | |||
| 313 | DBG("%s: apply done", omap_crtc->name); | ||
| 315 | } | 314 | } |
| 316 | 315 | ||
| 317 | /* ----------------------------------------------------------------------------- | 316 | /* ----------------------------------------------------------------------------- |
| @@ -324,9 +323,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) | |||
| 324 | 323 | ||
| 325 | DBG("%s", omap_crtc->name); | 324 | DBG("%s", omap_crtc->name); |
| 326 | 325 | ||
| 327 | WARN_ON(omap_crtc->vblank_irq.registered); | ||
| 328 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | ||
| 329 | |||
| 330 | drm_crtc_cleanup(crtc); | 326 | drm_crtc_cleanup(crtc); |
| 331 | 327 | ||
| 332 | kfree(omap_crtc); | 328 | kfree(omap_crtc); |
| @@ -335,17 +331,18 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) | |||
| 335 | static void omap_crtc_enable(struct drm_crtc *crtc) | 331 | static void omap_crtc_enable(struct drm_crtc *crtc) |
| 336 | { | 332 | { |
| 337 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 333 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| 334 | int ret; | ||
| 338 | 335 | ||
| 339 | DBG("%s", omap_crtc->name); | 336 | DBG("%s", omap_crtc->name); |
| 340 | 337 | ||
| 341 | rmb(); | 338 | spin_lock_irq(&crtc->dev->event_lock); |
| 339 | drm_crtc_vblank_on(crtc); | ||
| 340 | ret = drm_crtc_vblank_get(crtc); | ||
| 341 | WARN_ON(ret != 0); | ||
| 342 | |||
| 342 | WARN_ON(omap_crtc->pending); | 343 | WARN_ON(omap_crtc->pending); |
| 343 | omap_crtc->pending = true; | 344 | omap_crtc->pending = true; |
| 344 | wmb(); | 345 | spin_unlock_irq(&crtc->dev->event_lock); |
| 345 | |||
| 346 | omap_irq_register(crtc->dev, &omap_crtc->vblank_irq); | ||
| 347 | |||
| 348 | drm_crtc_vblank_on(crtc); | ||
| 349 | } | 346 | } |
| 350 | 347 | ||
| 351 | static void omap_crtc_disable(struct drm_crtc *crtc) | 348 | static void omap_crtc_disable(struct drm_crtc *crtc) |
| @@ -390,16 +387,15 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc, | |||
| 390 | } | 387 | } |
| 391 | 388 | ||
| 392 | static void omap_crtc_atomic_begin(struct drm_crtc *crtc, | 389 | static void omap_crtc_atomic_begin(struct drm_crtc *crtc, |
| 393 | struct drm_crtc_state *old_crtc_state) | 390 | struct drm_crtc_state *old_crtc_state) |
| 394 | { | 391 | { |
| 395 | } | 392 | } |
| 396 | 393 | ||
| 397 | static void omap_crtc_atomic_flush(struct drm_crtc *crtc, | 394 | static void omap_crtc_atomic_flush(struct drm_crtc *crtc, |
| 398 | struct drm_crtc_state *old_crtc_state) | 395 | struct drm_crtc_state *old_crtc_state) |
| 399 | { | 396 | { |
| 400 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 397 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| 401 | 398 | int ret; | |
| 402 | WARN_ON(omap_crtc->vblank_irq.registered); | ||
| 403 | 399 | ||
| 404 | if (crtc->state->color_mgmt_changed) { | 400 | if (crtc->state->color_mgmt_changed) { |
| 405 | struct drm_color_lut *lut = NULL; | 401 | struct drm_color_lut *lut = NULL; |
| @@ -414,18 +410,30 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, | |||
| 414 | dispc_mgr_set_gamma(omap_crtc->channel, lut, length); | 410 | dispc_mgr_set_gamma(omap_crtc->channel, lut, length); |
| 415 | } | 411 | } |
| 416 | 412 | ||
| 417 | if (dispc_mgr_is_enabled(omap_crtc->channel)) { | 413 | /* |
| 414 | * Only flush the CRTC if it is currently enabled. CRTCs that require a | ||
| 415 | * mode set are disabled prior plane updates and enabled afterwards. | ||
| 416 | * They are thus not active (regardless of what their CRTC core state | ||
| 417 | * reports) and the DRM core could thus call this function even though | ||
| 418 | * the CRTC is currently disabled. Do nothing in that case. | ||
| 419 | */ | ||
| 420 | if (!omap_crtc->enabled) | ||
| 421 | return; | ||
| 422 | |||
| 423 | DBG("%s: GO", omap_crtc->name); | ||
| 418 | 424 | ||
| 419 | DBG("%s: GO", omap_crtc->name); | 425 | ret = drm_crtc_vblank_get(crtc); |
| 426 | WARN_ON(ret != 0); | ||
| 420 | 427 | ||
| 421 | rmb(); | 428 | spin_lock_irq(&crtc->dev->event_lock); |
| 422 | WARN_ON(omap_crtc->pending); | 429 | dispc_mgr_go(omap_crtc->channel); |
| 423 | omap_crtc->pending = true; | ||
| 424 | wmb(); | ||
| 425 | 430 | ||
| 426 | dispc_mgr_go(omap_crtc->channel); | 431 | WARN_ON(omap_crtc->pending); |
| 427 | omap_irq_register(crtc->dev, &omap_crtc->vblank_irq); | 432 | omap_crtc->pending = true; |
| 428 | } | 433 | |
| 434 | if (crtc->state->event) | ||
| 435 | omap_crtc->event = crtc->state->event; | ||
| 436 | spin_unlock_irq(&crtc->dev->event_lock); | ||
| 429 | } | 437 | } |
| 430 | 438 | ||
| 431 | static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc, | 439 | static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc, |
| @@ -546,14 +554,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, | |||
| 546 | omap_crtc->channel = channel; | 554 | omap_crtc->channel = channel; |
| 547 | omap_crtc->name = channel_names[channel]; | 555 | omap_crtc->name = channel_names[channel]; |
| 548 | 556 | ||
| 549 | omap_crtc->vblank_irq.irqmask = pipe2vbl(crtc); | ||
| 550 | omap_crtc->vblank_irq.irq = omap_crtc_vblank_irq; | ||
| 551 | |||
| 552 | omap_crtc->error_irq.irqmask = | ||
| 553 | dispc_mgr_get_sync_lost_irq(channel); | ||
| 554 | omap_crtc->error_irq.irq = omap_crtc_error_irq; | ||
| 555 | omap_irq_register(dev, &omap_crtc->error_irq); | ||
| 556 | |||
| 557 | ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, | 557 | ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, |
| 558 | &omap_crtc_funcs, NULL); | 558 | &omap_crtc_funcs, NULL); |
| 559 | if (ret < 0) { | 559 | if (ret < 0) { |
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index 4ceed7a9762f..3cab06661a08 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | |||
| @@ -224,7 +224,7 @@ static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area, | |||
| 224 | int rows = (1 + area->y1 - area->y0); | 224 | int rows = (1 + area->y1 - area->y0); |
| 225 | int i = columns*rows; | 225 | int i = columns*rows; |
| 226 | 226 | ||
| 227 | pat = alloc_dma(txn, sizeof(struct pat), &pat_pa); | 227 | pat = alloc_dma(txn, sizeof(*pat), &pat_pa); |
| 228 | 228 | ||
| 229 | if (txn->last_pat) | 229 | if (txn->last_pat) |
| 230 | txn->last_pat->next_pa = (uint32_t)pat_pa; | 230 | txn->last_pat->next_pa = (uint32_t)pat_pa; |
| @@ -735,7 +735,7 @@ static int omap_dmm_probe(struct platform_device *dev) | |||
| 735 | 735 | ||
| 736 | /* alloc engines */ | 736 | /* alloc engines */ |
| 737 | omap_dmm->engines = kcalloc(omap_dmm->num_engines, | 737 | omap_dmm->engines = kcalloc(omap_dmm->num_engines, |
| 738 | sizeof(struct refill_engine), GFP_KERNEL); | 738 | sizeof(*omap_dmm->engines), GFP_KERNEL); |
| 739 | if (!omap_dmm->engines) { | 739 | if (!omap_dmm->engines) { |
| 740 | ret = -ENOMEM; | 740 | ret = -ENOMEM; |
| 741 | goto fail; | 741 | goto fail; |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 4fd2e1799a88..00aa214b7560 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
| @@ -96,7 +96,8 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) | |||
| 96 | dispc_runtime_get(); | 96 | dispc_runtime_get(); |
| 97 | 97 | ||
| 98 | drm_atomic_helper_commit_modeset_disables(dev, old_state); | 98 | drm_atomic_helper_commit_modeset_disables(dev, old_state); |
| 99 | drm_atomic_helper_commit_planes(dev, old_state, 0); | 99 | drm_atomic_helper_commit_planes(dev, old_state, |
| 100 | DRM_PLANE_COMMIT_ACTIVE_ONLY); | ||
| 100 | drm_atomic_helper_commit_modeset_enables(dev, old_state); | 101 | drm_atomic_helper_commit_modeset_enables(dev, old_state); |
| 101 | 102 | ||
| 102 | omap_atomic_wait_for_completion(dev, old_state); | 103 | omap_atomic_wait_for_completion(dev, old_state); |
| @@ -315,8 +316,6 @@ static int omap_modeset_init(struct drm_device *dev) | |||
| 315 | 316 | ||
| 316 | drm_mode_config_init(dev); | 317 | drm_mode_config_init(dev); |
| 317 | 318 | ||
| 318 | omap_drm_irq_install(dev); | ||
| 319 | |||
| 320 | ret = omap_modeset_init_properties(dev); | 319 | ret = omap_modeset_init_properties(dev); |
| 321 | if (ret < 0) | 320 | if (ret < 0) |
| 322 | return ret; | 321 | return ret; |
| @@ -489,12 +488,9 @@ static int omap_modeset_init(struct drm_device *dev) | |||
| 489 | 488 | ||
| 490 | drm_mode_config_reset(dev); | 489 | drm_mode_config_reset(dev); |
| 491 | 490 | ||
| 492 | return 0; | 491 | omap_drm_irq_install(dev); |
| 493 | } | ||
| 494 | 492 | ||
| 495 | static void omap_modeset_free(struct drm_device *dev) | 493 | return 0; |
| 496 | { | ||
| 497 | drm_mode_config_cleanup(dev); | ||
| 498 | } | 494 | } |
| 499 | 495 | ||
| 500 | /* | 496 | /* |
| @@ -632,93 +628,6 @@ static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = | |||
| 632 | * drm driver funcs | 628 | * drm driver funcs |
| 633 | */ | 629 | */ |
| 634 | 630 | ||
| 635 | /** | ||
| 636 | * load - setup chip and create an initial config | ||
| 637 | * @dev: DRM device | ||
| 638 | * @flags: startup flags | ||
| 639 | * | ||
| 640 | * The driver load routine has to do several things: | ||
| 641 | * - initialize the memory manager | ||
| 642 | * - allocate initial config memory | ||
| 643 | * - setup the DRM framebuffer with the allocated memory | ||
| 644 | */ | ||
| 645 | static int dev_load(struct drm_device *dev, unsigned long flags) | ||
| 646 | { | ||
| 647 | struct omap_drm_platform_data *pdata = dev->dev->platform_data; | ||
| 648 | struct omap_drm_private *priv; | ||
| 649 | unsigned int i; | ||
| 650 | int ret; | ||
| 651 | |||
| 652 | DBG("load: dev=%p", dev); | ||
| 653 | |||
| 654 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 655 | if (!priv) | ||
| 656 | return -ENOMEM; | ||
| 657 | |||
| 658 | priv->omaprev = pdata->omaprev; | ||
| 659 | |||
| 660 | dev->dev_private = priv; | ||
| 661 | |||
| 662 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); | ||
| 663 | init_waitqueue_head(&priv->commit.wait); | ||
| 664 | spin_lock_init(&priv->commit.lock); | ||
| 665 | |||
| 666 | spin_lock_init(&priv->list_lock); | ||
| 667 | INIT_LIST_HEAD(&priv->obj_list); | ||
| 668 | |||
| 669 | omap_gem_init(dev); | ||
| 670 | |||
| 671 | ret = omap_modeset_init(dev); | ||
| 672 | if (ret) { | ||
| 673 | dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); | ||
| 674 | dev->dev_private = NULL; | ||
| 675 | kfree(priv); | ||
| 676 | return ret; | ||
| 677 | } | ||
| 678 | |||
| 679 | /* Initialize vblank handling, start with all CRTCs disabled. */ | ||
| 680 | ret = drm_vblank_init(dev, priv->num_crtcs); | ||
| 681 | if (ret) | ||
| 682 | dev_warn(dev->dev, "could not init vblank\n"); | ||
| 683 | |||
| 684 | for (i = 0; i < priv->num_crtcs; i++) | ||
| 685 | drm_crtc_vblank_off(priv->crtcs[i]); | ||
| 686 | |||
| 687 | priv->fbdev = omap_fbdev_init(dev); | ||
| 688 | |||
| 689 | /* store off drm_device for use in pm ops */ | ||
| 690 | dev_set_drvdata(dev->dev, dev); | ||
| 691 | |||
| 692 | drm_kms_helper_poll_init(dev); | ||
| 693 | |||
| 694 | return 0; | ||
| 695 | } | ||
| 696 | |||
| 697 | static void dev_unload(struct drm_device *dev) | ||
| 698 | { | ||
| 699 | struct omap_drm_private *priv = dev->dev_private; | ||
| 700 | |||
| 701 | DBG("unload: dev=%p", dev); | ||
| 702 | |||
| 703 | drm_kms_helper_poll_fini(dev); | ||
| 704 | |||
| 705 | if (priv->fbdev) | ||
| 706 | omap_fbdev_free(dev); | ||
| 707 | |||
| 708 | omap_modeset_free(dev); | ||
| 709 | omap_gem_deinit(dev); | ||
| 710 | |||
| 711 | destroy_workqueue(priv->wq); | ||
| 712 | |||
| 713 | drm_vblank_cleanup(dev); | ||
| 714 | omap_drm_irq_uninstall(dev); | ||
| 715 | |||
| 716 | kfree(dev->dev_private); | ||
| 717 | dev->dev_private = NULL; | ||
| 718 | |||
| 719 | dev_set_drvdata(dev->dev, NULL); | ||
| 720 | } | ||
| 721 | |||
| 722 | static int dev_open(struct drm_device *dev, struct drm_file *file) | 631 | static int dev_open(struct drm_device *dev, struct drm_file *file) |
| 723 | { | 632 | { |
| 724 | file->driver_priv = NULL; | 633 | file->driver_priv = NULL; |
| @@ -803,8 +712,6 @@ static const struct file_operations omapdriver_fops = { | |||
| 803 | static struct drm_driver omap_drm_driver = { | 712 | static struct drm_driver omap_drm_driver = { |
| 804 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | | 713 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | |
| 805 | DRIVER_ATOMIC, | 714 | DRIVER_ATOMIC, |
| 806 | .load = dev_load, | ||
| 807 | .unload = dev_unload, | ||
| 808 | .open = dev_open, | 715 | .open = dev_open, |
| 809 | .lastclose = dev_lastclose, | 716 | .lastclose = dev_lastclose, |
| 810 | .get_vblank_counter = drm_vblank_no_hw_counter, | 717 | .get_vblank_counter = drm_vblank_no_hw_counter, |
| @@ -834,30 +741,125 @@ static struct drm_driver omap_drm_driver = { | |||
| 834 | .patchlevel = DRIVER_PATCHLEVEL, | 741 | .patchlevel = DRIVER_PATCHLEVEL, |
| 835 | }; | 742 | }; |
| 836 | 743 | ||
| 837 | static int pdev_probe(struct platform_device *device) | 744 | static int pdev_probe(struct platform_device *pdev) |
| 838 | { | 745 | { |
| 839 | int r; | 746 | struct omap_drm_platform_data *pdata = pdev->dev.platform_data; |
| 747 | struct omap_drm_private *priv; | ||
| 748 | struct drm_device *ddev; | ||
| 749 | unsigned int i; | ||
| 750 | int ret; | ||
| 751 | |||
| 752 | DBG("%s", pdev->name); | ||
| 840 | 753 | ||
| 841 | if (omapdss_is_initialized() == false) | 754 | if (omapdss_is_initialized() == false) |
| 842 | return -EPROBE_DEFER; | 755 | return -EPROBE_DEFER; |
| 843 | 756 | ||
| 844 | omap_crtc_pre_init(); | 757 | omap_crtc_pre_init(); |
| 845 | 758 | ||
| 846 | r = omap_connect_dssdevs(); | 759 | ret = omap_connect_dssdevs(); |
| 847 | if (r) { | 760 | if (ret) |
| 848 | omap_crtc_pre_uninit(); | 761 | goto err_crtc_uninit; |
| 849 | return r; | 762 | |
| 763 | /* Allocate and initialize the driver private structure. */ | ||
| 764 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 765 | if (!priv) { | ||
| 766 | ret = -ENOMEM; | ||
| 767 | goto err_disconnect_dssdevs; | ||
| 850 | } | 768 | } |
| 851 | 769 | ||
| 852 | DBG("%s", device->name); | 770 | priv->omaprev = pdata->omaprev; |
| 853 | return drm_platform_init(&omap_drm_driver, device); | 771 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); |
| 772 | |||
| 773 | init_waitqueue_head(&priv->commit.wait); | ||
| 774 | spin_lock_init(&priv->commit.lock); | ||
| 775 | spin_lock_init(&priv->list_lock); | ||
| 776 | INIT_LIST_HEAD(&priv->obj_list); | ||
| 777 | |||
| 778 | /* Allocate and initialize the DRM device. */ | ||
| 779 | ddev = drm_dev_alloc(&omap_drm_driver, &pdev->dev); | ||
| 780 | if (IS_ERR(ddev)) { | ||
| 781 | ret = PTR_ERR(ddev); | ||
| 782 | goto err_free_priv; | ||
| 783 | } | ||
| 784 | |||
| 785 | ddev->dev_private = priv; | ||
| 786 | platform_set_drvdata(pdev, ddev); | ||
| 787 | |||
| 788 | omap_gem_init(ddev); | ||
| 789 | |||
| 790 | ret = omap_modeset_init(ddev); | ||
| 791 | if (ret) { | ||
| 792 | dev_err(&pdev->dev, "omap_modeset_init failed: ret=%d\n", ret); | ||
| 793 | goto err_free_drm_dev; | ||
| 794 | } | ||
| 795 | |||
| 796 | /* Initialize vblank handling, start with all CRTCs disabled. */ | ||
| 797 | ret = drm_vblank_init(ddev, priv->num_crtcs); | ||
| 798 | if (ret) { | ||
| 799 | dev_err(&pdev->dev, "could not init vblank\n"); | ||
| 800 | goto err_cleanup_modeset; | ||
| 801 | } | ||
| 802 | |||
| 803 | for (i = 0; i < priv->num_crtcs; i++) | ||
| 804 | drm_crtc_vblank_off(priv->crtcs[i]); | ||
| 805 | |||
| 806 | priv->fbdev = omap_fbdev_init(ddev); | ||
| 807 | |||
| 808 | drm_kms_helper_poll_init(ddev); | ||
| 809 | |||
| 810 | /* | ||
| 811 | * Register the DRM device with the core and the connectors with | ||
| 812 | * sysfs. | ||
| 813 | */ | ||
| 814 | ret = drm_dev_register(ddev, 0); | ||
| 815 | if (ret) | ||
| 816 | goto err_cleanup_helpers; | ||
| 817 | |||
| 818 | return 0; | ||
| 819 | |||
| 820 | err_cleanup_helpers: | ||
| 821 | drm_kms_helper_poll_fini(ddev); | ||
| 822 | if (priv->fbdev) | ||
| 823 | omap_fbdev_free(ddev); | ||
| 824 | err_cleanup_modeset: | ||
| 825 | drm_mode_config_cleanup(ddev); | ||
| 826 | omap_drm_irq_uninstall(ddev); | ||
| 827 | err_free_drm_dev: | ||
| 828 | omap_gem_deinit(ddev); | ||
| 829 | drm_dev_unref(ddev); | ||
| 830 | err_free_priv: | ||
| 831 | destroy_workqueue(priv->wq); | ||
| 832 | kfree(priv); | ||
| 833 | err_disconnect_dssdevs: | ||
| 834 | omap_disconnect_dssdevs(); | ||
| 835 | err_crtc_uninit: | ||
| 836 | omap_crtc_pre_uninit(); | ||
| 837 | return ret; | ||
| 854 | } | 838 | } |
| 855 | 839 | ||
| 856 | static int pdev_remove(struct platform_device *device) | 840 | static int pdev_remove(struct platform_device *pdev) |
| 857 | { | 841 | { |
| 842 | struct drm_device *ddev = platform_get_drvdata(pdev); | ||
| 843 | struct omap_drm_private *priv = ddev->dev_private; | ||
| 844 | |||
| 858 | DBG(""); | 845 | DBG(""); |
| 859 | 846 | ||
| 860 | drm_put_dev(platform_get_drvdata(device)); | 847 | drm_dev_unregister(ddev); |
| 848 | |||
| 849 | drm_kms_helper_poll_fini(ddev); | ||
| 850 | |||
| 851 | if (priv->fbdev) | ||
| 852 | omap_fbdev_free(ddev); | ||
| 853 | |||
| 854 | drm_mode_config_cleanup(ddev); | ||
| 855 | |||
| 856 | omap_drm_irq_uninstall(ddev); | ||
| 857 | omap_gem_deinit(ddev); | ||
| 858 | |||
| 859 | drm_dev_unref(ddev); | ||
| 860 | |||
| 861 | destroy_workqueue(priv->wq); | ||
| 862 | kfree(priv); | ||
| 861 | 863 | ||
| 862 | omap_disconnect_dssdevs(); | 864 | omap_disconnect_dssdevs(); |
| 863 | omap_crtc_pre_uninit(); | 865 | omap_crtc_pre_uninit(); |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 7d9dd5400cef..b20377efd01b 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
| @@ -48,19 +48,6 @@ struct omap_drm_window { | |||
| 48 | uint32_t src_w, src_h; | 48 | uint32_t src_w, src_h; |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | /* For transiently registering for different DSS irqs that various parts | ||
| 52 | * of the KMS code need during setup/configuration. We these are not | ||
| 53 | * necessarily the same as what drm_vblank_get/put() are requesting, and | ||
| 54 | * the hysteresis in drm_vblank_put() is not necessarily desirable for | ||
| 55 | * internal housekeeping related irq usage. | ||
| 56 | */ | ||
| 57 | struct omap_drm_irq { | ||
| 58 | struct list_head node; | ||
| 59 | uint32_t irqmask; | ||
| 60 | bool registered; | ||
| 61 | void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus); | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* For KMS code that needs to wait for a certain # of IRQs: | 51 | /* For KMS code that needs to wait for a certain # of IRQs: |
| 65 | */ | 52 | */ |
| 66 | struct omap_irq_wait; | 53 | struct omap_irq_wait; |
| @@ -101,9 +88,9 @@ struct omap_drm_private { | |||
| 101 | struct drm_property *zorder_prop; | 88 | struct drm_property *zorder_prop; |
| 102 | 89 | ||
| 103 | /* irq handling: */ | 90 | /* irq handling: */ |
| 104 | struct list_head irq_list; /* list of omap_drm_irq */ | 91 | spinlock_t wait_lock; /* protects the wait_list */ |
| 105 | uint32_t vblank_mask; /* irq bits set for userspace vblank */ | 92 | struct list_head wait_list; /* list of omap_irq_wait */ |
| 106 | struct omap_drm_irq error_handler; | 93 | uint32_t irq_mask; /* enabled irqs in addition to wait_list */ |
| 107 | 94 | ||
| 108 | /* atomic commit */ | 95 | /* atomic commit */ |
| 109 | struct { | 96 | struct { |
| @@ -128,10 +115,6 @@ int omap_gem_resume(struct device *dev); | |||
| 128 | 115 | ||
| 129 | int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe); | 116 | int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe); |
| 130 | void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe); | 117 | void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe); |
| 131 | void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); | ||
| 132 | void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); | ||
| 133 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); | ||
| 134 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); | ||
| 135 | void omap_drm_irq_uninstall(struct drm_device *dev); | 118 | void omap_drm_irq_uninstall(struct drm_device *dev); |
| 136 | int omap_drm_irq_install(struct drm_device *dev); | 119 | int omap_drm_irq_install(struct drm_device *dev); |
| 137 | 120 | ||
| @@ -155,6 +138,8 @@ void omap_crtc_pre_uninit(void); | |||
| 155 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 138 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
| 156 | struct drm_plane *plane, enum omap_channel channel, int id); | 139 | struct drm_plane *plane, enum omap_channel channel, int id); |
| 157 | int omap_crtc_wait_pending(struct drm_crtc *crtc); | 140 | int omap_crtc_wait_pending(struct drm_crtc *crtc); |
| 141 | void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus); | ||
| 142 | void omap_crtc_vblank_irq(struct drm_crtc *crtc); | ||
| 158 | 143 | ||
| 159 | struct drm_plane *omap_plane_init(struct drm_device *dev, | 144 | struct drm_plane *omap_plane_init(struct drm_device *dev, |
| 160 | int id, enum drm_plane_type type, | 145 | int id, enum drm_plane_type type, |
| @@ -233,32 +218,6 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, | |||
| 233 | struct dma_buf *buffer); | 218 | struct dma_buf *buffer); |
| 234 | 219 | ||
| 235 | /* map crtc to vblank mask */ | 220 | /* map crtc to vblank mask */ |
| 236 | uint32_t pipe2vbl(struct drm_crtc *crtc); | ||
| 237 | struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder); | 221 | struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder); |
| 238 | 222 | ||
| 239 | /* should these be made into common util helpers? | ||
| 240 | */ | ||
| 241 | |||
| 242 | static inline int objects_lookup( | ||
| 243 | struct drm_file *filp, uint32_t pixel_format, | ||
| 244 | struct drm_gem_object **bos, const uint32_t *handles) | ||
| 245 | { | ||
| 246 | int i, n = drm_format_num_planes(pixel_format); | ||
| 247 | |||
| 248 | for (i = 0; i < n; i++) { | ||
| 249 | bos[i] = drm_gem_object_lookup(filp, handles[i]); | ||
| 250 | if (!bos[i]) | ||
| 251 | goto fail; | ||
| 252 | |||
| 253 | } | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | |||
| 257 | fail: | ||
| 258 | while (--i > 0) | ||
| 259 | drm_gem_object_unreference_unlocked(bos[i]); | ||
| 260 | |||
| 261 | return -ENOENT; | ||
| 262 | } | ||
| 263 | |||
| 264 | #endif /* __OMAP_DRV_H__ */ | 223 | #endif /* __OMAP_DRV_H__ */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index a20f30039aee..86c977b7189a 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c | |||
| @@ -117,7 +117,7 @@ static int omap_encoder_update(struct drm_encoder *encoder, | |||
| 117 | 117 | ||
| 118 | dssdrv->get_timings(dssdev, &t); | 118 | dssdrv->get_timings(dssdev, &t); |
| 119 | 119 | ||
| 120 | if (memcmp(vm, &t, sizeof(struct videomode))) | 120 | if (memcmp(vm, &t, sizeof(*vm))) |
| 121 | ret = -EINVAL; | 121 | ret = -EINVAL; |
| 122 | else | 122 | else |
| 123 | ret = 0; | 123 | ret = 0; |
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index bd6b94c38613..29dc677dd4d3 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c | |||
| @@ -29,37 +29,30 @@ | |||
| 29 | * framebuffer funcs | 29 | * framebuffer funcs |
| 30 | */ | 30 | */ |
| 31 | 31 | ||
| 32 | /* per-format info: */ | 32 | /* DSS to DRM formats mapping */ |
| 33 | struct format { | 33 | static const struct { |
| 34 | enum omap_color_mode dss_format; | 34 | enum omap_color_mode dss_format; |
| 35 | uint32_t pixel_format; | 35 | uint32_t pixel_format; |
| 36 | struct { | 36 | } formats[] = { |
| 37 | int stride_bpp; /* this times width is stride */ | ||
| 38 | int sub_y; /* sub-sample in y dimension */ | ||
| 39 | } planes[4]; | ||
| 40 | bool yuv; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static const struct format formats[] = { | ||
| 44 | /* 16bpp [A]RGB: */ | 37 | /* 16bpp [A]RGB: */ |
| 45 | { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565, {{2, 1}}, false }, /* RGB16-565 */ | 38 | { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565 }, /* RGB16-565 */ |
| 46 | { OMAP_DSS_COLOR_RGB12U, DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */ | 39 | { OMAP_DSS_COLOR_RGB12U, DRM_FORMAT_RGBX4444 }, /* RGB12x-4444 */ |
| 47 | { OMAP_DSS_COLOR_RGBX16, DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */ | 40 | { OMAP_DSS_COLOR_RGBX16, DRM_FORMAT_XRGB4444 }, /* xRGB12-4444 */ |
| 48 | { OMAP_DSS_COLOR_RGBA16, DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */ | 41 | { OMAP_DSS_COLOR_RGBA16, DRM_FORMAT_RGBA4444 }, /* RGBA12-4444 */ |
| 49 | { OMAP_DSS_COLOR_ARGB16, DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */ | 42 | { OMAP_DSS_COLOR_ARGB16, DRM_FORMAT_ARGB4444 }, /* ARGB16-4444 */ |
| 50 | { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */ | 43 | { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555 }, /* xRGB15-1555 */ |
| 51 | { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */ | 44 | { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555 }, /* ARGB16-1555 */ |
| 52 | /* 24bpp RGB: */ | 45 | /* 24bpp RGB: */ |
| 53 | { OMAP_DSS_COLOR_RGB24P, DRM_FORMAT_RGB888, {{3, 1}}, false }, /* RGB24-888 */ | 46 | { OMAP_DSS_COLOR_RGB24P, DRM_FORMAT_RGB888 }, /* RGB24-888 */ |
| 54 | /* 32bpp [A]RGB: */ | 47 | /* 32bpp [A]RGB: */ |
| 55 | { OMAP_DSS_COLOR_RGBX32, DRM_FORMAT_RGBX8888, {{4, 1}}, false }, /* RGBx24-8888 */ | 48 | { OMAP_DSS_COLOR_RGBX32, DRM_FORMAT_RGBX8888 }, /* RGBx24-8888 */ |
| 56 | { OMAP_DSS_COLOR_RGB24U, DRM_FORMAT_XRGB8888, {{4, 1}}, false }, /* xRGB24-8888 */ | 49 | { OMAP_DSS_COLOR_RGB24U, DRM_FORMAT_XRGB8888 }, /* xRGB24-8888 */ |
| 57 | { OMAP_DSS_COLOR_RGBA32, DRM_FORMAT_RGBA8888, {{4, 1}}, false }, /* RGBA32-8888 */ | 50 | { OMAP_DSS_COLOR_RGBA32, DRM_FORMAT_RGBA8888 }, /* RGBA32-8888 */ |
| 58 | { OMAP_DSS_COLOR_ARGB32, DRM_FORMAT_ARGB8888, {{4, 1}}, false }, /* ARGB32-8888 */ | 51 | { OMAP_DSS_COLOR_ARGB32, DRM_FORMAT_ARGB8888 }, /* ARGB32-8888 */ |
| 59 | /* YUV: */ | 52 | /* YUV: */ |
| 60 | { OMAP_DSS_COLOR_NV12, DRM_FORMAT_NV12, {{1, 1}, {1, 2}}, true }, | 53 | { OMAP_DSS_COLOR_NV12, DRM_FORMAT_NV12 }, |
| 61 | { OMAP_DSS_COLOR_YUV2, DRM_FORMAT_YUYV, {{2, 1}}, true }, | 54 | { OMAP_DSS_COLOR_YUV2, DRM_FORMAT_YUYV }, |
| 62 | { OMAP_DSS_COLOR_UYVY, DRM_FORMAT_UYVY, {{2, 1}}, true }, | 55 | { OMAP_DSS_COLOR_UYVY, DRM_FORMAT_UYVY }, |
| 63 | }; | 56 | }; |
| 64 | 57 | ||
| 65 | /* convert from overlay's pixel formats bitmask to an array of fourcc's */ | 58 | /* convert from overlay's pixel formats bitmask to an array of fourcc's */ |
| @@ -89,8 +82,9 @@ struct plane { | |||
| 89 | struct omap_framebuffer { | 82 | struct omap_framebuffer { |
| 90 | struct drm_framebuffer base; | 83 | struct drm_framebuffer base; |
| 91 | int pin_count; | 84 | int pin_count; |
| 92 | const struct format *format; | 85 | const struct drm_format_info *format; |
| 93 | struct plane planes[4]; | 86 | enum omap_color_mode dss_format; |
| 87 | struct plane planes[2]; | ||
| 94 | /* lock for pinning (pin_count and planes.paddr) */ | 88 | /* lock for pinning (pin_count and planes.paddr) */ |
| 95 | struct mutex lock; | 89 | struct mutex lock; |
| 96 | }; | 90 | }; |
| @@ -128,13 +122,13 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = { | |||
| 128 | }; | 122 | }; |
| 129 | 123 | ||
| 130 | static uint32_t get_linear_addr(struct plane *plane, | 124 | static uint32_t get_linear_addr(struct plane *plane, |
| 131 | const struct format *format, int n, int x, int y) | 125 | const struct drm_format_info *format, int n, int x, int y) |
| 132 | { | 126 | { |
| 133 | uint32_t offset; | 127 | uint32_t offset; |
| 134 | 128 | ||
| 135 | offset = plane->offset + | 129 | offset = plane->offset |
| 136 | (x * format->planes[n].stride_bpp) + | 130 | + (x * format->cpp[n] / (n == 0 ? 1 : format->hsub)) |
| 137 | (y * plane->pitch / format->planes[n].sub_y); | 131 | + (y * plane->pitch / (n == 0 ? 1 : format->vsub)); |
| 138 | 132 | ||
| 139 | return plane->paddr + offset; | 133 | return plane->paddr + offset; |
| 140 | } | 134 | } |
| @@ -153,11 +147,11 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, | |||
| 153 | struct omap_drm_window *win, struct omap_overlay_info *info) | 147 | struct omap_drm_window *win, struct omap_overlay_info *info) |
| 154 | { | 148 | { |
| 155 | struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); | 149 | struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); |
| 156 | const struct format *format = omap_fb->format; | 150 | const struct drm_format_info *format = omap_fb->format; |
| 157 | struct plane *plane = &omap_fb->planes[0]; | 151 | struct plane *plane = &omap_fb->planes[0]; |
| 158 | uint32_t x, y, orient = 0; | 152 | uint32_t x, y, orient = 0; |
| 159 | 153 | ||
| 160 | info->color_mode = format->dss_format; | 154 | info->color_mode = omap_fb->dss_format; |
| 161 | 155 | ||
| 162 | info->pos_x = win->crtc_x; | 156 | info->pos_x = win->crtc_x; |
| 163 | info->pos_y = win->crtc_y; | 157 | info->pos_y = win->crtc_y; |
| @@ -231,9 +225,9 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, | |||
| 231 | } | 225 | } |
| 232 | 226 | ||
| 233 | /* convert to pixels: */ | 227 | /* convert to pixels: */ |
| 234 | info->screen_width /= format->planes[0].stride_bpp; | 228 | info->screen_width /= format->cpp[0]; |
| 235 | 229 | ||
| 236 | if (format->dss_format == OMAP_DSS_COLOR_NV12) { | 230 | if (omap_fb->dss_format == OMAP_DSS_COLOR_NV12) { |
| 237 | plane = &omap_fb->planes[1]; | 231 | plane = &omap_fb->planes[1]; |
| 238 | 232 | ||
| 239 | if (info->rotation_type == OMAP_DSS_ROT_TILER) { | 233 | if (info->rotation_type == OMAP_DSS_ROT_TILER) { |
| @@ -360,47 +354,58 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) | |||
| 360 | struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, | 354 | struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, |
| 361 | struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) | 355 | struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) |
| 362 | { | 356 | { |
| 357 | unsigned int num_planes = drm_format_num_planes(mode_cmd->pixel_format); | ||
| 363 | struct drm_gem_object *bos[4]; | 358 | struct drm_gem_object *bos[4]; |
| 364 | struct drm_framebuffer *fb; | 359 | struct drm_framebuffer *fb; |
| 365 | int ret; | 360 | int i; |
| 366 | 361 | ||
| 367 | ret = objects_lookup(file, mode_cmd->pixel_format, | 362 | for (i = 0; i < num_planes; i++) { |
| 368 | bos, mode_cmd->handles); | 363 | bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); |
| 369 | if (ret) | 364 | if (!bos[i]) { |
| 370 | return ERR_PTR(ret); | 365 | fb = ERR_PTR(-ENOENT); |
| 366 | goto error; | ||
| 367 | } | ||
| 368 | } | ||
| 371 | 369 | ||
| 372 | fb = omap_framebuffer_init(dev, mode_cmd, bos); | 370 | fb = omap_framebuffer_init(dev, mode_cmd, bos); |
| 373 | if (IS_ERR(fb)) { | 371 | if (IS_ERR(fb)) |
| 374 | int i, n = drm_format_num_planes(mode_cmd->pixel_format); | 372 | goto error; |
| 375 | for (i = 0; i < n; i++) | 373 | |
| 376 | drm_gem_object_unreference_unlocked(bos[i]); | 374 | return fb; |
| 377 | return fb; | 375 | |
| 378 | } | 376 | error: |
| 377 | while (--i > 0) | ||
| 378 | drm_gem_object_unreference_unlocked(bos[i]); | ||
| 379 | |||
| 379 | return fb; | 380 | return fb; |
| 380 | } | 381 | } |
| 381 | 382 | ||
| 382 | struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, | 383 | struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, |
| 383 | const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos) | 384 | const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos) |
| 384 | { | 385 | { |
| 386 | const struct drm_format_info *format = NULL; | ||
| 385 | struct omap_framebuffer *omap_fb = NULL; | 387 | struct omap_framebuffer *omap_fb = NULL; |
| 386 | struct drm_framebuffer *fb = NULL; | 388 | struct drm_framebuffer *fb = NULL; |
| 387 | const struct format *format = NULL; | 389 | enum omap_color_mode dss_format = 0; |
| 388 | int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format); | 390 | unsigned int pitch = mode_cmd->pitches[0]; |
| 391 | int ret, i; | ||
| 389 | 392 | ||
| 390 | DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)", | 393 | DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)", |
| 391 | dev, mode_cmd, mode_cmd->width, mode_cmd->height, | 394 | dev, mode_cmd, mode_cmd->width, mode_cmd->height, |
| 392 | (char *)&mode_cmd->pixel_format); | 395 | (char *)&mode_cmd->pixel_format); |
| 393 | 396 | ||
| 397 | format = drm_format_info(mode_cmd->pixel_format); | ||
| 398 | |||
| 394 | for (i = 0; i < ARRAY_SIZE(formats); i++) { | 399 | for (i = 0; i < ARRAY_SIZE(formats); i++) { |
| 395 | if (formats[i].pixel_format == mode_cmd->pixel_format) { | 400 | if (formats[i].pixel_format == mode_cmd->pixel_format) { |
| 396 | format = &formats[i]; | 401 | dss_format = formats[i].dss_format; |
| 397 | break; | 402 | break; |
| 398 | } | 403 | } |
| 399 | } | 404 | } |
| 400 | 405 | ||
| 401 | if (!format) { | 406 | if (!format || !dss_format) { |
| 402 | dev_err(dev->dev, "unsupported pixel format: %4.4s\n", | 407 | dev_dbg(dev->dev, "unsupported pixel format: %4.4s\n", |
| 403 | (char *)&mode_cmd->pixel_format); | 408 | (char *)&mode_cmd->pixel_format); |
| 404 | ret = -EINVAL; | 409 | ret = -EINVAL; |
| 405 | goto fail; | 410 | goto fail; |
| 406 | } | 411 | } |
| @@ -413,40 +418,39 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, | |||
| 413 | 418 | ||
| 414 | fb = &omap_fb->base; | 419 | fb = &omap_fb->base; |
| 415 | omap_fb->format = format; | 420 | omap_fb->format = format; |
| 421 | omap_fb->dss_format = dss_format; | ||
| 416 | mutex_init(&omap_fb->lock); | 422 | mutex_init(&omap_fb->lock); |
| 417 | 423 | ||
| 418 | for (i = 0; i < n; i++) { | 424 | /* |
| 419 | struct plane *plane = &omap_fb->planes[i]; | 425 | * The code below assumes that no format use more than two planes, and |
| 420 | int size, pitch = mode_cmd->pitches[i]; | 426 | * that the two planes of multiplane formats need the same number of |
| 421 | 427 | * bytes per pixel. | |
| 422 | if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) { | 428 | */ |
| 423 | dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n", | 429 | if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) { |
| 424 | pitch, mode_cmd->width * format->planes[i].stride_bpp); | 430 | dev_dbg(dev->dev, "pitches differ between planes 0 and 1\n"); |
| 425 | ret = -EINVAL; | 431 | ret = -EINVAL; |
| 426 | goto fail; | 432 | goto fail; |
| 427 | } | 433 | } |
| 428 | 434 | ||
| 429 | if (pitch % format->planes[i].stride_bpp != 0) { | 435 | if (pitch % format->cpp[0]) { |
| 430 | dev_err(dev->dev, | 436 | dev_dbg(dev->dev, |
| 431 | "buffer pitch (%d bytes) is not a multiple of pixel size (%d bytes)\n", | 437 | "buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n", |
| 432 | pitch, format->planes[i].stride_bpp); | 438 | pitch, format->cpp[0]); |
| 433 | ret = -EINVAL; | 439 | ret = -EINVAL; |
| 434 | goto fail; | 440 | goto fail; |
| 435 | } | 441 | } |
| 436 | 442 | ||
| 437 | size = pitch * mode_cmd->height / format->planes[i].sub_y; | 443 | for (i = 0; i < format->num_planes; i++) { |
| 444 | struct plane *plane = &omap_fb->planes[i]; | ||
| 445 | unsigned int vsub = i == 0 ? 1 : format->vsub; | ||
| 446 | unsigned int size; | ||
| 438 | 447 | ||
| 439 | if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) { | 448 | size = pitch * mode_cmd->height / vsub; |
| 440 | dev_err(dev->dev, "provided buffer object is too small! %d < %d\n", | ||
| 441 | bos[i]->size - mode_cmd->offsets[i], size); | ||
| 442 | ret = -EINVAL; | ||
| 443 | goto fail; | ||
| 444 | } | ||
| 445 | 449 | ||
| 446 | if (i > 0 && pitch != mode_cmd->pitches[i - 1]) { | 450 | if (size > omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i]) { |
| 447 | dev_err(dev->dev, | 451 | dev_dbg(dev->dev, |
| 448 | "pitches are not the same between framebuffer planes %d != %d\n", | 452 | "provided buffer object is too small! %d < %d\n", |
| 449 | pitch, mode_cmd->pitches[i - 1]); | 453 | bos[i]->size - mode_cmd->offsets[i], size); |
| 450 | ret = -EINVAL; | 454 | ret = -EINVAL; |
| 451 | goto fail; | 455 | goto fail; |
| 452 | } | 456 | } |
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c index 60e1e8016708..9adfa7c99695 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.c +++ b/drivers/gpu/drm/omapdrm/omap_irq.c | |||
| @@ -19,25 +19,24 @@ | |||
| 19 | 19 | ||
| 20 | #include "omap_drv.h" | 20 | #include "omap_drv.h" |
| 21 | 21 | ||
| 22 | static DEFINE_SPINLOCK(list_lock); | 22 | struct omap_irq_wait { |
| 23 | 23 | struct list_head node; | |
| 24 | static void omap_irq_error_handler(struct omap_drm_irq *irq, | 24 | wait_queue_head_t wq; |
| 25 | uint32_t irqstatus) | 25 | uint32_t irqmask; |
| 26 | { | 26 | int count; |
| 27 | DRM_ERROR("errors: %08x\n", irqstatus); | 27 | }; |
| 28 | } | ||
| 29 | 28 | ||
| 30 | /* call with list_lock and dispc runtime held */ | 29 | /* call with wait_lock and dispc runtime held */ |
| 31 | static void omap_irq_update(struct drm_device *dev) | 30 | static void omap_irq_update(struct drm_device *dev) |
| 32 | { | 31 | { |
| 33 | struct omap_drm_private *priv = dev->dev_private; | 32 | struct omap_drm_private *priv = dev->dev_private; |
| 34 | struct omap_drm_irq *irq; | 33 | struct omap_irq_wait *wait; |
| 35 | uint32_t irqmask = priv->vblank_mask; | 34 | uint32_t irqmask = priv->irq_mask; |
| 36 | 35 | ||
| 37 | assert_spin_locked(&list_lock); | 36 | assert_spin_locked(&priv->wait_lock); |
| 38 | 37 | ||
| 39 | list_for_each_entry(irq, &priv->irq_list, node) | 38 | list_for_each_entry(wait, &priv->wait_list, node) |
| 40 | irqmask |= irq->irqmask; | 39 | irqmask |= wait->irqmask; |
| 41 | 40 | ||
| 42 | DBG("irqmask=%08x", irqmask); | 41 | DBG("irqmask=%08x", irqmask); |
| 43 | 42 | ||
| @@ -45,90 +44,48 @@ static void omap_irq_update(struct drm_device *dev) | |||
| 45 | dispc_read_irqenable(); /* flush posted write */ | 44 | dispc_read_irqenable(); /* flush posted write */ |
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) | 47 | static void omap_irq_wait_handler(struct omap_irq_wait *wait) |
| 49 | { | ||
| 50 | struct omap_drm_private *priv = dev->dev_private; | ||
| 51 | unsigned long flags; | ||
| 52 | |||
| 53 | spin_lock_irqsave(&list_lock, flags); | ||
| 54 | |||
| 55 | if (!WARN_ON(irq->registered)) { | ||
| 56 | irq->registered = true; | ||
| 57 | list_add(&irq->node, &priv->irq_list); | ||
| 58 | omap_irq_update(dev); | ||
| 59 | } | ||
| 60 | |||
| 61 | spin_unlock_irqrestore(&list_lock, flags); | ||
| 62 | } | ||
| 63 | |||
| 64 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) | ||
| 65 | { | ||
| 66 | dispc_runtime_get(); | ||
| 67 | |||
| 68 | __omap_irq_register(dev, irq); | ||
| 69 | |||
| 70 | dispc_runtime_put(); | ||
| 71 | } | ||
| 72 | |||
| 73 | void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) | ||
| 74 | { | 48 | { |
| 75 | unsigned long flags; | ||
| 76 | |||
| 77 | spin_lock_irqsave(&list_lock, flags); | ||
| 78 | |||
| 79 | if (!WARN_ON(!irq->registered)) { | ||
| 80 | irq->registered = false; | ||
| 81 | list_del(&irq->node); | ||
| 82 | omap_irq_update(dev); | ||
| 83 | } | ||
| 84 | |||
| 85 | spin_unlock_irqrestore(&list_lock, flags); | ||
| 86 | } | ||
| 87 | |||
| 88 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) | ||
| 89 | { | ||
| 90 | dispc_runtime_get(); | ||
| 91 | |||
| 92 | __omap_irq_unregister(dev, irq); | ||
| 93 | |||
| 94 | dispc_runtime_put(); | ||
| 95 | } | ||
| 96 | |||
| 97 | struct omap_irq_wait { | ||
| 98 | struct omap_drm_irq irq; | ||
| 99 | int count; | ||
| 100 | }; | ||
| 101 | |||
| 102 | static DECLARE_WAIT_QUEUE_HEAD(wait_event); | ||
| 103 | |||
| 104 | static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
| 105 | { | ||
| 106 | struct omap_irq_wait *wait = | ||
| 107 | container_of(irq, struct omap_irq_wait, irq); | ||
| 108 | wait->count--; | 49 | wait->count--; |
| 109 | wake_up_all(&wait_event); | 50 | wake_up(&wait->wq); |
| 110 | } | 51 | } |
| 111 | 52 | ||
| 112 | struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, | 53 | struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, |
| 113 | uint32_t irqmask, int count) | 54 | uint32_t irqmask, int count) |
| 114 | { | 55 | { |
| 56 | struct omap_drm_private *priv = dev->dev_private; | ||
| 115 | struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL); | 57 | struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL); |
| 116 | wait->irq.irq = wait_irq; | 58 | unsigned long flags; |
| 117 | wait->irq.irqmask = irqmask; | 59 | |
| 60 | init_waitqueue_head(&wait->wq); | ||
| 61 | wait->irqmask = irqmask; | ||
| 118 | wait->count = count; | 62 | wait->count = count; |
| 119 | omap_irq_register(dev, &wait->irq); | 63 | |
| 64 | spin_lock_irqsave(&priv->wait_lock, flags); | ||
| 65 | list_add(&wait->node, &priv->wait_list); | ||
| 66 | omap_irq_update(dev); | ||
| 67 | spin_unlock_irqrestore(&priv->wait_lock, flags); | ||
| 68 | |||
| 120 | return wait; | 69 | return wait; |
| 121 | } | 70 | } |
| 122 | 71 | ||
| 123 | int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, | 72 | int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, |
| 124 | unsigned long timeout) | 73 | unsigned long timeout) |
| 125 | { | 74 | { |
| 126 | int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout); | 75 | struct omap_drm_private *priv = dev->dev_private; |
| 127 | omap_irq_unregister(dev, &wait->irq); | 76 | unsigned long flags; |
| 77 | int ret; | ||
| 78 | |||
| 79 | ret = wait_event_timeout(wait->wq, (wait->count <= 0), timeout); | ||
| 80 | |||
| 81 | spin_lock_irqsave(&priv->wait_lock, flags); | ||
| 82 | list_del(&wait->node); | ||
| 83 | omap_irq_update(dev); | ||
| 84 | spin_unlock_irqrestore(&priv->wait_lock, flags); | ||
| 85 | |||
| 128 | kfree(wait); | 86 | kfree(wait); |
| 129 | if (ret == 0) | 87 | |
| 130 | return -1; | 88 | return ret == 0 ? -1 : 0; |
| 131 | return 0; | ||
| 132 | } | 89 | } |
| 133 | 90 | ||
| 134 | /** | 91 | /** |
| @@ -152,10 +109,10 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe) | |||
| 152 | 109 | ||
| 153 | DBG("dev=%p, crtc=%u", dev, pipe); | 110 | DBG("dev=%p, crtc=%u", dev, pipe); |
| 154 | 111 | ||
| 155 | spin_lock_irqsave(&list_lock, flags); | 112 | spin_lock_irqsave(&priv->wait_lock, flags); |
| 156 | priv->vblank_mask |= pipe2vbl(crtc); | 113 | priv->irq_mask |= dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc)); |
| 157 | omap_irq_update(dev); | 114 | omap_irq_update(dev); |
| 158 | spin_unlock_irqrestore(&list_lock, flags); | 115 | spin_unlock_irqrestore(&priv->wait_lock, flags); |
| 159 | 116 | ||
| 160 | return 0; | 117 | return 0; |
| 161 | } | 118 | } |
| @@ -177,17 +134,66 @@ void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe) | |||
| 177 | 134 | ||
| 178 | DBG("dev=%p, crtc=%u", dev, pipe); | 135 | DBG("dev=%p, crtc=%u", dev, pipe); |
| 179 | 136 | ||
| 180 | spin_lock_irqsave(&list_lock, flags); | 137 | spin_lock_irqsave(&priv->wait_lock, flags); |
| 181 | priv->vblank_mask &= ~pipe2vbl(crtc); | 138 | priv->irq_mask &= ~dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc)); |
| 182 | omap_irq_update(dev); | 139 | omap_irq_update(dev); |
| 183 | spin_unlock_irqrestore(&list_lock, flags); | 140 | spin_unlock_irqrestore(&priv->wait_lock, flags); |
| 141 | } | ||
| 142 | |||
| 143 | static void omap_irq_fifo_underflow(struct omap_drm_private *priv, | ||
| 144 | u32 irqstatus) | ||
| 145 | { | ||
| 146 | static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, | ||
| 147 | DEFAULT_RATELIMIT_BURST); | ||
| 148 | static const struct { | ||
| 149 | const char *name; | ||
| 150 | u32 mask; | ||
| 151 | } sources[] = { | ||
| 152 | { "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW }, | ||
| 153 | { "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW }, | ||
| 154 | { "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW }, | ||
| 155 | { "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW }, | ||
| 156 | }; | ||
| 157 | |||
| 158 | const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW | ||
| 159 | | DISPC_IRQ_VID1_FIFO_UNDERFLOW | ||
| 160 | | DISPC_IRQ_VID2_FIFO_UNDERFLOW | ||
| 161 | | DISPC_IRQ_VID3_FIFO_UNDERFLOW; | ||
| 162 | unsigned int i; | ||
| 163 | |||
| 164 | spin_lock(&priv->wait_lock); | ||
| 165 | irqstatus &= priv->irq_mask & mask; | ||
| 166 | spin_unlock(&priv->wait_lock); | ||
| 167 | |||
| 168 | if (!irqstatus) | ||
| 169 | return; | ||
| 170 | |||
| 171 | if (!__ratelimit(&_rs)) | ||
| 172 | return; | ||
| 173 | |||
| 174 | DRM_ERROR("FIFO underflow on "); | ||
| 175 | |||
| 176 | for (i = 0; i < ARRAY_SIZE(sources); ++i) { | ||
| 177 | if (sources[i].mask & irqstatus) | ||
| 178 | pr_cont("%s ", sources[i].name); | ||
| 179 | } | ||
| 180 | |||
| 181 | pr_cont("(0x%08x)\n", irqstatus); | ||
| 182 | } | ||
| 183 | |||
| 184 | static void omap_irq_ocp_error_handler(u32 irqstatus) | ||
| 185 | { | ||
| 186 | if (!(irqstatus & DISPC_IRQ_OCP_ERR)) | ||
| 187 | return; | ||
| 188 | |||
| 189 | DRM_ERROR("OCP error\n"); | ||
| 184 | } | 190 | } |
| 185 | 191 | ||
| 186 | static irqreturn_t omap_irq_handler(int irq, void *arg) | 192 | static irqreturn_t omap_irq_handler(int irq, void *arg) |
| 187 | { | 193 | { |
| 188 | struct drm_device *dev = (struct drm_device *) arg; | 194 | struct drm_device *dev = (struct drm_device *) arg; |
| 189 | struct omap_drm_private *priv = dev->dev_private; | 195 | struct omap_drm_private *priv = dev->dev_private; |
| 190 | struct omap_drm_irq *handler, *n; | 196 | struct omap_irq_wait *wait, *n; |
| 191 | unsigned long flags; | 197 | unsigned long flags; |
| 192 | unsigned int id; | 198 | unsigned int id; |
| 193 | u32 irqstatus; | 199 | u32 irqstatus; |
| @@ -200,24 +206,37 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) | |||
| 200 | 206 | ||
| 201 | for (id = 0; id < priv->num_crtcs; id++) { | 207 | for (id = 0; id < priv->num_crtcs; id++) { |
| 202 | struct drm_crtc *crtc = priv->crtcs[id]; | 208 | struct drm_crtc *crtc = priv->crtcs[id]; |
| 209 | enum omap_channel channel = omap_crtc_channel(crtc); | ||
| 203 | 210 | ||
| 204 | if (irqstatus & pipe2vbl(crtc)) | 211 | if (irqstatus & dispc_mgr_get_vsync_irq(channel)) { |
| 205 | drm_handle_vblank(dev, id); | 212 | drm_handle_vblank(dev, id); |
| 213 | omap_crtc_vblank_irq(crtc); | ||
| 214 | } | ||
| 215 | |||
| 216 | if (irqstatus & dispc_mgr_get_sync_lost_irq(channel)) | ||
| 217 | omap_crtc_error_irq(crtc, irqstatus); | ||
| 206 | } | 218 | } |
| 207 | 219 | ||
| 208 | spin_lock_irqsave(&list_lock, flags); | 220 | omap_irq_ocp_error_handler(irqstatus); |
| 209 | list_for_each_entry_safe(handler, n, &priv->irq_list, node) { | 221 | omap_irq_fifo_underflow(priv, irqstatus); |
| 210 | if (handler->irqmask & irqstatus) { | 222 | |
| 211 | spin_unlock_irqrestore(&list_lock, flags); | 223 | spin_lock_irqsave(&priv->wait_lock, flags); |
| 212 | handler->irq(handler, handler->irqmask & irqstatus); | 224 | list_for_each_entry_safe(wait, n, &priv->wait_list, node) { |
| 213 | spin_lock_irqsave(&list_lock, flags); | 225 | if (wait->irqmask & irqstatus) |
| 214 | } | 226 | omap_irq_wait_handler(wait); |
| 215 | } | 227 | } |
| 216 | spin_unlock_irqrestore(&list_lock, flags); | 228 | spin_unlock_irqrestore(&priv->wait_lock, flags); |
| 217 | 229 | ||
| 218 | return IRQ_HANDLED; | 230 | return IRQ_HANDLED; |
| 219 | } | 231 | } |
| 220 | 232 | ||
| 233 | static const u32 omap_underflow_irqs[] = { | ||
| 234 | [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW, | ||
| 235 | [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW, | ||
| 236 | [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW, | ||
| 237 | [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW, | ||
| 238 | }; | ||
| 239 | |||
| 221 | /* | 240 | /* |
| 222 | * We need a special version, instead of just using drm_irq_install(), | 241 | * We need a special version, instead of just using drm_irq_install(), |
| 223 | * because we need to register the irq via omapdss. Once omapdss and | 242 | * because we need to register the irq via omapdss. Once omapdss and |
| @@ -228,10 +247,25 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) | |||
| 228 | int omap_drm_irq_install(struct drm_device *dev) | 247 | int omap_drm_irq_install(struct drm_device *dev) |
| 229 | { | 248 | { |
| 230 | struct omap_drm_private *priv = dev->dev_private; | 249 | struct omap_drm_private *priv = dev->dev_private; |
| 231 | struct omap_drm_irq *error_handler = &priv->error_handler; | 250 | unsigned int num_mgrs = dss_feat_get_num_mgrs(); |
| 251 | unsigned int max_planes; | ||
| 252 | unsigned int i; | ||
| 232 | int ret; | 253 | int ret; |
| 233 | 254 | ||
| 234 | INIT_LIST_HEAD(&priv->irq_list); | 255 | spin_lock_init(&priv->wait_lock); |
| 256 | INIT_LIST_HEAD(&priv->wait_list); | ||
| 257 | |||
| 258 | priv->irq_mask = DISPC_IRQ_OCP_ERR; | ||
| 259 | |||
| 260 | max_planes = min(ARRAY_SIZE(priv->planes), | ||
| 261 | ARRAY_SIZE(omap_underflow_irqs)); | ||
| 262 | for (i = 0; i < max_planes; ++i) { | ||
| 263 | if (priv->planes[i]) | ||
| 264 | priv->irq_mask |= omap_underflow_irqs[i]; | ||
| 265 | } | ||
| 266 | |||
| 267 | for (i = 0; i < num_mgrs; ++i) | ||
| 268 | priv->irq_mask |= dispc_mgr_get_sync_lost_irq(i); | ||
| 235 | 269 | ||
| 236 | dispc_runtime_get(); | 270 | dispc_runtime_get(); |
| 237 | dispc_clear_irqstatus(0xffffffff); | 271 | dispc_clear_irqstatus(0xffffffff); |
| @@ -241,16 +275,6 @@ int omap_drm_irq_install(struct drm_device *dev) | |||
| 241 | if (ret < 0) | 275 | if (ret < 0) |
| 242 | return ret; | 276 | return ret; |
| 243 | 277 | ||
| 244 | error_handler->irq = omap_irq_error_handler; | ||
| 245 | error_handler->irqmask = DISPC_IRQ_OCP_ERR; | ||
| 246 | |||
| 247 | /* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think | ||
| 248 | * we just need to ignore it while enabling tv-out | ||
| 249 | */ | ||
| 250 | error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; | ||
| 251 | |||
| 252 | omap_irq_register(dev, error_handler); | ||
| 253 | |||
| 254 | dev->irq_enabled = true; | 278 | dev->irq_enabled = true; |
| 255 | 279 | ||
| 256 | return 0; | 280 | return 0; |
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 82b2c23d6769..386d90af70f7 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c | |||
| @@ -43,8 +43,6 @@ struct omap_plane { | |||
| 43 | 43 | ||
| 44 | uint32_t nformats; | 44 | uint32_t nformats; |
| 45 | uint32_t formats[32]; | 45 | uint32_t formats[32]; |
| 46 | |||
| 47 | struct omap_drm_irq error_irq; | ||
| 48 | }; | 46 | }; |
| 49 | 47 | ||
| 50 | struct omap_plane_state { | 48 | struct omap_plane_state { |
| @@ -204,8 +202,6 @@ static void omap_plane_destroy(struct drm_plane *plane) | |||
| 204 | 202 | ||
| 205 | DBG("%s", omap_plane->name); | 203 | DBG("%s", omap_plane->name); |
| 206 | 204 | ||
| 207 | omap_irq_unregister(plane->dev, &omap_plane->error_irq); | ||
| 208 | |||
| 209 | drm_plane_cleanup(plane); | 205 | drm_plane_cleanup(plane); |
| 210 | 206 | ||
| 211 | kfree(omap_plane); | 207 | kfree(omap_plane); |
| @@ -332,14 +328,6 @@ static const struct drm_plane_funcs omap_plane_funcs = { | |||
| 332 | .atomic_get_property = omap_plane_atomic_get_property, | 328 | .atomic_get_property = omap_plane_atomic_get_property, |
| 333 | }; | 329 | }; |
| 334 | 330 | ||
| 335 | static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
| 336 | { | ||
| 337 | struct omap_plane *omap_plane = | ||
| 338 | container_of(irq, struct omap_plane, error_irq); | ||
| 339 | DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_plane->name, | ||
| 340 | irqstatus); | ||
| 341 | } | ||
| 342 | |||
| 343 | static const char *plane_names[] = { | 331 | static const char *plane_names[] = { |
| 344 | [OMAP_DSS_GFX] = "gfx", | 332 | [OMAP_DSS_GFX] = "gfx", |
| 345 | [OMAP_DSS_VIDEO1] = "vid1", | 333 | [OMAP_DSS_VIDEO1] = "vid1", |
| @@ -347,13 +335,6 @@ static const char *plane_names[] = { | |||
| 347 | [OMAP_DSS_VIDEO3] = "vid3", | 335 | [OMAP_DSS_VIDEO3] = "vid3", |
| 348 | }; | 336 | }; |
| 349 | 337 | ||
| 350 | static const uint32_t error_irqs[] = { | ||
| 351 | [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW, | ||
| 352 | [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW, | ||
| 353 | [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW, | ||
| 354 | [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW, | ||
| 355 | }; | ||
| 356 | |||
| 357 | /* initialize plane */ | 338 | /* initialize plane */ |
| 358 | struct drm_plane *omap_plane_init(struct drm_device *dev, | 339 | struct drm_plane *omap_plane_init(struct drm_device *dev, |
| 359 | int id, enum drm_plane_type type, | 340 | int id, enum drm_plane_type type, |
| @@ -377,10 +358,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, | |||
| 377 | 358 | ||
| 378 | plane = &omap_plane->base; | 359 | plane = &omap_plane->base; |
| 379 | 360 | ||
| 380 | omap_plane->error_irq.irqmask = error_irqs[id]; | ||
| 381 | omap_plane->error_irq.irq = omap_plane_error_irq; | ||
| 382 | omap_irq_register(dev, &omap_plane->error_irq); | ||
| 383 | |||
| 384 | ret = drm_universal_plane_init(dev, plane, possible_crtcs, | 361 | ret = drm_universal_plane_init(dev, plane, possible_crtcs, |
| 385 | &omap_plane_funcs, omap_plane->formats, | 362 | &omap_plane_funcs, omap_plane->formats, |
| 386 | omap_plane->nformats, type, NULL); | 363 | omap_plane->nformats, type, NULL); |
| @@ -394,7 +371,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, | |||
| 394 | return plane; | 371 | return plane; |
| 395 | 372 | ||
| 396 | error: | 373 | error: |
| 397 | omap_irq_unregister(plane->dev, &omap_plane->error_irq); | ||
| 398 | kfree(omap_plane); | 374 | kfree(omap_plane); |
| 399 | return NULL; | 375 | return NULL; |
| 400 | } | 376 | } |
