static void
nv50_dac_destroy(struct drm_encoder *encoder)
{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+ nvif_outp_dtor(&nv_encoder->outp);
+
drm_encoder_cleanup(encoder);
kfree(encoder);
}
nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
{
struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ struct nv50_disp *disp = nv50_disp(connector->dev);
struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device);
struct nvkm_i2c_bus *bus;
struct nouveau_encoder *nv_encoder;
drm_encoder_helper_add(encoder, &nv50_dac_help);
drm_connector_attach_encoder(connector, encoder);
- return 0;
+ return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp);
}
/*
nv50_sor_destroy(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+ nvif_outp_dtor(&nv_encoder->outp);
+
nv50_mstm_del(&nv_encoder->dp.mstm);
drm_encoder_cleanup(encoder);
nv_encoder->i2c = &bus->i2c;
}
- return 0;
+ return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp);
}
/******************************************************************************
static void
nv50_pior_destroy(struct drm_encoder *encoder)
{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+ nvif_outp_dtor(&nv_encoder->outp);
+
drm_encoder_cleanup(encoder);
kfree(encoder);
}
disp->core->func->pior->get_caps(disp, nv_encoder, ffs(dcbe->or) - 1);
nv50_outp_dump_caps(drm, nv_encoder);
- return 0;
+ return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp);
}
/******************************************************************************
#define NVIF_CLASS_DISP /* if0010.h */ 0x80000010
#define NVIF_CLASS_CONN /* if0011.h */ 0x80000011
+#define NVIF_CLASS_OUTP /* if0012.h */ 0x80000012
#define NVIF_CLASS_DISP_CHAN /* if0014.h */ 0x80000014
/* the below match nvidia-assigned (either in hw, or sw) class numbers */
struct nvif_disp {
struct nvif_object object;
unsigned long conn_mask;
+ unsigned long outp_mask;
};
int nvif_disp_ctor(struct nvif_device *, const char *name, s32 oclass,
__u8 version;
__u8 pad01[3];
__u32 conn_mask;
+ __u32 outp_mask;
} v0;
};
#endif
--- /dev/null
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVIF_IF0012_H__
+#define __NVIF_IF0012_H__
+
+union nvif_outp_args {
+ struct nvif_outp_v0 {
+ __u8 version;
+ __u8 id; /* DCB device index. */
+ __u8 pad02[6];
+ } v0;
+};
+#endif
--- /dev/null
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVIF_OUTP_H__
+#define __NVIF_OUTP_H__
+#include <nvif/object.h>
+struct nvif_disp;
+
+struct nvif_outp {
+ struct nvif_object object;
+};
+
+int nvif_outp_ctor(struct nvif_disp *, const char *name, int id, struct nvif_outp *);
+void nvif_outp_dtor(struct nvif_outp *);
+#endif
} tmdsconf;
};
bool i2c_upper_default;
+ int id;
};
u16 dcb_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len);
ret = parse_dcb20_entry(dev, dcb, conn, conf, entry);
else
ret = parse_dcb15_entry(dev, dcb, conn, conf, entry);
+ entry->id = idx;
+
if (!ret)
return 1; /* stop parsing */
#ifndef __NOUVEAU_ENCODER_H__
#define __NOUVEAU_ENCODER_H__
-
+#include <nvif/outp.h>
#include <subdev/bios/dcb.h>
#include <drm/display/drm_dp_helper.h>
struct drm_encoder_slave base;
struct dcb_output *dcb;
+ struct nvif_outp outp;
int or;
int link;
nvif-y += nvif/mem.o
nvif-y += nvif/mmu.o
nvif-y += nvif/notify.o
+nvif-y += nvif/outp.o
nvif-y += nvif/timer.o
nvif-y += nvif/vmm.o
if (ret)
return ret;
- NVIF_DEBUG(&disp->object, "[NEW] conn_mask:%08x", args.conn_mask);
+ NVIF_DEBUG(&disp->object, "[NEW] conn_mask:%08x outp_mask:%08x",
+ args.conn_mask, args.outp_mask);
disp->conn_mask = args.conn_mask;
+ disp->outp_mask = args.outp_mask;
return 0;
}
--- /dev/null
+/*
+ * Copyright 2021 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/outp.h>
+#include <nvif/disp.h>
+#include <nvif/printf.h>
+
+#include <nvif/class.h>
+#include <nvif/if0012.h>
+
+void
+nvif_outp_dtor(struct nvif_outp *outp)
+{
+ nvif_object_dtor(&outp->object);
+}
+
+int
+nvif_outp_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_outp *outp)
+{
+ struct nvif_outp_v0 args;
+ int ret;
+
+ args.version = 0;
+ args.id = id;
+
+ ret = nvif_object_ctor(&disp->object, name ?: "nvifOutp", id, NVIF_CLASS_OUTP,
+ &args, sizeof(args), &outp->object);
+ NVIF_ERRON(ret, &disp->object, "[NEW outp id:%d]", id);
+ return ret;
+}
nvkm-y += nvkm/engine/disp/udisp.o
nvkm-y += nvkm/engine/disp/uconn.o
+nvkm-y += nvkm/engine/disp/uoutp.o
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_DISP_OUTP_H__
#define __NVKM_DISP_OUTP_H__
-#include <engine/disp.h>
+#include "priv.h"
#include <core/notify.h>
#include <subdev/bios.h>
} lt;
} dp;
};
+
+ struct nvkm_object object;
};
int nvkm_outp_new_(const struct nvkm_outp_func *, struct nvkm_disp *, int index,
int nvkm_udisp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **);
int nvkm_uconn_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **);
+int nvkm_uoutp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **);
#endif
*/
#include "priv.h"
#include "conn.h"
+#include "outp.h"
#include <nvif/class.h>
#include <nvif/if0010.h>
return 0;
}
+ if (index-- == 0) {
+ sclass->base = (struct nvkm_sclass) { 0, 0, NVIF_CLASS_OUTP };
+ sclass->ctor = nvkm_uoutp_new;
+ return 0;
+ }
+
if (disp->func->user[index].ctor) {
sclass->base = disp->func->user[index].base;
sclass->ctor = disp->func->user[index].ctor;
{
struct nvkm_disp *disp = nvkm_disp(oclass->engine);
struct nvkm_conn *conn;
+ struct nvkm_outp *outp;
union nvif_disp_args *args = argv;
if (argc != sizeof(args->v0) || args->v0.version != 0)
list_for_each_entry(conn, &disp->conns, head)
args->v0.conn_mask |= BIT(conn->index);
+ args->v0.outp_mask = 0;
+ list_for_each_entry(outp, &disp->outps, head)
+ args->v0.outp_mask |= BIT(outp->index);
+
return 0;
}
--- /dev/null
+/*
+ * Copyright 2021 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.
+ */
+#define nvkm_uoutp(p) container_of((p), struct nvkm_outp, object)
+#include "outp.h"
+
+#include <nvif/if0012.h>
+
+static int
+nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
+{
+ switch (mthd) {
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+static int
+nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
+{
+ struct nvkm_outp *outp = nvkm_uoutp(object);
+ struct nvkm_disp *disp = outp->disp;
+ int ret;
+
+ mutex_lock(&disp->super.mutex);
+
+ ret = nvkm_uoutp_mthd_noacquire(outp, mthd, argv, argc);
+ if (ret <= 0)
+ goto done;
+
+done:
+ mutex_unlock(&disp->super.mutex);
+ return ret;
+}
+
+static void *
+nvkm_uoutp_dtor(struct nvkm_object *object)
+{
+ struct nvkm_outp *outp = nvkm_uoutp(object);
+ struct nvkm_disp *disp = outp->disp;
+
+ spin_lock(&disp->client.lock);
+ outp->object.func = NULL;
+ spin_unlock(&disp->client.lock);
+ return NULL;
+}
+
+static const struct nvkm_object_func
+nvkm_uoutp = {
+ .dtor = nvkm_uoutp_dtor,
+ .mthd = nvkm_uoutp_mthd,
+};
+
+int
+nvkm_uoutp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject)
+{
+ struct nvkm_disp *disp = nvkm_udisp(oclass->parent);
+ struct nvkm_outp *outt, *outp = NULL;
+ union nvif_outp_args *args = argv;
+ int ret;
+
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+
+ list_for_each_entry(outt, &disp->outps, head) {
+ if (outt->index == args->v0.id) {
+ outp = outt;
+ break;
+ }
+ }
+
+ if (!outp)
+ return -EINVAL;
+
+ ret = -EBUSY;
+ spin_lock(&disp->client.lock);
+ if (!outp->object.func) {
+ nvkm_object_ctor(&nvkm_uoutp, oclass, &outp->object);
+ *pobject = &outp->object;
+ ret = 0;
+ }
+ spin_unlock(&disp->client.lock);
+ return ret;
+}