drm/nouveau/kms/nv50-: create connectors based on nvkm info
- preparation for GSP-RM Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Danilo Krummrich <me@dakr.org> Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230919220442.202488-43-lyude@redhat.com
This commit is contained in:
parent
9c3361de06
commit
8b7d92cad9
@ -256,7 +256,7 @@ nv04_display_create(struct drm_device *dev)
|
||||
for (i = 0; i < dcb->entries; i++) {
|
||||
struct dcb_output *dcbent = &dcb->entry[i];
|
||||
|
||||
connector = nouveau_connector_create(dev, dcbent);
|
||||
connector = nouveau_connector_create(dev, dcbent->connector);
|
||||
if (IS_ERR(connector))
|
||||
continue;
|
||||
|
||||
|
@ -2788,7 +2788,7 @@ nv50_display_create(struct drm_device *dev)
|
||||
continue;
|
||||
}
|
||||
|
||||
connector = nouveau_connector_create(dev, dcbe);
|
||||
connector = nouveau_connector_create(dev, dcbe->connector);
|
||||
if (IS_ERR(connector)) {
|
||||
nvif_outp_dtor(&outp->outp);
|
||||
kfree(outp);
|
||||
|
@ -7,6 +7,21 @@ struct nvif_disp;
|
||||
|
||||
struct nvif_conn {
|
||||
struct nvif_object object;
|
||||
u32 id;
|
||||
|
||||
struct {
|
||||
enum {
|
||||
NVIF_CONN_VGA,
|
||||
NVIF_CONN_TV,
|
||||
NVIF_CONN_DVI_I,
|
||||
NVIF_CONN_DVI_D,
|
||||
NVIF_CONN_LVDS,
|
||||
NVIF_CONN_LVDS_SPWG,
|
||||
NVIF_CONN_HDMI,
|
||||
NVIF_CONN_DP,
|
||||
NVIF_CONN_EDP,
|
||||
} type;
|
||||
} info;
|
||||
};
|
||||
|
||||
int nvif_conn_ctor(struct nvif_disp *, const char *name, int id, struct nvif_conn *);
|
||||
|
@ -7,6 +7,16 @@ union nvif_conn_args {
|
||||
__u8 version;
|
||||
__u8 id; /* DCB connector table index. */
|
||||
__u8 pad02[6];
|
||||
#define NVIF_CONN_V0_VGA 0x00
|
||||
#define NVIF_CONN_V0_TV 0x01
|
||||
#define NVIF_CONN_V0_DVI_I 0x02
|
||||
#define NVIF_CONN_V0_DVI_D 0x03
|
||||
#define NVIF_CONN_V0_LVDS 0x04
|
||||
#define NVIF_CONN_V0_LVDS_SPWG 0x05
|
||||
#define NVIF_CONN_V0_HDMI 0x06
|
||||
#define NVIF_CONN_V0_DP 0x07
|
||||
#define NVIF_CONN_V0_EDP 0x08
|
||||
__u8 type;
|
||||
} v0;
|
||||
};
|
||||
|
||||
|
@ -1275,15 +1275,13 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
|
||||
}
|
||||
|
||||
struct drm_connector *
|
||||
nouveau_connector_create(struct drm_device *dev,
|
||||
const struct dcb_output *dcbe)
|
||||
nouveau_connector_create(struct drm_device *dev, int index)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct nouveau_connector *nv_connector = NULL;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
int index = dcbe->connector;
|
||||
int type, ret = 0;
|
||||
bool dummy;
|
||||
|
||||
@ -1305,70 +1303,76 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
nv_connector->index = index;
|
||||
INIT_WORK(&nv_connector->irq_work, nouveau_dp_irq);
|
||||
|
||||
/* attempt to parse vbios connector type and hotplug gpio */
|
||||
nv_connector->dcb = olddcb_conn(dev, index);
|
||||
if (nv_connector->dcb) {
|
||||
u32 entry = ROM16(nv_connector->dcb[0]);
|
||||
if (olddcb_conntab(dev)[3] >= 4)
|
||||
entry |= (u32)ROM16(nv_connector->dcb[2]) << 16;
|
||||
|
||||
nv_connector->type = nv_connector->dcb[0];
|
||||
if (drm_conntype_from_dcb(nv_connector->type) ==
|
||||
DRM_MODE_CONNECTOR_Unknown) {
|
||||
NV_WARN(drm, "unknown connector type %02x\n",
|
||||
nv_connector->type);
|
||||
nv_connector->type = DCB_CONNECTOR_NONE;
|
||||
if (disp->disp.conn_mask & BIT(nv_connector->index)) {
|
||||
ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index,
|
||||
&nv_connector->conn);
|
||||
if (ret) {
|
||||
kfree(nv_connector);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/* Gigabyte NX85T */
|
||||
if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) {
|
||||
if (nv_connector->type == DCB_CONNECTOR_HDMI_1)
|
||||
nv_connector->type = DCB_CONNECTOR_DVI_I;
|
||||
switch (nv_connector->conn.info.type) {
|
||||
case NVIF_CONN_VGA : type = DCB_CONNECTOR_VGA; break;
|
||||
case NVIF_CONN_DVI_I : type = DCB_CONNECTOR_DVI_I; break;
|
||||
case NVIF_CONN_DVI_D : type = DCB_CONNECTOR_DVI_D; break;
|
||||
case NVIF_CONN_LVDS : type = DCB_CONNECTOR_LVDS; break;
|
||||
case NVIF_CONN_LVDS_SPWG: type = DCB_CONNECTOR_LVDS_SPWG; break;
|
||||
case NVIF_CONN_DP : type = DCB_CONNECTOR_DP; break;
|
||||
case NVIF_CONN_EDP : type = DCB_CONNECTOR_eDP; break;
|
||||
case NVIF_CONN_HDMI : type = DCB_CONNECTOR_HDMI_0; break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Gigabyte GV-NX86T512H */
|
||||
if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) {
|
||||
if (nv_connector->type == DCB_CONNECTOR_HDMI_1)
|
||||
nv_connector->type = DCB_CONNECTOR_DVI_I;
|
||||
}
|
||||
nv_connector->type = type;
|
||||
} else {
|
||||
nv_connector->type = DCB_CONNECTOR_NONE;
|
||||
}
|
||||
u8 *dcb = olddcb_conn(dev, nv_connector->index);
|
||||
|
||||
/* no vbios data, or an unknown dcb connector type - attempt to
|
||||
* figure out something suitable ourselves
|
||||
*/
|
||||
if (nv_connector->type == DCB_CONNECTOR_NONE) {
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct dcb_table *dcbt = &drm->vbios.dcb;
|
||||
u32 encoders = 0;
|
||||
int i;
|
||||
if (dcb)
|
||||
nv_connector->type = dcb[0];
|
||||
else
|
||||
nv_connector->type = DCB_CONNECTOR_NONE;
|
||||
|
||||
for (i = 0; i < dcbt->entries; i++) {
|
||||
if (dcbt->entry[i].connector == nv_connector->index)
|
||||
encoders |= (1 << dcbt->entry[i].type);
|
||||
/* attempt to parse vbios connector type and hotplug gpio */
|
||||
if (nv_connector->type != DCB_CONNECTOR_NONE) {
|
||||
if (drm_conntype_from_dcb(nv_connector->type) ==
|
||||
DRM_MODE_CONNECTOR_Unknown) {
|
||||
NV_WARN(drm, "unknown connector type %02x\n",
|
||||
nv_connector->type);
|
||||
nv_connector->type = DCB_CONNECTOR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (encoders & (1 << DCB_OUTPUT_DP)) {
|
||||
if (encoders & (1 << DCB_OUTPUT_TMDS))
|
||||
nv_connector->type = DCB_CONNECTOR_DP;
|
||||
else
|
||||
nv_connector->type = DCB_CONNECTOR_eDP;
|
||||
} else
|
||||
if (encoders & (1 << DCB_OUTPUT_TMDS)) {
|
||||
if (encoders & (1 << DCB_OUTPUT_ANALOG))
|
||||
nv_connector->type = DCB_CONNECTOR_DVI_I;
|
||||
else
|
||||
nv_connector->type = DCB_CONNECTOR_DVI_D;
|
||||
} else
|
||||
if (encoders & (1 << DCB_OUTPUT_ANALOG)) {
|
||||
nv_connector->type = DCB_CONNECTOR_VGA;
|
||||
} else
|
||||
if (encoders & (1 << DCB_OUTPUT_LVDS)) {
|
||||
nv_connector->type = DCB_CONNECTOR_LVDS;
|
||||
} else
|
||||
if (encoders & (1 << DCB_OUTPUT_TV)) {
|
||||
nv_connector->type = DCB_CONNECTOR_TV_0;
|
||||
/* no vbios data, or an unknown dcb connector type - attempt to
|
||||
* figure out something suitable ourselves
|
||||
*/
|
||||
if (nv_connector->type == DCB_CONNECTOR_NONE &&
|
||||
!WARN_ON(drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA)) {
|
||||
struct dcb_table *dcbt = &drm->vbios.dcb;
|
||||
u32 encoders = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dcbt->entries; i++) {
|
||||
if (dcbt->entry[i].connector == nv_connector->index)
|
||||
encoders |= (1 << dcbt->entry[i].type);
|
||||
}
|
||||
|
||||
if (encoders & (1 << DCB_OUTPUT_TMDS)) {
|
||||
if (encoders & (1 << DCB_OUTPUT_ANALOG))
|
||||
nv_connector->type = DCB_CONNECTOR_DVI_I;
|
||||
else
|
||||
nv_connector->type = DCB_CONNECTOR_DVI_D;
|
||||
} else
|
||||
if (encoders & (1 << DCB_OUTPUT_ANALOG)) {
|
||||
nv_connector->type = DCB_CONNECTOR_VGA;
|
||||
} else
|
||||
if (encoders & (1 << DCB_OUTPUT_LVDS)) {
|
||||
nv_connector->type = DCB_CONNECTOR_LVDS;
|
||||
} else
|
||||
if (encoders & (1 << DCB_OUTPUT_TV)) {
|
||||
nv_connector->type = DCB_CONNECTOR_TV_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1414,14 +1418,7 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
|
||||
if (nv_connector->dcb && (disp->disp.conn_mask & BIT(nv_connector->index))) {
|
||||
ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index,
|
||||
&nv_connector->conn);
|
||||
if (ret) {
|
||||
kfree(nv_connector);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (nvif_object_constructed(&nv_connector->conn.object)) {
|
||||
ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsHotplug",
|
||||
nouveau_connector_hotplug,
|
||||
NVIF_CONN_EVENT_V0_PLUG | NVIF_CONN_EVENT_V0_UNPLUG,
|
||||
|
@ -121,7 +121,6 @@ struct nouveau_connector {
|
||||
struct drm_connector base;
|
||||
enum dcb_connector_type type;
|
||||
u8 index;
|
||||
u8 *dcb;
|
||||
|
||||
struct nvif_conn conn;
|
||||
u64 hpd_pending;
|
||||
@ -200,7 +199,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
|
||||
}
|
||||
|
||||
struct drm_connector *
|
||||
nouveau_connector_create(struct drm_device *, const struct dcb_output *);
|
||||
nouveau_connector_create(struct drm_device *, int id);
|
||||
void nouveau_connector_hpd(struct nouveau_connector *, u64 bits);
|
||||
|
||||
extern int nouveau_tv_disable;
|
||||
|
@ -63,5 +63,25 @@ nvif_conn_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_con
|
||||
ret = nvif_object_ctor(&disp->object, name ?: "nvifConn", id, NVIF_CLASS_CONN,
|
||||
&args, sizeof(args), &conn->object);
|
||||
NVIF_ERRON(ret, &disp->object, "[NEW conn id:%d]", id);
|
||||
return ret;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
conn->id = id;
|
||||
|
||||
switch (args.type) {
|
||||
case NVIF_CONN_V0_VGA : conn->info.type = NVIF_CONN_VGA; break;
|
||||
case NVIF_CONN_V0_TV : conn->info.type = NVIF_CONN_TV; break;
|
||||
case NVIF_CONN_V0_DVI_I : conn->info.type = NVIF_CONN_DVI_I; break;
|
||||
case NVIF_CONN_V0_DVI_D : conn->info.type = NVIF_CONN_DVI_D; break;
|
||||
case NVIF_CONN_V0_LVDS : conn->info.type = NVIF_CONN_LVDS; break;
|
||||
case NVIF_CONN_V0_LVDS_SPWG: conn->info.type = NVIF_CONN_LVDS_SPWG; break;
|
||||
case NVIF_CONN_V0_HDMI : conn->info.type = NVIF_CONN_HDMI; break;
|
||||
case NVIF_CONN_V0_DP : conn->info.type = NVIF_CONN_DP; break;
|
||||
case NVIF_CONN_V0_EDP : conn->info.type = NVIF_CONN_EDP; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -142,6 +142,32 @@ nvkm_uconn_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv
|
||||
ret = -EBUSY;
|
||||
spin_lock(&disp->client.lock);
|
||||
if (!conn->object.func) {
|
||||
switch (conn->info.type) {
|
||||
case DCB_CONNECTOR_VGA : args->v0.type = NVIF_CONN_V0_VGA; break;
|
||||
case DCB_CONNECTOR_TV_0 :
|
||||
case DCB_CONNECTOR_TV_1 :
|
||||
case DCB_CONNECTOR_TV_3 : args->v0.type = NVIF_CONN_V0_TV; break;
|
||||
case DCB_CONNECTOR_DMS59_0 :
|
||||
case DCB_CONNECTOR_DMS59_1 :
|
||||
case DCB_CONNECTOR_DVI_I : args->v0.type = NVIF_CONN_V0_DVI_I; break;
|
||||
case DCB_CONNECTOR_DVI_D : args->v0.type = NVIF_CONN_V0_DVI_D; break;
|
||||
case DCB_CONNECTOR_LVDS : args->v0.type = NVIF_CONN_V0_LVDS; break;
|
||||
case DCB_CONNECTOR_LVDS_SPWG: args->v0.type = NVIF_CONN_V0_LVDS_SPWG; break;
|
||||
case DCB_CONNECTOR_DMS59_DP0:
|
||||
case DCB_CONNECTOR_DMS59_DP1:
|
||||
case DCB_CONNECTOR_DP :
|
||||
case DCB_CONNECTOR_mDP :
|
||||
case DCB_CONNECTOR_USB_C : args->v0.type = NVIF_CONN_V0_DP; break;
|
||||
case DCB_CONNECTOR_eDP : args->v0.type = NVIF_CONN_V0_EDP; break;
|
||||
case DCB_CONNECTOR_HDMI_0 :
|
||||
case DCB_CONNECTOR_HDMI_1 :
|
||||
case DCB_CONNECTOR_HDMI_C : args->v0.type = NVIF_CONN_V0_HDMI; break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
nvkm_object_ctor(&nvkm_uconn, oclass, &conn->object);
|
||||
*pobject = &conn->object;
|
||||
ret = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user