Skip to content

Commit

Permalink
drm/nv50/disp: allocate display from driver core
Browse files Browse the repository at this point in the history
EVO channels still handled "manually", this won't be ported here, and
will instead be held off until nv50_display/nvd0_display are merged.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Nov 28, 2012
1 parent 75f8693 commit 2d0aca2
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 73 deletions.
85 changes: 20 additions & 65 deletions drivers/gpu/drm/nouveau/nv50_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include "nouveau_fence.h"

#include <core/gpuobj.h>
#include <core/class.h>

#include <subdev/timer.h>

static void nv50_display_bh(unsigned long);
Expand Down Expand Up @@ -120,64 +122,13 @@ nv50_display_init(struct drm_device *dev)
struct nouveau_device *device = nouveau_dev(dev);
struct nouveau_channel *evo;
int ret, i;
u32 val;

nv_wr32(device, 0x00610184, nv_rd32(device, 0x00614004));

/*
* I think the 0x006101XX range is some kind of main control area
* that enables things.
*/
/* CRTC? */
for (i = 0; i < 2; i++) {
val = nv_rd32(device, 0x00616100 + (i * 0x800));
nv_wr32(device, 0x00610190 + (i * 0x10), val);
val = nv_rd32(device, 0x00616104 + (i * 0x800));
nv_wr32(device, 0x00610194 + (i * 0x10), val);
val = nv_rd32(device, 0x00616108 + (i * 0x800));
nv_wr32(device, 0x00610198 + (i * 0x10), val);
val = nv_rd32(device, 0x0061610c + (i * 0x800));
nv_wr32(device, 0x0061019c + (i * 0x10), val);
}

/* DAC */
for (i = 0; i < 3; i++) {
val = nv_rd32(device, 0x0061a000 + (i * 0x800));
nv_wr32(device, 0x006101d0 + (i * 0x04), val);
}

/* SOR */
for (i = 0; i < nv50_sor_nr(dev); i++) {
val = nv_rd32(device, 0x0061c000 + (i * 0x800));
nv_wr32(device, 0x006101e0 + (i * 0x04), val);
}

/* EXT */
for (i = 0; i < 3; i++) {
val = nv_rd32(device, 0x0061e000 + (i * 0x800));
nv_wr32(device, 0x006101f0 + (i * 0x04), val);
}

for (i = 0; i < 3; i++) {
nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 |
NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001);
}

/* The precise purpose is unknown, i suspect it has something to do
* with text mode.
*/
if (nv_rd32(device, NV50_PDISPLAY_INTR_1) & 0x100) {
nv_wr32(device, NV50_PDISPLAY_INTR_1, 0x100);
nv_wr32(device, 0x006194e8, nv_rd32(device, 0x006194e8) & ~1);
if (!nv_wait(device, 0x006194e8, 2, 0)) {
NV_ERROR(drm, "timeout: (0x6194e8 & 2) != 0\n");
NV_ERROR(drm, "0x6194e8 = 0x%08x\n",
nv_rd32(device, 0x6194e8));
return -EBUSY;
}
}

for (i = 0; i < 2; i++) {
nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000);
if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i),
Expand All @@ -201,22 +152,11 @@ nv50_display_init(struct drm_device *dev)
}
}

nv_wr32(device, NV50_PDISPLAY_PIO_CTRL, 0x00000000);
nv_mask(device, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000);
nv_wr32(device, NV50_PDISPLAY_INTR_EN_0, 0x00000000);
nv_mask(device, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000);
nv_wr32(device, NV50_PDISPLAY_INTR_EN_1,
NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 |
NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 |
NV50_PDISPLAY_INTR_EN_1_CLK_UNK40);

ret = nv50_evo_init(dev);
if (ret)
return ret;
evo = nv50_display(dev)->master;

nv_wr32(device, NV50_PDISPLAY_OBJECTS, (nv50_display(dev)->ramin->addr >> 8) | 9);

ret = RING_SPACE(evo, 3);
if (ret)
return ret;
Expand Down Expand Up @@ -289,14 +229,18 @@ nv50_display_fini(struct drm_device *dev)
nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_STATE(i)));
}
}

/* disable interrupts. */
nv_wr32(device, NV50_PDISPLAY_INTR_EN_1, 0x00000000);
}

int
nv50_display_create(struct drm_device *dev)
{
static const u16 oclass[] = {
NVA3_DISP_CLASS,
NV94_DISP_CLASS,
NVA0_DISP_CLASS,
NV84_DISP_CLASS,
NV50_DISP_CLASS,
};
struct nouveau_drm *drm = nouveau_drm(dev);
struct dcb_table *dcb = &drm->vbios.dcb;
struct drm_connector *connector, *ct;
Expand All @@ -312,6 +256,17 @@ nv50_display_create(struct drm_device *dev)
nouveau_display(dev)->init = nv50_display_init;
nouveau_display(dev)->fini = nv50_display_fini;

/* attempt to allocate a supported evo display class */
ret = -ENODEV;
for (i = 0; ret && i < ARRAY_SIZE(oclass); i++) {
ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
0xd1500000, oclass[i], NULL, 0,
&priv->core);
}

if (ret)
return ret;

/* Create CRTC objects */
for (i = 0; i < 2; i++) {
ret = nv50_crtc_create(dev, i);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nv50_display.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct nv50_display_crtc {
struct nv50_display {
struct nouveau_channel *master;

struct nouveau_object *core;
struct nouveau_gpuobj *ramin;
u32 dmao;
u32 hash;
Expand Down
9 changes: 1 addition & 8 deletions drivers/gpu/drm/nouveau/nv50_evo.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,6 @@ nv50_evo_destroy(struct drm_device *dev)
nv50_evo_channel_del(&disp->crtc[i].sync);
}
nv50_evo_channel_del(&disp->master);
nouveau_gpuobj_ref(NULL, &disp->ramin);
}

int
Expand All @@ -261,13 +260,7 @@ nv50_evo_create(struct drm_device *dev)
* use this also as there's no per-channel support on the
* hardware
*/
ret = nouveau_gpuobj_new(drm->device, NULL, 32768, 65536,
NVOBJ_FLAG_ZERO_ALLOC, &disp->ramin);
if (ret) {
NV_ERROR(drm, "Error allocating EVO channel memory: %d\n", ret);
goto err;
}

disp->ramin = nv_gpuobj(disp->core->parent);
disp->hash = 0x0000;
disp->dmao = 0x1000;

Expand Down

0 comments on commit 2d0aca2

Please sign in to comment.