From 0d4a2c5767dc6136079b11ed45934143d309026e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 8 May 2018 20:39:47 +1000 Subject: drm/nouveau/kms: move display class instantiation to library This function is useful outside of DRM code. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvif/disp.h | 12 ++++++ drivers/gpu/drm/nouveau/include/nvif/object.h | 16 ++++++++ drivers/gpu/drm/nouveau/nouveau_connector.c | 14 +++---- drivers/gpu/drm/nouveau/nouveau_display.c | 35 ++++------------ drivers/gpu/drm/nouveau/nouveau_display.h | 3 +- drivers/gpu/drm/nouveau/nv50_display.c | 50 +++++++++++------------ drivers/gpu/drm/nouveau/nvif/Kbuild | 1 + drivers/gpu/drm/nouveau/nvif/disp.c | 59 +++++++++++++++++++++++++++ 8 files changed, 129 insertions(+), 61 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvif/disp.h create mode 100644 drivers/gpu/drm/nouveau/nvif/disp.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/include/nvif/disp.h b/drivers/gpu/drm/nouveau/include/nvif/disp.h new file mode 100644 index 000000000000..7c0eda375c01 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/disp.h @@ -0,0 +1,12 @@ +#ifndef __NVIF_DISP_H__ +#define __NVIF_DISP_H__ +#include +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 diff --git a/drivers/gpu/drm/nouveau/include/nvif/object.h b/drivers/gpu/drm/nouveau/include/nvif/object.h index a2d5244ff2b7..20754d9e6883 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/object.h +++ b/drivers/gpu/drm/nouveau/include/nvif/object.h @@ -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 #define nvxx_object(a) ({ \ diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 6ed9cb053dfa..18e3239f7658 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -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, diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 7d0bec8dd03d..774b429142bc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 270ba56f2756..54aa7c3fa42d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -2,6 +2,7 @@ #ifndef __NOUVEAU_DISPLAY_H__ #define __NOUVEAU_DISPLAY_H__ #include "nouveau_drv.h" +#include 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; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index e90330e4e8c5..f2156c8ca90f 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild index c817b02b7acf..3db12504140f 100644 --- a/drivers/gpu/drm/nouveau/nvif/Kbuild +++ b/drivers/gpu/drm/nouveau/nvif/Kbuild @@ -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 index 000000000000..7006482e8e29 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvif/disp.c @@ -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 +#include + +#include + +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); +} -- cgit v1.2.3-59-g8ed1b