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) { struct drm_device *dev = container_of(ref, struct drm_device, ref); + drm_vblank_cleanup(dev); + if (drm_core_check_feature(dev, DRIVER_GEM)) drm_gem_destroy(dev); @@ -805,8 +807,6 @@ void drm_dev_unregister(struct drm_device *dev) if (dev->agp) drm_pci_agp_destroy(dev); - drm_vblank_cleanup(dev); - list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) drm_legacy_rmmap(dev, r_list->map); 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) dsicm_hw_reset(ddata); if (ddata->use_dsi_backlight) { - memset(&props, 0, sizeof(struct backlight_properties)); + memset(&props, 0, sizeof(props)); props.max_brightness = 255; 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 = { module_spi_driver(acx565akm_driver); +MODULE_ALIAS("spi:sony,acx565akm"); MODULE_AUTHOR("Nokia Corporation"); MODULE_DESCRIPTION("acx565akm LCD Driver"); 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) return DISPC_IRQ_FRAMEDONEWB; } +void dispc_mgr_enable(enum omap_channel channel, bool enable) +{ + mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); + /* flush posted write */ + mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); +} +EXPORT_SYMBOL(dispc_mgr_enable); + +static bool dispc_mgr_is_enabled(enum omap_channel channel) +{ + return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); +} + bool dispc_mgr_go_busy(enum omap_channel channel) { 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 } EXPORT_SYMBOL(dispc_mgr_get_supported_outputs); -void dispc_mgr_enable(enum omap_channel channel, bool enable) -{ - mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); - /* flush posted write */ - mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); -} -EXPORT_SYMBOL(dispc_mgr_enable); - -bool dispc_mgr_is_enabled(enum omap_channel channel) -{ - return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); -} -EXPORT_SYMBOL(dispc_mgr_is_enabled); - void dispc_wb_enable(bool enable) { 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, wc = DIV_ROUND_UP(t->hact * t->bitspp, 8); pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */ - bl = t->hss + t->hsa + t->hse + t->hbp + t->hfront_porch; + bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp; tot = bl + pps; #define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk)) @@ -4345,14 +4345,14 @@ static void print_dsi_vm(const char *str, "%u/%u/%u/%u/%u/%u = %u + %u = %u\n", str, byteclk, - t->hss, t->hsa, t->hse, t->hbp, pps, t->hfront_porch, + t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp, bl, pps, tot, TO_DSI_T(t->hss), TO_DSI_T(t->hsa), TO_DSI_T(t->hse), TO_DSI_T(t->hbp), TO_DSI_T(pps), - TO_DSI_T(t->hfront_porch), + TO_DSI_T(t->hfp), TO_DSI_T(bl), TO_DSI_T(pps), @@ -4367,7 +4367,7 @@ static void print_dispc_vm(const char *str, const struct videomode *vm) int hact, bl, tot; hact = vm->hactive; - bl = vm->hsync_len + vm->hbp + vm->hfront_porch; + bl = vm->hsync_len + vm->hback_porch + vm->hfront_porch; tot = hact + bl; #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) "%u/%u/%u/%u = %u + %u = %u\n", str, pck, - vm->hsync_len, vm->hbp, hact, vm->hfront_porch, + vm->hsync_len, vm->hback_porch, hact, vm->hfront_porch, bl, hact, tot, TO_DISPC_T(vm->hsync_len), - TO_DISPC_T(vm->hbp), + TO_DISPC_T(vm->hback_porch), TO_DISPC_T(hact), TO_DISPC_T(vm->hfront_porch), TO_DISPC_T(bl), @@ -4401,12 +4401,12 @@ static void print_dsi_dispc_vm(const char *str, dsi_tput = (u64)byteclk * t->ndl * 8; pck = (u32)div64_u64(dsi_tput, t->bitspp); dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl); - dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfront_porch; + dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp; vm.pixelclock = pck; vm.hsync_len = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); - vm.hbp = div64_u64((u64)t->hbp * pck, byteclk); - vm.hfront_porch = div64_u64((u64)t->hfront_porch * pck, byteclk); + vm.hback_porch = div64_u64((u64)t->hbp * pck, byteclk); + vm.hfront_porch = div64_u64((u64)t->hfp * pck, byteclk); vm.hactive = t->hact; 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) static void __init omapdss_add_to_list(struct device_node *node, bool root) { - struct dss_conv_node *n = kmalloc(sizeof(struct dss_conv_node), - GFP_KERNEL); + struct dss_conv_node *n = kmalloc(sizeof(*n), GFP_KERNEL); if (n) { n->node = node; 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); void dispc_runtime_put(void); void dispc_mgr_enable(enum omap_channel channel, bool enable); -bool dispc_mgr_is_enabled(enum omap_channel channel); u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); 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, dssdrv->get_timings(dssdev, &t); - if (memcmp(&vm, &t, sizeof(struct videomode))) + if (memcmp(&vm, &t, sizeof(vm))) r = -EINVAL; else r = 0; @@ -217,7 +217,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, omap_dss_get_device(dssdev); - omap_connector = kzalloc(sizeof(struct omap_connector), GFP_KERNEL); + omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL); if (!omap_connector) goto fail; @@ -240,8 +240,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, connector->interlace_allowed = 1; connector->doublescan_allowed = 0; - drm_connector_register(connector); - return connector; 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 { struct videomode vm; - struct omap_drm_irq vblank_irq; - struct omap_drm_irq error_irq; - bool ignore_digit_sync_lost; + bool enabled; bool pending; wait_queue_head_t pending_wait; + struct drm_pending_vblank_event *event; }; /* ----------------------------------------------------------------------------- * Helper Functions */ -uint32_t pipe2vbl(struct drm_crtc *crtc) -{ - struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - - return dispc_mgr_get_vsync_irq(omap_crtc->channel); -} - struct videomode *omap_crtc_timings(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -68,6 +60,19 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc) return omap_crtc->channel; } +static bool omap_crtc_is_pending(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + unsigned long flags; + bool pending; + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + pending = omap_crtc->pending; + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + return pending; +} + int omap_crtc_wait_pending(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -77,7 +82,7 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc) * a single frame refresh even on slower displays. */ return wait_event_timeout(omap_crtc->pending_wait, - !omap_crtc->pending, + !omap_crtc_is_pending(crtc), msecs_to_jiffies(250)); } @@ -135,14 +140,15 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) u32 framedone_irq, vsync_irq; int ret; + if (WARN_ON(omap_crtc->enabled == enable)) + return; + if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) { dispc_mgr_enable(channel, enable); + omap_crtc->enabled = enable; return; } - if (dispc_mgr_is_enabled(channel) == enable) - return; - if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) { /* * 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) } dispc_mgr_enable(channel, enable); + omap_crtc->enabled = enable; ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); if (ret) { @@ -259,26 +266,9 @@ static const struct dss_mgr_ops mgr_ops = { * Setup, Flush and Page Flip */ -static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) +void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus) { - struct drm_pending_vblank_event *event; - struct drm_device *dev = crtc->dev; - unsigned long flags; - - event = crtc->state->event; - - if (!event) - return; - - spin_lock_irqsave(&dev->event_lock, flags); - drm_crtc_send_vblank_event(crtc, event); - spin_unlock_irqrestore(&dev->event_lock, flags); -} - -static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) -{ - struct omap_crtc *omap_crtc = - container_of(irq, struct omap_crtc, error_irq); + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); if (omap_crtc->ignore_digit_sync_lost) { irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT; @@ -289,29 +279,38 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus); } -static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus) +void omap_crtc_vblank_irq(struct drm_crtc *crtc) { - struct omap_crtc *omap_crtc = - container_of(irq, struct omap_crtc, vblank_irq); - struct drm_device *dev = omap_crtc->base.dev; + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + bool pending; - if (dispc_mgr_go_busy(omap_crtc->channel)) + spin_lock(&crtc->dev->event_lock); + /* + * If the dispc is busy we're racing the flush operation. Try again on + * the next vblank interrupt. + */ + if (dispc_mgr_go_busy(omap_crtc->channel)) { + spin_unlock(&crtc->dev->event_lock); return; + } - DBG("%s: apply done", omap_crtc->name); - - __omap_irq_unregister(dev, &omap_crtc->vblank_irq); + /* Send the vblank event if one has been requested. */ + if (omap_crtc->event) { + drm_crtc_send_vblank_event(crtc, omap_crtc->event); + omap_crtc->event = NULL; + } - rmb(); - WARN_ON(!omap_crtc->pending); + pending = omap_crtc->pending; omap_crtc->pending = false; - wmb(); + spin_unlock(&crtc->dev->event_lock); - /* wake up userspace */ - omap_crtc_complete_page_flip(&omap_crtc->base); + if (pending) + drm_crtc_vblank_put(crtc); - /* wake up omap_atomic_complete */ + /* Wake up omap_atomic_complete. */ wake_up(&omap_crtc->pending_wait); + + DBG("%s: apply done", omap_crtc->name); } /* ----------------------------------------------------------------------------- @@ -324,9 +323,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) DBG("%s", omap_crtc->name); - WARN_ON(omap_crtc->vblank_irq.registered); - omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); - drm_crtc_cleanup(crtc); kfree(omap_crtc); @@ -335,17 +331,18 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) static void omap_crtc_enable(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + int ret; DBG("%s", omap_crtc->name); - rmb(); + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_vblank_on(crtc); + ret = drm_crtc_vblank_get(crtc); + WARN_ON(ret != 0); + WARN_ON(omap_crtc->pending); omap_crtc->pending = true; - wmb(); - - omap_irq_register(crtc->dev, &omap_crtc->vblank_irq); - - drm_crtc_vblank_on(crtc); + spin_unlock_irq(&crtc->dev->event_lock); } static void omap_crtc_disable(struct drm_crtc *crtc) @@ -390,16 +387,15 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc, } static void omap_crtc_atomic_begin(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) + struct drm_crtc_state *old_crtc_state) { } static void omap_crtc_atomic_flush(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) + struct drm_crtc_state *old_crtc_state) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - - WARN_ON(omap_crtc->vblank_irq.registered); + int ret; if (crtc->state->color_mgmt_changed) { struct drm_color_lut *lut = NULL; @@ -414,18 +410,30 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, dispc_mgr_set_gamma(omap_crtc->channel, lut, length); } - if (dispc_mgr_is_enabled(omap_crtc->channel)) { + /* + * Only flush the CRTC if it is currently enabled. CRTCs that require a + * mode set are disabled prior plane updates and enabled afterwards. + * They are thus not active (regardless of what their CRTC core state + * reports) and the DRM core could thus call this function even though + * the CRTC is currently disabled. Do nothing in that case. + */ + if (!omap_crtc->enabled) + return; + + DBG("%s: GO", omap_crtc->name); - DBG("%s: GO", omap_crtc->name); + ret = drm_crtc_vblank_get(crtc); + WARN_ON(ret != 0); - rmb(); - WARN_ON(omap_crtc->pending); - omap_crtc->pending = true; - wmb(); + spin_lock_irq(&crtc->dev->event_lock); + dispc_mgr_go(omap_crtc->channel); - dispc_mgr_go(omap_crtc->channel); - omap_irq_register(crtc->dev, &omap_crtc->vblank_irq); - } + WARN_ON(omap_crtc->pending); + omap_crtc->pending = true; + + if (crtc->state->event) + omap_crtc->event = crtc->state->event; + spin_unlock_irq(&crtc->dev->event_lock); } 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, omap_crtc->channel = channel; omap_crtc->name = channel_names[channel]; - omap_crtc->vblank_irq.irqmask = pipe2vbl(crtc); - omap_crtc->vblank_irq.irq = omap_crtc_vblank_irq; - - omap_crtc->error_irq.irqmask = - dispc_mgr_get_sync_lost_irq(channel); - omap_crtc->error_irq.irq = omap_crtc_error_irq; - omap_irq_register(dev, &omap_crtc->error_irq); - ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, &omap_crtc_funcs, NULL); 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, int rows = (1 + area->y1 - area->y0); int i = columns*rows; - pat = alloc_dma(txn, sizeof(struct pat), &pat_pa); + pat = alloc_dma(txn, sizeof(*pat), &pat_pa); if (txn->last_pat) txn->last_pat->next_pa = (uint32_t)pat_pa; @@ -735,7 +735,7 @@ static int omap_dmm_probe(struct platform_device *dev) /* alloc engines */ omap_dmm->engines = kcalloc(omap_dmm->num_engines, - sizeof(struct refill_engine), GFP_KERNEL); + sizeof(*omap_dmm->engines), GFP_KERNEL); if (!omap_dmm->engines) { ret = -ENOMEM; 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) dispc_runtime_get(); drm_atomic_helper_commit_modeset_disables(dev, old_state); - drm_atomic_helper_commit_planes(dev, old_state, 0); + drm_atomic_helper_commit_planes(dev, old_state, + DRM_PLANE_COMMIT_ACTIVE_ONLY); drm_atomic_helper_commit_modeset_enables(dev, old_state); omap_atomic_wait_for_completion(dev, old_state); @@ -315,8 +316,6 @@ static int omap_modeset_init(struct drm_device *dev) drm_mode_config_init(dev); - omap_drm_irq_install(dev); - ret = omap_modeset_init_properties(dev); if (ret < 0) return ret; @@ -489,12 +488,9 @@ static int omap_modeset_init(struct drm_device *dev) drm_mode_config_reset(dev); - return 0; -} + omap_drm_irq_install(dev); -static void omap_modeset_free(struct drm_device *dev) -{ - drm_mode_config_cleanup(dev); + return 0; } /* @@ -632,93 +628,6 @@ static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = * drm driver funcs */ -/** - * load - setup chip and create an initial config - * @dev: DRM device - * @flags: startup flags - * - * The driver load routine has to do several things: - * - initialize the memory manager - * - allocate initial config memory - * - setup the DRM framebuffer with the allocated memory - */ -static int dev_load(struct drm_device *dev, unsigned long flags) -{ - struct omap_drm_platform_data *pdata = dev->dev->platform_data; - struct omap_drm_private *priv; - unsigned int i; - int ret; - - DBG("load: dev=%p", dev); - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->omaprev = pdata->omaprev; - - dev->dev_private = priv; - - priv->wq = alloc_ordered_workqueue("omapdrm", 0); - init_waitqueue_head(&priv->commit.wait); - spin_lock_init(&priv->commit.lock); - - spin_lock_init(&priv->list_lock); - INIT_LIST_HEAD(&priv->obj_list); - - omap_gem_init(dev); - - ret = omap_modeset_init(dev); - if (ret) { - dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); - dev->dev_private = NULL; - kfree(priv); - return ret; - } - - /* Initialize vblank handling, start with all CRTCs disabled. */ - ret = drm_vblank_init(dev, priv->num_crtcs); - if (ret) - dev_warn(dev->dev, "could not init vblank\n"); - - for (i = 0; i < priv->num_crtcs; i++) - drm_crtc_vblank_off(priv->crtcs[i]); - - priv->fbdev = omap_fbdev_init(dev); - - /* store off drm_device for use in pm ops */ - dev_set_drvdata(dev->dev, dev); - - drm_kms_helper_poll_init(dev); - - return 0; -} - -static void dev_unload(struct drm_device *dev) -{ - struct omap_drm_private *priv = dev->dev_private; - - DBG("unload: dev=%p", dev); - - drm_kms_helper_poll_fini(dev); - - if (priv->fbdev) - omap_fbdev_free(dev); - - omap_modeset_free(dev); - omap_gem_deinit(dev); - - destroy_workqueue(priv->wq); - - drm_vblank_cleanup(dev); - omap_drm_irq_uninstall(dev); - - kfree(dev->dev_private); - dev->dev_private = NULL; - - dev_set_drvdata(dev->dev, NULL); -} - static int dev_open(struct drm_device *dev, struct drm_file *file) { file->driver_priv = NULL; @@ -803,8 +712,6 @@ static const struct file_operations omapdriver_fops = { static struct drm_driver omap_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, - .load = dev_load, - .unload = dev_unload, .open = dev_open, .lastclose = dev_lastclose, .get_vblank_counter = drm_vblank_no_hw_counter, @@ -834,30 +741,125 @@ static struct drm_driver omap_drm_driver = { .patchlevel = DRIVER_PATCHLEVEL, }; -static int pdev_probe(struct platform_device *device) +static int pdev_probe(struct platform_device *pdev) { - int r; + struct omap_drm_platform_data *pdata = pdev->dev.platform_data; + struct omap_drm_private *priv; + struct drm_device *ddev; + unsigned int i; + int ret; + + DBG("%s", pdev->name); if (omapdss_is_initialized() == false) return -EPROBE_DEFER; omap_crtc_pre_init(); - r = omap_connect_dssdevs(); - if (r) { - omap_crtc_pre_uninit(); - return r; + ret = omap_connect_dssdevs(); + if (ret) + goto err_crtc_uninit; + + /* Allocate and initialize the driver private structure. */ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto err_disconnect_dssdevs; } - DBG("%s", device->name); - return drm_platform_init(&omap_drm_driver, device); + priv->omaprev = pdata->omaprev; + priv->wq = alloc_ordered_workqueue("omapdrm", 0); + + init_waitqueue_head(&priv->commit.wait); + spin_lock_init(&priv->commit.lock); + spin_lock_init(&priv->list_lock); + INIT_LIST_HEAD(&priv->obj_list); + + /* Allocate and initialize the DRM device. */ + ddev = drm_dev_alloc(&omap_drm_driver, &pdev->dev); + if (IS_ERR(ddev)) { + ret = PTR_ERR(ddev); + goto err_free_priv; + } + + ddev->dev_private = priv; + platform_set_drvdata(pdev, ddev); + + omap_gem_init(ddev); + + ret = omap_modeset_init(ddev); + if (ret) { + dev_err(&pdev->dev, "omap_modeset_init failed: ret=%d\n", ret); + goto err_free_drm_dev; + } + + /* Initialize vblank handling, start with all CRTCs disabled. */ + ret = drm_vblank_init(ddev, priv->num_crtcs); + if (ret) { + dev_err(&pdev->dev, "could not init vblank\n"); + goto err_cleanup_modeset; + } + + for (i = 0; i < priv->num_crtcs; i++) + drm_crtc_vblank_off(priv->crtcs[i]); + + priv->fbdev = omap_fbdev_init(ddev); + + drm_kms_helper_poll_init(ddev); + + /* + * Register the DRM device with the core and the connectors with + * sysfs. + */ + ret = drm_dev_register(ddev, 0); + if (ret) + goto err_cleanup_helpers; + + return 0; + +err_cleanup_helpers: + drm_kms_helper_poll_fini(ddev); + if (priv->fbdev) + omap_fbdev_free(ddev); +err_cleanup_modeset: + drm_mode_config_cleanup(ddev); + omap_drm_irq_uninstall(ddev); +err_free_drm_dev: + omap_gem_deinit(ddev); + drm_dev_unref(ddev); +err_free_priv: + destroy_workqueue(priv->wq); + kfree(priv); +err_disconnect_dssdevs: + omap_disconnect_dssdevs(); +err_crtc_uninit: + omap_crtc_pre_uninit(); + return ret; } -static int pdev_remove(struct platform_device *device) +static int pdev_remove(struct platform_device *pdev) { + struct drm_device *ddev = platform_get_drvdata(pdev); + struct omap_drm_private *priv = ddev->dev_private; + DBG(""); - drm_put_dev(platform_get_drvdata(device)); + drm_dev_unregister(ddev); + + drm_kms_helper_poll_fini(ddev); + + if (priv->fbdev) + omap_fbdev_free(ddev); + + drm_mode_config_cleanup(ddev); + + omap_drm_irq_uninstall(ddev); + omap_gem_deinit(ddev); + + drm_dev_unref(ddev); + + destroy_workqueue(priv->wq); + kfree(priv); omap_disconnect_dssdevs(); 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 { uint32_t src_w, src_h; }; -/* For transiently registering for different DSS irqs that various parts - * of the KMS code need during setup/configuration. We these are not - * necessarily the same as what drm_vblank_get/put() are requesting, and - * the hysteresis in drm_vblank_put() is not necessarily desirable for - * internal housekeeping related irq usage. - */ -struct omap_drm_irq { - struct list_head node; - uint32_t irqmask; - bool registered; - void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus); -}; - /* For KMS code that needs to wait for a certain # of IRQs: */ struct omap_irq_wait; @@ -101,9 +88,9 @@ struct omap_drm_private { struct drm_property *zorder_prop; /* irq handling: */ - struct list_head irq_list; /* list of omap_drm_irq */ - uint32_t vblank_mask; /* irq bits set for userspace vblank */ - struct omap_drm_irq error_handler; + spinlock_t wait_lock; /* protects the wait_list */ + struct list_head wait_list; /* list of omap_irq_wait */ + uint32_t irq_mask; /* enabled irqs in addition to wait_list */ /* atomic commit */ struct { @@ -128,10 +115,6 @@ int omap_gem_resume(struct device *dev); int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe); void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe); -void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); -void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); -void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); -void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); void omap_drm_irq_uninstall(struct drm_device *dev); int omap_drm_irq_install(struct drm_device *dev); @@ -155,6 +138,8 @@ void omap_crtc_pre_uninit(void); struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id); int omap_crtc_wait_pending(struct drm_crtc *crtc); +void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus); +void omap_crtc_vblank_irq(struct drm_crtc *crtc); struct drm_plane *omap_plane_init(struct drm_device *dev, int id, enum drm_plane_type type, @@ -233,32 +218,6 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, struct dma_buf *buffer); /* map crtc to vblank mask */ -uint32_t pipe2vbl(struct drm_crtc *crtc); struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder); -/* should these be made into common util helpers? - */ - -static inline int objects_lookup( - struct drm_file *filp, uint32_t pixel_format, - struct drm_gem_object **bos, const uint32_t *handles) -{ - int i, n = drm_format_num_planes(pixel_format); - - for (i = 0; i < n; i++) { - bos[i] = drm_gem_object_lookup(filp, handles[i]); - if (!bos[i]) - goto fail; - - } - - return 0; - -fail: - while (--i > 0) - drm_gem_object_unreference_unlocked(bos[i]); - - return -ENOENT; -} - #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, dssdrv->get_timings(dssdev, &t); - if (memcmp(vm, &t, sizeof(struct videomode))) + if (memcmp(vm, &t, sizeof(*vm))) ret = -EINVAL; else 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 @@ * framebuffer funcs */ -/* per-format info: */ -struct format { +/* DSS to DRM formats mapping */ +static const struct { enum omap_color_mode dss_format; uint32_t pixel_format; - struct { - int stride_bpp; /* this times width is stride */ - int sub_y; /* sub-sample in y dimension */ - } planes[4]; - bool yuv; -}; - -static const struct format formats[] = { +} formats[] = { /* 16bpp [A]RGB: */ - { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565, {{2, 1}}, false }, /* RGB16-565 */ - { OMAP_DSS_COLOR_RGB12U, DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */ - { OMAP_DSS_COLOR_RGBX16, DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */ - { OMAP_DSS_COLOR_RGBA16, DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */ - { OMAP_DSS_COLOR_ARGB16, DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */ - { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */ - { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */ + { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565 }, /* RGB16-565 */ |