aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c163
1 files changed, 83 insertions, 80 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
index 6c532eadba17..99b3b9050635 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
@@ -21,111 +21,114 @@
*
* Authors: Ben Skeggs
*/
-#include "outpdp.h"
-#include "nv50.h"
+#include "ior.h"
+#include "head.h"
-#include <core/client.h>
#include <subdev/i2c.h>
#include <subdev/timer.h>
-#include <nvif/cl5070.h>
-#include <nvif/unpack.h>
-
-int
-nv50_pior_power(NV50_DISP_MTHD_V1)
+static void
+nv50_pior_clock(struct nvkm_ior *pior)
{
- struct nvkm_device *device = disp->base.engine.subdev.device;
- const u32 soff = outp->or * 0x800;
- union {
- struct nv50_disp_pior_pwr_v0 v0;
- } *args = data;
- u32 ctrl, type;
- int ret = -ENOSYS;
+ struct nvkm_device *device = pior->disp->engine.subdev.device;
+ const u32 poff = nv50_ior_base(pior);
+ nvkm_mask(device, 0x614380 + poff, 0x00000707, 0x00000001);
+}
- nvif_ioctl(object, "disp pior pwr size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(object, "disp pior pwr vers %d state %d type %x\n",
- args->v0.version, args->v0.state, args->v0.type);
- if (args->v0.type > 0x0f)
- return -EINVAL;
- ctrl = !!args->v0.state;
- type = args->v0.type;
- } else
+static int
+nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux)
+{
+ int ret = nvkm_i2c_aux_lnk_ctl(aux, pior->dp.nr, pior->dp.bw,
+ pior->dp.ef);
+ if (ret)
return ret;
+ return 1;
+}
+static void
+nv50_pior_power_wait(struct nvkm_device *device, u32 poff)
+{
nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x61e004 + soff) & 0x80000000))
- break;
- );
- nvkm_mask(device, 0x61e004 + soff, 0x80000101, 0x80000000 | ctrl);
- nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x61e004 + soff) & 0x80000000))
+ if (!(nvkm_rd32(device, 0x61e004 + poff) & 0x80000000))
break;
);
- disp->pior.type[outp->or] = type;
- return 0;
}
-/******************************************************************************
- * TMDS
- *****************************************************************************/
-static const struct nvkm_output_func
-nv50_pior_output_func = {
-};
-
-int
-nv50_pior_output_new(struct nvkm_disp *disp, int index,
- struct dcb_output *dcbE, struct nvkm_output **poutp)
+static void
+nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu,
+ bool data, bool vsync, bool hsync)
{
- return nvkm_output_new_(&nv50_pior_output_func, disp,
- index, dcbE, poutp);
-}
+ struct nvkm_device *device = pior->disp->engine.subdev.device;
+ const u32 poff = nv50_ior_base(pior);
+ const u32 shift = normal ? 0 : 16;
+ const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift;
+ const u32 field = 0x80000000 | (0x00000101 << shift);
-/******************************************************************************
- * DisplayPort
- *****************************************************************************/
-static int
-nv50_pior_output_dp_pattern(struct nvkm_output_dp *outp, int pattern)
-{
- return 0;
+ nv50_pior_power_wait(device, poff);
+ nvkm_mask(device, 0x61e004 + poff, field, state);
+ nv50_pior_power_wait(device, poff);
}
-static int
-nv50_pior_output_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
+void
+nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl)
{
- return 0;
+ /* GF119 moves this information to per-head methods, which is
+ * a lot more convenient, and where our shared code expect it.
+ */
+ if (state->head && state == &ior->asy) {
+ struct nvkm_head *head =
+ nvkm_head_find(ior->disp, __ffs(state->head));
+ if (!WARN_ON(!head)) {
+ struct nvkm_head_state *state = &head->asy;
+ switch ((ctrl & 0x000f0000) >> 16) {
+ case 6: state->or.depth = 30; break;
+ case 5: state->or.depth = 24; break;
+ case 2: state->or.depth = 18; break;
+ case 0: state->or.depth = 18; break; /*XXX*/
+ default:
+ state->or.depth = 18;
+ WARN_ON(1);
+ break;
+ }
+ }
+ }
}
-static int
-nv50_pior_output_dp_lnk_ctl(struct nvkm_output_dp *outp,
- int nr, int bw, bool ef)
+static void
+nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state)
{
- int ret = nvkm_i2c_aux_lnk_ctl(outp->aux, nr, bw, ef);
- if (ret)
- return ret;
- return 1;
+ struct nvkm_device *device = pior->disp->engine.subdev.device;
+ const u32 coff = pior->id * 8 + (state == &pior->arm) * 4;
+ u32 ctrl = nvkm_rd32(device, 0x610b80 + coff);
+
+ state->proto_evo = (ctrl & 0x00000f00) >> 8;
+ state->rgdiv = 1;
+ switch (state->proto_evo) {
+ case 0: state->proto = TMDS; break;
+ default:
+ state->proto = UNKNOWN;
+ break;
+ }
+
+ state->head = ctrl & 0x00000003;
+ nv50_pior_depth(pior, state, ctrl);
}
-static const struct nvkm_output_dp_func
-nv50_pior_output_dp_func = {
- .pattern = nv50_pior_output_dp_pattern,
- .lnk_pwr = nv50_pior_output_dp_lnk_pwr,
- .lnk_ctl = nv50_pior_output_dp_lnk_ctl,
+static const struct nvkm_ior_func
+nv50_pior = {
+ .state = nv50_pior_state,
+ .power = nv50_pior_power,
+ .clock = nv50_pior_clock,
+ .dp = {
+ .links = nv50_pior_dp_links,
+ },
};
int
-nv50_pior_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
- struct nvkm_output **poutp)
+nv50_pior_new(struct nvkm_disp *disp, int id)
{
- struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c;
- struct nvkm_i2c_aux *aux =
- nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbE->extdev));
- struct nvkm_output_dp *outp;
-
- if (!(outp = kzalloc(sizeof(*outp), GFP_KERNEL)))
- return -ENOMEM;
- *poutp = &outp->base;
-
- return nvkm_output_dp_ctor(&nv50_pior_output_dp_func, disp,
- index, dcbE, aux, outp);
+ struct nvkm_device *device = disp->engine.subdev.device;
+ if (!(nvkm_rd32(device, 0x610184) & (0x10000000 << id)))
+ return 0;
+ return nvkm_ior_new_(&nv50_pior, disp, PIOR, id);
}