aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_drv.c4
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c2
-rw-r--r--drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c1
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c27
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c18
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c3
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss.h1
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c154
-rw-r--r--drivers/gpu/drm/omapdrm/omap_dmm_tiler.c4
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c216
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h51
-rw-r--r--drivers/gpu/drm/omapdrm/omap_encoder.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c164
-rw-r--r--drivers/gpu/drm/omapdrm/omap_irq.c242
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c24
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
910module_spi_driver(acx565akm_driver); 910module_spi_driver(acx565akm_driver);
911 911
912MODULE_ALIAS("spi:sony,acx565akm");
912MODULE_AUTHOR("Nokia Corporation"); 913MODULE_AUTHOR("Nokia Corporation");
913MODULE_DESCRIPTION("acx565akm LCD Driver"); 914MODULE_DESCRIPTION("acx565akm LCD Driver");
914MODULE_LICENSE("GPL"); 915MODULE_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
623void 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}
629EXPORT_SYMBOL(dispc_mgr_enable);
630
631static bool dispc_mgr_is_enabled(enum omap_channel channel)
632{
633 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
634}
635
623bool dispc_mgr_go_busy(enum omap_channel channel) 636bool 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}
2902EXPORT_SYMBOL(dispc_mgr_get_supported_outputs); 2915EXPORT_SYMBOL(dispc_mgr_get_supported_outputs);
2903 2916
2904void 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}
2910EXPORT_SYMBOL(dispc_mgr_enable);
2911
2912bool dispc_mgr_is_enabled(enum omap_channel channel)
2913{
2914 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2915}
2916EXPORT_SYMBOL(dispc_mgr_is_enabled);
2917
2918void dispc_wb_enable(bool enable) 2917void 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
120static void __init omapdss_add_to_list(struct device_node *node, bool root) 120static 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);
856void dispc_runtime_put(void); 856void dispc_runtime_put(void);
857 857
858void dispc_mgr_enable(enum omap_channel channel, bool enable); 858void dispc_mgr_enable(enum omap_channel channel, bool enable);
859bool dispc_mgr_is_enabled(enum omap_channel channel);
860u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); 859u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
861u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); 860u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
862u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel); 861u32 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
247fail: 245fail:
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
52uint32_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
59struct videomode *omap_crtc_timings(struct drm_crtc *crtc) 51struct 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
63static 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
71int omap_crtc_wait_pending(struct drm_crtc *crtc) 76int 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
262static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) 269void 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
278static 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
292static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus) 282void 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)
335static void omap_crtc_enable(struct drm_crtc *crtc) 331static 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
351static void omap_crtc_disable(struct drm_crtc *crtc) 348static 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
392static void omap_crtc_atomic_begin(struct drm_crtc *crtc, 389static 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
397static void omap_crtc_atomic_flush(struct drm_crtc *crtc, 394static 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
431static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc, 439static 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
495static 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 */
645static 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
697static 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
722static int dev_open(struct drm_device *dev, struct drm_file *file) 631static 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 = {
803static struct drm_driver omap_drm_driver = { 712static 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
837static int pdev_probe(struct platform_device *device) 744static 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
820err_cleanup_helpers:
821 drm_kms_helper_poll_fini(ddev);
822 if (priv->fbdev)
823 omap_fbdev_free(ddev);
824err_cleanup_modeset:
825 drm_mode_config_cleanup(ddev);
826 omap_drm_irq_uninstall(ddev);
827err_free_drm_dev:
828 omap_gem_deinit(ddev);
829 drm_dev_unref(ddev);
830err_free_priv:
831 destroy_workqueue(priv->wq);
832 kfree(priv);
833err_disconnect_dssdevs:
834 omap_disconnect_dssdevs();
835err_crtc_uninit:
836 omap_crtc_pre_uninit();
837 return ret;
854} 838}
855 839
856static int pdev_remove(struct platform_device *device) 840static 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 */
57struct 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 */
66struct omap_irq_wait; 53struct 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
129int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe); 116int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe);
130void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe); 117void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe);
131void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
132void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
133void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
134void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
135void omap_drm_irq_uninstall(struct drm_device *dev); 118void omap_drm_irq_uninstall(struct drm_device *dev);
136int omap_drm_irq_install(struct drm_device *dev); 119int omap_drm_irq_install(struct drm_device *dev);
137 120
@@ -155,6 +138,8 @@ void omap_crtc_pre_uninit(void);
155struct drm_crtc *omap_crtc_init(struct drm_device *dev, 138struct 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);
157int omap_crtc_wait_pending(struct drm_crtc *crtc); 140int omap_crtc_wait_pending(struct drm_crtc *crtc);
141void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus);
142void omap_crtc_vblank_irq(struct drm_crtc *crtc);
158 143
159struct drm_plane *omap_plane_init(struct drm_device *dev, 144struct 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 */
236uint32_t pipe2vbl(struct drm_crtc *crtc);
237struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder); 221struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder);
238 222
239/* should these be made into common util helpers?
240 */
241
242static 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
257fail:
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 */
33struct format { 33static 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
43static 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 {
89struct omap_framebuffer { 82struct 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
130static uint32_t get_linear_addr(struct plane *plane, 124static 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)
360struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, 354struct 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 } 376error:
377 while (--i > 0)
378 drm_gem_object_unreference_unlocked(bos[i]);
379
379 return fb; 380 return fb;
380} 381}
381 382
382struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, 383struct 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
22static DEFINE_SPINLOCK(list_lock); 22struct omap_irq_wait {
23 23 struct list_head node;
24static 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 */
31static void omap_irq_update(struct drm_device *dev) 30static 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
48void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) 47static 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
64void 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
73void __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
88void 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
97struct omap_irq_wait {
98 struct omap_drm_irq irq;
99 int count;
100};
101
102static DECLARE_WAIT_QUEUE_HEAD(wait_event);
103
104static 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
112struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, 53struct 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
123int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, 72int 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
143static 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
184static 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
186static irqreturn_t omap_irq_handler(int irq, void *arg) 192static 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
233static 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)
228int omap_drm_irq_install(struct drm_device *dev) 247int 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
50struct omap_plane_state { 48struct 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
335static 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
343static const char *plane_names[] = { 331static 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
350static 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 */
358struct drm_plane *omap_plane_init(struct drm_device *dev, 339struct 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
396error: 373error:
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}