diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
31 files changed, 177 insertions, 104 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index d8291724dbd4..7a4e0891c5f8 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c | |||
@@ -98,6 +98,8 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, | |||
98 | u32 splitoff; | 98 | u32 splitoff; |
99 | u32 s, e; | 99 | u32 s, e; |
100 | 100 | ||
101 | BUG_ON(!type); | ||
102 | |||
101 | list_for_each_entry(this, &mm->free, fl_entry) { | 103 | list_for_each_entry(this, &mm->free, fl_entry) { |
102 | e = this->offset + this->length; | 104 | e = this->offset + this->length; |
103 | s = this->offset; | 105 | s = this->offset; |
@@ -162,6 +164,8 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, | |||
162 | struct nouveau_mm_node *prev, *this, *next; | 164 | struct nouveau_mm_node *prev, *this, *next; |
163 | u32 mask = align - 1; | 165 | u32 mask = align - 1; |
164 | 166 | ||
167 | BUG_ON(!type); | ||
168 | |||
165 | list_for_each_entry_reverse(this, &mm->free, fl_entry) { | 169 | list_for_each_entry_reverse(this, &mm->free, fl_entry) { |
166 | u32 e = this->offset + this->length; | 170 | u32 e = this->offset + this->length; |
167 | u32 s = this->offset; | 171 | u32 s = this->offset; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c index 373dbcc523b2..a19e7d79b847 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c | |||
@@ -36,6 +36,8 @@ nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size) | |||
36 | if (data && data[0]) { | 36 | if (data && data[0]) { |
37 | for (i = 0; i < size; i++) | 37 | for (i = 0; i < size; i++) |
38 | nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]); | 38 | nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]); |
39 | for (; i < 0x60; i++) | ||
40 | nv_wr32(priv, 0x61c440 + soff, (i << 8)); | ||
39 | nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003); | 41 | nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003); |
40 | } else | 42 | } else |
41 | if (data) { | 43 | if (data) { |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c index dc57e24fc1df..717639386ced 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c | |||
@@ -41,6 +41,8 @@ nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size) | |||
41 | if (data && data[0]) { | 41 | if (data && data[0]) { |
42 | for (i = 0; i < size; i++) | 42 | for (i = 0; i < size; i++) |
43 | nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]); | 43 | nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]); |
44 | for (; i < 0x60; i++) | ||
45 | nv_wr32(priv, 0x10ec00 + soff, (i << 8)); | ||
44 | nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003); | 46 | nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003); |
45 | } else | 47 | } else |
46 | if (data) { | 48 | if (data) { |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c index ab1e918469a8..526b75242899 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c | |||
@@ -47,14 +47,8 @@ int | |||
47 | nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) | 47 | nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) |
48 | { | 48 | { |
49 | struct nv50_disp_priv *priv = (void *)object->engine; | 49 | struct nv50_disp_priv *priv = (void *)object->engine; |
50 | struct nouveau_bios *bios = nouveau_bios(priv); | ||
51 | const u16 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12; | ||
52 | const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; | 50 | const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; |
53 | const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2; | ||
54 | const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR); | 51 | const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR); |
55 | const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or); | ||
56 | struct dcb_output outp; | ||
57 | u8 ver, hdr; | ||
58 | u32 data; | 52 | u32 data; |
59 | int ret = -EINVAL; | 53 | int ret = -EINVAL; |
60 | 54 | ||
@@ -62,8 +56,6 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) | |||
62 | return -EINVAL; | 56 | return -EINVAL; |
63 | data = *(u32 *)args; | 57 | data = *(u32 *)args; |
64 | 58 | ||
65 | if (type && !dcb_outp_match(bios, type, mask, &ver, &hdr, &outp)) | ||
66 | return -ENODEV; | ||
67 | 59 | ||
68 | switch (mthd & ~0x3f) { | 60 | switch (mthd & ~0x3f) { |
69 | case NV50_DISP_SOR_PWR: | 61 | case NV50_DISP_SOR_PWR: |
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 49ecbb859b25..c19004301309 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c | |||
@@ -265,8 +265,8 @@ nv31_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
265 | int | 265 | int |
266 | nv31_mpeg_init(struct nouveau_object *object) | 266 | nv31_mpeg_init(struct nouveau_object *object) |
267 | { | 267 | { |
268 | struct nouveau_engine *engine = nv_engine(object->engine); | 268 | struct nouveau_engine *engine = nv_engine(object); |
269 | struct nv31_mpeg_priv *priv = (void *)engine; | 269 | struct nv31_mpeg_priv *priv = (void *)object; |
270 | struct nouveau_fb *pfb = nouveau_fb(object); | 270 | struct nouveau_fb *pfb = nouveau_fb(object); |
271 | int ret, i; | 271 | int ret, i; |
272 | 272 | ||
@@ -284,7 +284,10 @@ nv31_mpeg_init(struct nouveau_object *object) | |||
284 | /* PMPEG init */ | 284 | /* PMPEG init */ |
285 | nv_wr32(priv, 0x00b32c, 0x00000000); | 285 | nv_wr32(priv, 0x00b32c, 0x00000000); |
286 | nv_wr32(priv, 0x00b314, 0x00000100); | 286 | nv_wr32(priv, 0x00b314, 0x00000100); |
287 | nv_wr32(priv, 0x00b220, nv44_graph_class(priv) ? 0x00000044 : 0x00000031); | 287 | if (nv_device(priv)->chipset >= 0x40 && nv44_graph_class(priv)) |
288 | nv_wr32(priv, 0x00b220, 0x00000044); | ||
289 | else | ||
290 | nv_wr32(priv, 0x00b220, 0x00000031); | ||
288 | nv_wr32(priv, 0x00b300, 0x02001ec1); | 291 | nv_wr32(priv, 0x00b300, 0x02001ec1); |
289 | nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); | 292 | nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); |
290 | 293 | ||
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c index f7c581ad1991..dd6196072e9c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c | |||
@@ -61,6 +61,7 @@ nv40_mpeg_context_ctor(struct nouveau_object *parent, | |||
61 | if (ret) | 61 | if (ret) |
62 | return ret; | 62 | return ret; |
63 | 63 | ||
64 | nv_wo32(&chan->base.base, 0x78, 0x02001ec1); | ||
64 | return 0; | 65 | return 0; |
65 | } | 66 | } |
66 | 67 | ||
diff --git a/drivers/gpu/drm/nouveau/core/engine/xtensa.c b/drivers/gpu/drm/nouveau/core/engine/xtensa.c index 0639bc59d0a5..5f6ede7c4892 100644 --- a/drivers/gpu/drm/nouveau/core/engine/xtensa.c +++ b/drivers/gpu/drm/nouveau/core/engine/xtensa.c | |||
@@ -118,7 +118,13 @@ _nouveau_xtensa_init(struct nouveau_object *object) | |||
118 | return ret; | 118 | return ret; |
119 | } | 119 | } |
120 | 120 | ||
121 | ret = nouveau_gpuobj_new(object, NULL, fw->size, 0x1000, 0, | 121 | if (fw->size > 0x40000) { |
122 | nv_warn(xtensa, "firmware %s too large\n", name); | ||
123 | release_firmware(fw); | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | |||
127 | ret = nouveau_gpuobj_new(object, NULL, 0x40000, 0x1000, 0, | ||
122 | &xtensa->gpu_fw); | 128 | &xtensa->gpu_fw); |
123 | if (ret) { | 129 | if (ret) { |
124 | release_firmware(fw); | 130 | release_firmware(fw); |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index d5502267c30f..9d2cd2006250 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h | |||
@@ -20,8 +20,8 @@ nouveau_mc(void *obj) | |||
20 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC]; | 20 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC]; |
21 | } | 21 | } |
22 | 22 | ||
23 | #define nouveau_mc_create(p,e,o,d) \ | 23 | #define nouveau_mc_create(p,e,o,m,d) \ |
24 | nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d) | 24 | nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d) |
25 | #define nouveau_mc_destroy(p) ({ \ | 25 | #define nouveau_mc_destroy(p) ({ \ |
26 | struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \ | 26 | struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \ |
27 | }) | 27 | }) |
@@ -33,7 +33,8 @@ nouveau_mc(void *obj) | |||
33 | }) | 33 | }) |
34 | 34 | ||
35 | int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *, | 35 | int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *, |
36 | struct nouveau_oclass *, int, void **); | 36 | struct nouveau_oclass *, const struct nouveau_mc_intr *, |
37 | int, void **); | ||
37 | void _nouveau_mc_dtor(struct nouveau_object *); | 38 | void _nouveau_mc_dtor(struct nouveau_object *); |
38 | int _nouveau_mc_init(struct nouveau_object *); | 39 | int _nouveau_mc_init(struct nouveau_object *); |
39 | int _nouveau_mc_fini(struct nouveau_object *, bool); | 40 | int _nouveau_mc_fini(struct nouveau_object *, bool); |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index f2e87b105666..fcf57fa309bf 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h | |||
@@ -55,7 +55,7 @@ struct nouveau_vma { | |||
55 | struct nouveau_vm { | 55 | struct nouveau_vm { |
56 | struct nouveau_vmmgr *vmm; | 56 | struct nouveau_vmmgr *vmm; |
57 | struct nouveau_mm mm; | 57 | struct nouveau_mm mm; |
58 | int refcount; | 58 | struct kref refcount; |
59 | 59 | ||
60 | struct list_head pgd_list; | 60 | struct list_head pgd_list; |
61 | atomic_t engref[NVDEV_SUBDEV_NR]; | 61 | atomic_t engref[NVDEV_SUBDEV_NR]; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h index 6c974dd83e8b..db9d6ddde52c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h | |||
@@ -81,7 +81,7 @@ void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); | |||
81 | void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, | 81 | void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, |
82 | u32 pitch, u32 flags, struct nouveau_fb_tile *); | 82 | u32 pitch, u32 flags, struct nouveau_fb_tile *); |
83 | 83 | ||
84 | void nv50_ram_put(struct nouveau_fb *, struct nouveau_mem **); | 84 | void __nv50_ram_put(struct nouveau_fb *, struct nouveau_mem *); |
85 | extern int nv50_fb_memtype[0x80]; | 85 | extern int nv50_fb_memtype[0x80]; |
86 | 86 | ||
87 | #endif | 87 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c index 19e3a9a63a02..ab7ef0ac9e34 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c | |||
@@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, | |||
40 | return ret; | 40 | return ret; |
41 | 41 | ||
42 | switch (pfb914 & 0x00000003) { | 42 | switch (pfb914 & 0x00000003) { |
43 | case 0x00000000: pfb->ram->type = NV_MEM_TYPE_DDR1; break; | 43 | case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break; |
44 | case 0x00000001: pfb->ram->type = NV_MEM_TYPE_DDR2; break; | 44 | case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break; |
45 | case 0x00000002: pfb->ram->type = NV_MEM_TYPE_GDDR3; break; | 45 | case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break; |
46 | case 0x00000003: break; | 46 | case 0x00000003: break; |
47 | } | 47 | } |
48 | 48 | ||
49 | pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; | 49 | ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; |
50 | pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; | 50 | ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; |
51 | pfb->ram->tags = nv_rd32(pfb, 0x100320); | 51 | ram->tags = nv_rd32(pfb, 0x100320); |
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
54 | 54 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c index 7192aa6e5577..63a6aab86028 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c | |||
@@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, | |||
38 | if (ret) | 38 | if (ret) |
39 | return ret; | 39 | return ret; |
40 | 40 | ||
41 | pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; | 41 | ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; |
42 | pfb->ram->type = NV_MEM_TYPE_STOLEN; | 42 | ram->type = NV_MEM_TYPE_STOLEN; |
43 | return 0; | 43 | return 0; |
44 | } | 44 | } |
45 | 45 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c index af5aa7ee8ad9..903baff77fdd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c | |||
@@ -27,17 +27,10 @@ | |||
27 | #include "priv.h" | 27 | #include "priv.h" |
28 | 28 | ||
29 | void | 29 | void |
30 | nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | 30 | __nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem *mem) |
31 | { | 31 | { |
32 | struct nouveau_mm_node *this; | 32 | struct nouveau_mm_node *this; |
33 | struct nouveau_mem *mem; | ||
34 | 33 | ||
35 | mem = *pmem; | ||
36 | *pmem = NULL; | ||
37 | if (unlikely(mem == NULL)) | ||
38 | return; | ||
39 | |||
40 | mutex_lock(&pfb->base.mutex); | ||
41 | while (!list_empty(&mem->regions)) { | 34 | while (!list_empty(&mem->regions)) { |
42 | this = list_first_entry(&mem->regions, typeof(*this), rl_entry); | 35 | this = list_first_entry(&mem->regions, typeof(*this), rl_entry); |
43 | 36 | ||
@@ -46,6 +39,19 @@ nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | |||
46 | } | 39 | } |
47 | 40 | ||
48 | nouveau_mm_free(&pfb->tags, &mem->tag); | 41 | nouveau_mm_free(&pfb->tags, &mem->tag); |
42 | } | ||
43 | |||
44 | void | ||
45 | nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | ||
46 | { | ||
47 | struct nouveau_mem *mem = *pmem; | ||
48 | |||
49 | *pmem = NULL; | ||
50 | if (unlikely(mem == NULL)) | ||
51 | return; | ||
52 | |||
53 | mutex_lock(&pfb->base.mutex); | ||
54 | __nv50_ram_put(pfb, mem); | ||
49 | mutex_unlock(&pfb->base.mutex); | 55 | mutex_unlock(&pfb->base.mutex); |
50 | 56 | ||
51 | kfree(mem); | 57 | kfree(mem); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c index 9c3634acbb9d..cf97c4de4a6b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c | |||
@@ -33,11 +33,19 @@ void | |||
33 | nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | 33 | nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) |
34 | { | 34 | { |
35 | struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb); | 35 | struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb); |
36 | struct nouveau_mem *mem = *pmem; | ||
36 | 37 | ||
37 | if ((*pmem)->tag) | 38 | *pmem = NULL; |
38 | ltcg->tags_free(ltcg, &(*pmem)->tag); | 39 | if (unlikely(mem == NULL)) |
40 | return; | ||
39 | 41 | ||
40 | nv50_ram_put(pfb, pmem); | 42 | mutex_lock(&pfb->base.mutex); |
43 | if (mem->tag) | ||
44 | ltcg->tags_free(ltcg, &mem->tag); | ||
45 | __nv50_ram_put(pfb, mem); | ||
46 | mutex_unlock(&pfb->base.mutex); | ||
47 | |||
48 | kfree(mem); | ||
41 | } | 49 | } |
42 | 50 | ||
43 | int | 51 | int |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index bf489dcf46e2..c4c1d415e7fe 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c | |||
@@ -103,7 +103,7 @@ nv50_gpio_intr(struct nouveau_subdev *subdev) | |||
103 | int i; | 103 | int i; |
104 | 104 | ||
105 | intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); | 105 | intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); |
106 | if (nv_device(priv)->chipset >= 0x90) | 106 | if (nv_device(priv)->chipset > 0x92) |
107 | intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070); | 107 | intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070); |
108 | 108 | ||
109 | hi = (intr0 & 0x0000ffff) | (intr1 << 16); | 109 | hi = (intr0 & 0x0000ffff) | (intr1 << 16); |
@@ -115,7 +115,7 @@ nv50_gpio_intr(struct nouveau_subdev *subdev) | |||
115 | } | 115 | } |
116 | 116 | ||
117 | nv_wr32(priv, 0xe054, intr0); | 117 | nv_wr32(priv, 0xe054, intr0); |
118 | if (nv_device(priv)->chipset >= 0x90) | 118 | if (nv_device(priv)->chipset > 0x92) |
119 | nv_wr32(priv, 0xe074, intr1); | 119 | nv_wr32(priv, 0xe074, intr1); |
120 | } | 120 | } |
121 | 121 | ||
@@ -146,7 +146,7 @@ nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
146 | int ret; | 146 | int ret; |
147 | 147 | ||
148 | ret = nouveau_gpio_create(parent, engine, oclass, | 148 | ret = nouveau_gpio_create(parent, engine, oclass, |
149 | nv_device(parent)->chipset >= 0x90 ? 32 : 16, | 149 | nv_device(parent)->chipset > 0x92 ? 32 : 16, |
150 | &priv); | 150 | &priv); |
151 | *pobject = nv_object(priv); | 151 | *pobject = nv_object(priv); |
152 | if (ret) | 152 | if (ret) |
@@ -182,7 +182,7 @@ nv50_gpio_init(struct nouveau_object *object) | |||
182 | /* disable, and ack any pending gpio interrupts */ | 182 | /* disable, and ack any pending gpio interrupts */ |
183 | nv_wr32(priv, 0xe050, 0x00000000); | 183 | nv_wr32(priv, 0xe050, 0x00000000); |
184 | nv_wr32(priv, 0xe054, 0xffffffff); | 184 | nv_wr32(priv, 0xe054, 0xffffffff); |
185 | if (nv_device(priv)->chipset >= 0x90) { | 185 | if (nv_device(priv)->chipset > 0x92) { |
186 | nv_wr32(priv, 0xe070, 0x00000000); | 186 | nv_wr32(priv, 0xe070, 0x00000000); |
187 | nv_wr32(priv, 0xe074, 0xffffffff); | 187 | nv_wr32(priv, 0xe074, 0xffffffff); |
188 | } | 188 | } |
@@ -195,7 +195,7 @@ nv50_gpio_fini(struct nouveau_object *object, bool suspend) | |||
195 | { | 195 | { |
196 | struct nv50_gpio_priv *priv = (void *)object; | 196 | struct nv50_gpio_priv *priv = (void *)object; |
197 | nv_wr32(priv, 0xe050, 0x00000000); | 197 | nv_wr32(priv, 0xe050, 0x00000000); |
198 | if (nv_device(priv)->chipset >= 0x90) | 198 | if (nv_device(priv)->chipset > 0x92) |
199 | nv_wr32(priv, 0xe070, 0x00000000); | 199 | nv_wr32(priv, 0xe070, 0x00000000); |
200 | return nouveau_gpio_fini(&priv->base, suspend); | 200 | return nouveau_gpio_fini(&priv->base, suspend); |
201 | } | 201 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c index bcca883018f4..cce65cc56514 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | |||
@@ -30,8 +30,9 @@ struct nvc0_ltcg_priv { | |||
30 | struct nouveau_ltcg base; | 30 | struct nouveau_ltcg base; |
31 | u32 part_nr; | 31 | u32 part_nr; |
32 | u32 subp_nr; | 32 | u32 subp_nr; |
33 | struct nouveau_mm tags; | ||
34 | u32 num_tags; | 33 | u32 num_tags; |
34 | u32 tag_base; | ||
35 | struct nouveau_mm tags; | ||
35 | struct nouveau_mm_node *tag_ram; | 36 | struct nouveau_mm_node *tag_ram; |
36 | }; | 37 | }; |
37 | 38 | ||
@@ -117,10 +118,6 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) | |||
117 | u32 tag_size, tag_margin, tag_align; | 118 | u32 tag_size, tag_margin, tag_align; |
118 | int ret; | 119 | int ret; |
119 | 120 | ||
120 | nv_wr32(priv, 0x17e8d8, priv->part_nr); | ||
121 | if (nv_device(pfb)->card_type >= NV_E0) | ||
122 | nv_wr32(priv, 0x17e000, priv->part_nr); | ||
123 | |||
124 | /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ | 121 | /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ |
125 | priv->num_tags = (pfb->ram->size >> 17) / 4; | 122 | priv->num_tags = (pfb->ram->size >> 17) / 4; |
126 | if (priv->num_tags > (1 << 17)) | 123 | if (priv->num_tags > (1 << 17)) |
@@ -142,7 +139,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) | |||
142 | tag_size += tag_align; | 139 | tag_size += tag_align; |
143 | tag_size = (tag_size + 0xfff) >> 12; /* round up */ | 140 | tag_size = (tag_size + 0xfff) >> 12; /* round up */ |
144 | 141 | ||
145 | ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1, | 142 | ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1, |
146 | &priv->tag_ram); | 143 | &priv->tag_ram); |
147 | if (ret) { | 144 | if (ret) { |
148 | priv->num_tags = 0; | 145 | priv->num_tags = 0; |
@@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) | |||
152 | tag_base += tag_align - 1; | 149 | tag_base += tag_align - 1; |
153 | ret = do_div(tag_base, tag_align); | 150 | ret = do_div(tag_base, tag_align); |
154 | 151 | ||
155 | nv_wr32(priv, 0x17e8d4, tag_base); | 152 | priv->tag_base = tag_base; |
156 | } | 153 | } |
157 | ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1); | 154 | ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1); |
158 | 155 | ||
@@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
182 | } | 179 | } |
183 | priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; | 180 | priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; |
184 | 181 | ||
185 | nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ | ||
186 | |||
187 | ret = nvc0_ltcg_init_tag_ram(pfb, priv); | 182 | ret = nvc0_ltcg_init_tag_ram(pfb, priv); |
188 | if (ret) | 183 | if (ret) |
189 | return ret; | 184 | return ret; |
@@ -209,13 +204,32 @@ nvc0_ltcg_dtor(struct nouveau_object *object) | |||
209 | nouveau_ltcg_destroy(ltcg); | 204 | nouveau_ltcg_destroy(ltcg); |
210 | } | 205 | } |
211 | 206 | ||
207 | static int | ||
208 | nvc0_ltcg_init(struct nouveau_object *object) | ||
209 | { | ||
210 | struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; | ||
211 | struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; | ||
212 | int ret; | ||
213 | |||
214 | ret = nouveau_ltcg_init(ltcg); | ||
215 | if (ret) | ||
216 | return ret; | ||
217 | |||
218 | nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ | ||
219 | nv_wr32(priv, 0x17e8d8, priv->part_nr); | ||
220 | if (nv_device(ltcg)->card_type >= NV_E0) | ||
221 | nv_wr32(priv, 0x17e000, priv->part_nr); | ||
222 | nv_wr32(priv, 0x17e8d4, priv->tag_base); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
212 | struct nouveau_oclass | 226 | struct nouveau_oclass |
213 | nvc0_ltcg_oclass = { | 227 | nvc0_ltcg_oclass = { |
214 | .handle = NV_SUBDEV(LTCG, 0xc0), | 228 | .handle = NV_SUBDEV(LTCG, 0xc0), |
215 | .ofuncs = &(struct nouveau_ofuncs) { | 229 | .ofuncs = &(struct nouveau_ofuncs) { |
216 | .ctor = nvc0_ltcg_ctor, | 230 | .ctor = nvc0_ltcg_ctor, |
217 | .dtor = nvc0_ltcg_dtor, | 231 | .dtor = nvc0_ltcg_dtor, |
218 | .init = _nouveau_ltcg_init, | 232 | .init = nvc0_ltcg_init, |
219 | .fini = _nouveau_ltcg_fini, | 233 | .fini = _nouveau_ltcg_fini, |
220 | }, | 234 | }, |
221 | }; | 235 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c index 2e7c5fd3de3d..20f9a538746e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c | |||
@@ -86,7 +86,9 @@ _nouveau_mc_dtor(struct nouveau_object *object) | |||
86 | 86 | ||
87 | int | 87 | int |
88 | nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, | 88 | nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, |
89 | struct nouveau_oclass *oclass, int length, void **pobject) | 89 | struct nouveau_oclass *oclass, |
90 | const struct nouveau_mc_intr *intr_map, | ||
91 | int length, void **pobject) | ||
90 | { | 92 | { |
91 | struct nouveau_device *device = nv_device(parent); | 93 | struct nouveau_device *device = nv_device(parent); |
92 | struct nouveau_mc *pmc; | 94 | struct nouveau_mc *pmc; |
@@ -98,6 +100,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, | |||
98 | if (ret) | 100 | if (ret) |
99 | return ret; | 101 | return ret; |
100 | 102 | ||
103 | pmc->intr_map = intr_map; | ||
104 | |||
101 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, | 105 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, |
102 | IRQF_SHARED, "nouveau", pmc); | 106 | IRQF_SHARED, "nouveau", pmc); |
103 | if (ret < 0) | 107 | if (ret < 0) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c index 8c769715227b..64aa4edb0d9d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c | |||
@@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
50 | struct nv04_mc_priv *priv; | 50 | struct nv04_mc_priv *priv; |
51 | int ret; | 51 | int ret; |
52 | 52 | ||
53 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 53 | ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv); |
54 | *pobject = nv_object(priv); | 54 | *pobject = nv_object(priv); |
55 | if (ret) | 55 | if (ret) |
56 | return ret; | 56 | return ret; |
57 | 57 | ||
58 | priv->base.intr_map = nv04_mc_intr; | ||
59 | return 0; | 58 | return 0; |
60 | } | 59 | } |
61 | 60 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c index 51919371810f..d9891782bf28 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c | |||
@@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
36 | struct nv44_mc_priv *priv; | 36 | struct nv44_mc_priv *priv; |
37 | int ret; | 37 | int ret; |
38 | 38 | ||
39 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 39 | ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv); |
40 | *pobject = nv_object(priv); | 40 | *pobject = nv_object(priv); |
41 | if (ret) | 41 | if (ret) |
42 | return ret; | 42 | return ret; |
43 | 43 | ||
44 | priv->base.intr_map = nv04_mc_intr; | ||
45 | return 0; | 44 | return 0; |
46 | } | 45 | } |
47 | 46 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c index 0cb322a5e72c..2b1afe225db8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c | |||
@@ -41,7 +41,7 @@ nv50_mc_intr[] = { | |||
41 | { 0x04000000, NVDEV_ENGINE_DISP }, | 41 | { 0x04000000, NVDEV_ENGINE_DISP }, |
42 | { 0x10000000, NVDEV_SUBDEV_BUS }, | 42 | { 0x10000000, NVDEV_SUBDEV_BUS }, |
43 | { 0x80000000, NVDEV_ENGINE_SW }, | 43 | { 0x80000000, NVDEV_ENGINE_SW }, |
44 | { 0x0000d101, NVDEV_SUBDEV_FB }, | 44 | { 0x0002d101, NVDEV_SUBDEV_FB }, |
45 | {}, | 45 | {}, |
46 | }; | 46 | }; |
47 | 47 | ||
@@ -53,12 +53,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
53 | struct nv50_mc_priv *priv; | 53 | struct nv50_mc_priv *priv; |
54 | int ret; | 54 | int ret; |
55 | 55 | ||
56 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 56 | ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv); |
57 | *pobject = nv_object(priv); | 57 | *pobject = nv_object(priv); |
58 | if (ret) | 58 | if (ret) |
59 | return ret; | 59 | return ret; |
60 | 60 | ||
61 | priv->base.intr_map = nv50_mc_intr; | ||
62 | return 0; | 61 | return 0; |
63 | } | 62 | } |
64 | 63 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c index e82fd21b5041..0d57b4d3e001 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c | |||
@@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
54 | struct nv98_mc_priv *priv; | 54 | struct nv98_mc_priv *priv; |
55 | int ret; | 55 | int ret; |
56 | 56 | ||
57 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 57 | ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv); |
58 | *pobject = nv_object(priv); | 58 | *pobject = nv_object(priv); |
59 | if (ret) | 59 | if (ret) |
60 | return ret; | 60 | return ret; |
61 | 61 | ||
62 | priv->base.intr_map = nv98_mc_intr; | ||
63 | return 0; | 62 | return 0; |
64 | } | 63 | } |
65 | 64 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index c5da3babbc62..104175c5a2dd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c | |||
@@ -57,12 +57,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
57 | struct nvc0_mc_priv *priv; | 57 | struct nvc0_mc_priv *priv; |
58 | int ret; | 58 | int ret; |
59 | 59 | ||
60 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 60 | ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv); |
61 | *pobject = nv_object(priv); | 61 | *pobject = nv_object(priv); |
62 | if (ret) | 62 | if (ret) |
63 | return ret; | 63 | return ret; |
64 | 64 | ||
65 | priv->base.intr_map = nvc0_mc_intr; | ||
66 | return 0; | 65 | return 0; |
67 | } | 66 | } |
68 | 67 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 67fcb6c852ac..ef3133e7575c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c | |||
@@ -361,7 +361,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, | |||
361 | 361 | ||
362 | INIT_LIST_HEAD(&vm->pgd_list); | 362 | INIT_LIST_HEAD(&vm->pgd_list); |
363 | vm->vmm = vmm; | 363 | vm->vmm = vmm; |
364 | vm->refcount = 1; | 364 | kref_init(&vm->refcount); |
365 | vm->fpde = offset >> (vmm->pgt_bits + 12); | 365 | vm->fpde = offset >> (vmm->pgt_bits + 12); |
366 | vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12); | 366 | vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12); |
367 | 367 | ||
@@ -441,8 +441,9 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) | |||
441 | } | 441 | } |
442 | 442 | ||
443 | static void | 443 | static void |
444 | nouveau_vm_del(struct nouveau_vm *vm) | 444 | nouveau_vm_del(struct kref *kref) |
445 | { | 445 | { |
446 | struct nouveau_vm *vm = container_of(kref, typeof(*vm), refcount); | ||
446 | struct nouveau_vm_pgd *vpgd, *tmp; | 447 | struct nouveau_vm_pgd *vpgd, *tmp; |
447 | 448 | ||
448 | list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { | 449 | list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { |
@@ -458,27 +459,19 @@ int | |||
458 | nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, | 459 | nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, |
459 | struct nouveau_gpuobj *pgd) | 460 | struct nouveau_gpuobj *pgd) |
460 | { | 461 | { |
461 | struct nouveau_vm *vm; | 462 | if (ref) { |
462 | int ret; | 463 | int ret = nouveau_vm_link(ref, pgd); |
463 | |||
464 | vm = ref; | ||
465 | if (vm) { | ||
466 | ret = nouveau_vm_link(vm, pgd); | ||
467 | if (ret) | 464 | if (ret) |
468 | return ret; | 465 | return ret; |
469 | 466 | ||
470 | vm->refcount++; | 467 | kref_get(&ref->refcount); |
471 | } | 468 | } |
472 | 469 | ||
473 | vm = *ptr; | 470 | if (*ptr) { |
474 | *ptr = ref; | 471 | nouveau_vm_unlink(*ptr, pgd); |
475 | 472 | kref_put(&(*ptr)->refcount, nouveau_vm_del); | |
476 | if (vm) { | ||
477 | nouveau_vm_unlink(vm, pgd); | ||
478 | |||
479 | if (--vm->refcount == 0) | ||
480 | nouveau_vm_del(vm); | ||
481 | } | 473 | } |
482 | 474 | ||
475 | *ptr = ref; | ||
483 | return 0; | 476 | return 0; |
484 | } | 477 | } |
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 6413552df21c..d4fbf11360fe 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c | |||
@@ -607,6 +607,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | |||
607 | regp->ramdac_a34 = 0x1; | 607 | regp->ramdac_a34 = 0x1; |
608 | } | 608 | } |
609 | 609 | ||
610 | static int | ||
611 | nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) | ||
612 | { | ||
613 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
614 | struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); | ||
615 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||
616 | int ret; | ||
617 | |||
618 | ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); | ||
619 | if (ret == 0) { | ||
620 | if (disp->image[nv_crtc->index]) | ||
621 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
622 | nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]); | ||
623 | } | ||
624 | |||
625 | return ret; | ||
626 | } | ||
627 | |||
610 | /** | 628 | /** |
611 | * Sets up registers for the given mode/adjusted_mode pair. | 629 | * Sets up registers for the given mode/adjusted_mode pair. |
612 | * | 630 | * |
@@ -623,10 +641,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
623 | struct drm_device *dev = crtc->dev; | 641 | struct drm_device *dev = crtc->dev; |
624 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 642 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
625 | struct nouveau_drm *drm = nouveau_drm(dev); | 643 | struct nouveau_drm *drm = nouveau_drm(dev); |
644 | int ret; | ||
626 | 645 | ||
627 | NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); | 646 | NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); |
628 | drm_mode_debug_printmodeline(adjusted_mode); | 647 | drm_mode_debug_printmodeline(adjusted_mode); |
629 | 648 | ||
649 | ret = nv_crtc_swap_fbs(crtc, old_fb); | ||
650 | if (ret) | ||
651 | return ret; | ||
652 | |||
630 | /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ | 653 | /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ |
631 | nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1); | 654 | nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1); |
632 | 655 | ||
@@ -723,6 +746,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc) | |||
723 | 746 | ||
724 | static void nv_crtc_destroy(struct drm_crtc *crtc) | 747 | static void nv_crtc_destroy(struct drm_crtc *crtc) |
725 | { | 748 | { |
749 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
726 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 750 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
727 | 751 | ||
728 | if (!nv_crtc) | 752 | if (!nv_crtc) |
@@ -730,6 +754,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) | |||
730 | 754 | ||
731 | drm_crtc_cleanup(crtc); | 755 | drm_crtc_cleanup(crtc); |
732 | 756 | ||
757 | if (disp->image[nv_crtc->index]) | ||
758 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
759 | nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]); | ||
760 | |||
733 | nouveau_bo_unmap(nv_crtc->cursor.nvbo); | 761 | nouveau_bo_unmap(nv_crtc->cursor.nvbo); |
734 | nouveau_bo_unpin(nv_crtc->cursor.nvbo); | 762 | nouveau_bo_unpin(nv_crtc->cursor.nvbo); |
735 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); | 763 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); |
@@ -755,6 +783,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) | |||
755 | } | 783 | } |
756 | 784 | ||
757 | static void | 785 | static void |
786 | nv_crtc_disable(struct drm_crtc *crtc) | ||
787 | { | ||
788 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
789 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||
790 | if (disp->image[nv_crtc->index]) | ||
791 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
792 | nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]); | ||
793 | } | ||
794 | |||
795 | static void | ||
758 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, | 796 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, |
759 | uint32_t size) | 797 | uint32_t size) |
760 | { | 798 | { |
@@ -792,7 +830,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
792 | struct drm_framebuffer *drm_fb; | 830 | struct drm_framebuffer *drm_fb; |
793 | struct nouveau_framebuffer *fb; | 831 | struct nouveau_framebuffer *fb; |
794 | int arb_burst, arb_lwm; | 832 | int arb_burst, arb_lwm; |
795 | int ret; | ||
796 | 833 | ||
797 | NV_DEBUG(drm, "index %d\n", nv_crtc->index); | 834 | NV_DEBUG(drm, "index %d\n", nv_crtc->index); |
798 | 835 | ||
@@ -802,10 +839,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
802 | return 0; | 839 | return 0; |
803 | } | 840 | } |
804 | 841 | ||
805 | |||
806 | /* If atomic, we want to switch to the fb we were passed, so | 842 | /* If atomic, we want to switch to the fb we were passed, so |
807 | * now we update pointers to do that. (We don't pin; just | 843 | * now we update pointers to do that. |
808 | * assume we're already pinned and update the base address.) | ||
809 | */ | 844 | */ |
810 | if (atomic) { | 845 | if (atomic) { |
811 | drm_fb = passed_fb; | 846 | drm_fb = passed_fb; |
@@ -813,17 +848,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
813 | } else { | 848 | } else { |
814 | drm_fb = crtc->fb; | 849 | drm_fb = crtc->fb; |
815 | fb = nouveau_framebuffer(crtc->fb); | 850 | fb = nouveau_framebuffer(crtc->fb); |
816 | /* If not atomic, we can go ahead and pin, and unpin the | ||
817 | * old fb we were passed. | ||
818 | */ | ||
819 | ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); | ||
820 | if (ret) | ||
821 | return ret; | ||
822 | |||
823 | if (passed_fb) { | ||
824 | struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb); | ||
825 | nouveau_bo_unpin(ofb->nvbo); | ||
826 | } | ||
827 | } | 851 | } |
828 | 852 | ||
829 | nv_crtc->fb.offset = fb->nvbo->bo.offset; | 853 | nv_crtc->fb.offset = fb->nvbo->bo.offset; |
@@ -878,6 +902,9 @@ static int | |||
878 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | 902 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, |
879 | struct drm_framebuffer *old_fb) | 903 | struct drm_framebuffer *old_fb) |
880 | { | 904 | { |
905 | int ret = nv_crtc_swap_fbs(crtc, old_fb); | ||
906 | if (ret) | ||
907 | return ret; | ||
881 | return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); | 908 | return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); |
882 | } | 909 | } |
883 | 910 | ||
@@ -1074,6 +1101,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { | |||
1074 | .mode_set_base = nv04_crtc_mode_set_base, | 1101 | .mode_set_base = nv04_crtc_mode_set_base, |
1075 | .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, | 1102 | .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, |
1076 | .load_lut = nv_crtc_gamma_load, | 1103 | .load_lut = nv_crtc_gamma_load, |
1104 | .disable = nv_crtc_disable, | ||
1077 | }; | 1105 | }; |
1078 | 1106 | ||
1079 | int | 1107 | int |
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index a0a031dad13f..9928187f0a7d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h | |||
@@ -81,6 +81,7 @@ struct nv04_display { | |||
81 | uint32_t saved_vga_font[4][16384]; | 81 | uint32_t saved_vga_font[4][16384]; |
82 | uint32_t dac_users[4]; | 82 | uint32_t dac_users[4]; |
83 | struct nouveau_object *core; | 83 | struct nouveau_object *core; |
84 | struct nouveau_bo *image[2]; | ||
84 | }; | 85 | }; |
85 | 86 | ||
86 | static inline struct nv04_display * | 87 | static inline struct nv04_display * |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e4444bacd0b2..755c38d06271 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -198,7 +198,12 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, | |||
198 | size_t acc_size; | 198 | size_t acc_size; |
199 | int ret; | 199 | int ret; |
200 | int type = ttm_bo_type_device; | 200 | int type = ttm_bo_type_device; |
201 | int max_size = INT_MAX & ~((1 << drm->client.base.vm->vmm->lpg_shift) - 1); | 201 | int lpg_shift = 12; |
202 | int max_size; | ||
203 | |||
204 | if (drm->client.base.vm) | ||
205 | lpg_shift = drm->client.base.vm->vmm->lpg_shift; | ||
206 | max_size = INT_MAX & ~((1 << lpg_shift) - 1); | ||
202 | 207 | ||
203 | if (size <= 0 || size > max_size) { | 208 | if (size <= 0 || size > max_size) { |
204 | nv_warn(drm, "skipped size %x\n", (u32)size); | 209 | nv_warn(drm, "skipped size %x\n", (u32)size); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 44202bf7b819..77ffded68837 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -580,6 +580,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
580 | ret = nv50_display_flip_next(crtc, fb, chan, 0); | 580 | ret = nv50_display_flip_next(crtc, fb, chan, 0); |
581 | if (ret) | 581 | if (ret) |
582 | goto fail_unreserve; | 582 | goto fail_unreserve; |
583 | } else { | ||
584 | struct nv04_display *dispnv04 = nv04_display(dev); | ||
585 | nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]); | ||
583 | } | 586 | } |
584 | 587 | ||
585 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); | 588 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 4c1bc061fae2..8f6d63d7edd3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -398,7 +398,8 @@ void | |||
398 | nouveau_fbcon_output_poll_changed(struct drm_device *dev) | 398 | nouveau_fbcon_output_poll_changed(struct drm_device *dev) |
399 | { | 399 | { |
400 | struct nouveau_drm *drm = nouveau_drm(dev); | 400 | struct nouveau_drm *drm = nouveau_drm(dev); |
401 | drm_fb_helper_hotplug_event(&drm->fbcon->helper); | 401 | if (drm->fbcon) |
402 | drm_fb_helper_hotplug_event(&drm->fbcon->helper); | ||
402 | } | 403 | } |
403 | 404 | ||
404 | static int | 405 | static int |
diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c index 8e47a9bae8c3..22aa9963ea6f 100644 --- a/drivers/gpu/drm/nouveau/nv17_fence.c +++ b/drivers/gpu/drm/nouveau/nv17_fence.c | |||
@@ -76,7 +76,7 @@ nv17_fence_context_new(struct nouveau_channel *chan) | |||
76 | struct ttm_mem_reg *mem = &priv->bo->bo.mem; | 76 | struct ttm_mem_reg *mem = &priv->bo->bo.mem; |
77 | struct nouveau_object *object; | 77 | struct nouveau_object *object; |
78 | u32 start = mem->start * PAGE_SIZE; | 78 | u32 start = mem->start * PAGE_SIZE; |
79 | u32 limit = mem->start + mem->size - 1; | 79 | u32 limit = start + mem->size - 1; |
80 | int ret = 0; | 80 | int ret = 0; |
81 | 81 | ||
82 | fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); | 82 | fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); |
diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index 3af5bcd0b203..625f80d53dc2 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c | |||
@@ -131,7 +131,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, | |||
131 | if (clk < pll->vco1.max_freq) | 131 | if (clk < pll->vco1.max_freq) |
132 | pll->vco2.max_freq = 0; | 132 | pll->vco2.max_freq = 0; |
133 | 133 | ||
134 | pclk->pll_calc(pclk, pll, clk, &coef); | 134 | ret = pclk->pll_calc(pclk, pll, clk, &coef); |
135 | if (ret == 0) | 135 | if (ret == 0) |
136 | return -ERANGE; | 136 | return -ERANGE; |
137 | 137 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index f9701e567db8..0ee363840035 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c | |||
@@ -39,6 +39,8 @@ nv50_fence_context_new(struct nouveau_channel *chan) | |||
39 | struct nv10_fence_chan *fctx; | 39 | struct nv10_fence_chan *fctx; |
40 | struct ttm_mem_reg *mem = &priv->bo->bo.mem; | 40 | struct ttm_mem_reg *mem = &priv->bo->bo.mem; |
41 | struct nouveau_object *object; | 41 | struct nouveau_object *object; |
42 | u32 start = mem->start * PAGE_SIZE; | ||
43 | u32 limit = start + mem->size - 1; | ||
42 | int ret, i; | 44 | int ret, i; |
43 | 45 | ||
44 | fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); | 46 | fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); |
@@ -51,26 +53,28 @@ nv50_fence_context_new(struct nouveau_channel *chan) | |||
51 | fctx->base.sync = nv17_fence_sync; | 53 | fctx->base.sync = nv17_fence_sync; |
52 | 54 | ||
53 | ret = nouveau_object_new(nv_object(chan->cli), chan->handle, | 55 | ret = nouveau_object_new(nv_object(chan->cli), chan->handle, |
54 | NvSema, 0x0002, | 56 | NvSema, 0x003d, |
55 | &(struct nv_dma_class) { | 57 | &(struct nv_dma_class) { |
56 | .flags = NV_DMA_TARGET_VRAM | | 58 | .flags = NV_DMA_TARGET_VRAM | |
57 | NV_DMA_ACCESS_RDWR, | 59 | NV_DMA_ACCESS_RDWR, |
58 | .start = mem->start * PAGE_SIZE, | 60 | .start = start, |
59 | .limit = mem->size - 1, | 61 | .limit = limit, |
60 | }, sizeof(struct nv_dma_class), | 62 | }, sizeof(struct nv_dma_class), |
61 | &object); | 63 | &object); |
62 | 64 | ||
63 | /* dma objects for display sync channel semaphore blocks */ | 65 | /* dma objects for display sync channel semaphore blocks */ |
64 | for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { | 66 | for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { |
65 | struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); | 67 | struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); |
68 | u32 start = bo->bo.mem.start * PAGE_SIZE; | ||
69 | u32 limit = start + bo->bo.mem.size - 1; | ||
66 | 70 | ||
67 | ret = nouveau_object_new(nv_object(chan->cli), chan->handle, | 71 | ret = nouveau_object_new(nv_object(chan->cli), chan->handle, |
68 | NvEvoSema0 + i, 0x003d, | 72 | NvEvoSema0 + i, 0x003d, |
69 | &(struct nv_dma_class) { | 73 | &(struct nv_dma_class) { |
70 | .flags = NV_DMA_TARGET_VRAM | | 74 | .flags = NV_DMA_TARGET_VRAM | |
71 | NV_DMA_ACCESS_RDWR, | 75 | NV_DMA_ACCESS_RDWR, |
72 | .start = bo->bo.offset, | 76 | .start = start, |
73 | .limit = bo->bo.offset + 0xfff, | 77 | .limit = limit, |
74 | }, sizeof(struct nv_dma_class), | 78 | }, sizeof(struct nv_dma_class), |
75 | &object); | 79 | &object); |
76 | } | 80 | } |