mirror of https://gitee.com/openkylin/linux.git
drm/nvd0/disp: call into core to handle sor power state changes
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
6c5a04249d
commit
74b6685089
|
@ -21,6 +21,7 @@ struct nv50_disp_priv {
|
||||||
} dac;
|
} dac;
|
||||||
struct {
|
struct {
|
||||||
int nr;
|
int nr;
|
||||||
|
int (*power)(struct nv50_disp_priv *, int sor, u32 data);
|
||||||
int (*dp_train)(struct nv50_disp_priv *, int sor, int link,
|
int (*dp_train)(struct nv50_disp_priv *, int sor, int link,
|
||||||
u16 type, u16 mask, u32 data,
|
u16 type, u16 mask, u32 data,
|
||||||
struct dcb_output *);
|
struct dcb_output *);
|
||||||
|
@ -38,6 +39,7 @@ extern struct nouveau_omthds nva3_disp_base_omthds[];
|
||||||
#define SOR_MTHD(n) (n), (n) + 0x3f
|
#define SOR_MTHD(n) (n), (n) + 0x3f
|
||||||
|
|
||||||
int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
|
int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
|
||||||
|
int nv50_sor_power(struct nv50_disp_priv *, int, u32);
|
||||||
|
|
||||||
int nvd0_sor_dp_train(struct nv50_disp_priv *, int, int, u16, u16, u32,
|
int nvd0_sor_dp_train(struct nv50_disp_priv *, int, int, u16, u16, u32,
|
||||||
struct dcb_output *);
|
struct dcb_output *);
|
||||||
|
|
|
@ -41,6 +41,7 @@ nva3_disp_sclass[] = {
|
||||||
|
|
||||||
struct nouveau_omthds
|
struct nouveau_omthds
|
||||||
nva3_disp_base_omthds[] = {
|
nva3_disp_base_omthds[] = {
|
||||||
|
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd },
|
{ SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd },
|
{ SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd },
|
||||||
{ SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd },
|
{ SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd },
|
||||||
|
|
|
@ -896,6 +896,7 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
priv->head.nr = nv_rd32(priv, 0x022448);
|
priv->head.nr = nv_rd32(priv, 0x022448);
|
||||||
priv->dac.nr = 3;
|
priv->dac.nr = 3;
|
||||||
priv->sor.nr = 4;
|
priv->sor.nr = 4;
|
||||||
|
priv->sor.power = nv50_sor_power;
|
||||||
priv->sor.dp_train = nvd0_sor_dp_train;
|
priv->sor.dp_train = nvd0_sor_dp_train;
|
||||||
priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
|
priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
|
||||||
priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
|
priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
|
||||||
|
|
|
@ -66,6 +66,7 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
priv->head.nr = nv_rd32(priv, 0x022448);
|
priv->head.nr = nv_rd32(priv, 0x022448);
|
||||||
priv->dac.nr = 3;
|
priv->dac.nr = 3;
|
||||||
priv->sor.nr = 4;
|
priv->sor.nr = 4;
|
||||||
|
priv->sor.power = nv50_sor_power;
|
||||||
priv->sor.dp_train = nvd0_sor_dp_train;
|
priv->sor.dp_train = nvd0_sor_dp_train;
|
||||||
priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
|
priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
|
||||||
priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
|
priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
|
||||||
|
|
|
@ -27,9 +27,22 @@
|
||||||
|
|
||||||
#include <subdev/bios.h>
|
#include <subdev/bios.h>
|
||||||
#include <subdev/bios/dcb.h>
|
#include <subdev/bios/dcb.h>
|
||||||
|
#include <subdev/timer.h>
|
||||||
|
|
||||||
#include "nv50.h"
|
#include "nv50.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
nv50_sor_power(struct nv50_disp_priv *priv, int or, u32 data)
|
||||||
|
{
|
||||||
|
const u32 stat = data & NV50_DISP_SOR_PWR_STATE;
|
||||||
|
const u32 soff = (or * 0x800);
|
||||||
|
nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000);
|
||||||
|
nv_mask(priv, 0x61c004 + soff, 0x80000001, 0x80000000 | stat);
|
||||||
|
nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000);
|
||||||
|
nv_wait(priv, 0x61c030 + soff, 0x10000000, 0x00000000);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
|
nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
|
||||||
{
|
{
|
||||||
|
@ -72,6 +85,9 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
|
||||||
|
|
||||||
data = *(u32 *)args;
|
data = *(u32 *)args;
|
||||||
switch (mthd & ~0x3f) {
|
switch (mthd & ~0x3f) {
|
||||||
|
case NV50_DISP_SOR_PWR:
|
||||||
|
ret = priv->sor.power(priv, or, data);
|
||||||
|
break;
|
||||||
case NV94_DISP_SOR_DP_TRAIN:
|
case NV94_DISP_SOR_DP_TRAIN:
|
||||||
ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp);
|
ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -177,6 +177,10 @@ struct nve0_channel_ind_class {
|
||||||
#define NV50_DISP_SOR_MTHD_LINK 0x00000004
|
#define NV50_DISP_SOR_MTHD_LINK 0x00000004
|
||||||
#define NV50_DISP_SOR_MTHD_OR 0x00000003
|
#define NV50_DISP_SOR_MTHD_OR 0x00000003
|
||||||
|
|
||||||
|
#define NV50_DISP_SOR_PWR 0x00010000
|
||||||
|
#define NV50_DISP_SOR_PWR_STATE 0x00000001
|
||||||
|
#define NV50_DISP_SOR_PWR_STATE_ON 0x00000001
|
||||||
|
#define NV50_DISP_SOR_PWR_STATE_OFF 0x00000000
|
||||||
#define NV94_DISP_SOR_DP_TRAIN 0x00016000
|
#define NV94_DISP_SOR_DP_TRAIN 0x00016000
|
||||||
#define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003
|
#define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003
|
||||||
#define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000
|
#define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000
|
||||||
|
|
|
@ -1434,10 +1434,9 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
|
||||||
{
|
{
|
||||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||||
struct drm_device *dev = encoder->dev;
|
struct drm_device *dev = encoder->dev;
|
||||||
struct nouveau_device *device = nouveau_dev(dev);
|
struct nvd0_disp *disp = nvd0_disp(dev);
|
||||||
struct drm_encoder *partner;
|
struct drm_encoder *partner;
|
||||||
int or = nv_encoder->or;
|
int or = nv_encoder->or;
|
||||||
u32 dpms_ctrl;
|
|
||||||
|
|
||||||
nv_encoder->last_dpms = mode;
|
nv_encoder->last_dpms = mode;
|
||||||
|
|
||||||
|
@ -1455,13 +1454,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dpms_ctrl = (mode == DRM_MODE_DPMS_ON);
|
nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON));
|
||||||
dpms_ctrl |= 0x80000000;
|
|
||||||
|
|
||||||
nv_wait(device, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
|
|
||||||
nv_mask(device, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl);
|
|
||||||
nv_wait(device, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000);
|
|
||||||
nv_wait(device, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000);
|
|
||||||
|
|
||||||
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
|
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
|
||||||
struct dp_train_func func = {
|
struct dp_train_func func = {
|
||||||
|
|
Loading…
Reference in New Issue