diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-23 13:46:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-23 13:46:28 -0400 |
commit | f07823e163d1296fa47986edb95198390553b2cc (patch) | |
tree | b915b1c49772a7632b59ece2fdb6c3f793be2c13 | |
parent | 41a00f7950a6bc0aa956f6d6b423f0fbf34d431a (diff) | |
parent | 4dd17ee95742f3e9fd55d07463981711a637bd20 (diff) |
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie:
"Ben was on holidays for a week so a few nouveau regression fixes
backed up, but they all seem necessary.
Otherwise one i915 and one gma500 fix"
* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
gma500: Fix SDVO turning off randomly
drm/nv04/disp: fix framebuffer pin refcounting
drm/nouveau/mc: fix race condition between constructor and request_irq()
drm/nouveau: fix reclocking on nv40
drm/nouveau/ltcg: fix allocating memory as free
drm/nouveau/ltcg: fix ltcg memory initialization after suspend
drm/nouveau/fb: fix null derefs in nv49 and nv4e init
drm/i915: Invalidate TLBs for the rings after a reset
-rw-r--r-- | drivers/gpu/drm/gma500/psb_intel_sdvo.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/core/mm.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/mc.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/mc/base.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv04/crtc.c | 58 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv04/disp.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv40_pm.c | 2 |
18 files changed, 114 insertions, 49 deletions
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 19e36603b23b..3bc8414533c9 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c | |||
@@ -500,7 +500,8 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo, | |||
500 | &status)) | 500 | &status)) |
501 | goto log_fail; | 501 | goto log_fail; |
502 | 502 | ||
503 | while (status == SDVO_CMD_STATUS_PENDING && retry--) { | 503 | while ((status == SDVO_CMD_STATUS_PENDING || |
504 | status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && retry--) { | ||
504 | udelay(15); | 505 | udelay(15); |
505 | if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, | 506 | if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, |
506 | SDVO_I2C_CMD_STATUS, | 507 | SDVO_I2C_CMD_STATUS, |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6f514297c483..53cddd985406 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -752,6 +752,8 @@ | |||
752 | will not assert AGPBUSY# and will only | 752 | will not assert AGPBUSY# and will only |
753 | be delivered when out of C3. */ | 753 | be delivered when out of C3. */ |
754 | #define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */ | 754 | #define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */ |
755 | #define INSTPM_TLB_INVALIDATE (1<<9) | ||
756 | #define INSTPM_SYNC_FLUSH (1<<5) | ||
755 | #define ACTHD 0x020c8 | 757 | #define ACTHD 0x020c8 |
756 | #define FW_BLC 0x020d8 | 758 | #define FW_BLC 0x020d8 |
757 | #define FW_BLC2 0x020dc | 759 | #define FW_BLC2 0x020dc |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 664118d8c1d6..079ef0129e74 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -968,6 +968,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) | |||
968 | 968 | ||
969 | I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); | 969 | I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); |
970 | POSTING_READ(mmio); | 970 | POSTING_READ(mmio); |
971 | |||
972 | /* Flush the TLB for this page */ | ||
973 | if (INTEL_INFO(dev)->gen >= 6) { | ||
974 | u32 reg = RING_INSTPM(ring->mmio_base); | ||
975 | I915_WRITE(reg, | ||
976 | _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | | ||
977 | INSTPM_SYNC_FLUSH)); | ||
978 | if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, | ||
979 | 1000)) | ||
980 | DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", | ||
981 | ring->name); | ||
982 | } | ||
971 | } | 983 | } |
972 | 984 | ||
973 | static int | 985 | static int |
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/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/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/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 1c0330b8c9a4..ec9cd6f10f91 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c | |||
@@ -80,7 +80,9 @@ _nouveau_mc_dtor(struct nouveau_object *object) | |||
80 | 80 | ||
81 | int | 81 | int |
82 | nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, | 82 | nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, |
83 | struct nouveau_oclass *oclass, int length, void **pobject) | 83 | struct nouveau_oclass *oclass, |
84 | const struct nouveau_mc_intr *intr_map, | ||
85 | int length, void **pobject) | ||
84 | { | 86 | { |
85 | struct nouveau_device *device = nv_device(parent); | 87 | struct nouveau_device *device = nv_device(parent); |
86 | struct nouveau_mc *pmc; | 88 | struct nouveau_mc *pmc; |
@@ -92,6 +94,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, | |||
92 | if (ret) | 94 | if (ret) |
93 | return ret; | 95 | return ret; |
94 | 96 | ||
97 | pmc->intr_map = intr_map; | ||
98 | |||
95 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, | 99 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, |
96 | IRQF_SHARED, "nouveau", pmc); | 100 | IRQF_SHARED, "nouveau", pmc); |
97 | if (ret < 0) | 101 | 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 f25fc5fc7dd1..2b1afe225db8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c | |||
@@ -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/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 0782bd2f1e04..6a13ffb53bdb 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c | |||
@@ -606,6 +606,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | |||
606 | regp->ramdac_a34 = 0x1; | 606 | regp->ramdac_a34 = 0x1; |
607 | } | 607 | } |
608 | 608 | ||
609 | static int | ||
610 | nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) | ||
611 | { | ||
612 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
613 | struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); | ||
614 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||
615 | int ret; | ||
616 | |||
617 | ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); | ||
618 | if (ret == 0) { | ||
619 | if (disp->image[nv_crtc->index]) | ||
620 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
621 | nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]); | ||
622 | } | ||
623 | |||
624 | return ret; | ||
625 | } | ||
626 | |||
609 | /** | 627 | /** |
610 | * Sets up registers for the given mode/adjusted_mode pair. | 628 | * Sets up registers for the given mode/adjusted_mode pair. |
611 | * | 629 | * |
@@ -622,10 +640,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
622 | struct drm_device *dev = crtc->dev; | 640 | struct drm_device *dev = crtc->dev; |
623 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 641 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
624 | struct nouveau_drm *drm = nouveau_drm(dev); | 642 | struct nouveau_drm *drm = nouveau_drm(dev); |
643 | int ret; | ||
625 | 644 | ||
626 | NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); | 645 | NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); |
627 | drm_mode_debug_printmodeline(adjusted_mode); | 646 | drm_mode_debug_printmodeline(adjusted_mode); |
628 | 647 | ||
648 | ret = nv_crtc_swap_fbs(crtc, old_fb); | ||
649 | if (ret) | ||
650 | return ret; | ||
651 | |||
629 | /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ | 652 | /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ |
630 | nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1); | 653 | nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1); |
631 | 654 | ||
@@ -722,6 +745,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc) | |||
722 | 745 | ||
723 | static void nv_crtc_destroy(struct drm_crtc *crtc) | 746 | static void nv_crtc_destroy(struct drm_crtc *crtc) |
724 | { | 747 | { |
748 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
725 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 749 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
726 | 750 | ||
727 | if (!nv_crtc) | 751 | if (!nv_crtc) |
@@ -729,6 +753,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) | |||
729 | 753 | ||
730 | drm_crtc_cleanup(crtc); | 754 | drm_crtc_cleanup(crtc); |
731 | 755 | ||
756 | if (disp->image[nv_crtc->index]) | ||
757 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
758 | nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]); | ||
759 | |||
732 | nouveau_bo_unmap(nv_crtc->cursor.nvbo); | 760 | nouveau_bo_unmap(nv_crtc->cursor.nvbo); |
733 | nouveau_bo_unpin(nv_crtc->cursor.nvbo); | 761 | nouveau_bo_unpin(nv_crtc->cursor.nvbo); |
734 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); | 762 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); |
@@ -754,6 +782,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) | |||
754 | } | 782 | } |
755 | 783 | ||
756 | static void | 784 | static void |
785 | nv_crtc_disable(struct drm_crtc *crtc) | ||
786 | { | ||
787 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
788 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||
789 | if (disp->image[nv_crtc->index]) | ||
790 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
791 | nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]); | ||
792 | } | ||
793 | |||
794 | static void | ||
757 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, | 795 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, |
758 | uint32_t size) | 796 | uint32_t size) |
759 | { | 797 | { |
@@ -791,7 +829,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
791 | struct drm_framebuffer *drm_fb; | 829 | struct drm_framebuffer *drm_fb; |
792 | struct nouveau_framebuffer *fb; | 830 | struct nouveau_framebuffer *fb; |
793 | int arb_burst, arb_lwm; | 831 | int arb_burst, arb_lwm; |
794 | int ret; | ||
795 | 832 | ||
796 | NV_DEBUG(drm, "index %d\n", nv_crtc->index); | 833 | NV_DEBUG(drm, "index %d\n", nv_crtc->index); |
797 | 834 | ||
@@ -801,10 +838,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
801 | return 0; | 838 | return 0; |
802 | } | 839 | } |
803 | 840 | ||
804 | |||
805 | /* If atomic, we want to switch to the fb we were passed, so | 841 | /* If atomic, we want to switch to the fb we were passed, so |
806 | * now we update pointers to do that. (We don't pin; just | 842 | * now we update pointers to do that. |
807 | * assume we're already pinned and update the base address.) | ||
808 | */ | 843 | */ |
809 | if (atomic) { | 844 | if (atomic) { |
810 | drm_fb = passed_fb; | 845 | drm_fb = passed_fb; |
@@ -812,17 +847,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
812 | } else { | 847 | } else { |
813 | drm_fb = crtc->fb; | 848 | drm_fb = crtc->fb; |
814 | fb = nouveau_framebuffer(crtc->fb); | 849 | fb = nouveau_framebuffer(crtc->fb); |
815 | /* If not atomic, we can go ahead and pin, and unpin the | ||
816 | * old fb we were passed. | ||
817 | */ | ||
818 | ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); | ||
819 | if (ret) | ||
820 | return ret; | ||
821 | |||
822 | if (passed_fb) { | ||
823 | struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb); | ||
824 | nouveau_bo_unpin(ofb->nvbo); | ||
825 | } | ||
826 | } | 850 | } |
827 | 851 | ||
828 | nv_crtc->fb.offset = fb->nvbo->bo.offset; | 852 | nv_crtc->fb.offset = fb->nvbo->bo.offset; |
@@ -877,6 +901,9 @@ static int | |||
877 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | 901 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, |
878 | struct drm_framebuffer *old_fb) | 902 | struct drm_framebuffer *old_fb) |
879 | { | 903 | { |
904 | int ret = nv_crtc_swap_fbs(crtc, old_fb); | ||
905 | if (ret) | ||
906 | return ret; | ||
880 | return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); | 907 | return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); |
881 | } | 908 | } |
882 | 909 | ||
@@ -1027,6 +1054,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { | |||
1027 | .mode_set_base = nv04_crtc_mode_set_base, | 1054 | .mode_set_base = nv04_crtc_mode_set_base, |
1028 | .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, | 1055 | .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, |
1029 | .load_lut = nv_crtc_gamma_load, | 1056 | .load_lut = nv_crtc_gamma_load, |
1057 | .disable = nv_crtc_disable, | ||
1030 | }; | 1058 | }; |
1031 | 1059 | ||
1032 | int | 1060 | 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_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 907d20ef6d4d..a03e75deacaf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -577,6 +577,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
577 | ret = nv50_display_flip_next(crtc, fb, chan, 0); | 577 | ret = nv50_display_flip_next(crtc, fb, chan, 0); |
578 | if (ret) | 578 | if (ret) |
579 | goto fail_unreserve; | 579 | goto fail_unreserve; |
580 | } else { | ||
581 | struct nv04_display *dispnv04 = nv04_display(dev); | ||
582 | nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]); | ||
580 | } | 583 | } |
581 | 584 | ||
582 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); | 585 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); |
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 | ||