linux/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Red Hat Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: Ben Skeggs
  23 */
  24#include "nv50.h"
  25#include "outpdp.h"
  26
  27#include <core/client.h>
  28#include <subdev/i2c.h>
  29#include <subdev/timer.h>
  30
  31#include <nvif/class.h>
  32#include <nvif/unpack.h>
  33
  34/******************************************************************************
  35 * TMDS
  36 *****************************************************************************/
  37
  38static int
  39nv50_pior_tmds_ctor(struct nvkm_object *parent,
  40                    struct nvkm_object *engine,
  41                    struct nvkm_oclass *oclass, void *info, u32 index,
  42                    struct nvkm_object **pobject)
  43{
  44        struct nvkm_i2c *i2c = nvkm_i2c(parent);
  45        struct nvkm_output *outp;
  46        int ret;
  47
  48        ret = nvkm_output_create(parent, engine, oclass, info, index, &outp);
  49        *pobject = nv_object(outp);
  50        if (ret)
  51                return ret;
  52
  53        outp->edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(outp->info.extdev));
  54        return 0;
  55}
  56
  57struct nvkm_output_impl
  58nv50_pior_tmds_impl = {
  59        .base.handle = DCB_OUTPUT_TMDS | 0x0100,
  60        .base.ofuncs = &(struct nvkm_ofuncs) {
  61                .ctor = nv50_pior_tmds_ctor,
  62                .dtor = _nvkm_output_dtor,
  63                .init = _nvkm_output_init,
  64                .fini = _nvkm_output_fini,
  65        },
  66};
  67
  68/******************************************************************************
  69 * DisplayPort
  70 *****************************************************************************/
  71
  72static int
  73nv50_pior_dp_pattern(struct nvkm_output_dp *outp, int pattern)
  74{
  75        struct nvkm_i2c_port *port = outp->base.edid;
  76        if (port && port->func->pattern)
  77                return port->func->pattern(port, pattern);
  78        return port ? 0 : -ENODEV;
  79}
  80
  81static int
  82nv50_pior_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
  83{
  84        return 0;
  85}
  86
  87static int
  88nv50_pior_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
  89{
  90        struct nvkm_i2c_port *port = outp->base.edid;
  91        if (port && port->func->lnk_ctl)
  92                return port->func->lnk_ctl(port, nr, bw, ef);
  93        return port ? 0 : -ENODEV;
  94}
  95
  96static int
  97nv50_pior_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)
  98{
  99        struct nvkm_i2c_port *port = outp->base.edid;
 100        if (port && port->func->drv_ctl)
 101                return port->func->drv_ctl(port, ln, vs, pe);
 102        return port ? 0 : -ENODEV;
 103}
 104
 105static int
 106nv50_pior_dp_ctor(struct nvkm_object *parent,
 107                  struct nvkm_object *engine,
 108                  struct nvkm_oclass *oclass, void *info, u32 index,
 109                  struct nvkm_object **pobject)
 110{
 111        struct nvkm_i2c *i2c = nvkm_i2c(parent);
 112        struct nvkm_output_dp *outp;
 113        int ret;
 114
 115        ret = nvkm_output_dp_create(parent, engine, oclass, info, index, &outp);
 116        *pobject = nv_object(outp);
 117        if (ret)
 118                return ret;
 119
 120        outp->base.edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(
 121                                         outp->base.info.extdev));
 122        return 0;
 123}
 124
 125struct nvkm_output_dp_impl
 126nv50_pior_dp_impl = {
 127        .base.base.handle = DCB_OUTPUT_DP | 0x0010,
 128        .base.base.ofuncs = &(struct nvkm_ofuncs) {
 129                .ctor = nv50_pior_dp_ctor,
 130                .dtor = _nvkm_output_dp_dtor,
 131                .init = _nvkm_output_dp_init,
 132                .fini = _nvkm_output_dp_fini,
 133        },
 134        .pattern = nv50_pior_dp_pattern,
 135        .lnk_pwr = nv50_pior_dp_lnk_pwr,
 136        .lnk_ctl = nv50_pior_dp_lnk_ctl,
 137        .drv_ctl = nv50_pior_dp_drv_ctl,
 138};
 139
 140/******************************************************************************
 141 * General PIOR handling
 142 *****************************************************************************/
 143
 144int
 145nv50_pior_power(NV50_DISP_MTHD_V1)
 146{
 147        const u32 soff = outp->or * 0x800;
 148        union {
 149                struct nv50_disp_pior_pwr_v0 v0;
 150        } *args = data;
 151        u32 ctrl, type;
 152        int ret;
 153
 154        nv_ioctl(object, "disp pior pwr size %d\n", size);
 155        if (nvif_unpack(args->v0, 0, 0, false)) {
 156                nv_ioctl(object, "disp pior pwr vers %d state %d type %x\n",
 157                         args->v0.version, args->v0.state, args->v0.type);
 158                if (args->v0.type > 0x0f)
 159                        return -EINVAL;
 160                ctrl = !!args->v0.state;
 161                type = args->v0.type;
 162        } else
 163                return ret;
 164
 165        nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
 166        nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | ctrl);
 167        nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
 168        priv->pior.type[outp->or] = type;
 169        return 0;
 170}
 171