|
@@ -47,8 +47,12 @@ int
|
|
|
nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
|
|
|
{
|
|
|
struct nv50_disp_priv *priv = (void *)object->engine;
|
|
|
+ const u8 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12;
|
|
|
const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3;
|
|
|
+ const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2;
|
|
|
const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR);
|
|
|
+ const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or);
|
|
|
+ struct nvkm_output *outp = NULL, *temp;
|
|
|
u32 data;
|
|
|
int ret = -EINVAL;
|
|
|
|
|
@@ -56,6 +60,13 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
|
|
|
return -EINVAL;
|
|
|
data = *(u32 *)args;
|
|
|
|
|
|
+ list_for_each_entry(temp, &priv->base.outp, head) {
|
|
|
+ if ((temp->info.hasht & 0xff) == type &&
|
|
|
+ (temp->info.hashm & mask) == mask) {
|
|
|
+ outp = temp;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
switch (mthd & ~0x3f) {
|
|
|
case NV50_DISP_SOR_PWR:
|
|
@@ -71,6 +82,23 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
|
|
|
priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;
|
|
|
ret = 0;
|
|
|
break;
|
|
|
+ case NV94_DISP_SOR_DP_PWR:
|
|
|
+ if (outp) {
|
|
|
+ struct nvkm_output_dp *outpdp = (void *)outp;
|
|
|
+ switch (data) {
|
|
|
+ case NV94_DISP_SOR_DP_PWR_STATE_OFF:
|
|
|
+ ((struct nvkm_output_dp_impl *)nv_oclass(outp))
|
|
|
+ ->lnk_pwr(outpdp, 0);
|
|
|
+ atomic_set(&outpdp->lt.done, 0);
|
|
|
+ break;
|
|
|
+ case NV94_DISP_SOR_DP_PWR_STATE_ON:
|
|
|
+ nvkm_output_dp_train(&outpdp->base, 0, true);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
default:
|
|
|
BUG_ON(1);
|
|
|
}
|