These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / engine / disp / piornv50.c
index 2a1d887..ab524bd 100644 (file)
@@ -21,8 +21,8 @@
  *
  * Authors: Ben Skeggs
  */
-#include "nv50.h"
 #include "outpdp.h"
+#include "nv50.h"
 
 #include <core/client.h>
 #include <subdev/i2c.h>
 #include <nvif/class.h>
 #include <nvif/unpack.h>
 
-/******************************************************************************
- * TMDS
- *****************************************************************************/
-
-static int
-nv50_pior_tmds_ctor(struct nvkm_object *parent,
-                   struct nvkm_object *engine,
-                   struct nvkm_oclass *oclass, void *info, u32 index,
-                   struct nvkm_object **pobject)
+int
+nv50_pior_power(NV50_DISP_MTHD_V1)
 {
-       struct nvkm_i2c *i2c = nvkm_i2c(parent);
-       struct nvkm_output *outp;
+       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;
 
-       ret = nvkm_output_create(parent, engine, oclass, info, index, &outp);
-       *pobject = nv_object(outp);
-       if (ret)
+       nvif_ioctl(object, "disp pior pwr size %d\n", size);
+       if (nvif_unpack(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
                return ret;
 
-       outp->edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(outp->info.extdev));
+       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))
+                       break;
+       );
+       disp->pior.type[outp->or] = type;
        return 0;
 }
 
-struct nvkm_output_impl
-nv50_pior_tmds_impl = {
-       .base.handle = DCB_OUTPUT_TMDS | 0x0100,
-       .base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_pior_tmds_ctor,
-               .dtor = _nvkm_output_dtor,
-               .init = _nvkm_output_init,
-               .fini = _nvkm_output_fini,
-       },
-};
-
 /******************************************************************************
- * DisplayPort
+ * TMDS
  *****************************************************************************/
+static const struct nvkm_output_func
+nv50_pior_output_func = {
+};
 
-static int
-nv50_pior_dp_pattern(struct nvkm_output_dp *outp, int pattern)
+int
+nv50_pior_output_new(struct nvkm_disp *disp, int index,
+                    struct dcb_output *dcbE, struct nvkm_output **poutp)
 {
-       struct nvkm_i2c_port *port = outp->base.edid;
-       if (port && port->func->pattern)
-               return port->func->pattern(port, pattern);
-       return port ? 0 : -ENODEV;
+       return nvkm_output_new_(&nv50_pior_output_func, disp,
+                               index, dcbE, poutp);
 }
 
+/******************************************************************************
+ * DisplayPort
+ *****************************************************************************/
 static int
-nv50_pior_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
+nv50_pior_output_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 {
        return 0;
 }
 
 static int
-nv50_pior_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
-{
-       struct nvkm_i2c_port *port = outp->base.edid;
-       if (port && port->func->lnk_ctl)
-               return port->func->lnk_ctl(port, nr, bw, ef);
-       return port ? 0 : -ENODEV;
-}
-
-static int
-nv50_pior_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
+nv50_pior_output_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
 {
-       struct nvkm_i2c_port *port = outp->base.edid;
-       if (port && port->func->drv_ctl)
-               return port->func->drv_ctl(port, ln, vs, pe);
-       return port ? 0 : -ENODEV;
+       return 0;
 }
 
 static int
-nv50_pior_dp_ctor(struct nvkm_object *parent,
-                 struct nvkm_object *engine,
-                 struct nvkm_oclass *oclass, void *info, u32 index,
-                 struct nvkm_object **pobject)
+nv50_pior_output_dp_lnk_ctl(struct nvkm_output_dp *outp,
+                           int nr, int bw, bool ef)
 {
-       struct nvkm_i2c *i2c = nvkm_i2c(parent);
-       struct nvkm_output_dp *outp;
-       int ret;
-
-       ret = nvkm_output_dp_create(parent, engine, oclass, info, index, &outp);
-       *pobject = nv_object(outp);
+       int ret = nvkm_i2c_aux_lnk_ctl(outp->aux, nr, bw, ef);
        if (ret)
                return ret;
-
-       outp->base.edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(
-                                        outp->base.info.extdev));
-       return 0;
+       return 1;
 }
 
-struct nvkm_output_dp_impl
-nv50_pior_dp_impl = {
-       .base.base.handle = DCB_OUTPUT_DP | 0x0010,
-       .base.base.ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_pior_dp_ctor,
-               .dtor = _nvkm_output_dp_dtor,
-               .init = _nvkm_output_dp_init,
-               .fini = _nvkm_output_dp_fini,
-       },
-       .pattern = nv50_pior_dp_pattern,
-       .lnk_pwr = nv50_pior_dp_lnk_pwr,
-       .lnk_ctl = nv50_pior_dp_lnk_ctl,
-       .drv_ctl = nv50_pior_dp_drv_ctl,
+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,
 };
 
-/******************************************************************************
- * General PIOR handling
- *****************************************************************************/
-
 int
-nv50_pior_power(NV50_DISP_MTHD_V1)
+nv50_pior_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE,
+                struct nvkm_output **poutp)
 {
-       const u32 soff = outp->or * 0x800;
-       union {
-               struct nv50_disp_pior_pwr_v0 v0;
-       } *args = data;
-       u32 ctrl, type;
-       int ret;
+       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;
 
-       nv_ioctl(object, "disp pior pwr size %d\n", size);
-       if (nvif_unpack(args->v0, 0, 0, false)) {
-               nv_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
-               return ret;
+       if (!(outp = kzalloc(sizeof(*outp), GFP_KERNEL)))
+               return -ENOMEM;
+       *poutp = &outp->base;
 
-       nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
-       nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | ctrl);
-       nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
-       priv->pior.type[outp->or] = type;
-       return 0;
+       return nvkm_output_dp_ctor(&nv50_pior_output_dp_func, disp,
+                                  index, dcbE, aux, outp);
 }