struct nvkm_engine engine;
struct list_head head;
+ struct list_head ior;
struct list_head outp;
struct list_head conn;
nvkm-y += nvkm/engine/disp/headnv50.o
nvkm-y += nvkm/engine/disp/headgf119.o
+nvkm-y += nvkm/engine/disp/ior.o
nvkm-y += nvkm/engine/disp/dacnv50.o
nvkm-y += nvkm/engine/disp/piornv50.o
nvkm-y += nvkm/engine/disp/sornv50.o
#include "priv.h"
#include "conn.h"
#include "head.h"
+#include "ior.h"
#include "outp.h"
#include <core/client.h>
nvkm_outp_del(&outp);
}
+ while (!list_empty(&disp->ior)) {
+ struct nvkm_ior *ior =
+ list_first_entry(&disp->ior, typeof(*ior), head);
+ nvkm_ior_del(&ior);
+ }
+
while (!list_empty(&disp->head)) {
struct nvkm_head *head =
list_first_entry(&disp->head, typeof(*head), head);
{
disp->func = func;
INIT_LIST_HEAD(&disp->head);
+ INIT_LIST_HEAD(&disp->ior);
INIT_LIST_HEAD(&disp->outp);
INIT_LIST_HEAD(&disp->conn);
return nvkm_engine_ctor(&nvkm_disp, device, index, true, &disp->engine);
*
* Authors: Ben Skeggs
*/
+#include "ior.h"
#include "nv50.h"
#include "outp.h"
);
return 0;
}
+
+static const struct nvkm_ior_func
+nv50_dac = {
+};
+
+int
+nv50_dac_new(struct nvkm_disp *disp, int id)
+{
+ return nvkm_ior_new_(&nv50_dac, disp, DAC, id);
+}
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 2,
+ .sor.new = nv50_sor_new,
.sor.power = nv50_sor_power,
.sor.hdmi = g84_hdmi_ctrl,
.pior.nr = 3,
+ .pior.new = nv50_pior_new,
.pior.power = nv50_pior_power,
};
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = g94_sor_new,
.sor.power = nv50_sor_power,
.sor.hdmi = g84_hdmi_ctrl,
.pior.nr = 3,
+ .pior.new = nv50_pior_new,
.pior.power = nv50_pior_power,
};
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
#include <subdev/bios.h>
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gf119_sor_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = gf119_sor_new,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gf119_hdmi_ctrl,
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gf119_sor_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = gf119_sor_new,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gf119_sor_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = gf119_sor_new,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gm107_sor_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = gm107_sor_new,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gm200_sor_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = gm200_sor_new,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.super = gf119_disp_super,
.root = &gp100_disp_root_oclass,
.head.new = gf119_head_new,
- .outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gm200_sor_dp_new,
- .dac.nr = 3,
- .dac.power = nv50_dac_power,
- .dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = gm200_sor_new,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static void
.super = gf119_disp_super,
.root = &gp102_disp_root_oclass,
.head.new = gf119_head_new,
- .outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gm200_sor_dp_new,
- .dac.nr = 3,
- .dac.power = nv50_dac_power,
- .dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = gm200_sor_new,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 2,
+ .sor.new = nv50_sor_new,
.sor.power = nv50_sor_power,
.sor.hdmi = g84_hdmi_ctrl,
.pior.nr = 3,
+ .pior.new = nv50_pior_new,
.pior.power = nv50_pior_power,
};
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
static const struct nv50_disp_func
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
+ .sor.new = g94_sor_new,
.sor.power = nv50_sor_power,
.sor.hda_eld = gt215_hda_eld,
.sor.hdmi = gt215_hdmi_ctrl,
.pior.nr = 3,
+ .pior.new = nv50_pior_new,
.pior.power = nv50_pior_power,
};
--- /dev/null
+/*
+ * Copyright 2017 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.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "ior.h"
+
+static const char *
+nvkm_ior_name[] = {
+ [DAC] = "DAC",
+ [SOR] = "SOR",
+ [PIOR] = "PIOR",
+};
+
+struct nvkm_ior *
+nvkm_ior_find(struct nvkm_disp *disp, enum nvkm_ior_type type, int id)
+{
+ struct nvkm_ior *ior;
+ list_for_each_entry(ior, &disp->ior, head) {
+ if (ior->type == type && (id < 0 || ior->id == id))
+ return ior;
+ }
+ return NULL;
+}
+
+void
+nvkm_ior_del(struct nvkm_ior **pior)
+{
+ struct nvkm_ior *ior = *pior;
+ if (ior) {
+ IOR_DBG(ior, "dtor");
+ list_del(&ior->head);
+ kfree(*pior);
+ *pior = NULL;
+ }
+}
+
+int
+nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *disp,
+ enum nvkm_ior_type type, int id)
+{
+ struct nvkm_ior *ior;
+ if (!(ior = kzalloc(sizeof(*ior), GFP_KERNEL)))
+ return -ENOMEM;
+ ior->func = func;
+ ior->disp = disp;
+ ior->type = type;
+ ior->id = id;
+ snprintf(ior->name, sizeof(ior->name), "%s-%d",
+ nvkm_ior_name[ior->type], ior->id);
+ list_add_tail(&ior->head, &disp->ior);
+ IOR_DBG(ior, "ctor");
+ return 0;
+}
--- /dev/null
+#ifndef __NVKM_DISP_IOR_H__
+#define __NVKM_DISP_IOR_H__
+#include "priv.h"
+
+struct nvkm_ior {
+ const struct nvkm_ior_func *func;
+ struct nvkm_disp *disp;
+ enum nvkm_ior_type {
+ DAC,
+ SOR,
+ PIOR,
+ } type;
+ int id;
+ char name[8];
+
+ struct list_head head;
+};
+
+struct nvkm_ior_func {
+};
+
+int nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *,
+ enum nvkm_ior_type type, int id);
+void nvkm_ior_del(struct nvkm_ior **);
+struct nvkm_ior *nvkm_ior_find(struct nvkm_disp *, enum nvkm_ior_type, int id);
+
+#define IOR_MSG(i,l,f,a...) do { \
+ struct nvkm_ior *_ior = (i); \
+ nvkm_##l(&_ior->disp->engine.subdev, "%s: "f, _ior->name, ##a); \
+} while(0)
+#define IOR_WARN(i,f,a...) IOR_MSG((i), warn, f, ##a)
+#define IOR_DBG(i,f,a...) IOR_MSG((i), debug, f, ##a)
+
+int nv50_dac_new(struct nvkm_disp *, int);
+
+int nv50_pior_new(struct nvkm_disp *, int);
+
+int nv50_sor_new(struct nvkm_disp *, int);
+int g94_sor_new(struct nvkm_disp *, int);
+int gf119_sor_new(struct nvkm_disp *, int);
+int gm107_sor_new(struct nvkm_disp *, int);
+int gm200_sor_new(struct nvkm_disp *, int);
+#endif
*/
#include "nv50.h"
#include "head.h"
+#include "ior.h"
#include "rootnv50.h"
#include <core/client.h>
return ret;
}
+ for (i = 0; func->dac.new && i < func->dac.nr; i++) {
+ ret = func->dac.new(&disp->base, i);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; func->pior.new && i < func->pior.nr; i++) {
+ ret = func->pior.new(&disp->base, i);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; func->sor.new && i < func->sor.nr; i++) {
+ ret = func->sor.new(&disp->base, i);
+ if (ret)
+ return ret;
+ }
+
return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent);
}
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
+ .dac.new = nv50_dac_new,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 2,
+ .sor.new = nv50_sor_new,
.sor.power = nv50_sor_power,
.pior.nr = 3,
+ .pior.new = nv50_pior_new,
.pior.power = nv50_pior_power,
};
struct {
int nr;
+ int (*new)(struct nvkm_disp *, int id);
int (*power)(NV50_DISP_MTHD_V1);
int (*sense)(NV50_DISP_MTHD_V1);
} dac;
struct {
int nr;
+ int (*new)(struct nvkm_disp *, int id);
int (*power)(NV50_DISP_MTHD_V1);
int (*hda_eld)(NV50_DISP_MTHD_V1);
int (*hdmi)(NV50_DISP_MTHD_V1);
struct {
int nr;
+ int (*new)(struct nvkm_disp *, int id);
int (*power)(NV50_DISP_MTHD_V1);
} pior;
};
*
* Authors: Ben Skeggs
*/
+#include "ior.h"
#include "nv50.h"
#include <core/client.h>
disp->pior.type[outp->or] = type;
return 0;
}
+
+static const struct nvkm_ior_func
+nv50_pior = {
+};
+
+int
+nv50_pior_new(struct nvkm_disp *disp, int id)
+{
+ return nvkm_ior_new_(&nv50_pior, disp, PIOR, id);
+}
*
* Authors: Ben Skeggs
*/
+#include "ior.h"
#include "nv50.h"
#include <subdev/timer.h>
nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f008000);
}
}
+
+static const struct nvkm_ior_func
+g94_sor = {
+};
+
+int
+g94_sor_new(struct nvkm_disp *disp, int id)
+{
+ return nvkm_ior_new_(&g94_sor, disp, SOR, id);
+}
*
* Authors: Ben Skeggs
*/
+#include "ior.h"
#include "nv50.h"
void
{
return nvkm_output_dp_new_(&gf119_sor_dp_func, disp, index, dcbE, poutp);
}
+
+static const struct nvkm_ior_func
+gf119_sor = {
+};
+
+int
+gf119_sor_new(struct nvkm_disp *disp, int id)
+{
+ return nvkm_ior_new_(&gf119_sor, disp, SOR, id);
+}
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
+#include "ior.h"
#include "nv50.h"
int
{
return nvkm_output_dp_new_(&gm107_sor_dp_func, disp, index, dcbE, poutp);
}
+
+static const struct nvkm_ior_func
+gm107_sor = {
+};
+
+int
+gm107_sor_new(struct nvkm_disp *disp, int id)
+{
+ return nvkm_ior_new_(&gm107_sor, disp, SOR, id);
+}
*
* Authors: Ben Skeggs
*/
+#include "ior.h"
#include "nv50.h"
#include <subdev/timer.h>
if (outp->info.sorconf.link & 2)
nvkm_mask(device, 0x612388 + soff, 0x0000001f, 0x00000010 | data);
}
+
+static const struct nvkm_ior_func
+gm200_sor = {
+};
+
+int
+gm200_sor_new(struct nvkm_disp *disp, int id)
+{
+ return nvkm_ior_new_(&gm200_sor, disp, SOR, id);
+}
*
* Authors: Ben Skeggs
*/
+#include "ior.h"
#include "nv50.h"
#include "outp.h"
);
return 0;
}
+
+static const struct nvkm_ior_func
+nv50_sor = {
+};
+
+int
+nv50_sor_new(struct nvkm_disp *disp, int id)
+{
+ return nvkm_ior_new_(&nv50_sor, disp, SOR, id);
+}