diff options
Diffstat (limited to 'nvkm/engine')
-rw-r--r-- | nvkm/engine/disp/dacnv50.c | 34 | ||||
-rw-r--r-- | nvkm/engine/disp/nv50.c | 73 | ||||
-rw-r--r-- | nvkm/engine/disp/nv50.h | 10 | ||||
-rw-r--r-- | nvkm/engine/disp/nv84.c | 1 | ||||
-rw-r--r-- | nvkm/engine/disp/nv94.c | 1 | ||||
-rw-r--r-- | nvkm/engine/disp/nva3.c | 1 | ||||
-rw-r--r-- | nvkm/engine/disp/nvd0.c | 2 | ||||
-rw-r--r-- | nvkm/engine/disp/outp.c | 1 | ||||
-rw-r--r-- | nvkm/engine/disp/outp.h | 1 |
9 files changed, 106 insertions, 18 deletions
diff --git a/nvkm/engine/disp/dacnv50.c b/nvkm/engine/disp/dacnv50.c index a66b27c0f..9fb1a8438 100644 --- a/nvkm/engine/disp/dacnv50.c +++ b/nvkm/engine/disp/dacnv50.c @@ -22,8 +22,10 @@ * Authors: Ben Skeggs */ -#include <core/os.h> +#include <core/client.h> #include <core/class.h> +#include <nvif/unpack.h> +#include <nvif/class.h> #include <subdev/bios.h> #include <subdev/bios/dcb.h> @@ -32,13 +34,28 @@ #include "nv50.h" int -nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data) +nv50_dac_power(NV50_DISP_MTHD_V1) { - const u32 stat = (data & NV50_DISP_DAC_PWR_HSYNC) | - (data & NV50_DISP_DAC_PWR_VSYNC) | - (data & NV50_DISP_DAC_PWR_DATA) | - (data & NV50_DISP_DAC_PWR_STATE); - const u32 doff = (or * 0x800); + const u32 doff = outp->or * 0x800; + union { + struct nv50_disp_dac_pwr_v0 v0; + } *args = data; + u32 stat; + int ret; + + nv_ioctl(object, "disp dac pwr size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, false)) { + nv_ioctl(object, "disp dac pwr vers %d state %d data %d " + "vsync %d hsync %d\n", + args->v0.version, args->v0.state, args->v0.data, + args->v0.vsync, args->v0.hsync); + stat = 0x00000040 * !args->v0.state; + stat |= 0x00000010 * !args->v0.data; + stat |= 0x00000004 * !args->v0.vsync; + stat |= 0x00000001 * !args->v0.hsync; + } else + return ret; + nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); nv_mask(priv, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat); nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); @@ -80,9 +97,6 @@ nv50_dac_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) return -EINVAL; switch (mthd & ~0x3f) { - case NV50_DISP_DAC_PWR: - ret = priv->dac.power(priv, or, data[0]); - break; case NV50_DISP_DAC_LOAD: ret = priv->dac.sense(priv, or, data[0]); if (ret >= 0) { diff --git a/nvkm/engine/disp/nv50.c b/nvkm/engine/disp/nv50.c index 4f1ed8928..00d1e34cb 100644 --- a/nvkm/engine/disp/nv50.c +++ b/nvkm/engine/disp/nv50.c @@ -23,10 +23,13 @@ */ #include <core/object.h> +#include <core/client.h> #include <core/parent.h> #include <core/handle.h> -#include <core/class.h> #include <core/enum.h> +#include <core/class.h> +#include <nvif/unpack.h> +#include <nvif/class.h> #include <subdev/bios.h> #include <subdev/bios/dcb.h> @@ -840,6 +843,72 @@ nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd, } int +nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd, + void *data, u32 size) +{ + union { + struct nv50_disp_mthd_v0 v0; + struct nv50_disp_mthd_v1 v1; + } *args = data; + struct nv50_disp_priv *priv = (void *)object->engine; + struct nvkm_output *outp = NULL; + struct nvkm_output *temp; + u16 type, mask = 0; + int head, ret; + + if (mthd != NV50_DISP_MTHD) + return -EINVAL; + + nv_ioctl(object, "disp mthd size %d\n", size); + if (nvif_unpack(args->v0, 0, 0, true)) { + nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n", + args->v0.version, args->v0.method, args->v0.head); + mthd = args->v0.method; + head = args->v0.head; + } else + if (nvif_unpack(args->v1, 1, 1, true)) { + nv_ioctl(object, "disp mthd vers %d mthd %02x " + "type %04x mask %04x\n", + args->v1.version, args->v1.method, + args->v1.hasht, args->v1.hashm); + mthd = args->v1.method; + type = args->v1.hasht; + mask = args->v1.hashm; + head = ffs((mask >> 8) & 0x0f) - 1; + } else + return ret; + + if (head < 0 || head >= priv->head.nr) + return -ENXIO; + + if (mask) { + list_for_each_entry(temp, &priv->base.outp, head) { + if ((temp->info.hasht == type) && + (temp->info.hashm & mask) == mask) { + outp = temp; + break; + } + } + if (outp == NULL) + return -ENXIO; + } + + switch (mthd) { + default: + break; + } + + switch (mthd * !!outp) { + case NV50_DISP_MTHD_V1_DAC_PWR: + return priv->dac.power(object, priv, data, size, head, outp); + default: + break; + } + + return -EINVAL; +} + +int nv50_disp_base_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -954,6 +1023,7 @@ nv50_disp_base_ofuncs = { .dtor = nv50_disp_base_dtor, .init = nv50_disp_base_init, .fini = nv50_disp_base_fini, + .mthd = nv50_disp_base_mthd, }; static struct nouveau_omthds @@ -961,7 +1031,6 @@ nv50_disp_base_omthds[] = { { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos }, { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, - { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, diff --git a/nvkm/engine/disp/nv50.h b/nvkm/engine/disp/nv50.h index a1ec6a556..4a874d776 100644 --- a/nvkm/engine/disp/nv50.h +++ b/nvkm/engine/disp/nv50.h @@ -24,6 +24,11 @@ struct nv50_disp_impl { } mthd; }; +#define NV50_DISP_MTHD_ struct nouveau_object *object, \ + struct nv50_disp_priv *priv, void *data, u32 size +#define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head +#define NV50_DISP_MTHD_V1 NV50_DISP_MTHD_, int head, struct nvkm_output *outp + struct nv50_disp_priv { struct nouveau_disp base; struct nouveau_oclass *sclass; @@ -36,7 +41,7 @@ struct nv50_disp_priv { } head; struct { int nr; - int (*power)(struct nv50_disp_priv *, int dac, u32 data); + int (*power)(NV50_DISP_MTHD_V1); int (*sense)(struct nv50_disp_priv *, int dac, u32 load); } dac; struct { @@ -56,11 +61,12 @@ struct nv50_disp_priv { #define HEAD_MTHD(n) (n), (n) + 0x03 int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32); +int nv50_disp_base_mthd(struct nouveau_object *, u32, void *, u32); #define DAC_MTHD(n) (n), (n) + 0x03 int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32); -int nv50_dac_power(struct nv50_disp_priv *, int, u32); +int nv50_dac_power(NV50_DISP_MTHD_V1); int nv50_dac_sense(struct nv50_disp_priv *, int, u32); #define SOR_MTHD(n) (n), (n) + 0x3f diff --git a/nvkm/engine/disp/nv84.c b/nvkm/engine/disp/nv84.c index 43ef1fab5..f2414a4bc 100644 --- a/nvkm/engine/disp/nv84.c +++ b/nvkm/engine/disp/nv84.c @@ -218,7 +218,6 @@ nv84_disp_base_omthds[] = { { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, - { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, diff --git a/nvkm/engine/disp/nv94.c b/nvkm/engine/disp/nv94.c index 2e38a79b1..7ae79cfbd 100644 --- a/nvkm/engine/disp/nv94.c +++ b/nvkm/engine/disp/nv94.c @@ -78,7 +78,6 @@ nv94_disp_base_omthds[] = { { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, - { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, diff --git a/nvkm/engine/disp/nva3.c b/nvkm/engine/disp/nva3.c index 4b601c87c..31cdf7a61 100644 --- a/nvkm/engine/disp/nva3.c +++ b/nvkm/engine/disp/nva3.c @@ -51,7 +51,6 @@ nva3_disp_base_omthds[] = { { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, - { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, diff --git a/nvkm/engine/disp/nvd0.c b/nvkm/engine/disp/nvd0.c index 57d6cb3ed..66959cde0 100644 --- a/nvkm/engine/disp/nvd0.c +++ b/nvkm/engine/disp/nvd0.c @@ -706,6 +706,7 @@ nvd0_disp_base_ofuncs = { .dtor = nv50_disp_base_dtor, .init = nvd0_disp_base_init, .fini = nvd0_disp_base_fini, + .mthd = nv50_disp_base_mthd, }; struct nouveau_omthds @@ -716,7 +717,6 @@ nvd0_disp_base_omthds[] = { { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, - { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, diff --git a/nvkm/engine/disp/outp.c b/nvkm/engine/disp/outp.c index ad9ba7cce..a5ff00a9c 100644 --- a/nvkm/engine/disp/outp.c +++ b/nvkm/engine/disp/outp.c @@ -78,6 +78,7 @@ nvkm_output_create_(struct nouveau_object *parent, outp->info = *dcbE; outp->index = index; + outp->or = ffs(outp->info.or) - 1; DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n", dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ? diff --git a/nvkm/engine/disp/outp.h b/nvkm/engine/disp/outp.h index bc76fbf85..187f435ad 100644 --- a/nvkm/engine/disp/outp.h +++ b/nvkm/engine/disp/outp.h @@ -9,6 +9,7 @@ struct nvkm_output { struct dcb_output info; int index; + int or; struct nouveau_i2c_port *port; struct nouveau_i2c_port *edid; |