Commit b06c47a1 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-nouveau-next' of...

Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next

There's really not a great deal this time due to me spending most of this window on Maxwell.  But, here's the random bits and pieces that's currently queued.
* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (25 commits)
  drm/gk208/gr: add missing registers to grctx init
  drm/nouveau/kms/nv04-nv40: fix pageflip events via special case.
  drm/nv50-/mc: fix kms pageflip events by reordering irq handling order.
  drm/nouveau/disp/nv04-nv40: abort scanoutpos query on vga analog.
  drm/nv50-/kms: wait for enough ring space in crtc_prepare()
  drm/nouveau/disp/dp: support training pattern 3
  drm/nouveau/disp/dp: support aux read interval during link training
  drm/gk104/gpio: fix incorrect interrupt register usage
  drm/nouveau/core: punt all object state change messages to trace level
  drm/nouveau/clk: allow end-user reclocking for nv40, nvaa, and nve0 clock types
  drm/nouveau/fb: default NvMemExec to on, turning it off is used for debugging only
  drm/nouveau/bios: fix a potential NULL deref in the PROM shadowing function
  drm/nouveau/i2c: bump the i2c delay for the adt7473
  drm/nouveau/therm/fan/tach: default to 2 pulses per revolution
  drm/nvf0/device: enable video decoding engines on gk110/gk208
  drm/nvf1/device: add support for 0xf1 (gk110b)
  drm/nouveau/device: support for probing GK20A
  drm/nouveau/graph: add GK20A support
  drm/nouveau/graph: pad firmware code at load time
  drm/nouveau/graph: enable when using external fw
  ...
parents 5b9adbd3 255b329c
......@@ -102,6 +102,7 @@ nouveau-y += core/subdev/fb/nvaa.o
nouveau-y += core/subdev/fb/nvaf.o
nouveau-y += core/subdev/fb/nvc0.o
nouveau-y += core/subdev/fb/nve0.o
nouveau-y += core/subdev/fb/gk20a.o
nouveau-y += core/subdev/fb/gm107.o
nouveau-y += core/subdev/fb/ramnv04.o
nouveau-y += core/subdev/fb/ramnv10.o
......@@ -117,6 +118,7 @@ nouveau-y += core/subdev/fb/ramnva3.o
nouveau-y += core/subdev/fb/ramnvaa.o
nouveau-y += core/subdev/fb/ramnvc0.o
nouveau-y += core/subdev/fb/ramnve0.o
nouveau-y += core/subdev/fb/ramgk20a.o
nouveau-y += core/subdev/fb/ramgm107.o
nouveau-y += core/subdev/fb/sddr3.o
nouveau-y += core/subdev/fb/gddr5.o
......@@ -136,6 +138,7 @@ nouveau-y += core/subdev/i2c/nv94.o
nouveau-y += core/subdev/i2c/nvd0.o
nouveau-y += core/subdev/ibus/nvc0.o
nouveau-y += core/subdev/ibus/nve0.o
nouveau-y += core/subdev/ibus/gk20a.o
nouveau-y += core/subdev/instmem/base.o
nouveau-y += core/subdev/instmem/nv04.o
nouveau-y += core/subdev/instmem/nv40.o
......@@ -245,6 +248,7 @@ nouveau-y += core/engine/fifo/nv50.o
nouveau-y += core/engine/fifo/nv84.o
nouveau-y += core/engine/fifo/nvc0.o
nouveau-y += core/engine/fifo/nve0.o
nouveau-y += core/engine/fifo/gk20a.o
nouveau-y += core/engine/fifo/nv108.o
nouveau-y += core/engine/graph/ctxnv40.o
nouveau-y += core/engine/graph/ctxnv50.o
......@@ -255,6 +259,7 @@ nouveau-y += core/engine/graph/ctxnvc8.o
nouveau-y += core/engine/graph/ctxnvd7.o
nouveau-y += core/engine/graph/ctxnvd9.o
nouveau-y += core/engine/graph/ctxnve4.o
nouveau-y += core/engine/graph/ctxgk20a.o
nouveau-y += core/engine/graph/ctxnvf0.o
nouveau-y += core/engine/graph/ctxnv108.o
nouveau-y += core/engine/graph/ctxgm107.o
......@@ -275,6 +280,7 @@ nouveau-y += core/engine/graph/nvc8.o
nouveau-y += core/engine/graph/nvd7.o
nouveau-y += core/engine/graph/nvd9.o
nouveau-y += core/engine/graph/nve4.o
nouveau-y += core/engine/graph/gk20a.o
nouveau-y += core/engine/graph/nvf0.o
nouveau-y += core/engine/graph/nv108.o
nouveau-y += core/engine/graph/gm107.o
......
......@@ -156,7 +156,7 @@ nouveau_object_ctor(struct nouveau_object *parent,
}
if (ret == 0) {
nv_debug(object, "created\n");
nv_trace(object, "created\n");
atomic_set(&object->refcount, 1);
}
......@@ -166,7 +166,7 @@ nouveau_object_ctor(struct nouveau_object *parent,
static void
nouveau_object_dtor(struct nouveau_object *object)
{
nv_debug(object, "destroying\n");
nv_trace(object, "destroying\n");
nv_ofuncs(object)->dtor(object);
}
......@@ -337,7 +337,7 @@ nouveau_object_inc(struct nouveau_object *object)
goto fail_self;
}
nv_debug(object, "initialised\n");
nv_trace(object, "initialised\n");
return 0;
fail_self:
......@@ -375,7 +375,7 @@ nouveau_object_decf(struct nouveau_object *object)
if (object->parent)
nouveau_object_dec(object->parent, false);
nv_debug(object, "stopped\n");
nv_trace(object, "stopped\n");
return 0;
}
......@@ -411,7 +411,7 @@ nouveau_object_decs(struct nouveau_object *object)
}
}
nv_debug(object, "suspended\n");
nv_trace(object, "suspended\n");
return 0;
fail_parent:
......
......@@ -156,6 +156,23 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;
break;
case 0xea:
device->cname = "GK20A";
device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = gk20a_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = gk20a_graph_oclass;
device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;
break;
case 0xf0:
device->cname = "GK110";
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
......@@ -184,11 +201,42 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
#if 0
device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
#endif
device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass;
break;
case 0xf1:
device->cname = "GK110B";
device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass;
device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass;
device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = nvc0_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvf0_graph_oclass;
device->oclass[NVDEV_ENGINE_DISP ] = nvf0_disp_oclass;
device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass;
break;
case 0x108:
......@@ -219,11 +267,9 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
#if 0
device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
#endif
break;
default:
nv_fatal(device, "unknown Kepler chipset\n");
......
......@@ -48,7 +48,7 @@ struct dp_state {
u8 version;
struct nouveau_i2c_port *aux;
int head;
u8 dpcd[4];
u8 dpcd[16];
int link_nr;
u32 link_bw;
u8 stat[6];
......@@ -149,7 +149,10 @@ dp_link_train_update(struct dp_state *dp, u32 delay)
{
int ret;
udelay(delay);
if (dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL])
mdelay(dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4);
else
udelay(delay);
ret = nv_rdaux(dp->aux, DPCD_LS02, dp->stat, 6);
if (ret)
......@@ -199,7 +202,10 @@ dp_link_train_eq(struct dp_state *dp)
bool eq_done = false, cr_done = true;
int tries = 0, i;
dp_set_training_pattern(dp, 2);
if (dp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED)
dp_set_training_pattern(dp, 3);
else
dp_set_training_pattern(dp, 2);
do {
if (dp_link_train_update(dp, 400))
......@@ -313,8 +319,10 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
}
/* bring capabilities within encoder limits */
if (nv_oclass(disp)->handle < NV_ENGINE(DISP, 0x90))
dp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
if ((dp->dpcd[2] & 0x1f) > dp->outp->dpconf.link_nr) {
dp->dpcd[2] &= ~0x1f;
dp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
dp->dpcd[2] |= dp->outp->dpconf.link_nr;
}
if (dp->dpcd[1] > dp->outp->dpconf.link_bw)
......
......@@ -2,15 +2,15 @@
#define __NVKM_DISP_DPORT_H__
/* DPCD Receiver Capabilities */
#define DPCD_RC00 0x00000
#define DPCD_RC00_DPCD_REV 0xff
#define DPCD_RC01 0x00001
#define DPCD_RC01_MAX_LINK_RATE 0xff
#define DPCD_RC00_DPCD_REV 0x00000
#define DPCD_RC01_MAX_LINK_RATE 0x00001
#define DPCD_RC02 0x00002
#define DPCD_RC02_ENHANCED_FRAME_CAP 0x80
#define DPCD_RC02_TPS3_SUPPORTED 0x40
#define DPCD_RC02_MAX_LANE_COUNT 0x1f
#define DPCD_RC03 0x00003
#define DPCD_RC03_MAX_DOWNSPREAD 0x01
#define DPCD_RC0E_AUX_RD_INTERVAL 0x0000e
/* DPCD Link Configuration */
#define DPCD_LC00 0x00100
......
......@@ -51,6 +51,14 @@ nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
args->htotal = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
args->hblanke = args->htotal - 1;
/*
* If output is vga instead of digital then vtotal/htotal is invalid
* so we have to give up and trigger the timestamping fallback in the
* drm core.
*/
if (!args->vtotal || !args->htotal)
return -ENOTSUPP;
args->time[0] = ktime_to_ns(ktime_get());
line = nv_rd32(priv, 0x600868 + (head * 0x2000));
args->time[1] = ktime_to_ns(ktime_get());
......
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "nve0.h"
struct nouveau_oclass *
gk20a_fifo_oclass = &(struct nve0_fifo_impl) {
.base.handle = NV_ENGINE(FIFO, 0xea),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nve0_fifo_ctor,
.dtor = nve0_fifo_dtor,
.init = nve0_fifo_init,
.fini = nve0_fifo_fini,
},
.channels = 128,
}.base;
......@@ -8,6 +8,7 @@ int nve0_fifo_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_object **);
void nve0_fifo_dtor(struct nouveau_object *);
int nve0_fifo_init(struct nouveau_object *);
int nve0_fifo_fini(struct nouveau_object *, bool);
struct nve0_fifo_impl {
struct nouveau_oclass base;
......
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "ctxnvc0.h"
static const struct nvc0_graph_pack
gk20a_grctx_pack_mthd[] = {
{ nve4_grctx_init_a097_0, 0xa297 },
{ nvc0_grctx_init_902d_0, 0x902d },
{}
};
struct nouveau_oclass *
gk20a_grctx_oclass = &(struct nvc0_grctx_oclass) {
.base.handle = NV_ENGCTX(GR, 0xea),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nvc0_graph_context_ctor,
.dtor = nvc0_graph_context_dtor,
.init = _nouveau_graph_context_init,
.fini = _nouveau_graph_context_fini,
.rd32 = _nouveau_graph_context_rd32,
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
.mods = nve4_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nve4_grctx_pack_hub,
.gpc = nve4_grctx_pack_gpc,
.zcull = nvc0_grctx_pack_zcull,
.tpc = nve4_grctx_pack_tpc,
.ppc = nve4_grctx_pack_ppc,
.icmd = nve4_grctx_pack_icmd,
.mthd = gk20a_grctx_pack_mthd,
}.base;
......@@ -545,10 +545,12 @@ nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
mmio_list(0x408010, 0x80000000, 0, 0);
mmio_list(0x419004, 0x00000000, 8, 1);
mmio_list(0x419008, 0x00000000, 0, 0);
mmio_list(0x4064cc, 0x80000000, 0, 0);
mmio_list(0x408004, 0x00000000, 8, 0);
mmio_list(0x408008, 0x80000030, 0, 0);
mmio_list(0x418808, 0x00000000, 8, 0);
mmio_list(0x41880c, 0x80000030, 0, 0);
mmio_list(0x4064c8, 0x00c20200, 0, 0);
mmio_list(0x418810, 0x80000000, 12, 2);
mmio_list(0x419848, 0x10000000, 12, 2);
......
......@@ -69,7 +69,9 @@ extern struct nouveau_oclass *nvd7_grctx_oclass;
extern struct nouveau_oclass *nvd9_grctx_oclass;
extern struct nouveau_oclass *nve4_grctx_oclass;
extern struct nouveau_oclass *gk20a_grctx_oclass;
void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
void nve4_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
......@@ -151,6 +153,13 @@ extern const struct nvc0_graph_init nve4_grctx_init_gpm_0[];
extern const struct nvc0_graph_init nve4_grctx_init_pes_0[];
extern const struct nvc0_graph_pack nve4_grctx_pack_hub[];
extern const struct nvc0_graph_pack nve4_grctx_pack_gpc[];
extern const struct nvc0_graph_pack nve4_grctx_pack_tpc[];
extern const struct nvc0_graph_pack nve4_grctx_pack_ppc[];
extern const struct nvc0_graph_pack nve4_grctx_pack_icmd[];
extern const struct nvc0_graph_init nve4_grctx_init_a097_0[];
extern const struct nvc0_graph_pack nvf0_grctx_pack_mthd[];
extern const struct nvc0_graph_init nvf0_grctx_init_pri_0[];
......
......@@ -272,13 +272,13 @@ nve4_grctx_init_icmd_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nve4_grctx_pack_icmd[] = {
{ nve4_grctx_init_icmd_0 },
{}
};
static const struct nvc0_graph_init
const struct nvc0_graph_init
nve4_grctx_init_a097_0[] = {
{ 0x000800, 8, 0x40, 0x00000000 },
{ 0x000804, 8, 0x40, 0x00000000 },
......@@ -697,7 +697,7 @@ nve4_grctx_init_be_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nve4_grctx_pack_hub[] = {
{ nvc0_grctx_init_main_0 },
{ nve4_grctx_init_fe_0 },
......@@ -737,7 +737,7 @@ nve4_grctx_init_gpm_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nve4_grctx_pack_gpc[] = {
{ nvc0_grctx_init_gpc_unk_0 },
{ nvd9_grctx_init_prop_0 },
......@@ -802,7 +802,7 @@ nve4_grctx_init_sm_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nve4_grctx_pack_tpc[] = {
{ nvd7_grctx_init_pe_0 },
{ nve4_grctx_init_tex_0 },
......@@ -826,7 +826,7 @@ nve4_grctx_init_cbm_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nve4_grctx_pack_ppc[] = {
{ nve4_grctx_init_pes_0 },
{ nve4_grctx_init_cbm_0 },
......@@ -838,7 +838,7 @@ nve4_grctx_pack_ppc[] = {
* PGRAPH context implementation
******************************************************************************/
static void
void
nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
{
u32 magic[GPC_MAX][2];
......
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "nvc0.h"
#include "ctxnvc0.h"
static struct nouveau_oclass
gk20a_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa040, &nouveau_object_ofuncs },
{ 0xa297, &nouveau_object_ofuncs },
{ 0xa0c0, &nouveau_object_ofuncs },
{}
};
struct nouveau_oclass *
gk20a_graph_oclass = &(struct nvc0_graph_oclass) {
.base.handle = NV_ENGINE(GR, 0xea),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nvc0_graph_ctor,
.dtor = nvc0_graph_dtor,
.init = nve4_graph_init,
.fini = nve4_graph_fini,
},
.cclass = &gk20a_grctx_oclass,
.sclass = gk20a_graph_sclass,
.mmio = nve4_graph_pack_mmio,
}.base;
......@@ -894,6 +894,10 @@ nvc0_graph_init_fw(struct nvc0_graph_priv *priv, u32 fuc_base,
nv_wr32(priv, fuc_base + 0x0188, i >> 6);
nv_wr32(priv, fuc_base + 0x0184, code->data[i]);
}
/* code must be padded to 0x40 words */
for (; i & 0x3f; i++)
nv_wr32(priv, fuc_base + 0x0184, 0);
}
static void
......@@ -1259,10 +1263,14 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_graph_oclass *oclass = (void *)bclass;
struct nouveau_device *device = nv_device(parent);
struct nvc0_graph_priv *priv;
bool use_ext_fw, enable;
int ret, i;
ret = nouveau_graph_create(parent, engine, bclass,
(oclass->fecs.ucode != NULL), &priv);
use_ext_fw = nouveau_boolopt(device->cfgopt, "NvGrUseFW",
oclass->fecs.ucode == NULL);
enable = use_ext_fw || oclass->fecs.ucode != NULL;
ret = nouveau_graph_create(parent, engine, bclass, enable, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
......@@ -1272,7 +1280,7 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->base.units = nvc0_graph_units;
if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) {
if (use_ext_fw) {
nv_info(priv, "using external firmware\n");
if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) ||
nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) ||
......
......@@ -116,6 +116,7 @@ int nvc0_graph_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_object **);
void nvc0_graph_dtor(struct nouveau_object *);
int nvc0_graph_init(struct nouveau_object *);
int nve4_graph_fini(struct nouveau_object *, bool);
int nve4_graph_init(struct nouveau_object *);
extern struct nouveau_oclass nvc0_graph_sclass[];
......@@ -217,6 +218,7 @@ extern const struct nvc0_graph_init nve4_graph_init_main_0[];
extern const struct nvc0_graph_init nve4_graph_init_tpccs_0[];
extern const struct nvc0_graph_init nve4_graph_init_pe_0[];
extern const struct nvc0_graph_init nve4_graph_init_be_0[];
extern const struct nvc0_graph_pack nve4_graph_pack_mmio[];
extern const struct nvc0_graph_init nvf0_graph_init_fe_0[];
extern const struct nvc0_graph_init nvf0_graph_init_sked_0[];
......
......@@ -151,7 +151,7 @@ nve4_graph_init_be_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nve4_graph_pack_mmio[] = {
{ nve4_graph_init_main_0 },
{ nvc0_graph_init_fe_0 },
......@@ -189,7 +189,7 @@ nve4_graph_pack_mmio[] = {
* PGRAPH engine/subdev functions
******************************************************************************/
static int
int
nve4_graph_fini(struct nouveau_object *object, bool suspend)
{
struct nvc0_graph_priv *priv = (void *)object;
......
......@@ -109,6 +109,7 @@ extern struct nouveau_oclass *nv50_fifo_oclass;
extern struct nouveau_oclass *nv84_fifo_oclass;
extern struct nouveau_oclass *nvc0_fifo_oclass;
extern struct nouveau_oclass *nve0_fifo_oclass;
extern struct nouveau_oclass *gk20a_fifo_oclass;
extern struct nouveau_oclass *nv108_fifo_oclass;
void nv04_fifo_intr(struct nouveau_subdev *);
......
......@@ -68,6 +68,7 @@ extern struct nouveau_oclass *nvc8_graph_oclass;
extern struct nouveau_oclass *nvd7_graph_oclass;
extern struct nouveau_oclass *nvd9_graph_oclass;
extern struct nouveau_oclass *nve4_graph_oclass;
extern struct nouveau_oclass *gk20a_graph_oclass;
extern struct nouveau_oclass *nvf0_graph_oclass;
extern struct nouveau_oclass *nv108_graph_oclass;
extern struct nouveau_oclass *gm107_graph_oclass;
......
......@@ -77,6 +77,8 @@ struct nouveau_clock {
int tstate; /* thermal adjustment (max-) */
int dstate; /* display adjustment (min+) */
bool allow_reclock;
int (*read)(struct nouveau_clock *, enum nv_clk_src);
int (*calc)(struct nouveau_clock *, struct nouveau_cstate *);
int (*prog)(struct nouveau_clock *);
......@@ -106,8 +108,8 @@ struct nouveau_clocks {
int mdiv;
};
#define nouveau_clock_create(p,e,o,i,d) \
nouveau_clock_create_((p), (e), (o), (i), sizeof(**d), (void **)d)
#define nouveau_clock_create(p,e,o,i,r,d) \
nouveau_clock_create_((p), (e), (o), (i), (r), sizeof(**d), (void **)d)
#define nouveau_clock_destroy(p) ({ \
struct nouveau_clock *clk = (p); \
_nouveau_clock_dtor(nv_object(clk)); \
......@@ -121,7 +123,7 @@ struct nouveau_clocks {
int nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *,
struct nouveau_clocks *, int, void **);
struct nouveau_clocks *, bool, int, void **);
void _nouveau_clock_dtor(struct nouveau_object *);
int _nouveau_clock_init(struct nouveau_object *);
#define _nouveau_clock_fini _nouveau_subdev_fini
......
......@@ -105,6 +105,7 @@ extern struct nouveau_oclass *nvaa_fb_oclass;
extern struct nouveau_oclass *nvaf_fb_oclass;
extern struct nouveau_oclass *nvc0_fb_oclass;
extern struct nouveau_oclass *nve0_fb_oclass;
extern struct nouveau_oclass *gk20a_fb_oclass;
extern struct nouveau_oclass *gm107_fb_oclass;
#include <subdev/bios/ramcfg.h>
......
......@@ -30,5 +30,6 @@ nouveau_ibus(void *obj)
extern struct nouveau_oclass nvc0_ibus_oclass;
extern struct nouveau_oclass nve0_ibus_oclass;
extern struct nouveau_oclass gk20a_ibus_oclass;
#endif
......@@ -118,8 +118,10 @@ nouveau_bar_create_(struct nouveau_object *parent,
if (ret)
return ret;
bar->iomem = ioremap(nv_device_resource_start(device, 3),
nv_device_resource_len(device, 3));
if (nv_device_resource_len(device, 3) != 0)
bar->iomem = ioremap(nv_device_resource_start(device, 3),
nv_device_resource_len(device, 3));
return 0;
}
......
......@@ -30,14 +30,16 @@
#include "priv.h"
struct nvc0_bar_priv_vm {
struct nouveau_gpuobj *mem;
struct nouveau_gpuobj *pgd;
struct nouveau_vm *vm;
};
struct nvc0_bar_priv {
struct nouveau_bar base;
spinlock_t lock;
struct {
struct nouveau_gpuobj *mem;
struct nouveau_gpuobj *pgd;
struct nouveau_vm *vm;
} bar[2];
struct nvc0_bar_priv_vm bar[2];
};
static int
......@@ -79,87 +81,87 @@ nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma)
}
static int
nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
nvc0_bar_init_vm(struct nvc0_bar_priv *priv, struct nvc0_bar_priv_vm *bar_vm,
int bar_nr)
{
struct nouveau_device *device = nv_device(parent);
struct nvc0_bar_priv *priv;
struct nouveau_gpuobj *mem;
struct nouveau_device *device = nv_device(&priv->base);
struct nouveau_vm *vm;
resource_size_t bar_len;
int ret;
ret = nouveau_bar_create(parent, engine, oclass, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
/* BAR3 */
ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
&priv->bar[0].mem);
mem = priv->bar[0].mem;
&bar_vm->mem);
if (ret)
return ret;
ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0,
&priv->bar[0].pgd);
&bar_vm->pgd);
if (ret)
return ret;
ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm);
bar_len = nv_device_resource_len(device, bar_nr);
ret = nouveau_vm_new(device, 0, bar_len, 0, &vm);
if (ret)
return ret;
atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
ret = nouveau_gpuobj_new(nv_object(priv), NULL,
(nv_device_resource_len(device, 3) >> 12) * 8,
0x1000, NVOBJ_FLAG_ZERO_ALLOC,
&vm->pgt[0].obj[0]);
vm->pgt[0].refcount[0] = 1;
if (ret)
return ret;
/*
* Bootstrap page table lookup.
*/
if (bar_nr == 3) {
ret = nouveau_gpuobj_new(nv_object(priv), NULL,
(bar_len >> 12) * 8, 0x1000,
NVOBJ_FLAG_ZERO_ALLOC,
&vm->pgt[0].obj[0]);
vm->pgt[0].refcount[0] = 1;
if (ret)
return ret;
}
ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd);
ret = nouveau_vm_ref(vm, &bar_vm->vm, bar_vm->pgd);
nouveau_vm_ref(NULL, &vm, NULL);
if (ret)
return ret;
nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr));
nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr));
nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1));
nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1));
nv_wo32(bar_vm->mem, 0x0200, lower_32_bits(bar_vm->pgd->addr));
nv_wo32(bar_vm->mem, 0x0204, upper_32_bits(bar_vm->pgd->addr));
nv_wo32(bar_vm->mem, 0x0208, lower_32_bits(bar_len - 1));
nv_wo32(bar_vm->mem, 0x020c, upper_32_bits(bar_len - 1));
/* BAR1 */
ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
&priv->bar[1].mem);
mem = priv->bar[1].mem;
if (ret)
return ret;
return 0;
}
ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0,
&priv->bar[1].pgd);
if (ret)
return ret;
static int
nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nouveau_device *device = nv_device(parent);
struct nvc0_bar_priv *priv;
bool has_bar3 = nv_device_resource_len(device, 3) != 0;
int ret;
ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm);
ret = nouveau_bar_create(parent, engine, oclass, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
/* BAR3 */
if (has_bar3) {
ret = nvc0_bar_init_vm(priv, &priv->bar[0], 3);
if (ret)
return ret;
priv->base.alloc = nouveau_bar_alloc;
priv->base.kmap = nvc0_bar_kmap;
}
ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd);
nouveau_vm_ref(NULL, &vm, NULL);
/* BAR1 */
ret = nvc0_bar_init_vm(priv, &priv->bar[1], 1);
if (ret)
return ret;
nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr));
nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr));
nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1));
nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1));
priv->base.alloc = nouveau_bar_alloc;
priv->base.kmap = nvc0_bar_kmap;
priv->base.umap = nvc0_bar_umap;
priv->base.unmap = nvc0_bar_unmap;
priv->base.flush = nv84_bar_flush;
......@@ -201,7 +203,9 @@ nvc0_bar_init(struct nouveau_object *object)
nv_mask(priv, 0x100c80, 0x00000001, 0x00000000);
nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12);
nv_wr32(priv, 0x001714, 0xc0000000 | priv->bar[0].mem->addr >> 12);
if (priv->bar[0].mem)
nv_wr32(priv, 0x001714,
0xc0000000 | priv->bar[0].mem->addr >> 12);
return 0;
}
......
......@@ -183,10 +183,11 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
goto out;
bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data) {
for (i = 0; i < bios->size; i += 4)
((u32 *)bios->data)[i/4] = nv_rd32(bios, 0x300000 + i);
}
if (!bios->data)
goto out;
for (i = 0; i < bios->size; i += 4)
((u32 *)bios->data)[i/4] = nv_rd32(bios, 0x300000 + i);
/* check the PCI record header */
pcir = nv_ro16(bios, 0x0018);
......
......@@ -346,8 +346,8 @@ nouveau_clock_ustate_update(struct nouveau_clock *clk, int req)
struct nouveau_pstate *pstate;
int i = 0;
/* YKW repellant */
return -ENOSYS;
if (!clk->allow_reclock)
return -ENOSYS;
if (req != -1 && req != -2) {
list_for_each_entry(pstate, &clk->states, head) {
......@@ -456,6 +456,7 @@ nouveau_clock_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass,
struct nouveau_clocks *clocks,
bool allow_reclock,
int length, void **object)
{
struct nouveau_device *device = nv_device(parent);
......@@ -478,6 +479,8 @@ nouveau_clock_create_(struct nouveau_object *parent,
ret = nouveau_pstate_new(clk, idx++);
} while (ret == 0);
clk->allow_reclock = allow_reclock;
mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen);
if (mode) {
if (!strncasecmpz(mode, "disabled", arglen)) {
......
......@@ -82,7 +82,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv04_clock_priv *priv;
int ret;
ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, &priv);
ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, false,
&priv);
*pobject = nv_object(priv);
if (ret)
return ret;
......
......@@ -213,7 +213,8 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv40_clock_priv *priv;
int ret;
ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, &priv);
ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, true,
&priv);
*pobject = nv_object(priv);
if (ret)
return ret;
......
......@@ -507,7 +507,7 @@ nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
int ret;
ret = nouveau_clock_create(parent, engine, oclass, pclass->domains,
&priv);
false, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
......
......@@ -302,7 +302,8 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nva3_clock_priv *priv;
int ret;
ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, &priv);
ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, false,
&priv);
*pobject = nv_object(priv);
if (ret)
return ret;
......
......@@ -421,7 +421,8 @@ nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvaa_clock_priv *priv;
int ret;
ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, &priv);
ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, true,
&priv);
*pobject = nv_object(priv);
if (ret)
return ret;
......
......@@ -437,7 +437,8 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_clock_priv *priv;
int ret;
ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, &priv);
ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, false,
&priv);
*pobject = nv_object(priv);
if (ret)
return ret;
......
......@@ -473,7 +473,8 @@ nve0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nve0_clock_priv *priv;
int ret;
ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, &priv);
ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, true,
&priv);
*pobject = nv_object(priv);
if (ret)
return ret;
......
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "nvc0.h"
struct gk20a_fb_priv {
struct nouveau_fb base;
};
static int
gk20a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct gk20a_fb_priv *priv;
int ret;
ret = nouveau_fb_create(parent, engine, oclass, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
return 0;
}
struct nouveau_oclass *
gk20a_fb_oclass = &(struct nouveau_fb_impl) {
.base.handle = NV_SUBDEV(FB, 0xea),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = gk20a_fb_ctor,
.dtor = _nouveau_fb_dtor,
.init = _nouveau_fb_init,
.fini = _nouveau_fb_fini,
},
.memtype = nvc0_fb_memtype_valid,
.ram = &gk20a_ram_oclass,
}.base;
......@@ -32,6 +32,7 @@ extern struct nouveau_oclass nva3_ram_oclass;
extern struct nouveau_oclass nvaa_ram_oclass;
extern struct nouveau_oclass nvc0_ram_oclass;
extern struct nouveau_oclass nve0_ram_oclass;
extern struct nouveau_oclass gk20a_ram_oclass;
extern struct nouveau_oclass gm107_ram_oclass;
int nouveau_sddr3_calc(struct nouveau_ram *ram);
......
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "priv.h"
#include <subdev/fb.h>
struct gk20a_mem {
struct nouveau_mem base;
void *cpuaddr;
dma_addr_t handle;
};
#define to_gk20a_mem(m) container_of(m, struct gk20a_mem, base)
static void
gk20a_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
{
struct device *dev = nv_device_base(nv_device(pfb));
struct gk20a_mem *mem = to_gk20a_mem(*pmem);
*pmem = NULL;
if (unlikely(mem == NULL))
return;
if (likely(mem->cpuaddr))
dma_free_coherent(dev, mem->base.size << PAGE_SHIFT,
mem->cpuaddr, mem->handle);
kfree(mem->base.pages);
kfree(mem);
}
static int
gk20a_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
u32 memtype, struct nouveau_mem **pmem)
{
struct device *dev = nv_device_base(nv_device(pfb));
struct gk20a_mem *mem;
u32 type = memtype & 0xff;
u32 npages, order;
int i;
nv_debug(pfb, "%s: size: %llx align: %x, ncmin: %x\n", __func__, size,
align, ncmin);
npages = size >> PAGE_SHIFT;
if (npages == 0)
npages = 1;
if (align == 0)
align = PAGE_SIZE;
align >>= PAGE_SHIFT;
/* round alignment to the next power of 2, if needed */
order = fls(align);
if ((align & (align - 1)) == 0)
order--;
align = BIT(order);
/* ensure returned address is correctly aligned */
npages = max(align, npages);
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
if (!mem)
return -ENOMEM;
mem->base.size = npages;
mem->base.memtype = type;
mem->base.pages = kzalloc(sizeof(dma_addr_t) * npages, GFP_KERNEL);
if (!mem->base.pages) {
kfree(mem);
return -ENOMEM;
}
*pmem = &mem->base;
mem->cpuaddr = dma_alloc_coherent(dev, npages << PAGE_SHIFT,
&mem->handle, GFP_KERNEL);
if (!mem->cpuaddr) {
nv_error(pfb, "%s: cannot allocate memory!\n", __func__);
gk20a_ram_put(pfb, pmem);
return -ENOMEM;
}
align <<= PAGE_SHIFT;
/* alignment check */
if (unlikely(mem->handle & (align - 1)))
nv_warn(pfb, "memory not aligned as requested: %pad (0x%x)\n",
&mem->handle, align);
nv_debug(pfb, "alloc size: 0x%x, align: 0x%x, paddr: %pad, vaddr: %p\n",
npages << PAGE_SHIFT, align, &mem->handle, mem->cpuaddr);
for (i = 0; i < npages; i++)
mem->base.pages[i] = mem->handle + (PAGE_SIZE * i);
mem->base.offset = (u64)mem->base.pages[0];
return 0;
}
static int
gk20a_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 datasize,
struct nouveau_object **pobject)
{
struct nouveau_ram *ram;
int ret;
ret = nouveau_ram_create(parent, engine, oclass, &ram);
*pobject = nv_object(ram);
if (ret)
return ret;
ram->type = NV_MEM_TYPE_STOLEN;
ram->size = get_num_physpages() << PAGE_SHIFT;
ram->get = gk20a_ram_get;
ram->put = gk20a_ram_put;
return 0;
}
struct nouveau_oclass
gk20a_ram_oclass = {
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = gk20a_ram_ctor,
.dtor = _nouveau_ram_dtor,
.init = _nouveau_ram_init,
.fini = _nouveau_ram_fini,
},
};
......@@ -211,7 +211,7 @@ nv50_ram_prog(struct nouveau_fb *pfb)
struct nv50_ram *ram = (void *)pfb->ram;
struct nv50_ramseq *hwsq = &ram->hwsq;
ram_exec(hwsq, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
ram_exec(hwsq, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
return 0;
}
......
......@@ -309,7 +309,7 @@ nva3_ram_prog(struct nouveau_fb *pfb)
struct nouveau_device *device = nv_device(pfb);
struct nva3_ram *ram = (void *)pfb->ram;
struct nva3_ramfuc *fuc = &ram->fuc;
ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
return 0;
}
......
......@@ -408,7 +408,7 @@ nvc0_ram_prog(struct nouveau_fb *pfb)
struct nouveau_device *device = nv_device(pfb);
struct nvc0_ram *ram = (void *)pfb->ram;
struct nvc0_ramfuc *fuc = &ram->fuc;
ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
return 0;
}
......
......@@ -1111,7 +1111,7 @@ nve0_ram_prog(struct nouveau_fb *pfb)
struct nouveau_device *device = nv_device(pfb);
struct nve0_ram *ram = (void *)pfb->ram;
struct nve0_ramfuc *fuc = &ram->fuc;
ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
return (ram->base.next == &ram->base.xition);
}
......
......@@ -44,7 +44,7 @@ nve0_gpio_intr(struct nouveau_subdev *subdev)
}
nv_wr32(priv, 0xdc00, intr0);
nv_wr32(priv, 0xdc88, intr1);
nv_wr32(priv, 0xdc80, intr1);
}
void
......@@ -52,8 +52,8 @@ nve0_gpio_intr_enable(struct nouveau_event *event, int line)
{
const u32 addr = line < 16 ? 0xdc00 : 0xdc80;
const u32 mask = 0x00010001 << (line & 0xf);
nv_wr32(event->priv, addr + 0x08, mask);
nv_mask(event->priv, addr + 0x00, mask, mask);
nv_wr32(event->priv, addr + 0x00, mask);
nv_mask(event->priv, addr + 0x08, mask, mask);
}
void
......@@ -61,8 +61,8 @@ nve0_gpio_intr_disable(struct nouveau_event *event, int line)
{
const u32 addr = line < 16 ? 0xdc00 : 0xdc80;
const u32 mask = 0x00010001 << (line & 0xf);
nv_wr32(event->priv, addr + 0x08, mask);
nv_mask(event->priv, addr + 0x00, mask, 0x00000000);
nv_mask(event->priv, addr + 0x08, mask, 0x00000000);
nv_wr32(event->priv, addr + 0x00, mask);
}
int
......
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <subdev/ibus.h>
#include <subdev/timer.h>
struct gk20a_ibus_priv {
struct nouveau_ibus base;
};
static void
gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv)
{
nv_mask(priv, 0x137250, 0x3f, 0);
nv_mask(priv, 0x000200, 0x20, 0);
usleep_range(20, 30);
nv_mask(priv, 0x000200, 0x20, 0x20);
nv_wr32(priv, 0x12004c, 0x4);
nv_wr32(priv, 0x122204, 0x2);
nv_rd32(priv, 0x122204);
}
static void
gk20a_ibus_intr(struct nouveau_subdev *subdev)
{
struct gk20a_ibus_priv *priv = (void *)subdev;
u32 status0 = nv_rd32(priv, 0x120058);
if (status0 & 0x7) {
nv_debug(priv, "resetting priv ring\n");
gk20a_ibus_init_priv_ring(priv);
}
/* Acknowledge interrupt */
nv_mask(priv, 0x12004c, 0x2, 0x2);
if (!nv_wait(subdev, 0x12004c, 0x3f, 0x00))
nv_warn(priv, "timeout waiting for ringmaster ack\n");
}
static int
gk20a_ibus_init(struct nouveau_object *object)
{
struct gk20a_ibus_priv *priv = (void *)object;
int ret;
ret = _nouveau_ibus_init(object);
if (ret)
return ret;
gk20a_ibus_init_priv_ring(priv);
return 0;
}
static int
gk20a_ibus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct gk20a_ibus_priv *priv;
int ret;
ret = nouveau_ibus_create(parent, engine, oclass, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
nv_subdev(priv)->intr = gk20a_ibus_intr;
return 0;
}
struct nouveau_oclass
gk20a_ibus_oclass = {
.handle = NV_SUBDEV(IBUS, 0xea),
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = gk20a_ibus_ctor,
.dtor = _nouveau_ibus_dtor,
.init = gk20a_ibus_init,
.fini = _nouveau_ibus_fini,
},
};
......@@ -26,6 +26,7 @@
const struct nouveau_mc_intr
nv50_mc_intr[] = {
{ 0x04000000, NVDEV_ENGINE_DISP }, /* DISP before FIFO, so pageflip-timestamping works! */
{ 0x00000001, NVDEV_ENGINE_MPEG },
{ 0x00000100, NVDEV_ENGINE_FIFO },
{ 0x00001000, NVDEV_ENGINE_GR },
......@@ -34,7 +35,6 @@ nv50_mc_intr[] = {
{ 0x00020000, NVDEV_ENGINE_VP }, /* NV84- */
{ 0x00100000, NVDEV_SUBDEV_TIMER },
{ 0x00200000, NVDEV_SUBDEV_GPIO },
{ 0x04000000, NVDEV_ENGINE_DISP },
{ 0x10000000, NVDEV_SUBDEV_BUS },
{ 0x80000000, NVDEV_ENGINE_SW },
{ 0x0002d101, NVDEV_SUBDEV_FB },
......
......@@ -26,6 +26,7 @@
static const struct nouveau_mc_intr
nv98_mc_intr[] = {
{ 0x04000000, NVDEV_ENGINE_DISP }, /* DISP first, so pageflip timestamps work */
{ 0x00000001, NVDEV_ENGINE_PPP },
{ 0x00000100, NVDEV_ENGINE_FIFO },
{ 0x00001000, NVDEV_ENGINE_GR },
......@@ -37,7 +38,6 @@ nv98_mc_intr[] = {
{ 0x00100000, NVDEV_SUBDEV_TIMER },
{ 0x00200000, NVDEV_SUBDEV_GPIO },
{ 0x00400000, NVDEV_ENGINE_COPY0 }, /* NVA3- */
{ 0x04000000, NVDEV_ENGINE_DISP },
{ 0x10000000, NVDEV_SUBDEV_BUS },
{ 0x80000000, NVDEV_ENGINE_SW },
{ 0x0042d101, NVDEV_SUBDEV_FB },
......
......@@ -26,6 +26,7 @@
const struct nouveau_mc_intr
nvc0_mc_intr[] = {
{ 0x04000000, NVDEV_ENGINE_DISP }, /* DISP first, so pageflip timestamps work. */
{ 0x00000001, NVDEV_ENGINE_PPP },
{ 0x00000020, NVDEV_ENGINE_COPY0 },
{ 0x00000040, NVDEV_ENGINE_COPY1 },
......@@ -40,7 +41,6 @@ nvc0_mc_intr[] = {
{ 0x00200000, NVDEV_SUBDEV_GPIO },
{ 0x01000000, NVDEV_SUBDEV_PWR },
{ 0x02000000, NVDEV_SUBDEV_LTCG },
{ 0x04000000, NVDEV_ENGINE_DISP },
{ 0x08000000, NVDEV_SUBDEV_FB },
{ 0x10000000, NVDEV_SUBDEV_BUS },
{ 0x40000000, NVDEV_SUBDEV_IBUS },
......
......@@ -60,9 +60,9 @@ static struct nouveau_i2c_board_info
nv_board_infos[] = {
{ { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 0 },
{ { I2C_BOARD_INFO("w83781d", 0x2d) }, 0 },
{ { I2C_BOARD_INFO("adt7473", 0x2e) }, 20 },
{ { I2C_BOARD_INFO("adt7473", 0x2d) }, 20 },
{ { I2C_BOARD_INFO("adt7473", 0x2c) }, 20 },
{ { I2C_BOARD_INFO("adt7473", 0x2e) }, 40 },
{ { I2C_BOARD_INFO("adt7473", 0x2d) }, 40 },
{ { I2C_BOARD_INFO("adt7473", 0x2c) }, 40 },
{ { I2C_BOARD_INFO("f75375", 0x2e) }, 0 },
{ { I2C_BOARD_INFO("lm99", 0x4c) }, 0 },
{ { I2C_BOARD_INFO("lm90", 0x4c) }, 0 },
......
......@@ -36,7 +36,7 @@ nva3_therm_fan_sense(struct nouveau_therm *therm)
u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff;
u32 ctrl = nv_rd32(therm, 0x00e720);
if (ctrl & 0x00000001)
return tach * 60;
return tach * 60 / 2;
return -ENODEV;
}
......
......@@ -798,6 +798,7 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
struct drm_device *dev = drm->dev;
struct nouveau_page_flip_state *s;
unsigned long flags;
int crtcid = -1;
spin_lock_irqsave(&dev->event_lock, flags);
......@@ -808,8 +809,13 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
}
s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
if (s->event)
drm_send_vblank_event(dev, s->crtc, s->event);
if (s->event) {
/* Vblank timestamps/counts are only correct on >= NV-50 */
if (nv_device(drm->device)->card_type >= NV_50)
crtcid = s->crtc;
drm_send_vblank_event(dev, crtcid, s->event);
}
list_del(&s->head);
if (ps)
......
/*
/*
* Copyright 2011 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
......@@ -957,7 +957,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
nv50_display_flip_stop(crtc);
push = evo_wait(mast, 2);
push = evo_wait(mast, 6);
if (push) {
if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment