drm/nouveau/kms: move display class instantiation to library
authorBen Skeggs <bskeggs@redhat.com>
Tue, 8 May 2018 10:39:47 +0000 (20:39 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 18 May 2018 05:01:26 +0000 (15:01 +1000)
This function is useful outside of DRM code.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvif/disp.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvif/object.h
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_display.h
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nvif/Kbuild
drivers/gpu/drm/nouveau/nvif/disp.c [new file with mode: 0644]

diff --git a/drivers/gpu/drm/nouveau/include/nvif/disp.h b/drivers/gpu/drm/nouveau/include/nvif/disp.h
new file mode 100644 (file)
index 0000000..7c0eda3
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __NVIF_DISP_H__
+#define __NVIF_DISP_H__
+#include <nvif/object.h>
+struct nvif_device;
+
+struct nvif_disp {
+       struct nvif_object object;
+};
+
+int nvif_disp_ctor(struct nvif_device *, s32 oclass, struct nvif_disp *);
+void nvif_disp_dtor(struct nvif_disp *);
+#endif
index a2d5244ff2b77ae6b270a5edf4f1e72007ca6226..20754d9e68838e167ad29a0fef9c2d4de66c9371 100644 (file)
@@ -99,6 +99,22 @@ struct nvif_mclass {
        ret;                                                                   \
 })
 
+#define nvif_sclass(o,m,u) ({                                                  \
+       const typeof(m[0]) *_mclass = (m);                                     \
+       s32 _oclass = (u);                                                     \
+       int _cid;                                                              \
+       if (_oclass) {                                                         \
+               for (_cid = 0; _mclass[_cid].oclass; _cid++) {                 \
+                       if (_mclass[_cid].oclass == _oclass)                   \
+                               break;                                         \
+               }                                                              \
+               _cid = _mclass[_cid].oclass ? _cid : -ENOSYS;                  \
+       } else {                                                               \
+               _cid = nvif_mclass((o), _mclass);                              \
+       }                                                                      \
+       _cid;                                                                  \
+})
+
 /*XXX*/
 #include <core/object.h>
 #define nvxx_object(a) ({                                                      \
index 6ed9cb053dfa5fd3bff312b155541ef17a4aadad..18e3239f7658460867f20409a0c38fb10eed59e4 100644 (file)
@@ -151,7 +151,7 @@ nouveau_conn_atomic_set_property(struct drm_connector *connector,
                                /* ... except prior to G80, where the code
                                 * doesn't support such things.
                                 */
-                               if (disp->disp.oclass < NV50_DISP)
+                               if (disp->disp.object.oclass < NV50_DISP)
                                        return -EINVAL;
                                break;
                        default:
@@ -260,7 +260,7 @@ nouveau_conn_reset(struct drm_connector *connector)
        asyc->procamp.color_vibrance = 150;
        asyc->procamp.vibrant_hue = 90;
 
-       if (nouveau_display(connector->dev)->disp.oclass < NV50_DISP) {
+       if (nouveau_display(connector->dev)->disp.object.oclass < NV50_DISP) {
                switch (connector->connector_type) {
                case DRM_MODE_CONNECTOR_LVDS:
                        /* See note in nouveau_conn_atomic_set_property(). */
@@ -314,7 +314,7 @@ nouveau_conn_attach_properties(struct drm_connector *connector)
        case DRM_MODE_CONNECTOR_TV:
                break;
        case DRM_MODE_CONNECTOR_VGA:
-               if (disp->disp.oclass < NV50_DISP)
+               if (disp->disp.object.oclass < NV50_DISP)
                        break; /* Can only scale on DFPs. */
                /* Fall-through. */
        default:
@@ -1321,7 +1321,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
        }
 
        /* HDMI 3D support */
-       if ((disp->disp.oclass >= G82_DISP)
+       if ((disp->disp.object.oclass >= G82_DISP)
            && ((type == DRM_MODE_CONNECTOR_DisplayPort)
                || (type == DRM_MODE_CONNECTOR_eDP)
                || (type == DRM_MODE_CONNECTOR_HDMIA)))
@@ -1343,7 +1343,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
        case DCB_CONNECTOR_LVDS_SPWG:
        case DCB_CONNECTOR_eDP:
                /* see note in nouveau_connector_set_property() */
-               if (disp->disp.oclass < NV50_DISP) {
+               if (disp->disp.object.oclass < NV50_DISP) {
                        nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
                        break;
                }
@@ -1366,8 +1366,8 @@ nouveau_connector_create(struct drm_device *dev, int index)
                break;
        }
 
-       ret = nvif_notify_init(&disp->disp, nouveau_connector_hotplug, true,
-                              NV04_DISP_NTFY_CONN,
+       ret = nvif_notify_init(&disp->disp.object, nouveau_connector_hotplug,
+                              true, NV04_DISP_NTFY_CONN,
                               &(struct nvif_notify_conn_req_v0) {
                                .mask = NVIF_NOTIFY_CONN_V0_ANY,
                                .conn = index,
index 7d0bec8dd03de706592dc0b47f02819e69e6bcb7..774b429142bc8e22c79e6b0ed46f97f72e3ffab1 100644 (file)
@@ -116,7 +116,7 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
        bool ret = false;
 
        do {
-               ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args));
+               ret = nvif_mthd(&disp->disp.object, 0, &args, sizeof(args));
                if (ret != 0)
                        return false;
 
@@ -175,7 +175,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,
+               ret = nvif_notify_init(&disp->disp.object,
                                       nouveau_display_vblank_handler, false,
                                       NV04_DISP_NTFY_VBLANK,
                                       &(struct nvif_notify_head_req_v0) {
@@ -454,10 +454,10 @@ nouveau_display_create_properties(struct drm_device *dev)
        struct nouveau_display *disp = nouveau_display(dev);
        int gen;
 
-       if (disp->disp.oclass < NV50_DISP)
+       if (disp->disp.object.oclass < NV50_DISP)
                gen = 0;
        else
-       if (disp->disp.oclass < GF110_DISP)
+       if (disp->disp.object.oclass < GF110_DISP)
                gen = 1;
        else
                gen = 2;
@@ -533,31 +533,10 @@ nouveau_display_create(struct drm_device *dev)
        drm_kms_helper_poll_disable(dev);
 
        if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
-               static const u16 oclass[] = {
-                       GP102_DISP,
-                       GP100_DISP,
-                       GM200_DISP,
-                       GM107_DISP,
-                       GK110_DISP,
-                       GK104_DISP,
-                       GF110_DISP,
-                       GT214_DISP,
-                       GT206_DISP,
-                       GT200_DISP,
-                       G82_DISP,
-                       NV50_DISP,
-                       NV04_DISP,
-               };
-               int i;
-
-               for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
-                       ret = nvif_object_init(&drm->client.device.object, 0,
-                                              oclass[i], NULL, 0, &disp->disp);
-               }
-
+               ret = nvif_disp_ctor(&drm->client.device, 0, &disp->disp);
                if (ret == 0) {
                        nouveau_display_create_properties(dev);
-                       if (disp->disp.oclass < NV50_DISP)
+                       if (disp->disp.object.oclass < NV50_DISP)
                                ret = nv04_display_create(dev);
                        else
                                ret = nv50_display_create(dev);
@@ -611,7 +590,7 @@ nouveau_display_destroy(struct drm_device *dev)
        if (disp->dtor)
                disp->dtor(dev);
 
-       nvif_object_fini(&disp->disp);
+       nvif_disp_dtor(&disp->disp);
 
        nouveau_drm(dev)->display = NULL;
        kfree(disp);
index 270ba56f27560e91205e922cd6f0551d1f7e475e..54aa7c3fa42dddfa96b684d308def526da9c4d1d 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef __NOUVEAU_DISPLAY_H__
 #define __NOUVEAU_DISPLAY_H__
 #include "nouveau_drv.h"
+#include <nvif/disp.h>
 
 struct nouveau_framebuffer {
        struct drm_framebuffer base;
@@ -38,7 +39,7 @@ struct nouveau_display {
        int  (*init)(struct drm_device *);
        void (*fini)(struct drm_device *);
 
-       struct nvif_object disp;
+       struct nvif_disp disp;
 
        struct drm_property *dithering_mode;
        struct drm_property *dithering_depth;
index e90330e4e8c519a6ddcbecbce995d1115a4d365f..f2156c8ca90f5bb2ac37ee671b7ae2c8091e8513 100644 (file)
@@ -663,7 +663,7 @@ struct nv50_head {
 #define nv50_vers(c) nv50_chan(c)->user.oclass
 
 struct nv50_disp {
-       struct nvif_object *disp;
+       struct nvif_disp *disp;
        struct nv50_mast mast;
 
        struct nouveau_bo *sync;
@@ -1201,7 +1201,7 @@ nv50_curs_new(struct nouveau_drm *drm, struct nv50_head *head,
        struct nv50_curs *curs;
        int cid, ret;
 
-       cid = nvif_mclass(disp->disp, curses);
+       cid = nvif_mclass(&disp->disp->object, curses);
        if (cid < 0) {
                NV_ERROR(drm, "No supported cursor immediate class\n");
                return cid;
@@ -1219,8 +1219,8 @@ nv50_curs_new(struct nouveau_drm *drm, struct nv50_head *head,
                return ret;
        }
 
-       ret = nvif_object_init(disp->disp, 0, curses[cid].oclass, &args,
-                              sizeof(args), &curs->chan);
+       ret = nvif_object_init(&disp->disp->object, 0, curses[cid].oclass,
+                              &args, sizeof(args), &curs->chan);
        if (ret) {
                NV_ERROR(drm, "curs%04x allocation failed: %d\n",
                         curses[cid].oclass, ret);
@@ -1517,8 +1517,8 @@ nv50_base_new(struct nouveau_drm *drm, struct nv50_head *head,
                return ret;
        }
 
-       ret = nv50_base_create(&drm->client.device, disp->disp, base->id,
-                              disp->sync->bo.offset, &base->chan);
+       ret = nv50_base_create(&drm->client.device, &disp->disp->object,
+                              base->id, disp->sync->bo.offset, &base->chan);
        if (ret)
                return ret;
 
@@ -2105,7 +2105,7 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
                return;
        }
 
-       if (disp->disp->oclass < GF110_DISP) {
+       if (disp->disp->object.oclass < GF110_DISP) {
                asyh->lut.mode = (asyh->base.cpp == 1) ? 0 : 1;
                asyh->set.ilut = true;
        } else {
@@ -2404,12 +2404,12 @@ nv50_head_create(struct drm_device *dev, int index)
        }
 
        /* allocate overlay resources */
-       ret = nv50_oimm_create(device, disp->disp, index, &head->oimm);
+       ret = nv50_oimm_create(device, &disp->disp->object, index, &head->oimm);
        if (ret)
                goto out;
 
-       ret = nv50_ovly_create(device, disp->disp, index, disp->sync->bo.offset,
-                              &head->ovly);
+       ret = nv50_ovly_create(device, &disp->disp->object, index,
+                              disp->sync->bo.offset, &head->ovly);
        if (ret)
                goto out;
 
@@ -2435,7 +2435,7 @@ nv50_outp_release(struct nouveau_encoder *nv_encoder)
                .base.hashm  = nv_encoder->dcb->hashm,
        };
 
-       nvif_mthd(disp->disp, 0, &args, sizeof(args));
+       nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
        nv_encoder->or = -1;
        nv_encoder->link = 0;
 }
@@ -2456,7 +2456,7 @@ nv50_outp_acquire(struct nouveau_encoder *nv_encoder)
        };
        int ret;
 
-       ret = nvif_mthd(disp->disp, 0, &args, sizeof(args));
+       ret = nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
        if (ret) {
                NV_ERROR(drm, "error acquiring output path: %d\n", ret);
                return ret;
@@ -2618,7 +2618,7 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
        if (args.load.data == 0)
                args.load.data = 340;
 
-       ret = nvif_mthd(disp->disp, 0, &args, sizeof(args));
+       ret = nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
        if (ret || !args.load.load)
                return connector_status_disconnected;
 
@@ -2694,7 +2694,7 @@ nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
                                (0x0100 << nv_crtc->index),
        };
 
-       nvif_mthd(disp->disp, 0, &args, sizeof(args));
+       nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
 }
 
 static void
@@ -2724,7 +2724,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
 
        memcpy(args.data, nv_connector->base.eld, sizeof(args.data));
 
-       nvif_mthd(disp->disp, 0, &args,
+       nvif_mthd(&disp->disp->object, 0, &args,
                  sizeof(args.base) + drm_eld_size(args.data));
 }
 
@@ -2747,7 +2747,7 @@ nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
                               (0x0100 << nv_crtc->index),
        };
 
-       nvif_mthd(disp->disp, 0, &args, sizeof(args));
+       nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
 }
 
 static void
@@ -2808,7 +2808,7 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
                + sizeof(args.pwr)
                + args.pwr.avi_infoframe_length
                + args.pwr.vendor_infoframe_length;
-       nvif_mthd(disp->disp, 0, &args, size);
+       nvif_mthd(&disp->disp->object, 0, &args, size);
        nv50_audio_enable(encoder, mode);
 }
 
@@ -2923,7 +2923,7 @@ nv50_msto_prepare(struct nv50_msto *msto)
                  msto->encoder.name, msto->head->base.base.name,
                  args.vcpi.start_slot, args.vcpi.num_slots,
                  args.vcpi.pbn, args.vcpi.aligned_pbn);
-       nvif_mthd(&drm->display->disp, 0, &args, sizeof(args));
+       nvif_mthd(&drm->display->disp.object, 0, &args, sizeof(args));
 }
 
 static int
@@ -3341,7 +3341,7 @@ nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state)
                .mst.state = state,
        };
        struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev);
-       struct nvif_object *disp = &drm->display->disp;
+       struct nvif_object *disp = &drm->display->disp.object;
        int ret;
 
        if (dpcd >= 0x12) {
@@ -3610,7 +3610,7 @@ nv50_sor_enable(struct drm_encoder *encoder)
                                lvds.lvds.script |= 0x0200;
                }
 
-               nvif_mthd(disp->disp, 0, &lvds, sizeof(lvds));
+               nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
                break;
        case DCB_OUTPUT_DP:
                if (nv_connector->base.display_info.bpc == 6)
@@ -3696,7 +3696,7 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
                struct nvkm_i2c_aux *aux =
                        nvkm_i2c_aux_find(i2c, dcbe->i2c_index);
                if (aux) {
-                       if (disp->disp->oclass < GF110_DISP) {
+                       if (disp->disp->object.oclass < GF110_DISP) {
                                /* HW has no support for address-only
                                 * transactions, so we're required to
                                 * use custom I2C-over-AUX code.
@@ -3709,7 +3709,7 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
                }
 
                /*TODO: Use DP Info Table to check for support. */
-               if (disp->disp->oclass >= GF110_DISP) {
+               if (disp->disp->object.oclass >= GF110_DISP) {
                        ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16,
                                            nv_connector->base.base.id,
                                            &nv_encoder->dp.mstm);
@@ -4474,13 +4474,13 @@ nv50_display_create(struct drm_device *dev)
                goto out;
 
        /* allocate master evo channel */
-       ret = nv50_core_create(device, disp->disp, disp->sync->bo.offset,
-                             &disp->mast);
+       ret = nv50_core_create(device, &disp->disp->object,
+                              disp->sync->bo.offset, &disp->mast);
        if (ret)
                goto out;
 
        /* create crtc objects to represent the hw heads */
-       if (disp->disp->oclass >= GF110_DISP)
+       if (disp->disp->object.oclass >= GF110_DISP)
                crtcs = nvif_rd32(&device->object, 0x612004) & 0xf;
        else
                crtcs = 0x3;
index c817b02b7acf293c0766f0eca7db5fc37059b4a5..3db12504140ff2be9093f9d9e2cfb184486c54a7 100644 (file)
@@ -1,6 +1,7 @@
 nvif-y := nvif/object.o
 nvif-y += nvif/client.o
 nvif-y += nvif/device.o
+nvif-y += nvif/disp.o
 nvif-y += nvif/driver.o
 nvif-y += nvif/fifo.o
 nvif-y += nvif/mem.o
diff --git a/drivers/gpu/drm/nouveau/nvif/disp.c b/drivers/gpu/drm/nouveau/nvif/disp.c
new file mode 100644 (file)
index 0000000..7006482
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <nvif/disp.h>
+#include <nvif/device.h>
+
+#include <nvif/class.h>
+
+void
+nvif_disp_dtor(struct nvif_disp *disp)
+{
+       nvif_object_fini(&disp->object);
+}
+
+int
+nvif_disp_ctor(struct nvif_device *device, s32 oclass, struct nvif_disp *disp)
+{
+       static const struct nvif_mclass disps[] = {
+               { GP102_DISP, -1 },
+               { GP100_DISP, -1 },
+               { GM200_DISP, -1 },
+               { GM107_DISP, -1 },
+               { GK110_DISP, -1 },
+               { GK104_DISP, -1 },
+               { GF110_DISP, -1 },
+               { GT214_DISP, -1 },
+               { GT206_DISP, -1 },
+               { GT200_DISP, -1 },
+               {   G82_DISP, -1 },
+               {  NV50_DISP, -1 },
+               {  NV04_DISP, -1 },
+               {}
+       };
+       int cid = nvif_sclass(&device->object, disps, oclass);
+       disp->object.client = NULL;
+       if (cid < 0)
+               return cid;
+
+       return nvif_object_init(&device->object, 0, disps[cid].oclass,
+                               NULL, 0, &disp->object);
+}