*/
#include "priv.h"
#include "conn.h"
+#include "dp.h"
#include "head.h"
#include "ior.h"
#include "outp.h"
nvkm_disp_oneinit(struct nvkm_engine *engine)
{
struct nvkm_disp *disp = nvkm_disp(engine);
- struct nvkm_bios *bios = disp->engine.subdev.device->bios;
+ struct nvkm_subdev *subdev = &disp->engine.subdev;
+ struct nvkm_bios *bios = subdev->device->bios;
struct nvkm_outp *outp, *outt, *pair;
struct nvkm_conn *conn;
struct nvkm_head *head;
/* Create output path objects for each VBIOS display path. */
i = -1;
while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE))) {
- const struct nvkm_disp_func_outp *outps;
- int (*ctor)(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_outp **);
-
if (dcbE.type == DCB_OUTPUT_UNUSED)
continue;
if (dcbE.type == DCB_OUTPUT_EOL)
break;
outp = NULL;
- switch (dcbE.location) {
- case 0: outps = &disp->func->outp.internal; break;
- case 1: outps = &disp->func->outp.external; break;
- default:
- nvkm_warn(&disp->engine.subdev,
- "dcb %d locn %d unknown\n", i, dcbE.location);
- continue;
- }
-
switch (dcbE.type) {
- case DCB_OUTPUT_ANALOG: ctor = outps->crt ; break;
- case DCB_OUTPUT_TV : ctor = outps->tv ; break;
- case DCB_OUTPUT_TMDS : ctor = outps->tmds; break;
- case DCB_OUTPUT_LVDS : ctor = outps->lvds; break;
- case DCB_OUTPUT_DP : ctor = outps->dp ; break;
+ case DCB_OUTPUT_ANALOG:
+ case DCB_OUTPUT_TV:
+ case DCB_OUTPUT_TMDS:
+ case DCB_OUTPUT_LVDS:
+ ret = nvkm_outp_new(disp, i, &dcbE, &outp);
+ break;
+ case DCB_OUTPUT_DP:
+ ret = nvkm_dp_new(disp, i, &dcbE, &outp);
+ break;
default:
- nvkm_warn(&disp->engine.subdev,
- "dcb %d type %d unknown\n", i, dcbE.type);
+ nvkm_warn(subdev, "dcb %d type %d unknown\n",
+ i, dcbE.type);
continue;
}
- if (ctor)
- ret = ctor(disp, i, &dcbE, &outp);
- else
- ret = -ENODEV;
-
if (ret) {
- if (ret == -ENODEV) {
- nvkm_debug(&disp->engine.subdev,
- "dcb %d %d/%d not supported\n",
- i, dcbE.location, dcbE.type);
+ if (outp) {
+ if (ret != -ENODEV)
+ OUTP_ERR(outp, "ctor failed: %d", ret);
+ else
+ OUTP_DBG(outp, "not supported");
+ nvkm_outp_del(&outp);
continue;
}
- nvkm_error(&disp->engine.subdev,
- "failed to create outp %d\n", i);
- nvkm_outp_del(&outp);
+ nvkm_error(subdev, "failed to create outp %d\n", i);
continue;
}
* Authors: Ben Skeggs
*/
#include "ior.h"
-#include "outp.h"
#include <subdev/timer.h>
-static const struct nvkm_output_func
-nv50_dac_output_func = {
-};
-
-int
-nv50_dac_output_new(struct nvkm_disp *disp, int index,
- struct dcb_output *dcbE, struct nvkm_output **poutp)
-{
- return nvkm_output_new_(&nv50_dac_output_func, disp,
- index, dcbE, poutp);
-}
-
int
nv50_dac_sense(struct nvkm_ior *dac, u32 loadval)
{
dp->aux = aux;
if (!dp->aux) {
OUTP_ERR(&dp->outp, "no aux");
- return -ENODEV;
+ return -EINVAL;
}
/* bios data is not optional */
&hdr, &cnt, &len, &dp->info);
if (!data) {
OUTP_ERR(&dp->outp, "no bios dp data");
- return -ENODEV;
+ return -EINVAL;
}
OUTP_DBG(&dp->outp, "bios dp %02x %02x %02x %02x",
}
int
-nvkm_output_dp_new_(const struct nvkm_output_dp_func *func,
- struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
- struct nvkm_outp **poutp)
+nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
+ struct nvkm_outp **poutp)
{
struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c;
struct nvkm_i2c_aux *aux;
if (!(dp = kzalloc(sizeof(*dp), GFP_KERNEL)))
return -ENOMEM;
- dp->func = func;
*poutp = &dp->outp;
return nvkm_dp_ctor(disp, index, dcbE, aux, dp);
#include <subdev/bios/dp.h>
struct nvkm_dp {
- const struct nvkm_output_dp_func *func;
union {
struct nvkm_outp base;
struct nvkm_outp outp;
#define nvkm_output_dp nvkm_dp
-struct nvkm_output_dp_func {
-};
-
int nvkm_output_dp_train(struct nvkm_output *, u32 rate);
-int nvkm_output_dp_new_(const struct nvkm_output_dp_func *, struct nvkm_disp *,
- int index, struct dcb_output *, struct nvkm_output **);
-
-int nv50_pior_dp_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
-
-int g94_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
-
-int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
-
-int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
-
-int gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
+int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *,
+ struct nvkm_outp **);
/* DPCD Receiver Capabilities */
#define DPCD_RC00_DPCD_REV 0x00000
.super = nv50_disp_super,
.root = &g84_disp_root_oclass,
.head.new = nv50_head_new,
- .outp.internal.crt = nv50_dac_output_new,
- .outp.internal.tmds = nv50_sor_output_new,
- .outp.internal.lvds = nv50_sor_output_new,
- .outp.external.tmds = nv50_pior_output_new,
- .outp.external.dp = nv50_pior_dp_new,
.dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 2, .new = g84_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new },
.super = nv50_disp_super,
.root = &g94_disp_root_oclass,
.head.new = nv50_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 = g94_sor_dp_new,
- .outp.external.tmds = nv50_pior_output_new,
- .outp.external.dp = nv50_pior_dp_new,
.dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 4, .new = g94_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new },
.super = gf119_disp_super,
.root = &gf119_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 = gf119_sor_dp_new,
.dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gf119_sor_new },
};
.super = gf119_disp_super,
.root = &gk104_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 = gf119_sor_dp_new,
.dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gk104_sor_new },
};
.super = gf119_disp_super,
.root = &gk110_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 = gf119_sor_dp_new,
.dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gk104_sor_new },
};
.super = gf119_disp_super,
.root = &gm107_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 = gm107_sor_dp_new,
.dac = { .nr = 3, .new = gf119_dac_new },
.sor = { .nr = 4, .new = gm107_sor_new },
};
.super = gf119_disp_super,
.root = &gm200_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, .new = gf119_dac_new },
.sor.nr = 4,
.sor.new = gm200_sor_new,
.super = gf119_disp_super,
.root = &gp100_disp_root_oclass,
.head.new = gf119_head_new,
- .outp.internal.tmds = nv50_sor_output_new,
- .outp.internal.lvds = nv50_sor_output_new,
- .outp.internal.dp = gm200_sor_dp_new,
.sor.nr = 4,
.sor.new = gm200_sor_new,
.sor.magic = gm200_sor_magic,
.super = gf119_disp_super,
.root = &gp102_disp_root_oclass,
.head.new = gf119_head_new,
- .outp.internal.tmds = nv50_sor_output_new,
- .outp.internal.lvds = nv50_sor_output_new,
- .outp.internal.dp = gm200_sor_dp_new,
.sor.nr = 4,
.sor.new = gm200_sor_new,
.sor.magic = gm200_sor_magic,
.super = nv50_disp_super,
.root = >200_disp_root_oclass,
.head.new = nv50_head_new,
- .outp.internal.crt = nv50_dac_output_new,
- .outp.internal.tmds = nv50_sor_output_new,
- .outp.internal.lvds = nv50_sor_output_new,
- .outp.external.tmds = nv50_pior_output_new,
- .outp.external.dp = nv50_pior_dp_new,
.dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 2, .new = g84_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new },
.super = nv50_disp_super,
.root = >215_disp_root_oclass,
.head.new = nv50_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 = g94_sor_dp_new,
- .outp.external.tmds = nv50_pior_output_new,
- .outp.external.dp = nv50_pior_dp_new,
.dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 4, .new = gt215_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new },
.super = nv50_disp_super,
.root = &g94_disp_root_oclass,
.head.new = nv50_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 = g94_sor_dp_new,
- .outp.external.tmds = nv50_pior_output_new,
- .outp.external.dp = nv50_pior_dp_new,
.dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 4, .new = mcp77_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new },
.super = nv50_disp_super,
.root = >215_disp_root_oclass,
.head.new = nv50_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 = g94_sor_dp_new,
- .outp.external.tmds = nv50_pior_output_new,
- .outp.external.dp = nv50_pior_dp_new,
.dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 4, .new = mcp89_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new },
return nv50_disp(base)->func->root;
}
-static int
-nv50_disp_outp_internal_crt_(struct nvkm_disp *base, int index,
- struct dcb_output *dcb, struct nvkm_output **poutp)
-{
- struct nv50_disp *disp = nv50_disp(base);
- return disp->func->outp.internal.crt(base, index, dcb, poutp);
-}
-
-static int
-nv50_disp_outp_internal_tmds_(struct nvkm_disp *base, int index,
- struct dcb_output *dcb,
- struct nvkm_output **poutp)
-{
- struct nv50_disp *disp = nv50_disp(base);
- return disp->func->outp.internal.tmds(base, index, dcb, poutp);
-}
-
-static int
-nv50_disp_outp_internal_lvds_(struct nvkm_disp *base, int index,
- struct dcb_output *dcb,
- struct nvkm_output **poutp)
-{
- struct nv50_disp *disp = nv50_disp(base);
- return disp->func->outp.internal.lvds(base, index, dcb, poutp);
-}
-
-static int
-nv50_disp_outp_internal_dp_(struct nvkm_disp *base, int index,
- struct dcb_output *dcb, struct nvkm_output **poutp)
-{
- struct nv50_disp *disp = nv50_disp(base);
- if (disp->func->outp.internal.dp)
- return disp->func->outp.internal.dp(base, index, dcb, poutp);
- return -ENODEV;
-}
-
-static int
-nv50_disp_outp_external_tmds_(struct nvkm_disp *base, int index,
- struct dcb_output *dcb,
- struct nvkm_output **poutp)
-{
- struct nv50_disp *disp = nv50_disp(base);
- if (disp->func->outp.external.tmds)
- return disp->func->outp.external.tmds(base, index, dcb, poutp);
- return -ENODEV;
-}
-
-static int
-nv50_disp_outp_external_dp_(struct nvkm_disp *base, int index,
- struct dcb_output *dcb, struct nvkm_output **poutp)
-{
- struct nv50_disp *disp = nv50_disp(base);
- if (disp->func->outp.external.dp)
- return disp->func->outp.external.dp(base, index, dcb, poutp);
- return -ENODEV;
-}
-
static void
nv50_disp_intr_(struct nvkm_disp *base)
{
.dtor = nv50_disp_dtor_,
.intr = nv50_disp_intr_,
.root = nv50_disp_root_,
- .outp.internal.crt = nv50_disp_outp_internal_crt_,
- .outp.internal.tmds = nv50_disp_outp_internal_tmds_,
- .outp.internal.lvds = nv50_disp_outp_internal_lvds_,
- .outp.internal.dp = nv50_disp_outp_internal_dp_,
- .outp.external.tmds = nv50_disp_outp_external_tmds_,
- .outp.external.dp = nv50_disp_outp_external_dp_,
};
int
.super = nv50_disp_super,
.root = &nv50_disp_root_oclass,
.head.new = nv50_head_new,
- .outp.internal.crt = nv50_dac_output_new,
- .outp.internal.tmds = nv50_sor_output_new,
- .outp.internal.lvds = nv50_sor_output_new,
- .outp.external.tmds = nv50_pior_output_new,
- .outp.external.dp = nv50_pior_dp_new,
.dac = { .nr = 3, .new = nv50_dac_new },
.sor = { .nr = 2, .new = nv50_sor_new },
.pior = { .nr = 3, .new = nv50_pior_new },
int gf119_disp_new_(const struct nv50_disp_func *, struct nvkm_device *,
int index, struct nvkm_disp **);
-struct nv50_disp_func_outp {
- int (* crt)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
- int (* tv)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
- int (*tmds)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
- int (*lvds)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
- int (* dp)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
-};
-
struct nv50_disp_func {
void (*intr)(struct nv50_disp *);
void (*intr_error)(struct nv50_disp *, int chid);
int (*new)(struct nvkm_disp *, int id);
} head;
- struct {
- const struct nv50_disp_func_outp internal;
- const struct nv50_disp_func_outp external;
- } outp;
-
struct {
int nr;
int (*new)(struct nvkm_disp *, int id);
return 0;
}
+static const struct nvkm_outp_func
+nvkm_outp = {
+};
+
int
-nvkm_outp_new_(const struct nvkm_outp_func *func,
- struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
- struct nvkm_outp **poutp)
+nvkm_outp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
+ struct nvkm_outp **poutp)
{
if (!(*poutp = kzalloc(sizeof(**poutp), GFP_KERNEL)))
return -ENOMEM;
- return nvkm_outp_ctor(func, disp, index, dcbE, *poutp);
+ return nvkm_outp_ctor(&nvkm_outp, disp, index, dcbE, *poutp);
}
int nvkm_outp_ctor(const struct nvkm_outp_func *, struct nvkm_disp *,
int index, struct dcb_output *, struct nvkm_outp *);
+int nvkm_outp_new(struct nvkm_disp *, int index, struct dcb_output *,
+ struct nvkm_outp **);
void nvkm_outp_del(struct nvkm_outp **);
void nvkm_outp_init(struct nvkm_outp *);
void nvkm_outp_fini(struct nvkm_outp *);
#define nvkm_output_func nvkm_outp_func
#define nvkm_output_new_ nvkm_outp_new_
-int nvkm_outp_new_(const struct nvkm_outp_func *, struct nvkm_disp *,
- int index, struct dcb_output *, struct nvkm_output **);
-
-int nv50_dac_output_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
-int nv50_sor_output_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
-int nv50_pior_output_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
-
void gm200_sor_magic(struct nvkm_output *outp);
#define OUTP_MSG(o,l,f,a...) do { \
* Authors: Ben Skeggs
*/
#include "ior.h"
-#include "dp.h"
#include <subdev/i2c.h>
#include <subdev/timer.h>
-/******************************************************************************
- * TMDS
- *****************************************************************************/
-static const struct nvkm_output_func
-nv50_pior_output_func = {
-};
-
-int
-nv50_pior_output_new(struct nvkm_disp *disp, int index,
- struct dcb_output *dcbE, struct nvkm_output **poutp)
-{
- return nvkm_output_new_(&nv50_pior_output_func, disp,
- index, dcbE, poutp);
-}
-
-/******************************************************************************
- * DisplayPort
- *****************************************************************************/
static int
nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux)
{
return 1;
}
-static const struct nvkm_output_dp_func
-nv50_pior_output_dp_func = {
-};
-
-int
-nv50_pior_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
- struct nvkm_output **poutp)
-{
- return nvkm_output_dp_new_(&nv50_pior_output_dp_func, disp,
- index, dcbE, poutp);
-}
-
static void
nv50_pior_power_wait(struct nvkm_device *device, u32 poff)
{
int index, struct nvkm_disp **);
void nvkm_disp_vblank(struct nvkm_disp *, int head);
-struct nvkm_disp_func_outp {
- int (* crt)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
- int (* tv)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
- int (*tmds)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
- int (*lvds)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
- int (* dp)(struct nvkm_disp *, int index, struct dcb_output *,
- struct nvkm_output **);
-};
-
struct nvkm_disp_func {
void *(*dtor)(struct nvkm_disp *);
void (*intr)(struct nvkm_disp *);
const struct nvkm_disp_oclass *(*root)(struct nvkm_disp *);
-
- struct {
- const struct nvkm_disp_func_outp internal;
- const struct nvkm_disp_func_outp external;
- } outp;
};
int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **);
return 0;
}
-static const struct nvkm_output_dp_func
-g94_sor_dp_func = {
-};
-
-int
-g94_sor_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
- struct nvkm_output **poutp)
-{
- return nvkm_output_dp_new_(&g94_sor_dp_func, disp, index, dcbE, poutp);
-}
-
static bool
nv50_disp_dptmds_war(struct nvkm_device *device)
{
* Authors: Ben Skeggs
*/
#include "ior.h"
-#include "nv50.h"
#include <subdev/timer.h>
return 0;
}
-static const struct nvkm_output_dp_func
-gf119_sor_dp_func = {
-};
-
-int
-gf119_sor_dp_new(struct nvkm_disp *disp, int index,
- struct dcb_output *dcbE, struct nvkm_output **poutp)
-{
- return nvkm_output_dp_new_(&gf119_sor_dp_func, disp, index, dcbE, poutp);
-}
-
void
gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state)
{
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include "ior.h"
-#include "nv50.h"
void
gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern)
nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
}
-static const struct nvkm_output_dp_func
-gm107_sor_dp_func = {
-};
-
-int
-gm107_sor_dp_new(struct nvkm_disp *disp, int index,
- struct dcb_output *dcbE, struct nvkm_output **poutp)
-{
- return nvkm_output_dp_new_(&gm107_sor_dp_func, disp, index, dcbE, poutp);
-}
-
static const struct nvkm_ior_func
gm107_sor = {
.state = gf119_sor_state,
* Authors: Ben Skeggs
*/
#include "ior.h"
-#include "nv50.h"
static void
gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu)
nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift));
}
-static const struct nvkm_output_dp_func
-gm200_sor_dp_func = {
-};
-
-int
-gm200_sor_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
- struct nvkm_output **poutp)
-{
- return nvkm_output_dp_new_(&gm200_sor_dp_func, disp, index, dcbE, poutp);
-}
-
void
gm200_sor_magic(struct nvkm_output *outp)
{
* Authors: Ben Skeggs
*/
#include "ior.h"
-#include "outp.h"
#include <subdev/timer.h>
-static const struct nvkm_output_func
-nv50_sor_output_func = {
-};
-
-int
-nv50_sor_output_new(struct nvkm_disp *disp, int index,
- struct dcb_output *dcbE, struct nvkm_output **poutp)
-{
- return nvkm_output_new_(&nv50_sor_output_func, disp,
- index, dcbE, poutp);
-}
-
static void
nv50_sor_power_wait(struct nvkm_device *device, u32 soff)
{