提交 7ebb38b5 编写于 作者: B Ben Skeggs

drm/nv50/disp: call into core for dac load detection

Signed-off-by: NBen Skeggs <bskeggs@redhat.com>
上级 ef22c8bb
...@@ -46,11 +46,11 @@ nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data) ...@@ -46,11 +46,11 @@ nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data)
} }
int int
nv50_dac_sense(struct nv50_disp_priv *priv, int or) nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
{ {
const u32 doff = (or * 0x800); const u32 doff = (or * 0x800);
int load = -EINVAL; int load = -EINVAL;
nv_wr32(priv, 0x61a00c + doff, 0x00100000); nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval);
udelay(9500); udelay(9500);
nv_wr32(priv, 0x61a00c + doff, 0x80000000); nv_wr32(priv, 0x61a00c + doff, 0x80000000);
load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27; load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27;
...@@ -74,7 +74,7 @@ nv50_dac_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) ...@@ -74,7 +74,7 @@ nv50_dac_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
ret = priv->dac.power(priv, or, data[0]); ret = priv->dac.power(priv, or, data[0]);
break; break;
case NV50_DISP_DAC_LOAD: case NV50_DISP_DAC_LOAD:
ret = priv->dac.sense(priv, or); ret = priv->dac.sense(priv, or, data[0]);
if (ret >= 0) { if (ret >= 0) {
data[0] = ret; data[0] = ret;
ret = 0; ret = 0;
......
...@@ -807,6 +807,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -807,6 +807,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->dac.nr = 3; priv->dac.nr = 3;
priv->sor.nr = 2; priv->sor.nr = 2;
priv->dac.power = nv50_dac_power; priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power; priv->sor.power = nv50_sor_power;
INIT_LIST_HEAD(&priv->base.vblank.list); INIT_LIST_HEAD(&priv->base.vblank.list);
......
...@@ -19,7 +19,7 @@ struct nv50_disp_priv { ...@@ -19,7 +19,7 @@ struct nv50_disp_priv {
struct { struct {
int nr; int nr;
int (*power)(struct nv50_disp_priv *, int dac, u32 data); int (*power)(struct nv50_disp_priv *, int dac, u32 data);
int (*sense)(struct nv50_disp_priv *, int dac); int (*sense)(struct nv50_disp_priv *, int dac, u32 load);
} dac; } dac;
struct { struct {
int nr; int nr;
...@@ -42,7 +42,7 @@ struct nv50_disp_priv { ...@@ -42,7 +42,7 @@ struct nv50_disp_priv {
int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32); int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
int nv50_dac_power(struct nv50_disp_priv *, int, u32); int nv50_dac_power(struct nv50_disp_priv *, int, u32);
int nv50_dac_sense(struct nv50_disp_priv *, int); int nv50_dac_sense(struct nv50_disp_priv *, int, u32);
#define SOR_MTHD(n) (n), (n) + 0x3f #define SOR_MTHD(n) (n), (n) + 0x3f
......
...@@ -76,6 +76,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -76,6 +76,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->dac.nr = 3; priv->dac.nr = 3;
priv->sor.nr = 2; priv->sor.nr = 2;
priv->dac.power = nv50_dac_power; priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power; priv->sor.power = nv50_sor_power;
INIT_LIST_HEAD(&priv->base.vblank.list); INIT_LIST_HEAD(&priv->base.vblank.list);
......
...@@ -82,6 +82,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -82,6 +82,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->dac.nr = 3; priv->dac.nr = 3;
priv->sor.nr = 4; priv->sor.nr = 4;
priv->dac.power = nv50_dac_power; priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power; priv->sor.power = nv50_sor_power;
INIT_LIST_HEAD(&priv->base.vblank.list); INIT_LIST_HEAD(&priv->base.vblank.list);
......
...@@ -67,6 +67,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -67,6 +67,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->dac.nr = 3; priv->dac.nr = 3;
priv->sor.nr = 2; priv->sor.nr = 2;
priv->dac.power = nv50_dac_power; priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power; priv->sor.power = nv50_sor_power;
INIT_LIST_HEAD(&priv->base.vblank.list); INIT_LIST_HEAD(&priv->base.vblank.list);
......
...@@ -83,6 +83,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -83,6 +83,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->dac.nr = 3; priv->dac.nr = 3;
priv->sor.nr = 4; priv->sor.nr = 4;
priv->dac.power = nv50_dac_power; priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power; priv->sor.power = nv50_sor_power;
INIT_LIST_HEAD(&priv->base.vblank.list); INIT_LIST_HEAD(&priv->base.vblank.list);
......
...@@ -71,56 +71,22 @@ nv50_dac_disconnect(struct drm_encoder *encoder) ...@@ -71,56 +71,22 @@ nv50_dac_disconnect(struct drm_encoder *encoder)
static enum drm_connector_status static enum drm_connector_status
nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{ {
struct nv50_display *priv = nv50_display(encoder->dev);
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_device *device = nouveau_dev(encoder->dev);
struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_drm *drm = nouveau_drm(encoder->dev);
enum drm_connector_status status = connector_status_disconnected; int or = nv_encoder->or, ret;
uint32_t dpms_state, load_pattern, load_state; u32 load;
int or = nv_encoder->or;
nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001);
dpms_state = nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or));
nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
if (!nv_wait(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
NV_ERROR(drm, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
NV_ERROR(drm, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
return status;
}
/* Use bios provided value if possible. */
if (drm->vbios.dactestval) {
load_pattern = drm->vbios.dactestval;
NV_DEBUG(drm, "Using bios provided load_pattern of %d\n",
load_pattern);
} else {
load_pattern = 340;
NV_DEBUG(drm, "Using default load_pattern of %d\n",
load_pattern);
}
nv_wr32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or),
NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern);
mdelay(45); /* give it some time to process */
load_state = nv_rd32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or));
nv_wr32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0);
nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state |
NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) == if (drm->vbios.dactestval)
NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) load = drm->vbios.dactestval;
status = connector_status_connected;
if (status == connector_status_connected)
NV_DEBUG(drm, "Load was detected on output with or %d\n", or);
else else
NV_DEBUG(drm, "Load was not detected on output with or %d\n", or); load = 340;
ret = nv_exec(priv->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
if (ret || load != 7)
return connector_status_disconnected;
return status; return connector_status_connected;
} }
static void static void
......
...@@ -1176,7 +1176,7 @@ nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) ...@@ -1176,7 +1176,7 @@ nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{ {
struct nvd0_disp *disp = nvd0_disp(encoder->dev); struct nvd0_disp *disp = nvd0_disp(encoder->dev);
int ret, or = nouveau_encoder(encoder)->or; int ret, or = nouveau_encoder(encoder)->or;
u32 load; u32 load = 0;
ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load)); ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
if (ret || load != 7) if (ret || load != 7)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册