提交 f07823e1 编写于 作者: L Linus Torvalds

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
...@@ -500,7 +500,8 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo, ...@@ -500,7 +500,8 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
&status)) &status))
goto log_fail; goto log_fail;
while (status == SDVO_CMD_STATUS_PENDING && retry--) { while ((status == SDVO_CMD_STATUS_PENDING ||
status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && retry--) {
udelay(15); udelay(15);
if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, if (!psb_intel_sdvo_read_byte(psb_intel_sdvo,
SDVO_I2C_CMD_STATUS, SDVO_I2C_CMD_STATUS,
......
...@@ -752,6 +752,8 @@ ...@@ -752,6 +752,8 @@
will not assert AGPBUSY# and will only will not assert AGPBUSY# and will only
be delivered when out of C3. */ be delivered when out of C3. */
#define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */ #define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */
#define INSTPM_TLB_INVALIDATE (1<<9)
#define INSTPM_SYNC_FLUSH (1<<5)
#define ACTHD 0x020c8 #define ACTHD 0x020c8
#define FW_BLC 0x020d8 #define FW_BLC 0x020d8
#define FW_BLC2 0x020dc #define FW_BLC2 0x020dc
......
...@@ -968,6 +968,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) ...@@ -968,6 +968,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
POSTING_READ(mmio); POSTING_READ(mmio);
/* Flush the TLB for this page */
if (INTEL_INFO(dev)->gen >= 6) {
u32 reg = RING_INSTPM(ring->mmio_base);
I915_WRITE(reg,
_MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
INSTPM_SYNC_FLUSH));
if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
1000))
DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
ring->name);
}
} }
static int static int
......
...@@ -98,6 +98,8 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, ...@@ -98,6 +98,8 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
u32 splitoff; u32 splitoff;
u32 s, e; u32 s, e;
BUG_ON(!type);
list_for_each_entry(this, &mm->free, fl_entry) { list_for_each_entry(this, &mm->free, fl_entry) {
e = this->offset + this->length; e = this->offset + this->length;
s = this->offset; s = this->offset;
...@@ -162,6 +164,8 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, ...@@ -162,6 +164,8 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
struct nouveau_mm_node *prev, *this, *next; struct nouveau_mm_node *prev, *this, *next;
u32 mask = align - 1; u32 mask = align - 1;
BUG_ON(!type);
list_for_each_entry_reverse(this, &mm->free, fl_entry) { list_for_each_entry_reverse(this, &mm->free, fl_entry) {
u32 e = this->offset + this->length; u32 e = this->offset + this->length;
u32 s = this->offset; u32 s = this->offset;
......
...@@ -20,8 +20,8 @@ nouveau_mc(void *obj) ...@@ -20,8 +20,8 @@ nouveau_mc(void *obj)
return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC]; return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
} }
#define nouveau_mc_create(p,e,o,d) \ #define nouveau_mc_create(p,e,o,m,d) \
nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d) nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
#define nouveau_mc_destroy(p) ({ \ #define nouveau_mc_destroy(p) ({ \
struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \ struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \
}) })
...@@ -33,7 +33,8 @@ nouveau_mc(void *obj) ...@@ -33,7 +33,8 @@ nouveau_mc(void *obj)
}) })
int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *, int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, int, void **); struct nouveau_oclass *, const struct nouveau_mc_intr *,
int, void **);
void _nouveau_mc_dtor(struct nouveau_object *); void _nouveau_mc_dtor(struct nouveau_object *);
int _nouveau_mc_init(struct nouveau_object *); int _nouveau_mc_init(struct nouveau_object *);
int _nouveau_mc_fini(struct nouveau_object *, bool); int _nouveau_mc_fini(struct nouveau_object *, bool);
......
...@@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
return ret; return ret;
switch (pfb914 & 0x00000003) { switch (pfb914 & 0x00000003) {
case 0x00000000: pfb->ram->type = NV_MEM_TYPE_DDR1; break; case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break;
case 0x00000001: pfb->ram->type = NV_MEM_TYPE_DDR2; break; case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break;
case 0x00000002: pfb->ram->type = NV_MEM_TYPE_GDDR3; break; case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break;
case 0x00000003: break; case 0x00000003: break;
} }
pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
pfb->ram->tags = nv_rd32(pfb, 0x100320); ram->tags = nv_rd32(pfb, 0x100320);
return 0; return 0;
} }
......
...@@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret) if (ret)
return ret; return ret;
pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
pfb->ram->type = NV_MEM_TYPE_STOLEN; ram->type = NV_MEM_TYPE_STOLEN;
return 0; return 0;
} }
......
...@@ -30,8 +30,9 @@ struct nvc0_ltcg_priv { ...@@ -30,8 +30,9 @@ struct nvc0_ltcg_priv {
struct nouveau_ltcg base; struct nouveau_ltcg base;
u32 part_nr; u32 part_nr;
u32 subp_nr; u32 subp_nr;
struct nouveau_mm tags;
u32 num_tags; u32 num_tags;
u32 tag_base;
struct nouveau_mm tags;
struct nouveau_mm_node *tag_ram; struct nouveau_mm_node *tag_ram;
}; };
...@@ -117,10 +118,6 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) ...@@ -117,10 +118,6 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
u32 tag_size, tag_margin, tag_align; u32 tag_size, tag_margin, tag_align;
int ret; int ret;
nv_wr32(priv, 0x17e8d8, priv->part_nr);
if (nv_device(pfb)->card_type >= NV_E0)
nv_wr32(priv, 0x17e000, priv->part_nr);
/* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
priv->num_tags = (pfb->ram->size >> 17) / 4; priv->num_tags = (pfb->ram->size >> 17) / 4;
if (priv->num_tags > (1 << 17)) 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,7 +139,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
tag_size += tag_align; tag_size += tag_align;
tag_size = (tag_size + 0xfff) >> 12; /* round up */ tag_size = (tag_size + 0xfff) >> 12; /* round up */
ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1, ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
&priv->tag_ram); &priv->tag_ram);
if (ret) { if (ret) {
priv->num_tags = 0; priv->num_tags = 0;
...@@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) ...@@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
tag_base += tag_align - 1; tag_base += tag_align - 1;
ret = do_div(tag_base, tag_align); ret = do_div(tag_base, tag_align);
nv_wr32(priv, 0x17e8d4, tag_base); priv->tag_base = tag_base;
} }
ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1); ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
...@@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
} }
priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
ret = nvc0_ltcg_init_tag_ram(pfb, priv); ret = nvc0_ltcg_init_tag_ram(pfb, priv);
if (ret) if (ret)
return ret; return ret;
...@@ -209,13 +204,32 @@ nvc0_ltcg_dtor(struct nouveau_object *object) ...@@ -209,13 +204,32 @@ nvc0_ltcg_dtor(struct nouveau_object *object)
nouveau_ltcg_destroy(ltcg); nouveau_ltcg_destroy(ltcg);
} }
static int
nvc0_ltcg_init(struct nouveau_object *object)
{
struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
int ret;
ret = nouveau_ltcg_init(ltcg);
if (ret)
return ret;
nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
nv_wr32(priv, 0x17e8d8, priv->part_nr);
if (nv_device(ltcg)->card_type >= NV_E0)
nv_wr32(priv, 0x17e000, priv->part_nr);
nv_wr32(priv, 0x17e8d4, priv->tag_base);
return 0;
}
struct nouveau_oclass struct nouveau_oclass
nvc0_ltcg_oclass = { nvc0_ltcg_oclass = {
.handle = NV_SUBDEV(LTCG, 0xc0), .handle = NV_SUBDEV(LTCG, 0xc0),
.ofuncs = &(struct nouveau_ofuncs) { .ofuncs = &(struct nouveau_ofuncs) {
.ctor = nvc0_ltcg_ctor, .ctor = nvc0_ltcg_ctor,
.dtor = nvc0_ltcg_dtor, .dtor = nvc0_ltcg_dtor,
.init = _nouveau_ltcg_init, .init = nvc0_ltcg_init,
.fini = _nouveau_ltcg_fini, .fini = _nouveau_ltcg_fini,
}, },
}; };
...@@ -80,7 +80,9 @@ _nouveau_mc_dtor(struct nouveau_object *object) ...@@ -80,7 +80,9 @@ _nouveau_mc_dtor(struct nouveau_object *object)
int int
nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, int length, void **pobject) struct nouveau_oclass *oclass,
const struct nouveau_mc_intr *intr_map,
int length, void **pobject)
{ {
struct nouveau_device *device = nv_device(parent); struct nouveau_device *device = nv_device(parent);
struct nouveau_mc *pmc; struct nouveau_mc *pmc;
...@@ -92,6 +94,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -92,6 +94,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret) if (ret)
return ret; return ret;
pmc->intr_map = intr_map;
ret = request_irq(device->pdev->irq, nouveau_mc_intr, ret = request_irq(device->pdev->irq, nouveau_mc_intr,
IRQF_SHARED, "nouveau", pmc); IRQF_SHARED, "nouveau", pmc);
if (ret < 0) if (ret < 0)
......
...@@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv04_mc_priv *priv; struct nv04_mc_priv *priv;
int ret; int ret;
ret = nouveau_mc_create(parent, engine, oclass, &priv); ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
*pobject = nv_object(priv); *pobject = nv_object(priv);
if (ret) if (ret)
return ret; return ret;
priv->base.intr_map = nv04_mc_intr;
return 0; return 0;
} }
......
...@@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv44_mc_priv *priv; struct nv44_mc_priv *priv;
int ret; int ret;
ret = nouveau_mc_create(parent, engine, oclass, &priv); ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
*pobject = nv_object(priv); *pobject = nv_object(priv);
if (ret) if (ret)
return ret; return ret;
priv->base.intr_map = nv04_mc_intr;
return 0; return 0;
} }
......
...@@ -53,12 +53,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -53,12 +53,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv50_mc_priv *priv; struct nv50_mc_priv *priv;
int ret; int ret;
ret = nouveau_mc_create(parent, engine, oclass, &priv); ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv);
*pobject = nv_object(priv); *pobject = nv_object(priv);
if (ret) if (ret)
return ret; return ret;
priv->base.intr_map = nv50_mc_intr;
return 0; return 0;
} }
......
...@@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv98_mc_priv *priv; struct nv98_mc_priv *priv;
int ret; int ret;
ret = nouveau_mc_create(parent, engine, oclass, &priv); ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv);
*pobject = nv_object(priv); *pobject = nv_object(priv);
if (ret) if (ret)
return ret; return ret;
priv->base.intr_map = nv98_mc_intr;
return 0; return 0;
} }
......
...@@ -57,12 +57,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -57,12 +57,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_mc_priv *priv; struct nvc0_mc_priv *priv;
int ret; int ret;
ret = nouveau_mc_create(parent, engine, oclass, &priv); ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv);
*pobject = nv_object(priv); *pobject = nv_object(priv);
if (ret) if (ret)
return ret; return ret;
priv->base.intr_map = nvc0_mc_intr;
return 0; return 0;
} }
......
...@@ -606,6 +606,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) ...@@ -606,6 +606,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
regp->ramdac_a34 = 0x1; regp->ramdac_a34 = 0x1;
} }
static int
nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
{
struct nv04_display *disp = nv04_display(crtc->dev);
struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
int ret;
ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
if (ret == 0) {
if (disp->image[nv_crtc->index])
nouveau_bo_unpin(disp->image[nv_crtc->index]);
nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]);
}
return ret;
}
/** /**
* Sets up registers for the given mode/adjusted_mode pair. * Sets up registers for the given mode/adjusted_mode pair.
* *
...@@ -622,10 +640,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -622,10 +640,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
int ret;
NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
drm_mode_debug_printmodeline(adjusted_mode); drm_mode_debug_printmodeline(adjusted_mode);
ret = nv_crtc_swap_fbs(crtc, old_fb);
if (ret)
return ret;
/* unlock must come after turning off FP_TG_CONTROL in output_prepare */ /* unlock must come after turning off FP_TG_CONTROL in output_prepare */
nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1); nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
...@@ -722,6 +745,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc) ...@@ -722,6 +745,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)
static void nv_crtc_destroy(struct drm_crtc *crtc) static void nv_crtc_destroy(struct drm_crtc *crtc)
{ {
struct nv04_display *disp = nv04_display(crtc->dev);
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
if (!nv_crtc) if (!nv_crtc)
...@@ -729,6 +753,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) ...@@ -729,6 +753,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
drm_crtc_cleanup(crtc); drm_crtc_cleanup(crtc);
if (disp->image[nv_crtc->index])
nouveau_bo_unpin(disp->image[nv_crtc->index]);
nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
nouveau_bo_unmap(nv_crtc->cursor.nvbo); nouveau_bo_unmap(nv_crtc->cursor.nvbo);
nouveau_bo_unpin(nv_crtc->cursor.nvbo); nouveau_bo_unpin(nv_crtc->cursor.nvbo);
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
...@@ -753,6 +781,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) ...@@ -753,6 +781,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc)
nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg); nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
} }
static void
nv_crtc_disable(struct drm_crtc *crtc)
{
struct nv04_display *disp = nv04_display(crtc->dev);
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
if (disp->image[nv_crtc->index])
nouveau_bo_unpin(disp->image[nv_crtc->index]);
nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
}
static void static void
nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
uint32_t size) uint32_t size)
...@@ -791,7 +829,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, ...@@ -791,7 +829,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
struct drm_framebuffer *drm_fb; struct drm_framebuffer *drm_fb;
struct nouveau_framebuffer *fb; struct nouveau_framebuffer *fb;
int arb_burst, arb_lwm; int arb_burst, arb_lwm;
int ret;
NV_DEBUG(drm, "index %d\n", nv_crtc->index); NV_DEBUG(drm, "index %d\n", nv_crtc->index);
...@@ -801,10 +838,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, ...@@ -801,10 +838,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
return 0; return 0;
} }
/* If atomic, we want to switch to the fb we were passed, so /* If atomic, we want to switch to the fb we were passed, so
* now we update pointers to do that. (We don't pin; just * now we update pointers to do that.
* assume we're already pinned and update the base address.)
*/ */
if (atomic) { if (atomic) {
drm_fb = passed_fb; drm_fb = passed_fb;
...@@ -812,17 +847,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, ...@@ -812,17 +847,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
} else { } else {
drm_fb = crtc->fb; drm_fb = crtc->fb;
fb = nouveau_framebuffer(crtc->fb); fb = nouveau_framebuffer(crtc->fb);
/* If not atomic, we can go ahead and pin, and unpin the
* old fb we were passed.
*/
ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
if (ret)
return ret;
if (passed_fb) {
struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
nouveau_bo_unpin(ofb->nvbo);
}
} }
nv_crtc->fb.offset = fb->nvbo->bo.offset; nv_crtc->fb.offset = fb->nvbo->bo.offset;
...@@ -877,6 +901,9 @@ static int ...@@ -877,6 +901,9 @@ static int
nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb) struct drm_framebuffer *old_fb)
{ {
int ret = nv_crtc_swap_fbs(crtc, old_fb);
if (ret)
return ret;
return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
} }
...@@ -1027,6 +1054,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { ...@@ -1027,6 +1054,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
.mode_set_base = nv04_crtc_mode_set_base, .mode_set_base = nv04_crtc_mode_set_base,
.mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
.load_lut = nv_crtc_gamma_load, .load_lut = nv_crtc_gamma_load,
.disable = nv_crtc_disable,
}; };
int int
......
...@@ -81,6 +81,7 @@ struct nv04_display { ...@@ -81,6 +81,7 @@ struct nv04_display {
uint32_t saved_vga_font[4][16384]; uint32_t saved_vga_font[4][16384];
uint32_t dac_users[4]; uint32_t dac_users[4];
struct nouveau_object *core; struct nouveau_object *core;
struct nouveau_bo *image[2];
}; };
static inline struct nv04_display * static inline struct nv04_display *
......
...@@ -577,6 +577,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -577,6 +577,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
ret = nv50_display_flip_next(crtc, fb, chan, 0); ret = nv50_display_flip_next(crtc, fb, chan, 0);
if (ret) if (ret)
goto fail_unreserve; goto fail_unreserve;
} else {
struct nv04_display *dispnv04 = nv04_display(dev);
nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]);
} }
ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
......
...@@ -131,7 +131,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, ...@@ -131,7 +131,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll,
if (clk < pll->vco1.max_freq) if (clk < pll->vco1.max_freq)
pll->vco2.max_freq = 0; pll->vco2.max_freq = 0;
pclk->pll_calc(pclk, pll, clk, &coef); ret = pclk->pll_calc(pclk, pll, clk, &coef);
if (ret == 0) if (ret == 0)
return -ERANGE; return -ERANGE;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册