These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nouveau_display.c
index 8670d90..58a3f7c 100644 (file)
@@ -51,12 +51,12 @@ nouveau_display_vblank_handler(struct nvif_notify *notify)
 }
 
 int
-nouveau_display_vblank_enable(struct drm_device *dev, int head)
+nouveau_display_vblank_enable(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_crtc *crtc;
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-               if (nv_crtc->index == head) {
+               if (nv_crtc->index == pipe) {
                        nvif_notify_get(&nv_crtc->vblank);
                        return 0;
                }
@@ -65,12 +65,12 @@ nouveau_display_vblank_enable(struct drm_device *dev, int head)
 }
 
 void
-nouveau_display_vblank_disable(struct drm_device *dev, int head)
+nouveau_display_vblank_disable(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_crtc *crtc;
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-               if (nv_crtc->index == head) {
+               if (nv_crtc->index == pipe) {
                        nvif_notify_put(&nv_crtc->vblank);
                        return;
                }
@@ -103,6 +103,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
                .base.head = nouveau_crtc(crtc)->index,
        };
        struct nouveau_display *disp = nouveau_display(crtc->dev);
+       struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
        int ret, retry = 1;
 
        do {
@@ -116,7 +117,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
                        break;
                }
 
-               if (retry) ndelay(crtc->linedur_ns);
+               if (retry) ndelay(vblank->linedur_ns);
        } while (retry--);
 
        *hpos = args.scan.hline;
@@ -131,13 +132,15 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
 }
 
 int
-nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
-                          int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
+nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe,
+                          unsigned int flags, int *vpos, int *hpos,
+                          ktime_t *stime, ktime_t *etime,
+                          const struct drm_display_mode *mode)
 {
        struct drm_crtc *crtc;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (nouveau_crtc(crtc)->index == head) {
+               if (nouveau_crtc(crtc)->index == pipe) {
                        return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
                                                               stime, etime);
                }
@@ -147,15 +150,15 @@ nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
 }
 
 int
-nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
-                        struct timeval *time, unsigned flags)
+nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe,
+                        int *max_error, struct timeval *time, unsigned flags)
 {
        struct drm_crtc *crtc;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (nouveau_crtc(crtc)->index == head) {
+               if (nouveau_crtc(crtc)->index == pipe) {
                        return drm_calc_vbltimestamp_from_scanoutpos(dev,
-                                       head, max_error, time, flags, crtc,
+                                       pipe, max_error, time, flags,
                                        &crtc->hwmode);
                }
        }
@@ -185,7 +188,7 @@ nouveau_display_vblank_init(struct drm_device *dev)
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-               ret = nvif_notify_init(&disp->disp, NULL,
+               ret = nvif_notify_init(&disp->disp,
                                       nouveau_display_vblank_handler, false,
                                       NV04_DISP_NTFY_VBLANK,
                                       &(struct nvif_notify_head_req_v0) {
@@ -358,6 +361,7 @@ int
 nouveau_display_init(struct drm_device *dev)
 {
        struct nouveau_display *disp = nouveau_display(dev);
+       struct nouveau_drm *drm = nouveau_drm(dev);
        struct drm_connector *connector;
        int ret;
 
@@ -374,6 +378,8 @@ nouveau_display_init(struct drm_device *dev)
                nvif_notify_get(&conn->hpd);
        }
 
+       /* enable flip completion events */
+       nvif_notify_get(&drm->flip);
        return ret;
 }
 
@@ -381,6 +387,7 @@ void
 nouveau_display_fini(struct drm_device *dev)
 {
        struct nouveau_display *disp = nouveau_display(dev);
+       struct nouveau_drm *drm = nouveau_drm(dev);
        struct drm_connector *connector;
        int head;
 
@@ -388,6 +395,9 @@ nouveau_display_fini(struct drm_device *dev)
        for (head = 0; head < dev->mode_config.num_crtc; head++)
                drm_vblank_off(dev, head);
 
+       /* disable flip completion events */
+       nvif_notify_put(&drm->flip);
+
        /* disable hotplug interrupts */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct nouveau_connector *conn = nouveau_connector(connector);
@@ -438,6 +448,7 @@ int
 nouveau_display_create(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nvkm_device *device = nvxx_device(&drm->device);
        struct nouveau_display *disp;
        int ret;
 
@@ -450,7 +461,7 @@ nouveau_display_create(struct drm_device *dev)
        drm_mode_create_dvi_i_properties(dev);
 
        dev->mode_config.funcs = &nouveau_mode_config_funcs;
-       dev->mode_config.fb_base = nv_device_resource_start(nvxx_device(&drm->device), 1);
+       dev->mode_config.fb_base = device->func->resource_addr(device, 1);
 
        dev->mode_config.min_width = 0;
        dev->mode_config.min_height = 0;
@@ -461,9 +472,13 @@ nouveau_display_create(struct drm_device *dev)
        if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
                dev->mode_config.max_width = 4096;
                dev->mode_config.max_height = 4096;
-       } else {
+       } else
+       if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) {
                dev->mode_config.max_width = 8192;
                dev->mode_config.max_height = 8192;
+       } else {
+               dev->mode_config.max_width = 16384;
+               dev->mode_config.max_height = 16384;
        }
 
        dev->mode_config.preferred_depth = 24;
@@ -494,9 +509,8 @@ nouveau_display_create(struct drm_device *dev)
                int i;
 
                for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
-                       ret = nvif_object_init(nvif_object(&drm->device), NULL,
-                                              NVDRM_DISPLAY, oclass[i],
-                                              NULL, 0, &disp->disp);
+                       ret = nvif_object_init(&drm->device.object, 0,
+                                              oclass[i], NULL, 0, &disp->disp);
                }
 
                if (ret == 0) {
@@ -620,10 +634,6 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
                nv_crtc->lut.depth = 0;
        }
 
-       /* Make sure that drm and hw vblank irqs get resumed if needed. */
-       for (head = 0; head < dev->mode_config.num_crtc; head++)
-               drm_vblank_on(dev, head);
-
        /* This should ensure we don't hit a locking problem when someone
         * wakes us up via a connector.  We should never go into suspend
         * while the display is on anyways.
@@ -633,6 +643,10 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
 
        drm_helper_resume_force_mode(dev);
 
+       /* Make sure that drm and hw vblank irqs get resumed if needed. */
+       for (head = 0; head < dev->mode_config.num_crtc; head++)
+               drm_vblank_on(dev, head);
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
@@ -711,7 +725,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        chan = drm->channel;
        if (!chan)
                return -ENODEV;
-       cli = (void *)nvif_client(&chan->device->base);
+       cli = (void *)chan->user.client;
 
        s = kzalloc(sizeof(*s), GFP_KERNEL);
        if (!s)
@@ -815,7 +829,6 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
        struct drm_device *dev = drm->dev;
        struct nouveau_page_flip_state *s;
        unsigned long flags;
-       int crtcid = -1;
 
        spin_lock_irqsave(&dev->event_lock, flags);
 
@@ -827,15 +840,19 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
 
        s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
        if (s->event) {
-               /* Vblank timestamps/counts are only correct on >= NV-50 */
-               if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
-                       crtcid = s->crtc;
+               if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
+                       drm_arm_vblank_event(dev, s->crtc, s->event);
+               } else {
+                       drm_send_vblank_event(dev, s->crtc, s->event);
 
-               drm_send_vblank_event(dev, crtcid, s->event);
+                       /* Give up ownership of vblank for page-flipped crtc */
+                       drm_vblank_put(dev, s->crtc);
+               }
+       }
+       else {
+               /* Give up ownership of vblank for page-flipped crtc */
+               drm_vblank_put(dev, s->crtc);
        }
-
-       /* Give up ownership of vblank for page-flipped crtc */
-       drm_vblank_put(dev, s->crtc);
 
        list_del(&s->head);
        if (ps)
@@ -847,10 +864,10 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
 }
 
 int
-nouveau_flip_complete(void *data)
+nouveau_flip_complete(struct nvif_notify *notify)
 {
-       struct nouveau_channel *chan = data;
-       struct nouveau_drm *drm = chan->drm;
+       struct nouveau_drm *drm = container_of(notify, typeof(*drm), flip);
+       struct nouveau_channel *chan = drm->channel;
        struct nouveau_page_flip_state state;
 
        if (!nouveau_finish_page_flip(chan, &state)) {
@@ -861,7 +878,7 @@ nouveau_flip_complete(void *data)
                }
        }
 
-       return 0;
+       return NVIF_NOTIFY_KEEP;
 }
 
 int