About buffer sychronization mechanism and cache operation
Hello all, The purpose of this email is to get other opinions and advices to buffer synchronization mechanism, and coupling cache operation feature with the buffer synchronization mechanism. First of all, I am not a native English speaker so I'm not sure that I can convey my intention to you. And I'm not a specialist in Linux than other people so also there might be my missing points. I had posted the buffer synchronization mechanism called dmabuf sync framework like below, http://lists.infradead.org/pipermail/linux-arm-kernel/2013-June/177045.html And I'm sending this email before posting next version with more stable patch set and features. The purpose of this framework is to provide not only buffer access control to CPU and DMA but also easy-to-use interfaces for device drivers and user application. This framework can be used for all DMA devices using system memory as DMA buffer, especially for most ARM based SoCs. There are two cases we are using this buffer synchronization framework. One is to primarily enhance GPU rendering performance on Tizen platform in case of 3d app with compositing mode that the 3d app draws something in off-screen buffer. And other is to couple buffer access control and cache operation between CPU and DMA; the cache operation is done by the dmabuf sync framework in kernel side. Why do we need buffer access control between CPU and DMA? - The below shows simple 3D software layers, 3D Application - Standard OpenGL ES and EGL Interfaces --- [A] - MALI OpenGL ES and EGL Native modules - [B] - Exynos DRM Driver|GPU Driver -- [C] 3d application requests 3d rendering through A. And then B fills a 3d command buffer with the requests from A. And then 3D application calls glFlush so that the 3d command buffer can be submitted to C, and rendered by GPU hardware. Internally, glFlush(also glFinish) will call a function of native module[B] glFinish blocks caller's task until all GL execution is complete. On the other hand, glFlush forces execution of GL commands but doesn't block the caller's task until the completion. In composting mode, in case of using glFinish, the 3d rendering performance is quite lower than using glFlush because glFinish makes CPU blocked until the execution of the 3d commands is completed. However, the use of glFlush has one issue that the shared buffer with GPU could be broken when CPU accesses the shared buffer at once after glFlush because CPU cannot be aware of the completion of GPU access to the shared buffer: actually, Tizen platform internally calls only eglSwapBuffer instead of glFlush and glFinish, and whether flushing or finishing is decided according to compositing mode or not. So in such case, we would need buffer access control between CPU and DMA for more performance. About cache operation - The dmabuf sync framework can include cache operation feature, and the below shows how the cache operation based on dmabuf sync framework is performed, device driver in kernel or fctrl in user land dmabuf_sync_lock or dmabuf_sync_single_lock check before and after buffer access dma_buf_begin_cpu_access or dma_buf_end_cpu_access begin_cpu_access or end_cpu_access of exporter dma_sync_sg_for_device or dma_sync_sg_for_cpu In case that using dmabuf sync framework, kernel can be aware of when CPU and DMA access to a shared buffer is completed so we can do cache operation in kernel so that way, we can couple buffer access control and cache operation. So with this, we can avoid that user land overuses cache operation. I guess most Linux based platforms are using cachable mapped buffer for more performance: in case that CPU frequently accesses the shared buffer which is shared with DMA, the use of cachable mapped buffer is more fast than the use of non-cachable. However, this way could make cache operation overused by user land because only user land can be aware of the completion of CPU or DMA access to the shared buffer so user land could request cache operations every time it wants even the cache operation is unnecessary. That is how user land could overuse cache operations. To Android, Chrome OS, and other forks, Are there other cases that buffer access control between CPU and DMA is needed? I know Android sync driver and KDS are already being used for Android, Chrome OS, and so on. How does your platform do cache operation? And How do you think about coupling buffer access control and cache operation between CPU and DMA?. Lastly, I think we may need Linux generic buffer synchroni
Re: [PATCH] drm: drm_drv: Only call drm_agp_clear() in __OS_HAS_AGP case
Hi On Fri, Aug 9, 2013 at 12:00 AM, Fabio Estevam wrote: > From: Fabio Estevam > > Commit 28ec711 (drm/agp: move AGP cleanup paths to drm_agpsupport.c) causes > the > following link error on ARM (imx_v6_v7_defconfig): > > drivers/built-in.o: In function `drm_lastclose': > :(.text+0x588a0): undefined reference to `drm_agp_clear' > make: *** [vmlinux] Error 1 > > drm_agp_clear() is defined only '#if __OS_HAS_AGP' is true, so add this 'if' > logic when calling it. > > Signed-off-by: Fabio Estevam This has already been fixed 4 days ago in the drm-next tree. You can find the patch here: http://cgit.freedesktop.org/~airlied/linux/commit/?h=drm-next&id=00fd78e5279aec3aa504307ff2db892d3efb555d Thanks David > --- > drivers/gpu/drm/drm_drv.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c > index 799..58f7f39 100644 > --- a/drivers/gpu/drm/drm_drv.c > +++ b/drivers/gpu/drm/drm_drv.c > @@ -195,7 +195,9 @@ int drm_lastclose(struct drm_device * dev) > > mutex_lock(&dev->struct_mutex); > > +#if __OS_HAS_AGP > drm_agp_clear(dev); > +#endif > > if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg && > !drm_core_check_feature(dev, DRIVER_MODESET)) { > -- > 1.8.1.2 > ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/nouveau: fix ltcg allocating memory as free
Allocating type=0 marks the memory as free. This allows the ltcg memory to be allocated twice. Add a BUG_ON in core/mm.c to prevent this ever happening again. Signed-off-by: Maarten Lankhorst --- diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index d829172..7a4e089 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, u32 splitoff; u32 s, e; + BUG_ON(!type); + list_for_each_entry(this, &mm->free, fl_entry) { e = this->offset + this->length; s = this->offset; @@ -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; u32 mask = align - 1; + BUG_ON(!type); + list_for_each_entry_reverse(this, &mm->free, fl_entry) { u32 e = this->offset + this->length; u32 s = this->offset; diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c index bcca883..7288940 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c @@ -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_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); if (ret) { priv->num_tags = 0; ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/nouveau: fix ltcg memory initialization after suspend
Some registers were not initialized in init, this causes them to be uninitialized after suspend. Signed-off-by: Maarten Lankhorst --- diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c index bcca883..7288940 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 { struct nouveau_ltcg base; u32 part_nr; u32 subp_nr; - struct nouveau_mm tags; u32 num_tags; + u32 tag_base; + struct nouveau_mm tags; struct nouveau_mm_node *tag_ram; }; @@ -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; 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) */ priv->num_tags = (pfb->ram->size >> 17) / 4; if (priv->num_tags > (1 << 17)) @@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) tag_base += tag_align - 1; 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); @@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, } priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; - nv_mask(priv, 0x17e820, 0x0010, 0x); /* INTR_EN &= ~0x10 */ - ret = nvc0_ltcg_init_tag_ram(pfb, priv); if (ret) return ret; @@ -209,13 +204,36 @@ nvc0_ltcg_dtor(struct nouveau_object *object) nouveau_ltcg_destroy(ltcg); } +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; + struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent); + int ret; + + ret = nouveau_subdev_init(&pfb->base); + if (ret) + return ret; + + nv_mask(priv, 0x17e820, 0x0010, 0x); /* INTR_EN &= ~0x10 */ + + nv_wr32(priv, 0x17e8d8, priv->part_nr); + if (nv_device(pfb)->card_type >= NV_E0) + nv_wr32(priv, 0x17e000, priv->part_nr); + + nv_wr32(priv, 0x17e8d4, priv->tag_base); + + return 0; +} + struct nouveau_oclass nvc0_ltcg_oclass = { .handle = NV_SUBDEV(LTCG, 0xc0), .ofuncs = &(struct nouveau_ofuncs) { .ctor = nvc0_ltcg_ctor, .dtor = nvc0_ltcg_dtor, - .init = _nouveau_ltcg_init, + .init = nvc0_ltcg_init, .fini = _nouveau_ltcg_fini, }, }; ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/nouveau: fix vblank deadlock
This fixes a deadlock inversion when vblank is enabled/disabled by drm. &dev->vblank_time_lock is always taken when the vblank state is toggled, which caused a deadlock when &event->lock was also taken during event_get/put. Solve the race by requiring that lock to change enable/disable state, and always keeping vblank on the event list. Core drm ignores unwanted vblanks, so extra calls to drm_handle_vblank are harmless. Signed-off-by: Maarten Lankhorst --- diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c index 7eb81c1..78bff7c 100644 --- a/drivers/gpu/drm/nouveau/core/core/event.c +++ b/drivers/gpu/drm/nouveau/core/core/event.c @@ -23,43 +23,64 @@ #include #include -static void -nouveau_event_put_locked(struct nouveau_event *event, int index, -struct nouveau_eventh *handler) -{ - if (!--event->index[index].refs) { - if (event->disable) - event->disable(event, index); - } - list_del(&handler->head); -} - void nouveau_event_put(struct nouveau_event *event, int index, struct nouveau_eventh *handler) { unsigned long flags; + if (index >= event->index_nr) + return; + spin_lock_irqsave(&event->lock, flags); - if (index < event->index_nr) - nouveau_event_put_locked(event, index, handler); + list_del(&handler->head); + + if (event->toggle_lock) + spin_lock(event->toggle_lock); + nouveau_event_disable_locked(event, index, 1); + if (event->toggle_lock) + spin_unlock(event->toggle_lock); + spin_unlock_irqrestore(&event->lock, flags); } void +nouveau_event_enable_locked(struct nouveau_event *event, int index) +{ + if (index >= event->index_nr) + return; + + if (!event->index[index].refs++ && event->enable) + event->enable(event, index); +} + +void +nouveau_event_disable_locked(struct nouveau_event *event, int index, int refs) +{ + if (index >= event->index_nr) + return; + + event->index[index].refs -= refs; + if (!event->index[index].refs && event->disable) + event->disable(event, index); +} + +void nouveau_event_get(struct nouveau_event *event, int index, struct nouveau_eventh *handler) { unsigned long flags; + if (index >= event->index_nr) + return; + spin_lock_irqsave(&event->lock, flags); - if (index < event->index_nr) { - list_add(&handler->head, &event->index[index].list); - if (!event->index[index].refs++) { - if (event->enable) - event->enable(event, index); - } - } + list_add(&handler->head, &event->index[index].list); + if (event->toggle_lock) + spin_lock(event->toggle_lock); + nouveau_event_enable_locked(event, index); + if (event->toggle_lock) + spin_unlock(event->toggle_lock); spin_unlock_irqrestore(&event->lock, flags); } @@ -68,6 +89,7 @@ nouveau_event_trigger(struct nouveau_event *event, int index) { struct nouveau_eventh *handler, *temp; unsigned long flags; + int refs = 0; if (index >= event->index_nr) return; @@ -75,9 +97,17 @@ nouveau_event_trigger(struct nouveau_event *event, int index) spin_lock_irqsave(&event->lock, flags); list_for_each_entry_safe(handler, temp, &event->index[index].list, head) { if (handler->func(handler, index) == NVKM_EVENT_DROP) { - nouveau_event_put_locked(event, index, handler); + list_del(&handler->head); + refs++; } } + if (refs) { + if (event->toggle_lock) + spin_lock(event->toggle_lock); + nouveau_event_disable_locked(event, index, refs); + if (event->toggle_lock) + spin_unlock(event->toggle_lock); + } spin_unlock_irqrestore(&event->lock, flags); } diff --git a/drivers/gpu/drm/nouveau/core/include/core/event.h b/drivers/gpu/drm/nouveau/core/include/core/event.h index 9e09440..b1a6c91 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/event.h +++ b/drivers/gpu/drm/nouveau/core/include/core/event.h @@ -12,6 +12,7 @@ struct nouveau_eventh { struct nouveau_event { spinlock_t lock; + spinlock_t *toggle_lock; void *priv; void (*enable)(struct nouveau_event *, int index); @@ -33,4 +34,8 @@ void nouveau_event_get(struct nouveau_event *, int index, void nouveau_event_put(struct nouveau_event *, int index, struct nouveau_eventh *); +void nouveau_event_enable_locked(struct nouveau_event *event, int index); +void nouveau_event_disable_locked(struct nouveau_
[RFC PATCH] drm/nv50-nvd0: implement precise vblank timing support on nv50/nvc0.
Not as thoroughly tested as I would like. Newer nvd0 and kepler are unsupported, as I don't know the registers yet. Information of the scanout position is based on Lucas Stach's original patch, with a teak to read vline twice, to prevent a race of hline with vline. Cc: Lucas Stach Cc: Mario Kleiner Signed-off-by: Maarten Lankhorst --- diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index c168ae3..96268b7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -1285,6 +1285,57 @@ nv50_disp_intr(struct nouveau_subdev *subdev) } } +u32 nv50_disp_get_vblank_count(struct nouveau_disp *disp, int head) +{ + if (head < 0 || head >= 2) + return 0; + + return nv_rd32(disp, 0x616340 + head * 0x800) >> 16; +} + +int nv50_disp_get_scanoutpos(struct nouveau_disp *disp, int head, int *vpos, int *hpos) +{ + u32 reg, vbias, hbias, vbl_start, vbl_end, hline, vline; + + if (head < 0 || head >= 2) + return -1; + + reg = nv_rd32(disp, 0x610ae8 + head * 4); + vbias = reg >> 16; + hbias = reg & 0x; + + vbl_start = nv_rd32(disp, 0x610af0 + head * 4) >> 16; + vbl_end = nv_rd32(disp, 0x610af8 + head * 4) >> 16; + + reg = nv_rd32(disp, 0x616340 + head * 0x800) & 0x; + while (1) { + hline = nv_rd32(disp, 0x616344 + head * 0x800) & 0x; + + vline = nv_rd32(disp, 0x616340 + head * 0x800) & 0x; + if (vline == reg) + break; + + reg = vline; + } + + if((vline >= vbl_start) || (vline < vbias)) { + /* we are in vblank so do a neg countdown */ + vline -= vbias; + hline -= hbias; + + if (vline > 0) + vline -= vbl_end; + } else { + /* apply corrective offset */ + vline -= vbias; + hline -= hbias; + } + + *vpos = vline; + *hpos = hline; + return 0; +} + static int nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -1302,6 +1353,9 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nv50_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nv50_disp_intr; + priv->base.max_vblank_count = 0x; + priv->base.get_vblank_count = nv50_disp_get_vblank_count; + priv->base.get_scanoutpos = nv50_disp_get_scanoutpos; INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); priv->sclass = nv50_disp_sclass; priv->head.nr = 2; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index 1ae6ceb..e3900ce 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h @@ -144,4 +144,7 @@ extern struct nouveau_oclass nvd0_disp_cclass; void nvd0_disp_intr_supervisor(struct work_struct *); void nvd0_disp_intr(struct nouveau_subdev *); +u32 nv50_disp_get_vblank_count(struct nouveau_disp *disp, int head); +int nv50_disp_get_scanoutpos(struct nouveau_disp *disp, int head, int *vpos, int *hpos); + #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c index d8c74c0..df357cf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c @@ -75,6 +75,9 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nv84_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nv50_disp_intr; + priv->base.max_vblank_count = 0x; + priv->base.get_vblank_count = nv50_disp_get_vblank_count; + priv->base.get_scanoutpos = nv50_disp_get_scanoutpos; INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); priv->sclass = nv84_disp_sclass; priv->head.nr = 2; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c index a66f949..38eafdf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c @@ -75,6 +75,9 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nv94_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nv50_disp_intr; + priv->base.max_vblank_count = 0x; + priv->base.get_vblank_count = nv50_disp_get_vblank_count; + priv->base.get_scanoutpos = nv50_disp_get_scanoutpos; INIT_WORK(&priv->supervisor, nv50_disp_intr_supervis
Re: [PATCH] drm/radeon: fix UVD message buffer validation
On Sun, Aug 11, 2013 at 3:27 PM, Christian König wrote: > From: Christian König > > When the message buffer is currently moving block until it is idle again. > > Signed-off-by: Christian König > Cc: sta...@vger.kernel.org Applied to my fixes tree. Alex > --- > drivers/gpu/drm/radeon/radeon_uvd.c |8 > 1 file changed, 8 insertions(+) > > diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c > b/drivers/gpu/drm/radeon/radeon_uvd.c > index f1c1575..b79f4f5 100644 > --- a/drivers/gpu/drm/radeon/radeon_uvd.c > +++ b/drivers/gpu/drm/radeon/radeon_uvd.c > @@ -356,6 +356,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, > struct radeon_bo *bo, > return -EINVAL; > } > > + if (bo->tbo.sync_obj) { > + r = radeon_fence_wait(bo->tbo.sync_obj, false); > + if (r) { > + DRM_ERROR("Failed waiting for UVD message (%d)!\n", > r); > + return r; > + } > + } > + > r = radeon_bo_kmap(bo, &ptr); > if (r) { > DRM_ERROR("Failed mapping the UVD message (%d)!\n", r); > -- > 1.7.9.5 > ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/edid: add quirk for Medion MD30217PG
This LCD monitor (1280x1024 native) has a completely bogus detailed timing (640x350@70hz). User reports that 1280x1024@60 has waves so prefer 1280x1024@75. Manufacturer: MED Model: 7b8 Serial#: 99188 Year: 2005 Week: 5 EDID Version: 1.3 Analog Display Input, Input Voltage Level: 0.700/0.700 V Sync: Separate Max Image Size [cm]: horiz.: 34 vert.: 27 Gamma: 2.50 DPMS capabilities: Off; RGB/Color Display First detailed timing is preferred mode redX: 0.645 redY: 0.348 greenX: 0.280 greenY: 0.605 blueX: 0.142 blueY: 0.071 whiteX: 0.313 whiteY: 0.329 Supported established timings: 720x400@70Hz 640x480@60Hz 640x480@72Hz 640x480@75Hz 800x600@56Hz 800x600@60Hz 800x600@72Hz 800x600@75Hz 1024x768@60Hz 1024x768@70Hz 1024x768@75Hz 1280x1024@75Hz Manufacturer's mask: 0 Supported standard timings: Supported detailed timing: clock: 25.2 MHz Image Size: 337 x 270 mm h_active: 640 h_sync: 688 h_sync_end 784 h_blank_end 800 h_border: 0 v_active: 350 v_sync: 350 v_sync_end 352 v_blanking: 449 v_border: 0 Monitor name: MD30217PG Ranges: V min: 56 V max: 76 Hz, H min: 30 H max: 83 kHz, PixClock max 145 MHz Serial No: 501099188 EDID (in hex): 000034a4b80774830100 050f010368221b962a0c55a559479b24 125054afcf00310a0101010101018180 d60980a0205e63103060 0200510e111e00fc004d4433 3032313750470a20202000fd0038 4c1e530e000a20202020202000ff 003530313039393138380a2020200078 Signed-off-by: Alex Deucher Reported-by: friedr...@mailstation.de Cc: sta...@vger.kernel.org --- drivers/gpu/drm/drm_edid.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 95d6f4b..70fc133 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -125,6 +125,9 @@ static struct edid_quirk { /* ViewSonic VA2026w */ { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, + + /* Medion MD 30217 PG */ + { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 }, }; /* -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC PATCH] fence: dma-buf cross-device synchronization (v12)
On Mon, Jul 29, 2013 at 10:05 AM, Maarten Lankhorst wrote: > A fence can be attached to a buffer which is being filled or consumed > by hw, to allow userspace to pass the buffer without waiting to another > device. For example, userspace can call page_flip ioctl to display the > next frame of graphics after kicking the GPU but while the GPU is still > rendering. The display device sharing the buffer with the GPU would > attach a callback to get notified when the GPU's rendering-complete IRQ > fires, to update the scan-out address of the display, without having to > wake up userspace. > > A driver must allocate a fence context for each execution ring that can > run in parallel. The function for this takes an argument with how many > contexts to allocate: > + fence_context_alloc() > > A fence is transient, one-shot deal. It is allocated and attached > to one or more dma-buf's. When the one that attached it is done, with > the pending operation, it can signal the fence: > + fence_signal() > > To have a rough approximation whether a fence is fired, call: > + fence_is_signaled() > > The dma-buf-mgr handles tracking, and waiting on, the fences associated > with a dma-buf. > > The one pending on the fence can add an async callback: > + fence_add_callback() > > The callback can optionally be cancelled with: > + fence_remove_callback() > > To wait synchronously, optionally with a timeout: > + fence_wait() > + fence_wait_timeout() > > A default software-only implementation is provided, which can be used > by drivers attaching a fence to a buffer when they have no other means > for hw sync. But a memory backed fence is also envisioned, because it > is common that GPU's can write to, or poll on some memory location for > synchronization. For example: > > fence = custom_get_fence(...); > if ((seqno_fence = to_seqno_fence(fence)) != NULL) { > dma_buf *fence_buf = fence->sync_buf; > get_dma_buf(fence_buf); > > ... tell the hw the memory location to wait ... > custom_wait_on(fence_buf, fence->seqno_ofs, fence->seqno); > } else { > /* fall-back to sw sync * / > fence_add_callback(fence, my_cb); > } > > On SoC platforms, if some other hw mechanism is provided for synchronizing > between IP blocks, it could be supported as an alternate implementation > with it's own fence ops in a similar way. > > enable_signaling callback is used to provide sw signaling in case a cpu > waiter is requested or no compatible hardware signaling could be used. > > The intention is to provide a userspace interface (presumably via eventfd) > later, to be used in conjunction with dma-buf's mmap support for sw access > to buffers (or for userspace apps that would prefer to do their own > synchronization). > > v1: Original > v2: After discussion w/ danvet and mlankhorst on #dri-devel, we decided > that dma-fence didn't need to care about the sw->hw signaling path > (it can be handled same as sw->sw case), and therefore the fence->ops > can be simplified and more handled in the core. So remove the signal, > add_callback, cancel_callback, and wait ops, and replace with a simple > enable_signaling() op which can be used to inform a fence supporting > hw->hw signaling that one or more devices which do not support hw > signaling are waiting (and therefore it should enable an irq or do > whatever is necessary in order that the CPU is notified when the > fence is passed). > v3: Fix locking fail in attach_fence() and get_fence() > v4: Remove tie-in w/ dma-buf.. after discussion w/ danvet and mlankorst > we decided that we need to be able to attach one fence to N dma-buf's, > so using the list_head in dma-fence struct would be problematic. > v5: [ Maarten Lankhorst ] Updated for dma-bikeshed-fence and dma-buf-manager. > v6: [ Maarten Lankhorst ] I removed dma_fence_cancel_callback and some > comments > about checking if fence fired or not. This is broken by design. > waitqueue_active during destruction is now fatal, since the signaller > should be holding a reference in enable_signalling until it signalled > the fence. Pass the original dma_fence_cb along, and call __remove_wait > in the dma_fence_callback handler, so that no cleanup needs to be > performed. > v7: [ Maarten Lankhorst ] Set cb->func and only enable sw signaling if > fence wasn't signaled yet, for example for hardware fences that may > choose to signal blindly. > v8: [ Maarten Lankhorst ] Tons of tiny fixes, moved __dma_fence_init to > header and fixed include mess. dma-fence.h now includes dma-buf.h > All members are now initialized, so kmalloc can be used for > allocating a dma-fence. More documentation added. > v9: Change compiler bitfields to flags, change return type of > enable_signaling to bool. Rework dma_fence_wait. Added > dma_fence_is_signaled and dma_fence_wait_timeout. > s/dma// and change exports to non GPL. Added fence_is_sign
Re: [Nouveau] [PATCH] drm/nouveau: fix ltcg memory initialization after suspend
On Mon, Aug 12, 2013 at 6:43 AM, Maarten Lankhorst wrote: > Some registers were not initialized in init, this causes them to be > uninitialized after suspend. > > Signed-off-by: Maarten Lankhorst > --- > diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c > b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c > index bcca883..7288940 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 { > struct nouveau_ltcg base; > u32 part_nr; > u32 subp_nr; > - struct nouveau_mm tags; > u32 num_tags; > + u32 tag_base; > + struct nouveau_mm tags; > struct nouveau_mm_node *tag_ram; > }; > > @@ -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; > 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) */ > priv->num_tags = (pfb->ram->size >> 17) / 4; > if (priv->num_tags > (1 << 17)) > @@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct > nvc0_ltcg_priv *priv) > tag_base += tag_align - 1; > 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); > > @@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct > nouveau_object *engine, > } > priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; > > - nv_mask(priv, 0x17e820, 0x0010, 0x); /* INTR_EN &= ~0x10 > */ > - > ret = nvc0_ltcg_init_tag_ram(pfb, priv); > if (ret) > return ret; > @@ -209,13 +204,36 @@ nvc0_ltcg_dtor(struct nouveau_object *object) > nouveau_ltcg_destroy(ltcg); > } > > +int > +nvc0_ltcg_init(struct nouveau_object *object) This should probably be a static int. > +{ > + struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; > + struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; > + struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent); Hm, it's all a bit confusing, but wouldn't nouveau_fb(ltcg) (or priv) work just fine here? nv_device looks at ->parent... but perhaps not hard enough :) > + int ret; > + > + ret = nouveau_subdev_init(&pfb->base); Should this bebase? (Or nouveau_ltcg_init(ltcg) for consistency...) > + if (ret) > + return ret; > + > + nv_mask(priv, 0x17e820, 0x0010, 0x); /* INTR_EN &= ~0x10 > */ > + > + nv_wr32(priv, 0x17e8d8, priv->part_nr); > + if (nv_device(pfb)->card_type >= NV_E0) > + nv_wr32(priv, 0x17e000, priv->part_nr); > + > + nv_wr32(priv, 0x17e8d4, priv->tag_base); > + > + return 0; > +} > + > struct nouveau_oclass > nvc0_ltcg_oclass = { > .handle = NV_SUBDEV(LTCG, 0xc0), > .ofuncs = &(struct nouveau_ofuncs) { > .ctor = nvc0_ltcg_ctor, > .dtor = nvc0_ltcg_dtor, > - .init = _nouveau_ltcg_init, > + .init = nvc0_ltcg_init, > .fini = _nouveau_ltcg_fini, > }, > }; > > ___ > Nouveau mailing list > nouv...@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/nouveau ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 00/53] Initial 3.12 radeon patches
This is the initial set of patches for 3.12 for radeon. The big changes here are adding ASPM and DPM support to CIK asics. There are also some cleanups related to removing bo copy support using the 3D engine in favor of the sDMA engines or CP DMA. For easier review the patches are also available here: http://cgit.freedesktop.org/~agd5f/linux/log/?h=drm-next-3.12-wip Alex Deucher (53): drm/radeon: switch r6xx+ to using CP DMA for the blit copy callback drm/radeon/kms: remove r6xx+ blit copy routines drm/radeon: add UVD->DPM helper function (v5) drm/radeon/dpm: use multiple UVD power states (v3) drm/radeon/dpm: rework thermal state handling drm/radeon: default to 1024M gart size on rv770+ drm/radeon/dpm: use performance state if no UVD state drm/radeon/kms: fix up dce8 display watermark calc for dpm drm/radeon/cik: implement some more atom helpers for DPM drm/radeon: switch CIK to use radeon_ucode.h drm/radeon/cik: add support for pcie gen1/2/3 switching drm/radeon: add support for ASPM on CIK asics drm/radeon/cik: restructure rlc setup drm/radeon: clean up sumo_rlc_init() for code sharing drm/radeon: convert SI,CIK to use sumo_rlc functions drm/radeon: implement clock and power gating for CIK (v3) drm/radeon: add indirect accessors for dift registers on CIK drm/radeon/sumo add helper to go from vid7 to vid2 drm/radeon: switch to pptable.h drm/radeon: add structs to store uvd clock voltage deps drm/radeon/cik: add rlc helpers for DPM drm/radeon: add support for thermal controller on KB/KV drm/radeon: add CI to r600_is_internal_thermal_sensor() drm/radeon: add KB/KV to r600_is_internal_thermal_sensor drm/radeon: add get_temperature() callbacks for CIK drm/radeon: adjust si_dpm function for code sharing drm/radeon/dpm: update cac leakage table parsing for CI drm/radeon/dpm: add support for parsing the atom powertune table drm/radeon/dpm: grab mvdd_dependency_on_mclk info from vbios drm/radeon: add structs to store vce clock voltage deps drm/radeon: add clock voltage dep tables for acp, samu drm/radeon: parse the vce clock voltage deps table drm/radeon: parse the uvd clock voltage deps table drm/radeon/dpm: clean up the extended table error pathes drm/radeon: parse the samu clock voltage deps table drm/radeon: parse the acp clock voltage deps table drm/radeon: add r600_get_pcie_lane_support helper drm/radeon/dpm: add vce clocks to radeon_ps drm/radeon/dpm: add a helper to encode pcie lane setting drm/radeon/dpm: add helper to fetch the vrefresh of the current mode drm/radeon/kms: add dpm support for KB/KV drm/radeon: add dpm support for CI dGPUs (v2) drm/radeon/dpm: add debugfs support for CI drm/radeon/dpm: implement force performance level for CI drm/radeon/dpm: implement vblank_too_short callback for CI drm/radeon/dpm: add debugfs support for KB/KV drm/radeon/dpm: implement force performance level for KB/KV drm/radeon/dpm: add new callback for powergating UVD (v3) drm/radeon: restructure UVD code to handle UVD PG (v2) drm/radeon/dpm: implement UVD powergating for KB/KV drm/radeon/dpm: implement UVD powergating for CI drm/radeon/dpm: add reclocking quirk for ASUS K70AF drm/radeon/dpm: adjust the vblank time checks for eg, ni, si drivers/gpu/drm/radeon/Makefile |7 +- drivers/gpu/drm/radeon/atombios.h | 615 +-- drivers/gpu/drm/radeon/cayman_blit_shaders.c| 54 - drivers/gpu/drm/radeon/ci_dpm.c | 5179 +++ drivers/gpu/drm/radeon/ci_dpm.h | 331 ++ drivers/gpu/drm/radeon/ci_smc.c | 262 ++ drivers/gpu/drm/radeon/cik.c| 2115 - drivers/gpu/drm/radeon/cik_reg.h|3 + drivers/gpu/drm/radeon/cikd.h | 589 ++- drivers/gpu/drm/radeon/clearstate_cayman.h |2 +- drivers/gpu/drm/radeon/clearstate_ci.h | 944 + drivers/gpu/drm/radeon/clearstate_evergreen.h |2 +- drivers/gpu/drm/radeon/cypress_dpm.c|3 +- drivers/gpu/drm/radeon/evergreen.c | 296 +- drivers/gpu/drm/radeon/evergreen_blit_kms.c | 729 drivers/gpu/drm/radeon/evergreen_blit_shaders.c | 54 - drivers/gpu/drm/radeon/kv_dpm.c | 2610 drivers/gpu/drm/radeon/kv_dpm.h | 199 + drivers/gpu/drm/radeon/kv_smc.c | 207 + drivers/gpu/drm/radeon/ni.c | 16 +- drivers/gpu/drm/radeon/ni_dpm.c |3 +- drivers/gpu/drm/radeon/ppsmc.h | 57 + drivers/gpu/drm/radeon/pptable.h| 682 +++ drivers/gpu/drm/radeon/r600.c | 100 +- drivers/gpu/drm/radeon/r600_blit.c | 31 + drivers/gpu/drm/radeon/r600_blit_kms.c | 785 drivers/gpu/drm/radeon/r600_blit_shaders.h |1 - drivers/gpu/drm/radeon/r600_dpm.c | 258 +- drivers/gpu/
[PATCH 01/53] drm/radeon: switch r6xx+ to using CP DMA for the blit copy callback
CP DMA is lighter weight than using the 3D engine. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_asic.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index f8f8b31..1926ec0 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -1022,7 +1022,7 @@ static struct radeon_asic r600_asic = { .hdmi_setmode = &r600_hdmi_setmode, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -1115,7 +1115,7 @@ static struct radeon_asic rv6xx_asic = { .get_backlight_level = &atombios_get_backlight_level, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -1226,7 +1226,7 @@ static struct radeon_asic rs780_asic = { .hdmi_setmode = &r600_hdmi_setmode, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -1348,7 +1348,7 @@ static struct radeon_asic rv770_asic = { .hdmi_setmode = &r600_hdmi_setmode, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &rv770_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -1473,7 +1473,7 @@ static struct radeon_asic evergreen_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &evergreen_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -1598,7 +1598,7 @@ static struct radeon_asic sumo_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &evergreen_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -1722,7 +1722,7 @@ static struct radeon_asic btc_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &evergreen_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -1899,7 +1899,7 @@ static struct radeon_asic cayman_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &evergreen_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -2074,7 +2074,7 @@ static struct radeon_asic trinity_asic = { .get_backlight_level = &atombios_get_backlight_level, }, .copy = { - .blit = &r600_copy_blit, + .blit = &r600_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &evergreen_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 03/53] drm/radeon: add UVD->DPM helper function (v5)
Add a helper function for counting the number of open stream handles. v2: fix copy-pasta in comments and whitespace error v3: make function static since it's only used in radeon_uvd.c at the moment v4: make non-static again for future changes v5: make static again for new rework of dpm uvd changes Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_uvd.c | 35 +++ 2 files changed, 36 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index a6da0db..23dc0c0 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1441,6 +1441,7 @@ struct radeon_uvd { void*saved_bo; atomic_thandles[RADEON_MAX_UVD_HANDLES]; struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; + unsignedimg_size[RADEON_MAX_UVD_HANDLES]; struct delayed_work idle_work; }; diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index b79f4f5..2a4cff1 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -147,6 +147,7 @@ int radeon_uvd_init(struct radeon_device *rdev) for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { atomic_set(&rdev->uvd.handles[i], 0); rdev->uvd.filp[i] = NULL; + rdev->uvd.img_size[i] = 0; } return 0; @@ -347,6 +348,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, unsigned offset, unsigned buf_sizes[]) { int32_t *msg, msg_type, handle; + unsigned img_size = 0; void *ptr; int i, r; @@ -383,6 +385,8 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, if (msg_type == 1) { /* it's a decode msg, calc buffer sizes */ r = radeon_uvd_cs_msg_decode(msg, buf_sizes); + /* calc image size (width * height) */ + img_size = msg[6] * msg[7]; radeon_bo_kunmap(bo); if (r) return r; @@ -394,6 +398,8 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, radeon_bo_kunmap(bo); return 0; } else { + /* it's a create msg, calc image size (width * height) */ + img_size = msg[7] * msg[8]; radeon_bo_kunmap(bo); if (msg_type != 0) { @@ -414,6 +420,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { p->rdev->uvd.filp[i] = p->filp; + p->rdev->uvd.img_size[i] = img_size; return 0; } } @@ -733,6 +740,34 @@ int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring, return radeon_uvd_send_msg(rdev, ring, bo, fence); } +/** + * radeon_uvd_count_handles - count number of open streams + * + * @rdev: radeon_device pointer + * @sd: number of SD streams + * @hd: number of HD streams + * + * Count the number of open SD/HD streams as a hint for power mangement + */ +static void radeon_uvd_count_handles(struct radeon_device *rdev, +unsigned *sd, unsigned *hd) +{ + unsigned i; + + *sd = 0; + *hd = 0; + + for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { + if (!atomic_read(&rdev->uvd.handles[i])) + continue; + + if (rdev->uvd.img_size[i] >= 720*576) + ++(*hd); + else + ++(*sd); + } +} + static void radeon_uvd_idle_work_handler(struct work_struct *work) { struct radeon_device *rdev = -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 04/53] drm/radeon/dpm: use multiple UVD power states (v3)
Use the UVD handle information to determine which which power states to select when using UVD. For example, decoding a single SD stream requires much lower clocks than multiple HD streams. v2: switch to a cleaner dpm/uvd interface v3: change the uvd power state while streams are active if need be Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 5 - drivers/gpu/drm/radeon/radeon_cs.c | 11 +++ drivers/gpu/drm/radeon/radeon_pm.c | 30 ++ drivers/gpu/drm/radeon/radeon_uvd.c | 23 --- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 23dc0c0..7196752 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1360,11 +1360,14 @@ struct radeon_dpm { struct radeon_dpm_thermal thermal; /* forced levels */ enum radeon_dpm_forced_level forced_level; + /* track UVD streams */ + unsigned sd; + unsigned hd; }; void radeon_dpm_enable_power_state(struct radeon_device *rdev, enum radeon_pm_state_type dpm_state); - +void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable); struct radeon_pm { struct mutexmutex; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 13a130f..5384fa4 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -383,6 +383,10 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, DRM_ERROR("Invalid command stream !\n"); return r; } + + if (parser->ring == R600_RING_TYPE_UVD_INDEX) + radeon_uvd_note_usage(rdev); + radeon_cs_sync_rings(parser); r = radeon_ib_schedule(rdev, &parser->ib, NULL); if (r) { @@ -474,6 +478,9 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, return r; } + if (parser->ring == R600_RING_TYPE_UVD_INDEX) + radeon_uvd_note_usage(rdev); + mutex_lock(&rdev->vm_manager.lock); mutex_lock(&vm->mutex); r = radeon_vm_alloc_pt(rdev, vm); @@ -552,10 +559,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) return r; } - /* XXX pick SD/HD/MVC */ - if (parser.ring == R600_RING_TYPE_UVD_INDEX) - radeon_uvd_note_usage(rdev); - r = radeon_cs_ib_chunk(rdev, &parser); if (r) { goto out; diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index c557850..59d7a0c 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -729,6 +729,8 @@ restart_search: /* use a fallback state if we didn't match */ switch (dpm_state) { case POWER_STATE_TYPE_INTERNAL_UVD_SD: + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + goto restart_search; case POWER_STATE_TYPE_INTERNAL_UVD_HD: case POWER_STATE_TYPE_INTERNAL_UVD_HD2: case POWER_STATE_TYPE_INTERNAL_UVD_MVC: @@ -884,6 +886,34 @@ void radeon_dpm_enable_power_state(struct radeon_device *rdev, radeon_pm_compute_clocks(rdev); } +void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) +{ + enum radeon_pm_state_type dpm_state; + + if (enable) { + mutex_lock(&rdev->pm.mutex); + rdev->pm.dpm.uvd_active = true; + if ((rdev->pm.dpm.sd == 1) && (rdev->pm.dpm.hd == 0)) + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_SD; + else if ((rdev->pm.dpm.sd == 2) && (rdev->pm.dpm.hd == 0)) + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 1)) + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 2)) + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD2; + else + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD; + rdev->pm.dpm.state = dpm_state; + mutex_unlock(&rdev->pm.mutex); + } else { + mutex_lock(&rdev->pm.mutex); + rdev->pm.dpm.uvd_active = false; + mutex_unlock(&rdev->pm.mutex); + } + + radeon_pm_compute_clocks(rdev); +} + static void radeon_pm_suspend_old(struct radeon_device *rdev) { mutex_lock(&rdev->pm.mutex); diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 2a4cff1..1a01bbf 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -775,10 +775,7 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work) if (radeon_fence_count_emitted(rdev,
[PATCH 05/53] drm/radeon/dpm: rework thermal state handling
1. Handle the the thermal state directly in the work handler. Remove the state selection function since nothing else uses it now. 2. On some asics there is no thermal state, so we just use a regular state and force the low performance state. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h| 2 -- drivers/gpu/drm/radeon/radeon_pm.c | 44 +- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 7196752..54edeab 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1365,8 +1365,6 @@ struct radeon_dpm { unsigned hd; }; -void radeon_dpm_enable_power_state(struct radeon_device *rdev, - enum radeon_pm_state_type dpm_state); void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable); struct radeon_pm { diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 59d7a0c..b72508b 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -624,7 +624,15 @@ static void radeon_dpm_thermal_work_handler(struct work_struct *work) /* switch back the user state */ dpm_state = rdev->pm.dpm.user_state; } - radeon_dpm_enable_power_state(rdev, dpm_state); + mutex_lock(&rdev->pm.mutex); + if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) + rdev->pm.dpm.thermal_active = true; + else + rdev->pm.dpm.thermal_active = false; + rdev->pm.dpm.state = dpm_state; + mutex_unlock(&rdev->pm.mutex); + + radeon_pm_compute_clocks(rdev); } static struct radeon_ps *radeon_dpm_pick_power_state(struct radeon_device *rdev, @@ -852,40 +860,18 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev) radeon_dpm_post_set_power_state(rdev); + /* force low perf level for thermal */ + if (rdev->pm.dpm.thermal_active && + rdev->asic->dpm.force_performance_level) { + radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_LOW); + } + done: mutex_unlock(&rdev->ring_lock); up_write(&rdev->pm.mclk_lock); mutex_unlock(&rdev->ddev->struct_mutex); } -void radeon_dpm_enable_power_state(struct radeon_device *rdev, - enum radeon_pm_state_type dpm_state) -{ - if (!rdev->pm.dpm_enabled) - return; - - mutex_lock(&rdev->pm.mutex); - switch (dpm_state) { - case POWER_STATE_TYPE_INTERNAL_THERMAL: - rdev->pm.dpm.thermal_active = true; - break; - case POWER_STATE_TYPE_INTERNAL_UVD: - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - rdev->pm.dpm.uvd_active = true; - break; - default: - rdev->pm.dpm.thermal_active = false; - rdev->pm.dpm.uvd_active = false; - break; - } - rdev->pm.dpm.state = dpm_state; - mutex_unlock(&rdev->pm.mutex); - radeon_pm_compute_clocks(rdev); -} - void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) { enum radeon_pm_state_type dpm_state; -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 06/53] drm/radeon: default to 1024M gart size on rv770+
Newer asics have a lot of vram so it's less of an issue to waste a little more space for the gart page table. This gives us some additional gart space before having to migrate to non-gart system ram for games, etc. where we use up most of vram. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 22 +- drivers/gpu/drm/radeon/radeon_drv.c| 4 ++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 63398ae..e887641 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1003,16 +1003,28 @@ static void radeon_check_arguments(struct radeon_device *rdev) radeon_vram_limit = 0; } + if (radeon_gart_size == -1) { + /* default to a larger gart size on newer asics */ + if (rdev->family >= CHIP_RV770) + radeon_gart_size = 1024; + else + radeon_gart_size = 512; + } /* gtt size must be power of two and greater or equal to 32M */ if (radeon_gart_size < 32) { - dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n", + dev_warn(rdev->dev, "gart size (%d) too small\n", radeon_gart_size); - radeon_gart_size = 512; - + if (rdev->family >= CHIP_RV770) + radeon_gart_size = 1024; + else + radeon_gart_size = 512; } else if (!radeon_check_pot_argument(radeon_gart_size)) { dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", radeon_gart_size); - radeon_gart_size = 512; + if (rdev->family >= CHIP_RV770) + radeon_gart_size = 1024; + else + radeon_gart_size = 512; } rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; @@ -1144,7 +1156,7 @@ int radeon_device_init(struct radeon_device *rdev, rdev->family = flags & RADEON_FAMILY_MASK; rdev->is_atom_bios = false; rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + rdev->mc.gtt_size = 512 * 1024 * 1024; rdev->accel_working = false; /* set up ring ids */ for (i = 0; i < RADEON_NUM_RINGS; i++) { diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 29876b1..62bd176 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -154,7 +154,7 @@ int radeon_dynclks = -1; int radeon_r4xx_atom = 0; int radeon_agpmode = 0; int radeon_vram_limit = 0; -int radeon_gart_size = 512; /* default gart size */ +int radeon_gart_size = -1; /* auto */ int radeon_benchmarking = 0; int radeon_testing = 0; int radeon_connector_table = 0; @@ -187,7 +187,7 @@ module_param_named(vramlimit, radeon_vram_limit, int, 0600); MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); module_param_named(agpmode, radeon_agpmode, int, 0444); -MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc)"); +MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc., -1 = auto)"); module_param_named(gartsize, radeon_gart_size, int, 0600); MODULE_PARM_DESC(benchmark, "Run benchmark"); -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 07/53] drm/radeon/dpm: use performance state if no UVD state
Newer asics don't have specific UVD states. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_pm.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index b72508b..79a03de 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -695,7 +695,10 @@ restart_search: break; /* internal states */ case POWER_STATE_TYPE_INTERNAL_UVD: - return rdev->pm.dpm.uvd_ps; + if (rdev->pm.dpm.uvd_ps) + return rdev->pm.dpm.uvd_ps; + else + break; case POWER_STATE_TYPE_INTERNAL_UVD_SD: if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) return ps; @@ -742,7 +745,12 @@ restart_search: case POWER_STATE_TYPE_INTERNAL_UVD_HD: case POWER_STATE_TYPE_INTERNAL_UVD_HD2: case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - return rdev->pm.dpm.uvd_ps; + if (rdev->pm.dpm.uvd_ps) { + return rdev->pm.dpm.uvd_ps; + } else { + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + } case POWER_STATE_TYPE_INTERNAL_THERMAL: dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; goto restart_search; -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 09/53] drm/radeon/cik: implement some more atom helpers for DPM
Required for DPM on CIK. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atombios.c | 115 +++ 1 file changed, 115 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 4ccd61f..27de73c 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -3077,6 +3077,121 @@ int radeon_atom_get_leakage_vddc_based_on_leakage_idx(struct radeon_device *rdev return radeon_atom_get_max_vddc(rdev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage); } +int radeon_atom_get_leakage_id_from_vbios(struct radeon_device *rdev, + u16 *leakage_id) +{ + union set_voltage args; + int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); + u8 frev, crev; + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return -EINVAL; + + switch (crev) { + case 3: + case 4: + args.v3.ucVoltageType = 0; + args.v3.ucVoltageMode = ATOM_GET_LEAKAGE_ID; + args.v3.usVoltageLevel = 0; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + *leakage_id = le16_to_cpu(args.v3.usVoltageLevel); + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); + return -EINVAL; + } + + return 0; +} + +int radeon_atom_get_leakage_vddc_based_on_leakage_params(struct radeon_device *rdev, +u16 *vddc, u16 *vddci, +u16 virtual_voltage_id, +u16 vbios_voltage_id) +{ + int index = GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo); + u8 frev, crev; + u16 data_offset, size; + int i, j; + ATOM_ASIC_PROFILING_INFO_V2_1 *profile; + u16 *leakage_bin, *vddc_id_buf, *vddc_buf, *vddci_id_buf, *vddci_buf; + + *vddc = 0; + *vddci = 0; + + if (!atom_parse_data_header(rdev->mode_info.atom_context, index, &size, + &frev, &crev, &data_offset)) + return -EINVAL; + + profile = (ATOM_ASIC_PROFILING_INFO_V2_1 *) + (rdev->mode_info.atom_context->bios + data_offset); + + switch (frev) { + case 1: + return -EINVAL; + case 2: + switch (crev) { + case 1: + if (size < sizeof(ATOM_ASIC_PROFILING_INFO_V2_1)) + return -EINVAL; + leakage_bin = (u16 *) + (rdev->mode_info.atom_context->bios + data_offset + +le16_to_cpu(profile->usLeakageBinArrayOffset)); + vddc_id_buf = (u16 *) + (rdev->mode_info.atom_context->bios + data_offset + +le16_to_cpu(profile->usElbVDDC_IdArrayOffset)); + vddc_buf = (u16 *) + (rdev->mode_info.atom_context->bios + data_offset + + le16_to_cpu(profile->usElbVDDC_LevelArrayOffset)); + vddci_id_buf = (u16 *) + (rdev->mode_info.atom_context->bios + data_offset + + le16_to_cpu(profile->usElbVDDCI_IdArrayOffset)); + vddci_buf = (u16 *) + (rdev->mode_info.atom_context->bios + data_offset + + le16_to_cpu(profile->usElbVDDCI_LevelArrayOffset)); + + if (profile->ucElbVDDC_Num > 0) { + for (i = 0; i < profile->ucElbVDDC_Num; i++) { + if (vddc_id_buf[i] == virtual_voltage_id) { + for (j = 0; j < profile->ucLeakageBinNum; j++) { + if (vbios_voltage_id <= leakage_bin[j]) { + *vddc = vddc_buf[j * profile->ucElbVDDC_Num + i]; + break; + } + } + break; + } + } + } + if (profile->ucElbVDDCI_Num > 0) { + for (i = 0; i < profile->ucElbVDDCI_Num; i++) { + if (vddci_id_buf[i] == virtual_voltage_id) { + for (j = 0; j < profile->ucLeakageBinNum; j++) { +
[PATCH 08/53] drm/radeon/kms: fix up dce8 display watermark calc for dpm
Calculate the low and high watermarks based on the low and high clocks for the current power state. The dynamic pm hw will select the appropriate watermark based on the internal dpm state. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 96 ++-- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 8928bd1..42b143e 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -6826,7 +6826,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev, u32 lb_size, u32 num_heads) { struct drm_display_mode *mode = &radeon_crtc->base.mode; - struct dce8_wm_params wm; + struct dce8_wm_params wm_low, wm_high; u32 pixel_period; u32 line_time = 0; u32 latency_watermark_a = 0, latency_watermark_b = 0; @@ -6836,35 +6836,82 @@ static void dce8_program_watermarks(struct radeon_device *rdev, pixel_period = 100 / (u32)mode->clock; line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); - wm.yclk = rdev->pm.current_mclk * 10; - wm.sclk = rdev->pm.current_sclk * 10; - wm.disp_clk = mode->clock; - wm.src_width = mode->crtc_hdisplay; - wm.active_time = mode->crtc_hdisplay * pixel_period; - wm.blank_time = line_time - wm.active_time; - wm.interlaced = false; + /* watermark for high clocks */ + if ((rdev->pm.pm_method == PM_METHOD_DPM) && + rdev->pm.dpm_enabled) { + wm_high.yclk = + radeon_dpm_get_mclk(rdev, false) * 10; + wm_high.sclk = + radeon_dpm_get_sclk(rdev, false) * 10; + } else { + wm_high.yclk = rdev->pm.current_mclk * 10; + wm_high.sclk = rdev->pm.current_sclk * 10; + } + + wm_high.disp_clk = mode->clock; + wm_high.src_width = mode->crtc_hdisplay; + wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.blank_time = line_time - wm_high.active_time; + wm_high.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) - wm.interlaced = true; - wm.vsc = radeon_crtc->vsc; - wm.vtaps = 1; + wm_high.interlaced = true; + wm_high.vsc = radeon_crtc->vsc; + wm_high.vtaps = 1; if (radeon_crtc->rmx_type != RMX_OFF) - wm.vtaps = 2; - wm.bytes_per_pixel = 4; /* XXX: get this from fb config */ - wm.lb_size = lb_size; - wm.dram_channels = cik_get_number_of_dram_channels(rdev); - wm.num_heads = num_heads; + wm_high.vtaps = 2; + wm_high.bytes_per_pixel = 4; /* XXX: get this from fb config */ + wm_high.lb_size = lb_size; + wm_high.dram_channels = cik_get_number_of_dram_channels(rdev); + wm_high.num_heads = num_heads; /* set for high clocks */ - latency_watermark_a = min(dce8_latency_watermark(&wm), (u32)65535); + latency_watermark_a = min(dce8_latency_watermark(&wm_high), (u32)65535); + + /* possibly force display priority to high */ + /* should really do this at mode validation time... */ + if (!dce8_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) || + !dce8_average_bandwidth_vs_available_bandwidth(&wm_high) || + !dce8_check_latency_hiding(&wm_high) || + (rdev->disp_priority == 2)) { + DRM_DEBUG_KMS("force priority to high\n"); + } + + /* watermark for low clocks */ + if ((rdev->pm.pm_method == PM_METHOD_DPM) && + rdev->pm.dpm_enabled) { + wm_low.yclk = + radeon_dpm_get_mclk(rdev, true) * 10; + wm_low.sclk = + radeon_dpm_get_sclk(rdev, true) * 10; + } else { + wm_low.yclk = rdev->pm.current_mclk * 10; + wm_low.sclk = rdev->pm.current_sclk * 10; + } + + wm_low.disp_clk = mode->clock; + wm_low.src_width = mode->crtc_hdisplay; + wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.blank_time = line_time - wm_low.active_time; + wm_low.interlaced = false; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + wm_low.interlaced = true; + wm_
[PATCH 10/53] drm/radeon: switch CIK to use radeon_ucode.h
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 17 + drivers/gpu/drm/radeon/radeon_ucode.h | 14 ++ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 42b143e..2ceb900 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -30,22 +30,7 @@ #include "cikd.h" #include "atom.h" #include "cik_blit_shaders.h" - -/* GFX */ -#define CIK_PFP_UCODE_SIZE 2144 -#define CIK_ME_UCODE_SIZE 2144 -#define CIK_CE_UCODE_SIZE 2144 -/* compute */ -#define CIK_MEC_UCODE_SIZE 4192 -/* interrupts */ -#define BONAIRE_RLC_UCODE_SIZE 2048 -#define KB_RLC_UCODE_SIZE 2560 -#define KV_RLC_UCODE_SIZE 2560 -/* gddr controller */ -#define CIK_MC_UCODE_SIZE 7866 -/* sdma */ -#define CIK_SDMA_UCODE_SIZE 1050 -#define CIK_SDMA_UCODE_VERSION 64 +#include "radeon_ucode.h" MODULE_FIRMWARE("radeon/BONAIRE_pfp.bin"); MODULE_FIRMWARE("radeon/BONAIRE_me.bin"); diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index d8b05f7..fad27c0 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h @@ -35,6 +35,12 @@ #define SI_PFP_UCODE_SIZE2144 #define SI_PM4_UCODE_SIZE2144 #define SI_CE_UCODE_SIZE 2144 +#define CIK_PFP_UCODE_SIZE 2144 +#define CIK_ME_UCODE_SIZE2144 +#define CIK_CE_UCODE_SIZE2144 + +/* MEC */ +#define CIK_MEC_UCODE_SIZE 4192 /* RLC */ #define R600_RLC_UCODE_SIZE 768 @@ -43,12 +49,20 @@ #define CAYMAN_RLC_UCODE_SIZE1024 #define ARUBA_RLC_UCODE_SIZE 1536 #define SI_RLC_UCODE_SIZE2048 +#define BONAIRE_RLC_UCODE_SIZE 2048 +#define KB_RLC_UCODE_SIZE2560 +#define KV_RLC_UCODE_SIZE2560 /* MC */ #define BTC_MC_UCODE_SIZE6024 #define CAYMAN_MC_UCODE_SIZE 6037 #define SI_MC_UCODE_SIZE 7769 #define OLAND_MC_UCODE_SIZE 7863 +#define CIK_MC_UCODE_SIZE7866 + +/* SDMA */ +#define CIK_SDMA_UCODE_SIZE 1050 +#define CIK_SDMA_UCODE_VERSION 64 /* SMC */ #define RV770_SMC_UCODE_START0x0100 -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 11/53] drm/radeon/cik: add support for pcie gen1/2/3 switching
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 161 ++ drivers/gpu/drm/radeon/cikd.h | 57 +++ 2 files changed, 218 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 2ceb900..a30fb32 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -61,6 +61,7 @@ extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *m extern void si_rlc_fini(struct radeon_device *rdev); extern int si_rlc_init(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); +static void cik_pcie_gen3_enable(struct radeon_device *rdev); /* * Indirect registers accessor @@ -5949,6 +5950,9 @@ static int cik_startup(struct radeon_device *rdev) struct radeon_ring *ring; int r; + /* enable pcie gen2/3 link */ + cik_pcie_gen3_enable(rdev); + cik_mc_program(rdev); if (rdev->flags & RADEON_IS_IGP) { @@ -7051,3 +7055,160 @@ int cik_uvd_resume(struct radeon_device *rdev) return 0; } + +static void cik_pcie_gen3_enable(struct radeon_device *rdev) +{ + struct pci_dev *root = rdev->pdev->bus->self; + int bridge_pos, gpu_pos; + u32 speed_cntl, mask, current_data_rate; + int ret, i; + u16 tmp16; + + if (radeon_pcie_gen2 == 0) + return; + + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); + if (ret != 0) + return; + + if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) + return; + + speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); + current_data_rate = (speed_cntl & LC_CURRENT_DATA_RATE_MASK) >> + LC_CURRENT_DATA_RATE_SHIFT; + if (mask & DRM_PCIE_SPEED_80) { + if (current_data_rate == 2) { + DRM_INFO("PCIE gen 3 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 3 link speeds, disable with radeon.pcie_gen2=0\n"); + } else if (mask & DRM_PCIE_SPEED_50) { + if (current_data_rate == 1) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); + } + + bridge_pos = pci_pcie_cap(root); + if (!bridge_pos) + return; + + gpu_pos = pci_pcie_cap(rdev->pdev); + if (!gpu_pos) + return; + + if (mask & DRM_PCIE_SPEED_80) { + /* re-try equalization if gen3 is not already enabled */ + if (current_data_rate != 2) { + u16 bridge_cfg, gpu_cfg; + u16 bridge_cfg2, gpu_cfg2; + u32 max_lw, current_lw, tmp; + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg); + pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg); + + tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD; + pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16); + + tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD; + pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16); + + tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1); + max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT; + current_lw = (tmp & LC_OPERATING_LINK_WIDTH_MASK) >> LC_OPERATING_LINK_WIDTH_SHIFT; + + if (current_lw < max_lw) { + tmp = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); + if (tmp & LC_RENEGOTIATION_SUPPORT) { + tmp &= ~(LC_LINK_WIDTH_MASK | LC_UPCONFIGURE_DIS); + tmp |= (max_lw << LC_LINK_WIDTH_SHIFT); + tmp |= LC_UPCONFIGURE_SUPPORT | LC_RENEGOTIATE_EN | LC_RECONFIG_NOW; + WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, tmp); + } + } + + for (i = 0; i < 10; i++) { + /* check status */ + pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_DEVSTA, &tmp16); + if (tmp16 & PCI_EXP_DEVSTA_TRPND) + break; + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg); + pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL,
[PATCH 12/53] drm/radeon: add support for ASPM on CIK asics
Enables PCIE ASPM (Active State Power Management) on CIK asics. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 151 ++ drivers/gpu/drm/radeon/cikd.h | 72 +++- 2 files changed, 222 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index a30fb32..0da9d67 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -62,6 +62,7 @@ extern void si_rlc_fini(struct radeon_device *rdev); extern int si_rlc_init(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); static void cik_pcie_gen3_enable(struct radeon_device *rdev); +static void cik_program_aspm(struct radeon_device *rdev); /* * Indirect registers accessor @@ -5952,6 +5953,8 @@ static int cik_startup(struct radeon_device *rdev) /* enable pcie gen2/3 link */ cik_pcie_gen3_enable(rdev); + /* enable aspm */ + cik_program_aspm(rdev); cik_mc_program(rdev); @@ -7212,3 +7215,151 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev) udelay(1); } } + +static void cik_program_aspm(struct radeon_device *rdev) +{ + u32 data, orig; + bool disable_l0s = false, disable_l1 = false, disable_plloff_in_l1 = false; + bool disable_clkreq = false; + + if (radeon_aspm == 0) + return; + + /* XXX double check IGPs */ + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + orig = data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL); + data &= ~LC_XMIT_N_FTS_MASK; + data |= LC_XMIT_N_FTS(0x24) | LC_XMIT_N_FTS_OVERRIDE_EN; + if (orig != data) + WREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL, data); + + orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL3); + data |= LC_GO_TO_RECOVERY; + if (orig != data) + WREG32_PCIE_PORT(PCIE_LC_CNTL3, data); + + orig = data = RREG32_PCIE_PORT(PCIE_P_CNTL); + data |= P_IGNORE_EDB_ERR; + if (orig != data) + WREG32_PCIE_PORT(PCIE_P_CNTL, data); + + orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL); + data &= ~(LC_L0S_INACTIVITY_MASK | LC_L1_INACTIVITY_MASK); + data |= LC_PMI_TO_L1_DIS; + if (!disable_l0s) + data |= LC_L0S_INACTIVITY(7); + + if (!disable_l1) { + data |= LC_L1_INACTIVITY(7); + data &= ~LC_PMI_TO_L1_DIS; + if (orig != data) + WREG32_PCIE_PORT(PCIE_LC_CNTL, data); + + if (!disable_plloff_in_l1) { + bool clk_req_support; + + orig = data = RREG32_PCIE_PORT(PB0_PIF_PWRDOWN_0); + data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK); + data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7); + if (orig != data) + WREG32_PCIE_PORT(PB0_PIF_PWRDOWN_0, data); + + orig = data = RREG32_PCIE_PORT(PB0_PIF_PWRDOWN_1); + data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK); + data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7); + if (orig != data) + WREG32_PCIE_PORT(PB0_PIF_PWRDOWN_1, data); + + orig = data = RREG32_PCIE_PORT(PB1_PIF_PWRDOWN_0); + data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK); + data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7); + if (orig != data) + WREG32_PCIE_PORT(PB1_PIF_PWRDOWN_0, data); + + orig = data = RREG32_PCIE_PORT(PB1_PIF_PWRDOWN_1); + data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK); + data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7); + if (orig != data) + WREG32_PCIE_PORT(PB1_PIF_PWRDOWN_1, data); + + orig = data = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); + data &= ~LC_DYN_LANES_PWR_STATE_MASK; + data |= LC_DYN_LANES_PWR_STATE(3); + if (orig != data) + WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data); + + if (!disable_clkreq) { + struct pci_dev *root = rdev->pdev->bus->self; + u32 lnkcap; + + clk_req_support = false; + pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap); + if (lnkcap & PCI_EXP_LNKCAP_CLKPM) +
[PATCH 13/53] drm/radeon/cik: restructure rlc setup
Restructure rlc setup to handle clock and power gating. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 84 +++ drivers/gpu/drm/radeon/cikd.h | 1 + drivers/gpu/drm/radeon/si.c | 2 +- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 0da9d67..e92a972 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -60,6 +60,7 @@ extern bool evergreen_is_display_hung(struct radeon_device *rdev); extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern void si_rlc_fini(struct radeon_device *rdev); extern int si_rlc_init(struct radeon_device *rdev); +extern void si_rlc_reset(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); static void cik_pcie_gen3_enable(struct radeon_device *rdev); static void cik_program_aspm(struct radeon_device *rdev); @@ -4728,31 +4729,34 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm * variety of functions, the most important of which is * the interrupt controller. */ -/** - * cik_rlc_stop - stop the RLC ME - * - * @rdev: radeon_device pointer - * - * Halt the RLC ME (MicroEngine) (CIK). - */ -static void cik_rlc_stop(struct radeon_device *rdev) +static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev, + bool enable) { - int i, j, k; - u32 mask, tmp; + u32 tmp = RREG32(CP_INT_CNTL_RING0); - tmp = RREG32(CP_INT_CNTL_RING0); - tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + if (enable) + tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + else + tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); WREG32(CP_INT_CNTL_RING0, tmp); +} - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); +static void cik_enable_lbpw(struct radeon_device *rdev, bool enable) +{ + u32 tmp; - tmp = RREG32(RLC_CGCG_CGLS_CTRL) & 0xfffc; - WREG32(RLC_CGCG_CGLS_CTRL, tmp); + tmp = RREG32(RLC_LB_CNTL); + if (enable) + tmp |= LOAD_BALANCE_ENABLE; + else + tmp &= ~LOAD_BALANCE_ENABLE; + WREG32(RLC_LB_CNTL, tmp); +} - WREG32(RLC_CNTL, 0); +static void cik_wait_for_rlc_serdes(struct radeon_device *rdev) +{ + u32 i, j, k; + u32 mask; for (i = 0; i < rdev->config.cik.max_shader_engines; i++) { for (j = 0; j < rdev->config.cik.max_sh_per_se; j++) { @@ -4775,6 +4779,32 @@ static void cik_rlc_stop(struct radeon_device *rdev) } /** + * cik_rlc_stop - stop the RLC ME + * + * @rdev: radeon_device pointer + * + * Halt the RLC ME (MicroEngine) (CIK). + */ +static void cik_rlc_stop(struct radeon_device *rdev) +{ + u32 tmp; + + cik_enable_gui_idle_interrupt(rdev, false); + + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + + tmp = RREG32(RLC_CGCG_CGLS_CTRL) & 0xfffc; + WREG32(RLC_CGCG_CGLS_CTRL, tmp); + + WREG32(RLC_CNTL, 0); + + cik_wait_for_rlc_serdes(rdev); +} + +/** * cik_rlc_start - start the RLC ME * * @rdev: radeon_device pointer @@ -4783,13 +4813,9 @@ static void cik_rlc_stop(struct radeon_device *rdev) */ static void cik_rlc_start(struct radeon_device *rdev) { - u32 tmp; - WREG32(RLC_CNTL, RLC_ENABLE); - tmp = RREG32(CP_INT_CNTL_RING0); - tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); - WREG32(CP_INT_CNTL_RING0, tmp); + cik_enable_gui_idle_interrupt(rdev, true); udelay(50); } @@ -4827,12 +4853,7 @@ static int cik_rlc_resume(struct radeon_device *rdev) cik_rlc_stop(rdev); - WREG32(GRBM_SOFT_RESET, SOFT_RESET_RLC); - RREG32(GRBM_SOFT_RESET); - udelay(50); - WREG32(GRBM_SOFT_RESET, 0); - RREG32(GRBM_SOFT_RESET); - udelay(50); + si_rlc_reset(rdev); WREG32(RLC_LB_CNTR_INIT, 0); WREG32(RLC_LB_CNTR_MAX, 0x8000); @@ -4851,6 +4872,9 @@ static int cik_rlc_resume(struct radeon_device *rdev) WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++)); WREG32(RLC_GPM_UCODE_ADDR, 0); + /* XXX - find out what chips support lbpw */ + cik_enable_lbpw(rdev, false); + /* XXX */ clear_state_info[0] = 0;//upper_32_bits(rdev->rlc.save_restore_gpu_addr); clear_state_info[1] = 0;//rdev->rlc.save_restore_gpu_addr; diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index d50593f..4742f3d 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -905,6 +905,7 @@ #define RLC_LB_CNTR_MAX 0xC348 #define RLC_LB
[PATCH 14/53] drm/radeon: clean up sumo_rlc_init() for code sharing
This will eventually be shared with newer asics to reduce code duplication. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen.c | 221 +++-- 1 file changed, 113 insertions(+), 108 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index a5ab569..6178408 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -3910,131 +3910,136 @@ int sumo_rlc_init(struct radeon_device *rdev) dws = rdev->rlc.reg_list_size; cs_data = rdev->rlc.cs_data; - /* save restore block */ - if (rdev->rlc.save_restore_obj == NULL) { - r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true, -RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.save_restore_obj); + if (src_ptr) { + /* save restore block */ + if (rdev->rlc.save_restore_obj == NULL) { + r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true, +RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.save_restore_obj); + if (r) { + dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); + return r; + } + } + + r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); + if (unlikely(r != 0)) { + sumo_rlc_fini(rdev); + return r; + } + r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->rlc.save_restore_gpu_addr); if (r) { - dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); + radeon_bo_unreserve(rdev->rlc.save_restore_obj); + dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); + sumo_rlc_fini(rdev); return r; } - } - r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); - if (unlikely(r != 0)) { - sumo_rlc_fini(rdev); - return r; - } - r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, - &rdev->rlc.save_restore_gpu_addr); - if (r) { + r = radeon_bo_kmap(rdev->rlc.save_restore_obj, (void **)&rdev->rlc.sr_ptr); + if (r) { + dev_warn(rdev->dev, "(%d) map RLC sr bo failed\n", r); + sumo_rlc_fini(rdev); + return r; + } + /* write the sr buffer */ + dst_ptr = rdev->rlc.sr_ptr; + /* format: +* dw0: (reg2 << 16) | reg1 +* dw1: reg1 save space +* dw2: reg2 save space +*/ + for (i = 0; i < dws; i++) { + data = src_ptr[i] >> 2; + i++; + if (i < dws) + data |= (src_ptr[i] >> 2) << 16; + j = (((i - 1) * 3) / 2); + dst_ptr[j] = data; + } + j = ((i * 3) / 2); + dst_ptr[j] = RLC_SAVE_RESTORE_LIST_END_MARKER; + + radeon_bo_kunmap(rdev->rlc.save_restore_obj); radeon_bo_unreserve(rdev->rlc.save_restore_obj); - dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); - sumo_rlc_fini(rdev); - return r; - } - r = radeon_bo_kmap(rdev->rlc.save_restore_obj, (void **)&rdev->rlc.sr_ptr); - if (r) { - dev_warn(rdev->dev, "(%d) map RLC sr bo failed\n", r); - sumo_rlc_fini(rdev); - return r; - } - /* write the sr buffer */ - dst_ptr = rdev->rlc.sr_ptr; - /* format: -* dw0: (reg2 << 16) | reg1 -* dw1: reg1 save space -* dw2: reg2 save space -*/ - for (i = 0; i < dws; i++) { - data = src_ptr[i] >> 2; - i++; - if (i < dws) - data |= (src_ptr[i] >> 2) << 16; - j = (((i - 1) * 3) / 2); - dst_ptr[j] = data; } - j = ((i * 3) / 2); - dst_ptr[j] = RLC_SAVE_RESTORE_LIST_END_MARKER; - - radeon_bo_kunmap(rdev->rlc.save_restore_obj); - radeon_bo_unreserve(rdev->rlc.save_restore_obj); - /* clear state block */ - reg_list_num = 0; - dws = 0; - for (i = 0; cs_data[i].section != NULL; i++) { - for (j = 0; cs_data[i].section[j].extent != NULL; j++) { - reg_list_num++; - dws += cs_data[i].section[j].reg_count; + if (cs_data) { + /* clear state block */ + reg_list_num = 0; +
[PATCH 15/53] drm/radeon: convert SI,CIK to use sumo_rlc functions
and remove duplicate si_rlc functions. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 10 +- drivers/gpu/drm/radeon/clearstate_cayman.h| 2 +- drivers/gpu/drm/radeon/clearstate_evergreen.h | 2 +- drivers/gpu/drm/radeon/evergreen.c| 46 --- drivers/gpu/drm/radeon/ni.c | 6 +- drivers/gpu/drm/radeon/radeon.h | 4 +- drivers/gpu/drm/radeon/si.c | 174 ++ 7 files changed, 49 insertions(+), 195 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index e92a972..8389917 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -57,9 +57,9 @@ extern void r600_ih_ring_fini(struct radeon_device *rdev); extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); extern bool evergreen_is_display_hung(struct radeon_device *rdev); +extern void sumo_rlc_fini(struct radeon_device *rdev); +extern int sumo_rlc_init(struct radeon_device *rdev); extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); -extern void si_rlc_fini(struct radeon_device *rdev); -extern int si_rlc_init(struct radeon_device *rdev); extern void si_rlc_reset(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); static void cik_pcie_gen3_enable(struct radeon_device *rdev); @@ -6019,7 +6019,7 @@ static int cik_startup(struct radeon_device *rdev) cik_gpu_init(rdev); /* allocate rlc buffers */ - r = si_rlc_init(rdev); + r = sumo_rlc_init(rdev); if (r) { DRM_ERROR("Failed to init rlc BOs!\n"); return r; @@ -6343,7 +6343,7 @@ int cik_init(struct radeon_device *rdev) cik_cp_fini(rdev); cik_sdma_fini(rdev); cik_irq_fini(rdev); - si_rlc_fini(rdev); + sumo_rlc_fini(rdev); cik_mec_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -6379,7 +6379,7 @@ void cik_fini(struct radeon_device *rdev) cik_cp_fini(rdev); cik_sdma_fini(rdev); cik_irq_fini(rdev); - si_rlc_fini(rdev); + sumo_rlc_fini(rdev); cik_mec_fini(rdev); radeon_wb_fini(rdev); radeon_vm_manager_fini(rdev); diff --git a/drivers/gpu/drm/radeon/clearstate_cayman.h b/drivers/gpu/drm/radeon/clearstate_cayman.h index c003394..aa908c5 100644 --- a/drivers/gpu/drm/radeon/clearstate_cayman.h +++ b/drivers/gpu/drm/radeon/clearstate_cayman.h @@ -1073,7 +1073,7 @@ static const struct cs_extent_def SECT_CTRLCONST_defs[] = {SECT_CTRLCONST_def_1, 0xf3fc, 2 }, { 0, 0, 0 } }; -struct cs_section_def cayman_cs_data[] = { +static const struct cs_section_def cayman_cs_data[] = { { SECT_CONTEXT_defs, SECT_CONTEXT }, { SECT_CLEAR_defs, SECT_CLEAR }, { SECT_CTRLCONST_defs, SECT_CTRLCONST }, diff --git a/drivers/gpu/drm/radeon/clearstate_evergreen.h b/drivers/gpu/drm/radeon/clearstate_evergreen.h index 4791d85..63a1ffb 100644 --- a/drivers/gpu/drm/radeon/clearstate_evergreen.h +++ b/drivers/gpu/drm/radeon/clearstate_evergreen.h @@ -1072,7 +1072,7 @@ static const struct cs_extent_def SECT_CTRLCONST_defs[] = {SECT_CTRLCONST_def_1, 0xf3fc, 2 }, { 0, 0, 0 } }; -struct cs_section_def evergreen_cs_data[] = { +static const struct cs_section_def evergreen_cs_data[] = { { SECT_CONTEXT_defs, SECT_CONTEXT }, { SECT_CLEAR_defs, SECT_CLEAR }, { SECT_CTRLCONST_defs, SECT_CTRLCONST }, diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 6178408..6fc876a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -47,7 +47,7 @@ static const u32 crtc_offsets[6] = #include "clearstate_evergreen.h" -static u32 sumo_rlc_save_restore_register_list[] = +static const u32 sumo_rlc_save_restore_register_list[] = { 0x98fc, 0x9830, @@ -131,7 +131,6 @@ static u32 sumo_rlc_save_restore_register_list[] = 0x9150, 0x802c, }; -static u32 sumo_rlc_save_restore_register_list_size = ARRAY_SIZE(sumo_rlc_save_restore_register_list); static void evergreen_gpu_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); @@ -3898,12 +3897,12 @@ void sumo_rlc_fini(struct radeon_device *rdev) int sumo_rlc_init(struct radeon_device *rdev) { - u32 *src_ptr; + const u32 *src_ptr; volatile u32 *dst_ptr; u32 dws, data, i, j, k, reg_num; u32 reg_list_num, reg_list_hdr_blk_index, reg_list_blk_index; u64 reg_list_mc_addr; - struct cs_section_def *cs_data; + const struct cs_section_def *cs_data; int r; src_ptr = rdev->rlc.reg_list; @@ -3943,22 +3942,28 @@ int sumo_rlc_
[PATCH 17/53] drm/radeon: add indirect accessors for dift registers on CIK
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik_reg.h | 3 +++ drivers/gpu/drm/radeon/radeon.h | 18 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik_reg.h b/drivers/gpu/drm/radeon/cik_reg.h index d71e46d..ca1bb61 100644 --- a/drivers/gpu/drm/radeon/cik_reg.h +++ b/drivers/gpu/drm/radeon/cik_reg.h @@ -24,6 +24,9 @@ #ifndef __CIK_REG_H__ #define __CIK_REG_H__ +#define CIK_DIDT_IND_INDEX0xca00 +#define CIK_DIDT_IND_DATA 0xca04 + #define CIK_DC_GPIO_HPD_MASK 0x65b0 #define CIK_DC_GPIO_HPD_A 0x65b4 #define CIK_DC_GPIO_HPD_EN0x65b8 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ed241d6..37b0fc4 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2141,6 +2141,8 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v); #define WREG32_PIF_PHY1(reg, v) eg_pif_phy1_wreg(rdev, (reg), (v)) #define RREG32_UVD_CTX(reg) r600_uvd_ctx_rreg(rdev, (reg)) #define WREG32_UVD_CTX(reg, v) r600_uvd_ctx_wreg(rdev, (reg), (v)) +#define RREG32_DIDT(reg) cik_didt_rreg(rdev, (reg)) +#define WREG32_DIDT(reg, v) cik_didt_wreg(rdev, (reg), (v)) #define WREG32_P(reg, val, mask) \ do {\ uint32_t tmp_ = RREG32(reg);\ @@ -2272,6 +2274,22 @@ static inline void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v) WREG32(R600_UVD_CTX_DATA, (v)); } + +static inline u32 cik_didt_rreg(struct radeon_device *rdev, u32 reg) +{ + u32 r; + + WREG32(CIK_DIDT_IND_INDEX, (reg)); + r = RREG32(CIK_DIDT_IND_DATA); + return r; +} + +static inline void cik_didt_wreg(struct radeon_device *rdev, u32 reg, u32 v) +{ + WREG32(CIK_DIDT_IND_INDEX, (reg)); + WREG32(CIK_DIDT_IND_DATA, (v)); +} + void r100_pll_errata_after_index(struct radeon_device *rdev); -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 18/53] drm/radeon/sumo add helper to go from vid7 to vid2
Needed for DPM on KB/KV. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/sumo_dpm.c | 14 ++ drivers/gpu/drm/radeon/sumo_dpm.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index c0a8503..2cefe59 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c @@ -1530,6 +1530,20 @@ u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; } +u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_7bit) +{ + u32 i; + + for (i = 0; i < vid_mapping_table->num_entries; i++) { + if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) + return vid_mapping_table->entries[i].vid_2bit; + } + + return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; +} + static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev, u32 vid_2bit) { diff --git a/drivers/gpu/drm/radeon/sumo_dpm.h b/drivers/gpu/drm/radeon/sumo_dpm.h index 07dda29..db1ea32 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.h +++ b/drivers/gpu/drm/radeon/sumo_dpm.h @@ -202,6 +202,9 @@ void sumo_construct_vid_mapping_table(struct radeon_device *rdev, u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, struct sumo_vid_mapping_table *vid_mapping_table, u32 vid_2bit); +u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_7bit); u32 sumo_get_sleep_divider_from_id(u32 id); u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev, u32 sclk, -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 19/53] drm/radeon: switch to pptable.h
Internally we switched to using a separate header for atombios pplib definitions. Switch over the open source driver. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios.h | 615 +- drivers/gpu/drm/radeon/pptable.h | 682 ++ 2 files changed, 685 insertions(+), 612 deletions(-) create mode 100644 drivers/gpu/drm/radeon/pptable.h diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 16b120c..af10f85 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -7661,618 +7661,6 @@ typedef struct _ATOM_POWERPLAY_INFO_V3 ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; }ATOM_POWERPLAY_INFO_V3; -/* New PPlib */ -/**/ -typedef struct _ATOM_PPLIB_THERMALCONTROLLER - -{ -UCHAR ucType; // one of ATOM_PP_THERMALCONTROLLER_* -UCHAR ucI2cLine;// as interpreted by DAL I2C -UCHAR ucI2cAddress; -UCHAR ucFanParameters; // Fan Control Parameters. -UCHAR ucFanMinRPM; // Fan Minimum RPM (hundreds) -- for display purposes only. -UCHAR ucFanMaxRPM; // Fan Maximum RPM (hundreds) -- for display purposes only. -UCHAR ucReserved; // -UCHAR ucFlags; // to be defined -} ATOM_PPLIB_THERMALCONTROLLER; - -#define ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f -#define ATOM_PP_FANPARAMETERS_NOFAN 0x80// No fan is connected to this controller. - -#define ATOM_PP_THERMALCONTROLLER_NONE 0 -#define ATOM_PP_THERMALCONTROLLER_LM63 1 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_ADM1032 2 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_ADM1030 3 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_MUA6649 4 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_LM64 5 -#define ATOM_PP_THERMALCONTROLLER_F753756 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_RV6xx 7 -#define ATOM_PP_THERMALCONTROLLER_RV770 8 -#define ATOM_PP_THERMALCONTROLLER_ADT7473 9 -#define ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO 11 -#define ATOM_PP_THERMALCONTROLLER_EVERGREEN 12 -#define ATOM_PP_THERMALCONTROLLER_EMC2103 13 /* 0x0D */ // Only fan control will be implemented, do NOT show this in PPGen. -#define ATOM_PP_THERMALCONTROLLER_SUMO 14 /* 0x0E */ // Sumo type, used internally -#define ATOM_PP_THERMALCONTROLLER_NISLANDS 15 -#define ATOM_PP_THERMALCONTROLLER_SISLANDS 16 -#define ATOM_PP_THERMALCONTROLLER_LM96163 17 -#define ATOM_PP_THERMALCONTROLLER_CISLANDS 18 - -// Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. -// We probably should reserve the bit 0x80 for this use. -// To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). -// The driver can pick the correct internal controller based on the ASIC. - -#define ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89// ADT7473 Fan Control + Internal Thermal Controller -#define ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D// EMC2103 Fan Control + Internal Thermal Controller - -typedef struct _ATOM_PPLIB_STATE -{ -UCHAR ucNonClockStateIndex; -UCHAR ucClockStateIndices[1]; // variable-sized -} ATOM_PPLIB_STATE; - - -typedef struct _ATOM_PPLIB_FANTABLE -{ -UCHAR ucFanTableFormat;// Change this if the table format changes or version changes so that the other fields are not the same. -UCHAR ucTHyst; // Temperature hysteresis. Integer. -USHORT usTMin; // The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. -USHORT usTMed; // The middle temperature where we change slopes. -USHORT usTHigh; // The high point above TMed for adjusting the second slope. -USHORT usPWMMin;// The minimum PWM value in percent (0.01% increments). -USHORT usPWMMed;// The PWM value (in percent) at TMed. -USHORT usPWMHigh; // The PWM value at THigh. -} ATOM_PPLIB_FANTABLE; - -typedef struct _ATOM_PPLIB_FANTABLE2 -{ -ATOM_PPLIB_FANTABLE basicTable; -USHORT usTMax; // The max temperature -} ATOM_PPLIB_FANTABLE2; - -typedef struct _ATOM_PPLIB_EXTENDEDHEADER -{ -USHORT usSize; -ULONG ulMaxEngineClock; // For Overdrive. -ULONG ulMaxMemoryClock; // For Overdrive. -// Add extra system parameters here, always adjust size to include all fields. -USHORT usVCETableOffset; //points to ATOM_PPLIB_VCE_Table -USHORT usUVDTableOffset; //points to ATOM_PPLIB_UVD_Table -USHORT usSAMUTable
[PATCH 21/53] drm/radeon/cik: add rlc helpers for DPM
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 29 + drivers/gpu/drm/radeon/cikd.h | 9 + 2 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index a36e98c..727c296 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -5587,6 +5587,35 @@ static u32 cik_halt_rlc(struct radeon_device *rdev) return orig; } +void cik_enter_rlc_safe_mode(struct radeon_device *rdev) +{ + u32 tmp, i, mask; + + tmp = REQ | MESSAGE(MSG_ENTER_RLC_SAFE_MODE); + WREG32(RLC_GPR_REG2, tmp); + + mask = GFX_POWER_STATUS | GFX_CLOCK_STATUS; + for (i = 0; i < rdev->usec_timeout; i++) { + if ((RREG32(RLC_GPM_STAT) & mask) == mask) + break; + udelay(1); + } + + for (i = 0; i < rdev->usec_timeout; i++) { + if ((RREG32(RLC_GPR_REG2) & REQ) == 0) + break; + udelay(1); + } +} + +void cik_exit_rlc_safe_mode(struct radeon_device *rdev) +{ + u32 tmp; + + tmp = REQ | MESSAGE(MSG_EXIT_RLC_SAFE_MODE); + WREG32(RLC_GPR_REG2, tmp); +} + /** * cik_rlc_stop - stop the RLC ME * diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 63955ab..116b313 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -952,6 +952,8 @@ #define RLC_GPM_STAT 0xC400 # define RLC_GPM_BUSY (1 << 0) +# define GFX_POWER_STATUS (1 << 1) +# define GFX_CLOCK_STATUS (1 << 2) #define RLC_PG_CNTL 0xC40C # define GFX_PG_ENABLE (1 << 0) @@ -1004,6 +1006,13 @@ #define RLC_GPM_SCRATCH_ADDR 0xC4B0 #define RLC_GPM_SCRATCH_DATA 0xC4B4 +#define RLC_GPR_REG2 0xC4E8 +#defineREQ 0x0001 +#defineMESSAGE(x) ((x) << 1) +#defineMESSAGE_MASK0x001e +#defineMSG_ENTER_RLC_SAFE_MODE 1 +#defineMSG_EXIT_RLC_SAFE_MODE 0 + #define CP_HPD_EOP_BASE_ADDR 0xC904 #define CP_HPD_EOP_BASE_ADDR_HI 0xC908 #define CP_HPD_EOP_VMID 0xC90C -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 22/53] drm/radeon: add support for thermal controller on KB/KV
No support for reading temperature back yet. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_atombios.c | 5 + 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 00d154d..876f423 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1132,6 +1132,7 @@ enum radeon_int_thermal_type { THERMAL_TYPE_SI, THERMAL_TYPE_EMC2103_WITH_INTERNAL, THERMAL_TYPE_CI, + THERMAL_TYPE_KV, }; struct radeon_voltage { diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 27de73c..6247b5e 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2237,6 +2237,11 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); rdev->pm.int_thermal_type = THERMAL_TYPE_CI; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) { + DRM_INFO("Internal thermal controller %s fan control\n", +(controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_KV; } else if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || (controller->ucType == -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 20/53] drm/radeon: add structs to store uvd clock voltage deps
Used for uvd power management. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 12 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 37b0fc4..00d154d 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1276,6 +1276,17 @@ struct radeon_phase_shedding_limits_table { struct radeon_phase_shedding_limits_entry *entries; }; +struct radeon_uvd_clock_voltage_dependency_entry { + u32 vclk; + u32 dclk; + u16 v; +}; + +struct radeon_uvd_clock_voltage_dependency_table { + u8 count; + struct radeon_uvd_clock_voltage_dependency_entry *entries; +}; + struct radeon_ppm_table { u8 ppm_design; u16 cpu_core_number; @@ -1294,6 +1305,7 @@ struct radeon_dpm_dynamic_state { struct radeon_clock_voltage_dependency_table vddci_dependency_on_mclk; struct radeon_clock_voltage_dependency_table vddc_dependency_on_mclk; struct radeon_clock_voltage_dependency_table vddc_dependency_on_dispclk; + struct radeon_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table; struct radeon_clock_array valid_sclk_values; struct radeon_clock_array valid_mclk_values; struct radeon_clock_and_voltage_limits max_clock_voltage_on_dc; -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 24/53] drm/radeon: add KB/KV to r600_is_internal_thermal_sensor
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index e246e3a..d54a838 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -746,6 +746,7 @@ bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor) case THERMAL_TYPE_NI: case THERMAL_TYPE_SI: case THERMAL_TYPE_CI: + case THERMAL_TYPE_KV: return true; case THERMAL_TYPE_ADT7473_WITH_INTERNAL: case THERMAL_TYPE_EMC2103_WITH_INTERNAL: -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 23/53] drm/radeon: add CI to r600_is_internal_thermal_sensor()
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index e5c860f..e246e3a 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -745,6 +745,7 @@ bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor) case THERMAL_TYPE_SUMO: case THERMAL_TYPE_NI: case THERMAL_TYPE_SI: + case THERMAL_TYPE_CI: return true; case THERMAL_TYPE_ADT7473_WITH_INTERNAL: case THERMAL_TYPE_EMC2103_WITH_INTERNAL: -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 25/53] drm/radeon: add get_temperature() callbacks for CIK
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 37 drivers/gpu/drm/radeon/cikd.h| 8 drivers/gpu/drm/radeon/radeon_asic.c | 2 ++ drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ drivers/gpu/drm/radeon/radeon_pm.c | 2 ++ 5 files changed, 51 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 727c296..d0804f7 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -69,6 +69,43 @@ static void cik_program_aspm(struct radeon_device *rdev); static void cik_init_pg(struct radeon_device *rdev); static void cik_init_cg(struct radeon_device *rdev); +/* get temperature in millidegrees */ +int ci_get_temp(struct radeon_device *rdev) +{ + u32 temp; + int actual_temp = 0; + + temp = (RREG32_SMC(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >> + CTF_TEMP_SHIFT; + + if (temp & 0x200) + actual_temp = 255; + else + actual_temp = temp & 0x1ff; + + actual_temp = actual_temp * 1000; + + return actual_temp; +} + +/* get temperature in millidegrees */ +int kv_get_temp(struct radeon_device *rdev) +{ + u32 temp; + int actual_temp = 0; + + temp = RREG32_SMC(0xC0300E0C); + + if (temp) + actual_temp = (temp / 8) - 49; + else + actual_temp = 0; + + actual_temp = actual_temp * 1000; + + return actual_temp; +} + /* * Indirect registers accessor */ diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 116b313..b66518a 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -32,6 +32,14 @@ #define GENERAL_PWRMGT0xC020 # define GPU_COUNTER_CLK(1 << 15) +#defineCG_MULT_THERMAL_STATUS 0xC0300010 +#defineASIC_MAX_TEMP(x)((x) << 0) +#defineASIC_MAX_TEMP_MASK 0x01ff +#defineASIC_MAX_TEMP_SHIFT 0 +#defineCTF_TEMP(x) ((x) << 9) +#defineCTF_TEMP_MASK 0x0003fe00 +#defineCTF_TEMP_SHIFT 9 + #defineMPLL_BYPASSCLK_SEL 0xC050019C # define MPLL_CLKOUT_SEL(x) ((x) << 8) # define MPLL_CLKOUT_SEL_MASK 0xFF00 diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 880551b..3a55540 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2452,6 +2452,7 @@ static struct radeon_asic ci_asic = { .set_pcie_lanes = NULL, .set_clock_gating = NULL, .set_uvd_clocks = &cik_set_uvd_clocks, + .get_temperature = &ci_get_temp, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, @@ -2607,6 +2608,7 @@ static struct radeon_asic kv_asic = { .set_pcie_lanes = NULL, .set_clock_gating = NULL, .set_uvd_clocks = &cik_set_uvd_clocks, + .get_temperature = &kv_get_temp, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 3cf7d89..d5c6c5b 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -747,5 +747,7 @@ u32 cik_compute_ring_get_wptr(struct radeon_device *rdev, struct radeon_ring *ring); void cik_compute_ring_set_wptr(struct radeon_device *rdev, struct radeon_ring *ring); +int ci_get_temp(struct radeon_device *rdev); +int kv_get_temp(struct radeon_device *rdev); #endif diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 79a03de..1408014 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -569,6 +569,8 @@ static int radeon_hwmon_init(struct radeon_device *rdev) case THERMAL_TYPE_NI: case THERMAL_TYPE_SUMO: case THERMAL_TYPE_SI: + case THERMAL_TYPE_CI: + case THERMAL_TYPE_KV: if (rdev->asic->pm.get_temperature == NULL) return err; rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 26/53] drm/radeon: adjust si_dpm function for code sharing
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si_dpm.c | 21 ++--- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 88699e3..0f8be48 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -3759,19 +3759,20 @@ static bool si_validate_phase_shedding_tables(struct radeon_device *rdev, } static void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev, +u32 max_voltage_steps, struct atom_voltage_table *voltage_table) { unsigned int i, diff; - if (voltage_table->count <= SISLANDS_MAX_NO_VREG_STEPS) + if (voltage_table->count <= max_voltage_steps) return; - diff = voltage_table->count - SISLANDS_MAX_NO_VREG_STEPS; + diff = voltage_table->count - max_voltage_steps; - for (i= 0; i < SISLANDS_MAX_NO_VREG_STEPS; i++) + for (i= 0; i < max_voltage_steps; i++) voltage_table->entries[i] = voltage_table->entries[i + diff]; - voltage_table->count = SISLANDS_MAX_NO_VREG_STEPS; + voltage_table->count = max_voltage_steps; } static int si_construct_voltage_tables(struct radeon_device *rdev) @@ -3787,7 +3788,9 @@ static int si_construct_voltage_tables(struct radeon_device *rdev) return ret; if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) - si_trim_voltage_table_to_fit_state_table(rdev, &eg_pi->vddc_voltage_table); + si_trim_voltage_table_to_fit_state_table(rdev, + SISLANDS_MAX_NO_VREG_STEPS, + &eg_pi->vddc_voltage_table); if (eg_pi->vddci_control) { ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDCI, @@ -3796,7 +3799,9 @@ static int si_construct_voltage_tables(struct radeon_device *rdev) return ret; if (eg_pi->vddci_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) - si_trim_voltage_table_to_fit_state_table(rdev, &eg_pi->vddci_voltage_table); + si_trim_voltage_table_to_fit_state_table(rdev, + SISLANDS_MAX_NO_VREG_STEPS, + &eg_pi->vddci_voltage_table); } if (pi->mvdd_control) { @@ -3814,7 +3819,9 @@ static int si_construct_voltage_tables(struct radeon_device *rdev) } if (si_pi->mvdd_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) - si_trim_voltage_table_to_fit_state_table(rdev, &si_pi->mvdd_voltage_table); + si_trim_voltage_table_to_fit_state_table(rdev, + SISLANDS_MAX_NO_VREG_STEPS, + &si_pi->mvdd_voltage_table); } if (si_pi->vddc_phase_shed_control) { -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 27/53] drm/radeon/dpm: update cac leakage table parsing for CI
Uses a different table format if the board supports EVV. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 17 + drivers/gpu/drm/radeon/radeon.h | 15 +++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index d54a838..ccdf770 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -956,10 +956,19 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) return -ENOMEM; } for (i = 0; i < cac_table->ucNumEntries; i++) { - rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = - le16_to_cpu(cac_table->entries[i].usVddc); - rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = - le32_to_cpu(cac_table->entries[i].ulLeakageValue); + if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { + rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = + le16_to_cpu(cac_table->entries[i].usVddc1); + rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = + le16_to_cpu(cac_table->entries[i].usVddc2); + rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = + le16_to_cpu(cac_table->entries[i].usVddc3); + } else { + rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = + le16_to_cpu(cac_table->entries[i].usVddc); + rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = + le32_to_cpu(cac_table->entries[i].ulLeakageValue); + } } rdev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 876f423..e6541e3 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1256,14 +1256,21 @@ struct radeon_clock_voltage_dependency_table { struct radeon_clock_voltage_dependency_entry *entries; }; -struct radeon_cac_leakage_entry { - u16 vddc; - u32 leakage; +union radeon_cac_leakage_entry { + struct { + u16 vddc; + u32 leakage; + }; + struct { + u16 vddc1; + u16 vddc2; + u16 vddc3; + }; }; struct radeon_cac_leakage_table { u32 count; - struct radeon_cac_leakage_entry *entries; + union radeon_cac_leakage_entry *entries; }; struct radeon_phase_shedding_limits_entry { -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 31/53] drm/radeon: add clock voltage dep tables for acp, samu
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index d21fa20..661e7c1 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1338,6 +1338,8 @@ struct radeon_dpm_dynamic_state { struct radeon_clock_voltage_dependency_table vddc_dependency_on_dispclk; struct radeon_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table; struct radeon_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table; + struct radeon_clock_voltage_dependency_table samu_clock_voltage_dependency_table; + struct radeon_clock_voltage_dependency_table acp_clock_voltage_dependency_table; struct radeon_clock_array valid_sclk_values; struct radeon_clock_array valid_mclk_values; struct radeon_clock_and_voltage_limits max_clock_voltage_on_dc; -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 33/53] drm/radeon: parse the uvd clock voltage deps table
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 40 +++ 1 file changed, 40 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index b49b0f0..c103d3f 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -1030,6 +1030,42 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) le16_to_cpu(limits->entries[i].usVoltage); } } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && + ext_hdr->usUVDTableOffset) { + UVDClockInfoArray *array = (UVDClockInfoArray *) + (mode_info->atom_context->bios + data_offset + +le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = + (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + +le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + +1 + (array->ucNumEntries * sizeof (UVDClockInfo))); + u32 size = limits->numEntries * + sizeof(struct radeon_uvd_clock_voltage_dependency_entry); + rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); + kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); + kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries); + return -ENOMEM; + } + rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = + limits->numEntries; + for (i = 0; i < limits->numEntries; i++) { + UVDClockInfo *uvd_clk = + &array->entries[limits->entries[i].ucUVDClockInfoIndex]; + rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = + le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); + rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = + le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); + rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(limits->entries[i].usVoltage); + } + } if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && ext_hdr->usPPMTableOffset) { ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) @@ -1044,6 +1080,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries); + kfree(rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries); return -ENOMEM; } rdev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; @@ -1081,6 +1118,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); kfree(rdev->pm.dpm.dyn_state.ppm_table); kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries); + kfree(rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries); return -ENOMEM; } if (rev > 0) { @@ -1135,6 +1173,8 @@ void r600_free_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.cac_tdp_t
[PATCH 34/53] drm/radeon/dpm: clean up the extended table error pathes
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 40 ++- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index c103d3f..98db6ea 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -919,10 +919,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) sizeof(struct radeon_phase_shedding_limits_entry), GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); + r600_free_extended_power_table(rdev); return -ENOMEM; } @@ -964,10 +961,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) u32 size = cac_table->ucNumEntries * sizeof(struct radeon_cac_leakage_table); rdev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.cac_leakage_table.entries) { - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); + r600_free_extended_power_table(rdev); return -ENOMEM; } for (i = 0; i < cac_table->ucNumEntries; i++) { @@ -1010,11 +1004,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = kzalloc(size, GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); + r600_free_extended_power_table(rdev); return -ENOMEM; } rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = @@ -1045,12 +1035,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = kzalloc(size, GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); - kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries); + r600_free_extended_power_table(rdev); return -ENOMEM; } rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = @@ -1074,13 +1059,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) rdev->pm.dpm.dyn_state.ppm_table = kzalloc(sizeof(struct radeon_ppm_table), GFP_KERNEL); if (!rdev->pm.dpm.dyn_state.ppm_table) { - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); -
[PATCH 32/53] drm/radeon: parse the vce clock voltage deps table
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 41 ++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 9dda735..b49b0f0 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -989,12 +989,47 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) } } - /* ppm table */ + /* ext tables */ if (le16_to_cpu(power_info->pplib.usTableSize) >= sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && + ext_hdr->usVCETableOffset) { + VCEClockInfoArray *array = (VCEClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usVCETableOffset) + 1); + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = + (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + +le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + +1 + array->ucNumEntries * sizeof(VCEClockInfo)); + u32 size = limits->numEntries * + sizeof(struct radeon_vce_clock_voltage_dependency_entry); + rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); + kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); + return -ENOMEM; + } + rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = + limits->numEntries; + for (i = 0; i < limits->numEntries; i++) { + VCEClockInfo *vce_clk = + &array->entries[limits->entries[i].ucVCEClockInfoIndex]; + rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = + le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); + rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = + le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); + rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(limits->entries[i].usVoltage); + } + } if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && ext_hdr->usPPMTableOffset) { ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) @@ -1008,6 +1043,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); + kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries); return -ENOMEM; } rdev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; @@ -1044,6 +1080,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); kfree(rdev->pm.dpm.dyn_state.ppm_table); + kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries); return -ENOMEM;
[PATCH 35/53] drm/radeon: parse the samu clock voltage deps table
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 98db6ea..314886a 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -1051,6 +1051,30 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) le16_to_cpu(limits->entries[i].usVoltage); } } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && + ext_hdr->usSAMUTableOffset) { + ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = + (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + +le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); + u32 size = limits->numEntries * + sizeof(struct radeon_clock_voltage_dependency_entry); + rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { + r600_free_extended_power_table(rdev); + return -ENOMEM; + } + rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = + limits->numEntries; + for (i = 0; i < limits->numEntries; i++) { + rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = + le16_to_cpu(limits->entries[i].usSAMClockLow) | + (limits->entries[i].ucSAMClockHigh << 16); + rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(limits->entries[i].usVoltage); + } + } if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && ext_hdr->usPPMTableOffset) { ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) @@ -1147,6 +1171,8 @@ void r600_free_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries); if (rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) kfree(rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries); + if (rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) + kfree(rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries); } enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 36/53] drm/radeon: parse the acp clock voltage deps table
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 314886a..bf851ac 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -1106,6 +1106,30 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) rdev->pm.dpm.dyn_state.ppm_table->tj_max = le32_to_cpu(ppm->ulTjmax); } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && + ext_hdr->usACPTableOffset) { + ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = + (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + +le16_to_cpu(ext_hdr->usACPTableOffset) + 1); + u32 size = limits->numEntries * + sizeof(struct radeon_clock_voltage_dependency_entry); + rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { + r600_free_extended_power_table(rdev); + return -ENOMEM; + } + rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = + limits->numEntries; + for (i = 0; i < limits->numEntries; i++) { + rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = + le16_to_cpu(limits->entries[i].usACPClockLow) | + (limits->entries[i].ucACPClockHigh << 16); + rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(limits->entries[i].usVoltage); + } + } if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && ext_hdr->usPowerTuneTableOffset) { u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + @@ -1173,6 +1197,8 @@ void r600_free_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries); if (rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) kfree(rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries); + if (rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) + kfree(rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries); } enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 37/53] drm/radeon: add r600_get_pcie_lane_support helper
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 23 +++ drivers/gpu/drm/radeon/r600_dpm.h | 4 2 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index bf851ac..34ea5d6 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -1223,3 +1223,26 @@ enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, } return RADEON_PCIE_GEN1; } + +u16 r600_get_pcie_lane_support(struct radeon_device *rdev, + u16 asic_lanes, + u16 default_lanes) +{ + switch (asic_lanes) { + case 0: + default: + return default_lanes; + case 1: + return 1; + case 2: + return 2; + case 4: + return 4; + case 8: + return 8; + case 12: + return 12; + case 16: + return 16; + } +} diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h index 7c822d9..71d5d93 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.h +++ b/drivers/gpu/drm/radeon/r600_dpm.h @@ -224,4 +224,8 @@ enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, enum radeon_pcie_gen asic_gen, enum radeon_pcie_gen default_gen); +u16 r600_get_pcie_lane_support(struct radeon_device *rdev, + u16 asic_lanes, + u16 default_lanes); + #endif -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 38/53] drm/radeon/dpm: add vce clocks to radeon_ps
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 661e7c1..13e402c 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1206,6 +1206,9 @@ struct radeon_ps { /* UVD clocks */ u32 vclk; u32 dclk; + /* VCE clocks */ + u32 evclk; + u32 ecclk; /* asic priv */ void *ps_priv; }; -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 39/53] drm/radeon/dpm: add a helper to encode pcie lane setting
convert from number of lanes to register setting. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 10 ++ drivers/gpu/drm/radeon/r600_dpm.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 34ea5d6..89c46c5 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -1246,3 +1246,13 @@ u16 r600_get_pcie_lane_support(struct radeon_device *rdev, return 16; } } + +u8 r600_encode_pci_lane_width(u32 lanes) +{ + u8 encoded_lanes[] = { 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 }; + + if (lanes > 16) + return 0; + + return encoded_lanes[lanes]; +} diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h index 71d5d93..8dc1fbd 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.h +++ b/drivers/gpu/drm/radeon/r600_dpm.h @@ -227,5 +227,6 @@ enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, u16 r600_get_pcie_lane_support(struct radeon_device *rdev, u16 asic_lanes, u16 default_lanes); +u8 r600_encode_pci_lane_width(u32 lanes); #endif -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 40/53] drm/radeon/dpm: add helper to fetch the vrefresh of the current mode
Needed for DPM on CI. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 18 ++ drivers/gpu/drm/radeon/r600_dpm.h | 1 + 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 89c46c5..26a7878 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -174,6 +174,24 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev) return vblank_time_us; } +u32 r600_dpm_get_vrefresh(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_crtc *crtc; + struct radeon_crtc *radeon_crtc; + u32 vrefresh = 0; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { + vrefresh = radeon_crtc->hw_mode.vrefresh; + break; + } + } + + return vrefresh; +} + void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, u32 *p, u32 *u) { diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h index 8dc1fbd..1000bf9 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.h +++ b/drivers/gpu/drm/radeon/r600_dpm.h @@ -130,6 +130,7 @@ void r600_dpm_print_cap_info(u32 caps); void r600_dpm_print_ps_status(struct radeon_device *rdev, struct radeon_ps *rps); u32 r600_dpm_get_vblank_time(struct radeon_device *rdev); +u32 r600_dpm_get_vrefresh(struct radeon_device *rdev); bool r600_is_uvd_state(u32 class, u32 class2); void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, u32 *p, u32 *u); -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 43/53] drm/radeon/dpm: add debugfs support for CI
This allows you to look at the current DPM state via debugfs. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 11 +++ drivers/gpu/drm/radeon/cikd.h| 12 drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ 4 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 72ab92b..28b2b36 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -27,6 +27,7 @@ #include "r600_dpm.h" #include "ci_dpm.h" #include "atom.h" +#include #define MC_CG_ARB_FREQ_F0 0x0a #define MC_CG_ARB_FREQ_F1 0x0b @@ -4965,6 +4966,16 @@ int ci_dpm_init(struct radeon_device *rdev) return 0; } +void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m) +{ + u32 sclk = ci_get_average_sclk_freq(rdev); + u32 mclk = ci_get_average_mclk_freq(rdev); + + seq_printf(m, "power level avgsclk: %u mclk: %u\n", + sclk, mclk); +} + void ci_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *rps) { diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 52cbf6f..baada55 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -110,6 +110,14 @@ # define RESET_SCLK_CNT (1 << 5) # define DYNAMIC_PM_EN (1 << 21) +#define TARGET_AND_CURRENT_PROFILE_INDEX 0xC0200014 +# define CURRENT_STATE_MASK (0xf << 4) +# define CURRENT_STATE_SHIFT4 +# define CURR_MCLK_INDEX_MASK (0xf << 8) +# define CURR_MCLK_INDEX_SHIFT 8 +# define CURR_SCLK_INDEX_MASK (0x1f << 16) +# define CURR_SCLK_INDEX_SHIFT 16 + #define CG_SSP0xC0200044 # define SST(x) ((x) << 0) # define SST_MASK (0x << 0) @@ -126,6 +134,10 @@ # define DISP_GAP_MCHG(x) ((x) << 24) # define DISP_GAP_MCHG_MASK (3 << 24) +#define TARGET_AND_CURRENT_PROFILE_INDEX_10xC02000F0 +# define CURR_PCIE_INDEX_MASK (0xf << 24) +# define CURR_PCIE_INDEX_SHIFT 24 + #define CG_ULV_PARAMETER 0xC0200158 #define CG_FTV_0 0xC02001A8 diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index c633fa5..e28f08b 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2467,6 +2467,7 @@ static struct radeon_asic ci_asic = { .get_sclk = &ci_dpm_get_sclk, .get_mclk = &ci_dpm_get_mclk, .print_power_state = &ci_dpm_print_power_state, + .debugfs_print_current_performance_level = &ci_dpm_debugfs_print_current_performance_level, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 350da17..371a6f2 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -763,6 +763,8 @@ u32 ci_dpm_get_sclk(struct radeon_device *rdev, bool low); u32 ci_dpm_get_mclk(struct radeon_device *rdev, bool low); void ci_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *ps); +void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m); int kv_dpm_init(struct radeon_device *rdev); int kv_dpm_enable(struct radeon_device *rdev); -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 44/53] drm/radeon/dpm: implement force performance level for CI
Allows you to force the selected performance level via sysfs. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 153 +++ drivers/gpu/drm/radeon/ppsmc.h | 1 + drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 2 + 4 files changed, 157 insertions(+) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 28b2b36..9eebf1f 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -3601,6 +3601,153 @@ static int ci_generate_dpm_level_enable_mask(struct radeon_device *rdev, return 0; } +static u32 ci_get_lowest_enabled_level(struct radeon_device *rdev, + u32 level_mask) +{ + u32 level = 0; + + while ((level_mask & (1 << level)) == 0) + level++; + + return level; +} + + +int ci_dpm_force_performance_level(struct radeon_device *rdev, + enum radeon_dpm_forced_level level) +{ + struct ci_power_info *pi = ci_get_pi(rdev); + PPSMC_Result smc_result; + u32 tmp, levels, i; + int ret; + + if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { + if ((!pi->sclk_dpm_key_disabled) && + pi->dpm_level_enable_mask.sclk_dpm_enable_mask) { + levels = 0; + tmp = pi->dpm_level_enable_mask.sclk_dpm_enable_mask; + while (tmp >>= 1) + levels++; + if (levels) { + ret = ci_dpm_force_state_sclk(rdev, levels); + if (ret) + return ret; + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) & + CURR_SCLK_INDEX_MASK) >> CURR_SCLK_INDEX_SHIFT; + if (tmp == levels) + break; + udelay(1); + } + } + } + if ((!pi->mclk_dpm_key_disabled) && + pi->dpm_level_enable_mask.mclk_dpm_enable_mask) { + levels = 0; + tmp = pi->dpm_level_enable_mask.mclk_dpm_enable_mask; + while (tmp >>= 1) + levels++; + if (levels) { + ret = ci_dpm_force_state_mclk(rdev, levels); + if (ret) + return ret; + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) & + CURR_MCLK_INDEX_MASK) >> CURR_MCLK_INDEX_SHIFT; + if (tmp == levels) + break; + udelay(1); + } + } + } + if ((!pi->pcie_dpm_key_disabled) && + pi->dpm_level_enable_mask.pcie_dpm_enable_mask) { + levels = 0; + tmp = pi->dpm_level_enable_mask.pcie_dpm_enable_mask; + while (tmp >>= 1) + levels++; + if (levels) { + ret = ci_dpm_force_state_pcie(rdev, level); + if (ret) + return ret; + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX_1) & + CURR_PCIE_INDEX_MASK) >> CURR_PCIE_INDEX_SHIFT; + if (tmp == levels) + break; + udelay(1); + } + } + } + } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { + if ((!pi->sclk_dpm_key_disabled) && + pi->dpm_level_enable_mask.sclk_dpm_enable_mask) { + levels = ci_get_lowest_enabled_level(rdev, + pi->dpm_level_enable_mask.sclk_dpm_enable_mask); + ret = ci_dpm_force_state_sclk(rdev, levels); + if (ret) + return ret; + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_I
[PATCH 28/53] drm/radeon/dpm: add support for parsing the atom powertune table
Needed for DPM on CI. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 44 +++ drivers/gpu/drm/radeon/radeon.h | 12 +++ 2 files changed, 56 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index ccdf770..e6905f0 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -1014,6 +1014,48 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) rdev->pm.dpm.dyn_state.ppm_table->tj_max = le32_to_cpu(ppm->ulTjmax); } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && + ext_hdr->usPowerTuneTableOffset) { + u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + ATOM_PowerTune_Table *pt; + rdev->pm.dpm.dyn_state.cac_tdp_table = + kzalloc(sizeof(struct radeon_cac_tdp_table), GFP_KERNEL); + if (!rdev->pm.dpm.dyn_state.cac_tdp_table) { + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); + kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); + kfree(rdev->pm.dpm.dyn_state.ppm_table); + return -ENOMEM; + } + if (rev > 0) { + ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = + ppt->usMaximumPowerDeliveryLimit; + pt = &ppt->power_tune_table; + } else { + ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; + pt = &ppt->power_tune_table; + } + rdev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); + rdev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = + le16_to_cpu(pt->usConfigurableTDP); + rdev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); + rdev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = + le16_to_cpu(pt->usBatteryPowerLimit); + rdev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = + le16_to_cpu(pt->usSmallPowerLimit); + rdev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = + le16_to_cpu(pt->usLowCACLeakage); + rdev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = + le16_to_cpu(pt->usHighCACLeakage); + } } return 0; @@ -1033,6 +1075,8 @@ void r600_free_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries); if (rdev->pm.dpm.dyn_state.ppm_table) kfree(rdev->pm.dpm.dyn_state.ppm_table); + if (rdev->pm.dpm.dyn_state.cac_tdp_table) + kfree(rdev->pm.dpm.dyn_state.cac_tdp_table); } enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index e6541e3..286e34a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1308,6 +1308,17 @@ struct radeon_ppm_table { u32 tj_max; }; +struct radeon_cac_tdp_table { + u16 tdp; + u16 configurable_tdp; + u16 tdc; + u16 battery_power_limit; + u16 small_power_limit; + u16 low_cac_leakage; + u16 high_cac_leakage; + u16 maximum_power_delivery_limit; +}; + struct radeon_dpm_dynamic_state { struct radeon_clock_voltage_dependency_table vddc_dependency_on_sclk; struct radeon_clock_voltage_dependency_table vddci_dependency_on
[PATCH 29/53] drm/radeon/dpm: grab mvdd_dependency_on_mclk info from vbios
Required for dpm on CI. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 19 +++ drivers/gpu/drm/radeon/radeon.h | 1 + 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index e6905f0..9dda735 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -877,6 +877,19 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) return ret; } } + if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); + ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, + dep_table); + if (ret) { + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); + kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + return ret; + } + } if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = (ATOM_PPLIB_Clock_Voltage_Limit_Table *) @@ -909,6 +922,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); return -ENOMEM; } @@ -953,6 +967,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); return -ENOMEM; } for (i = 0; i < cac_table->ucNumEntries; i++) { @@ -991,6 +1006,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); return -ENOMEM; } @@ -1025,6 +1041,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); kfree(rdev->pm.dpm.dyn_state.ppm_table); return -ENOMEM; @@ -1069,6 +1086,8 @@ void r600_free_extended_power_table(struct radeon_device *rdev) kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); if (rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries) kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); + if (rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries) + kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); if (rdev->pm.dpm.dyn_state.cac_leakage_table.entries) kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); if (rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 286e34a..e65304a 100644 --- a/drivers/gpu/drm/radeon/radeon
[PATCH 30/53] drm/radeon: add structs to store vce clock voltage deps
Used for vce power management. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 12 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index e65304a..d21fa20 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1295,6 +1295,17 @@ struct radeon_uvd_clock_voltage_dependency_table { struct radeon_uvd_clock_voltage_dependency_entry *entries; }; +struct radeon_vce_clock_voltage_dependency_entry { + u32 ecclk; + u32 evclk; + u16 v; +}; + +struct radeon_vce_clock_voltage_dependency_table { + u8 count; + struct radeon_vce_clock_voltage_dependency_entry *entries; +}; + struct radeon_ppm_table { u8 ppm_design; u16 cpu_core_number; @@ -1326,6 +1337,7 @@ struct radeon_dpm_dynamic_state { struct radeon_clock_voltage_dependency_table mvdd_dependency_on_mclk; struct radeon_clock_voltage_dependency_table vddc_dependency_on_dispclk; struct radeon_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table; + struct radeon_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table; struct radeon_clock_array valid_sclk_values; struct radeon_clock_array valid_mclk_values; struct radeon_clock_and_voltage_limits max_clock_voltage_on_dc; -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 45/53] drm/radeon/dpm: implement vblank_too_short callback for CI
Check if we can switch the mclk during the vblank time otherwise we may get artifacts on the screen when the mclk changes. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 16 +++- drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 9eebf1f..6e3d387 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -682,6 +682,19 @@ static void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) ci_update_uvd_dpm(rdev, gate); } +bool ci_dpm_vblank_too_short(struct radeon_device *rdev) +{ + struct ci_power_info *pi = ci_get_pi(rdev); + u32 vblank_time = r600_dpm_get_vblank_time(rdev); + u32 switch_limit = pi->mem_gddr5 ? 450 : 300; + + if (vblank_time < switch_limit) + return true; + else + return false; + +} + static void ci_apply_state_adjust_rules(struct radeon_device *rdev, struct radeon_ps *rps) { @@ -692,7 +705,8 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev, u32 sclk, mclk; int i; - if (rdev->pm.dpm.new_active_crtc_count > 1) + if ((rdev->pm.dpm.new_active_crtc_count > 1) || + ci_dpm_vblank_too_short(rdev)) disable_mclk_switching = true; else disable_mclk_switching = false; diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 705bc74..2d7bdda 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2469,6 +2469,7 @@ static struct radeon_asic ci_asic = { .print_power_state = &ci_dpm_print_power_state, .debugfs_print_current_performance_level = &ci_dpm_debugfs_print_current_performance_level, .force_performance_level = &ci_dpm_force_performance_level, + .vblank_too_short = &ci_dpm_vblank_too_short, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index a887928..b5f4e43 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -767,6 +767,7 @@ void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m); int ci_dpm_force_performance_level(struct radeon_device *rdev, enum radeon_dpm_forced_level level); +bool ci_dpm_vblank_too_short(struct radeon_device *rdev); int kv_dpm_init(struct radeon_device *rdev); int kv_dpm_enable(struct radeon_device *rdev); -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 46/53] drm/radeon/dpm: add debugfs support for KB/KV
This allows you to look at the current DPM state via debugfs. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cikd.h| 4 drivers/gpu/drm/radeon/kv_dpm.c | 23 +++ drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ 4 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index baada55..0977cf8 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -134,6 +134,10 @@ # define DISP_GAP_MCHG(x) ((x) << 24) # define DISP_GAP_MCHG_MASK (3 << 24) +#define SMU_VOLTAGE_STATUS0xC0200094 +# define SMU_VOLTAGE_CURRENT_LEVEL_MASK (0xff << 1) +# define SMU_VOLTAGE_CURRENT_LEVEL_SHIFT1 + #define TARGET_AND_CURRENT_PROFILE_INDEX_10xC02000F0 # define CURR_PCIE_INDEX_MASK (0xf << 24) # define CURR_PCIE_INDEX_SHIFT 24 diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index 2e40163..d584ee4 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -26,6 +26,7 @@ #include "cikd.h" #include "r600_dpm.h" #include "kv_dpm.h" +#include #define KV_MAX_DEEPSLEEP_DIVIDER_ID 5 #define KV_MINIMUM_ENGINE_CLOCK 800 @@ -2481,6 +2482,28 @@ int kv_dpm_init(struct radeon_device *rdev) return 0; } +void kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m) +{ + struct kv_power_info *pi = kv_get_pi(rdev); + u32 current_index = + (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_SCLK_INDEX_MASK) >> + CURR_SCLK_INDEX_SHIFT; + u32 sclk, tmp; + u16 vddc; + + if (current_index >= SMU__NUM_SCLK_DPM_STATE) { + seq_printf(m, "invalid dpm profile %d\n", current_index); + } else { + sclk = be32_to_cpu(pi->graphics_level[current_index].SclkFrequency); + tmp = (RREG32_SMC(SMU_VOLTAGE_STATUS) & SMU_VOLTAGE_CURRENT_LEVEL_MASK) >> + SMU_VOLTAGE_CURRENT_LEVEL_SHIFT; + vddc = kv_convert_8bit_index_to_voltage(rdev, (u16)tmp); + seq_printf(m, "power level %dsclk: %u vddc: %u\n", + current_index, sclk, vddc); + } +} + void kv_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *rps) { diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 2d7bdda..b25172b 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2640,6 +2640,7 @@ static struct radeon_asic kv_asic = { .get_sclk = &kv_dpm_get_sclk, .get_mclk = &kv_dpm_get_mclk, .print_power_state = &kv_dpm_print_power_state, + .debugfs_print_current_performance_level = &kv_dpm_debugfs_print_current_performance_level, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index b5f4e43..80ad5d8 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -782,5 +782,7 @@ u32 kv_dpm_get_sclk(struct radeon_device *rdev, bool low); u32 kv_dpm_get_mclk(struct radeon_device *rdev, bool low); void kv_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *ps); +void kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m); #endif -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 47/53] drm/radeon/dpm: implement force performance level for KB/KV
Allows you to force the selected performance level via sysfs. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/kv_dpm.c | 43 drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ 3 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index d584ee4..c26c4e3 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -40,6 +40,7 @@ static void kv_enable_new_levels(struct radeon_device *rdev); static void kv_program_nbps_index_settings(struct radeon_device *rdev, struct radeon_ps *new_rps); static int kv_set_enabled_levels(struct radeon_device *rdev); +static int kv_force_dpm_highest(struct radeon_device *rdev); static int kv_force_dpm_lowest(struct radeon_device *rdev); static void kv_apply_state_adjust_rules(struct radeon_device *rdev, struct radeon_ps *new_rps, @@ -1641,6 +1642,30 @@ static int kv_enable_nb_dpm(struct radeon_device *rdev) return ret; } +int kv_dpm_force_performance_level(struct radeon_device *rdev, + enum radeon_dpm_forced_level level) +{ + int ret; + + if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { + ret = kv_force_dpm_highest(rdev); + if (ret) + return ret; + } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { + ret = kv_force_dpm_lowest(rdev); + if (ret) + return ret; + } else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) { + ret = kv_unforce_levels(rdev); + if (ret) + return ret; + } + + rdev->pm.dpm.forced_level = level; + + return 0; +} + int kv_dpm_pre_set_power_state(struct radeon_device *rdev) { struct kv_power_info *pi = kv_get_pi(rdev); @@ -1720,6 +1745,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) kv_enable_nb_dpm(rdev); } } + rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; return 0; } @@ -1796,6 +1822,23 @@ static void kv_construct_boot_state(struct radeon_device *rdev) pi->boot_pl.vce_wm = 0; } +static int kv_force_dpm_highest(struct radeon_device *rdev) +{ + int ret; + u32 enable_mask, i; + + ret = kv_dpm_get_enable_mask(rdev, &enable_mask); + if (ret) + return ret; + + for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i >= 0; i--) { + if (enable_mask & (1 << i)) + break; + } + + return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); +} + static int kv_force_dpm_lowest(struct radeon_device *rdev) { int ret; diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index b25172b..1dad80c 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2641,6 +2641,7 @@ static struct radeon_asic kv_asic = { .get_mclk = &kv_dpm_get_mclk, .print_power_state = &kv_dpm_print_power_state, .debugfs_print_current_performance_level = &kv_dpm_debugfs_print_current_performance_level, + .force_performance_level = &kv_dpm_force_performance_level, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 80ad5d8..1e386c4 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -784,5 +784,7 @@ void kv_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *ps); void kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m); +int kv_dpm_force_performance_level(struct radeon_device *rdev, + enum radeon_dpm_forced_level level); #endif -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 48/53] drm/radeon/dpm: add new callback for powergating UVD (v3)
Starting on CIK, multi-media blocks like UVD no longer have special power state. Rather they have their own DPM implementation which adjusts their clocks dynamically when active. When they are not active, the blocks are powergated to save power. v2: add missing pm locks v3: rebase on uvd state selection rework Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h| 2 ++ drivers/gpu/drm/radeon/radeon_pm.c | 43 ++ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 297e744..09a2434 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1730,6 +1730,7 @@ struct radeon_asic { void (*debugfs_print_current_performance_level)(struct radeon_device *rdev, struct seq_file *m); int (*force_performance_level)(struct radeon_device *rdev, enum radeon_dpm_forced_level level); bool (*vblank_too_short)(struct radeon_device *rdev); + void (*powergate_uvd)(struct radeon_device *rdev, bool gate); } dpm; /* pageflipping */ struct { @@ -2518,6 +2519,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_dpm_debugfs_print_current_performance_level(rdev, m) rdev->asic->dpm.debugfs_print_current_performance_level((rdev), (m)) #define radeon_dpm_force_performance_level(rdev, l) rdev->asic->dpm.force_performance_level((rdev), (l)) #define radeon_dpm_vblank_too_short(rdev) rdev->asic->dpm.vblank_too_short((rdev)) +#define radeon_dpm_powergate_uvd(rdev, g) rdev->asic->dpm.powergate_uvd((rdev), (g)) /* Common functions */ /* AGP */ diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 66b04af..a44ae9a 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -886,28 +886,35 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) { enum radeon_pm_state_type dpm_state; - if (enable) { + if (rdev->asic->dpm.powergate_uvd) { mutex_lock(&rdev->pm.mutex); - rdev->pm.dpm.uvd_active = true; - if ((rdev->pm.dpm.sd == 1) && (rdev->pm.dpm.hd == 0)) - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_SD; - else if ((rdev->pm.dpm.sd == 2) && (rdev->pm.dpm.hd == 0)) - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; - else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 1)) - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; - else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 2)) - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD2; - else - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD; - rdev->pm.dpm.state = dpm_state; + /* enable/disable UVD */ + radeon_dpm_powergate_uvd(rdev, enable); mutex_unlock(&rdev->pm.mutex); } else { - mutex_lock(&rdev->pm.mutex); - rdev->pm.dpm.uvd_active = false; - mutex_unlock(&rdev->pm.mutex); - } + if (enable) { + mutex_lock(&rdev->pm.mutex); + rdev->pm.dpm.uvd_active = true; + if ((rdev->pm.dpm.sd == 1) && (rdev->pm.dpm.hd == 0)) + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_SD; + else if ((rdev->pm.dpm.sd == 2) && (rdev->pm.dpm.hd == 0)) + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 1)) + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 2)) + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD2; + else + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD; + rdev->pm.dpm.state = dpm_state; + mutex_unlock(&rdev->pm.mutex); + } else { + mutex_lock(&rdev->pm.mutex); + rdev->pm.dpm.uvd_active = false; + mutex_unlock(&rdev->pm.mutex); + } - radeon_pm_compute_clocks(rdev); + radeon_pm_compute_clocks(rdev); + } } static void radeon_pm_suspend_old(struct radeon_device *rdev) -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 49/53] drm/radeon: restructure UVD code to handle UVD PG (v2)
When we PG (powergate) UVD, we need to re-initialize it before we can use it again. v2: rebase on UVD stop fixes Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 14 +++ drivers/gpu/drm/radeon/evergreen.c | 2 +- drivers/gpu/drm/radeon/ni.c | 2 +- drivers/gpu/drm/radeon/r600.c| 74 +++- drivers/gpu/drm/radeon/radeon_asic.h | 4 +- drivers/gpu/drm/radeon/rv770.c | 2 +- drivers/gpu/drm/radeon/si.c | 2 +- 7 files changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 736a416..59b866a 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -69,6 +69,7 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev); static void cik_program_aspm(struct radeon_device *rdev); static void cik_init_pg(struct radeon_device *rdev); static void cik_init_cg(struct radeon_device *rdev); +static void cik_uvd_resume(struct radeon_device *rdev); /* get temperature in millidegrees */ int ci_get_temp(struct radeon_device *rdev) @@ -7619,8 +7620,9 @@ static int cik_startup(struct radeon_device *rdev) return r; } - r = cik_uvd_resume(rdev); + r = radeon_uvd_resume(rdev); if (!r) { + cik_uvd_resume(rdev); r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); if (r) @@ -7708,7 +7710,7 @@ static int cik_startup(struct radeon_device *rdev) UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, 0, 0xf, RADEON_CP_PACKET2); if (!r) - r = r600_uvd_init(rdev); + r = r600_uvd_init(rdev, true); if (r) DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); } @@ -8598,15 +8600,10 @@ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) return r; } -int cik_uvd_resume(struct radeon_device *rdev) +static void cik_uvd_resume(struct radeon_device *rdev) { uint64_t addr; uint32_t size; - int r; - - r = radeon_uvd_resume(rdev); - if (r) - return r; /* programm the VCPU memory controller bits 0-27 */ addr = rdev->uvd.gpu_addr >> 3; @@ -8632,7 +8629,6 @@ int cik_uvd_resume(struct radeon_device *rdev) addr = (rdev->uvd.gpu_addr >> 32) & 0xFF; WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31)); - return 0; } static void cik_pcie_gen3_enable(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 2ce12ee..710c1d4 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -5296,7 +5296,7 @@ static int evergreen_startup(struct radeon_device *rdev) UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, 0, 0xf, RADEON_CP_PACKET2); if (!r) - r = r600_uvd_init(rdev); + r = r600_uvd_init(rdev, true); if (r) DRM_ERROR("radeon: error initializing UVD (%d).\n", r); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 21f2ece..bc298a35 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -2230,7 +2230,7 @@ static int cayman_startup(struct radeon_device *rdev) UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, 0, 0xf, RADEON_CP_PACKET2); if (!r) - r = r600_uvd_init(rdev); + r = r600_uvd_init(rdev, true); if (r) DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 3db2e4d..8a60015 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2623,7 +2623,7 @@ void r600_dma_fini(struct radeon_device *rdev) /* * UVD */ -int r600_uvd_rbc_start(struct radeon_device *rdev) +static int r600_uvd_rbc_start(struct radeon_device *rdev, bool ring_test) { struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; uint64_t rptr_addr; @@ -2664,47 +2664,47 @@ int r600_uvd_rbc_start(struct radeon_device *rdev) rb_bufsz = (0x1 << 8) | rb_bufsz; WREG32(UVD_RBC_RB_CNTL, rb_bufsz); - ring->ready = true; - r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring); - if (r) { - ring->ready = false; - return r; - } + if (ring_test) { + ring->ready = true; + r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring); + if (
[PATCH 50/53] drm/radeon/dpm: implement UVD powergating for KB/KV
Powergate the UVD block when not in use to save power. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 4 ++-- drivers/gpu/drm/radeon/kv_dpm.c | 22 +++--- drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 1 + 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 59b866a..e661aec 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -69,7 +69,7 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev); static void cik_program_aspm(struct radeon_device *rdev); static void cik_init_pg(struct radeon_device *rdev); static void cik_init_cg(struct radeon_device *rdev); -static void cik_uvd_resume(struct radeon_device *rdev); +void cik_uvd_resume(struct radeon_device *rdev); /* get temperature in millidegrees */ int ci_get_temp(struct radeon_device *rdev) @@ -8600,7 +8600,7 @@ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) return r; } -static void cik_uvd_resume(struct radeon_device *rdev) +void cik_uvd_resume(struct radeon_device *rdev) { uint64_t addr; uint32_t size; diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index c26c4e3..3e232a4 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -49,7 +49,7 @@ static int kv_set_thermal_temperature_range(struct radeon_device *rdev, int min_temp, int max_temp); static int kv_init_fps_limits(struct radeon_device *rdev); -static void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); +void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); static void kv_dpm_powergate_vce(struct radeon_device *rdev, bool gate); static void kv_dpm_powergate_samu(struct radeon_device *rdev, bool gate); static void kv_dpm_powergate_acp(struct radeon_device *rdev, bool gate); @@ -59,6 +59,10 @@ extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev); extern void cik_update_cg(struct radeon_device *rdev, u32 block, bool enable); +extern void cik_uvd_resume(struct radeon_device *rdev); +extern int r600_uvd_init(struct radeon_device *rdev, bool ring_test); +extern void r600_do_uvd_stop(struct radeon_device *rdev); + static const struct kv_lcac_config_values sx_local_cac_cfg_kv[] = { { 0, 4,1}, @@ -1201,6 +1205,7 @@ int kv_dpm_enable(struct radeon_device *rdev) kv_dpm_powergate_acp(rdev, true); kv_dpm_powergate_samu(rdev, true); kv_dpm_powergate_vce(rdev, true); + kv_dpm_powergate_uvd(rdev, true); kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); @@ -1458,7 +1463,7 @@ static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate) return kv_enable_acp_dpm(rdev, !gate); } -static void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) +void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) { struct kv_power_info *pi = kv_get_pi(rdev); @@ -1468,13 +1473,18 @@ static void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) pi->uvd_power_gated = gate; if (gate) { - kv_update_uvd_dpm(rdev, true); + r600_do_uvd_stop(rdev); + cik_update_cg(rdev, RADEON_CG_BLOCK_UVD, false); + kv_update_uvd_dpm(rdev, gate); if (pi->caps_uvd_pg) kv_notify_message_to_smu(rdev, PPSMC_MSG_UVDPowerOFF); } else { if (pi->caps_uvd_pg) kv_notify_message_to_smu(rdev, PPSMC_MSG_UVDPowerON); - kv_update_uvd_dpm(rdev, false); + cik_uvd_resume(rdev); + r600_uvd_init(rdev, false); + cik_update_cg(rdev, RADEON_CG_BLOCK_UVD, true); + kv_update_uvd_dpm(rdev, gate); } } @@ -1714,7 +1724,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) return ret; } #endif - kv_update_uvd_dpm(rdev, false); kv_update_sclk_t(rdev); } } else { @@ -1740,7 +1749,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) return ret; } #endif - kv_update_uvd_dpm(rdev, false); kv_update_sclk_t(rdev); kv_enable_nb_dpm(rdev); } @@ -2502,7 +2510,7 @@ int kv_dpm_init(struct radeon_device *rdev) pi->voltage_drop_t = 0; pi->caps_sclk_throttle_low_notification = false; pi->caps_fps = false; /* true? */ - pi->caps_uvd_pg = false; /* XXX */ + pi->caps_uvd_pg = true; pi->caps_uvd_dpm = true; pi->caps_vce_pg = false; pi->caps_samu_pg = false; diff --git a/driver
[PATCH 51/53] drm/radeon/dpm: implement UVD powergating for CI
Disable the UVD block when not in use to save power. The block is not actually powergated on CI, but we switch between UVD DPM (where the uvd clocks are adjusted on demand) and clocks off. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 7 +-- drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 6e3d387..e4d9d50 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -677,7 +677,7 @@ static int ci_power_control_set_level(struct radeon_device *rdev) return ret; } -static void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) +void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) { ci_update_uvd_dpm(rdev, gate); } @@ -4674,11 +4674,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev) return ret; } #endif - ret = ci_update_uvd_dpm(rdev, false); - if (ret) { - DRM_ERROR("ci_update_uvd_dpm failed\n"); - return ret; - } ret = ci_update_sclk_t(rdev); if (ret) { DRM_ERROR("ci_update_sclk_t failed\n"); diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 63b6aae..61c0644 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2470,6 +2470,7 @@ static struct radeon_asic ci_asic = { .debugfs_print_current_performance_level = &ci_dpm_debugfs_print_current_performance_level, .force_performance_level = &ci_dpm_force_performance_level, .vblank_too_short = &ci_dpm_vblank_too_short, + .powergate_uvd = &ci_dpm_powergate_uvd, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 9060757..5630291 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -766,6 +766,7 @@ void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, int ci_dpm_force_performance_level(struct radeon_device *rdev, enum radeon_dpm_forced_level level); bool ci_dpm_vblank_too_short(struct radeon_device *rdev); +void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); int kv_dpm_init(struct radeon_device *rdev); int kv_dpm_enable(struct radeon_device *rdev); -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 53/53] drm/radeon/dpm: adjust the vblank time checks for eg, ni, si
According to the internal teams, we never hit the limit for mclk switching on these asics, so we can disable the check. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cypress_dpm.c | 3 ++- drivers/gpu/drm/radeon/ni_dpm.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c index 7e5d0b5..95a66db 100644 --- a/drivers/gpu/drm/radeon/cypress_dpm.c +++ b/drivers/gpu/drm/radeon/cypress_dpm.c @@ -2166,7 +2166,8 @@ bool cypress_dpm_vblank_too_short(struct radeon_device *rdev) { struct rv7xx_power_info *pi = rv770_get_pi(rdev); u32 vblank_time = r600_dpm_get_vblank_time(rdev); - u32 switch_limit = pi->mem_gddr5 ? 450 : 300; + /* we never hit the non-gddr5 limit so disable it */ + u32 switch_limit = pi->mem_gddr5 ? 450 : 0; if (vblank_time < switch_limit) return true; diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index f0f5f74..238078c 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -769,7 +769,8 @@ bool ni_dpm_vblank_too_short(struct radeon_device *rdev) { struct rv7xx_power_info *pi = rv770_get_pi(rdev); u32 vblank_time = r600_dpm_get_vblank_time(rdev); - u32 switch_limit = pi->mem_gddr5 ? 450 : 300; + /* we never hit the non-gddr5 limit so disable it */ + u32 switch_limit = pi->mem_gddr5 ? 450 : 0; if (vblank_time < switch_limit) return true; -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 52/53] drm/radeon/dpm: add reclocking quirk for ASUS K70AF
The LCD has a relatively short vblank time (216us), but the card is able to reclock memory fine in that time. Signed-off-by: Alex Deucher Reported-by: normalr...@gmail.com --- drivers/gpu/drm/radeon/rv770_dpm.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 094c67a..44c1e78 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2517,8 +2517,16 @@ u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low) bool rv770_dpm_vblank_too_short(struct radeon_device *rdev) { u32 vblank_time = r600_dpm_get_vblank_time(rdev); + u32 switch_limit = 300; - if (vblank_time < 300) + /* quirks */ + /* ASUS K70AF */ + if ((rdev->pdev->device == 0x9553) && + (rdev->pdev->subsystem_vendor == 0x1043) && + (rdev->pdev->subsystem_device == 0x1c42)) + switch_limit = 200; + + if (vblank_time < switch_limit) return true; else return false; -- 1.8.3.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/radeon: add RADEON_TILING_R600_SCANOUT to radeon_drm.h
Signed-off-by: Marek Olšák --- include/uapi/drm/radeon_drm.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h index 321d4ac..0b6740a 100644 --- a/include/uapi/drm/radeon_drm.h +++ b/include/uapi/drm/radeon_drm.h @@ -806,8 +806,9 @@ struct drm_radeon_gem_create { #define RADEON_TILING_MACRO0x1 #define RADEON_TILING_MICRO0x2 -#define RADEON_TILING_SWAP_16BIT 0x4 -#define RADEON_TILING_SWAP_32BIT 0x8 +#define RADEON_TILING_R600_SCANOUT 0x4 /* r600 and later */ +#define RADEON_TILING_SWAP_16BIT 0x4 /* r100-r500 */ +#define RADEON_TILING_SWAP_32BIT 0x8 /* r100-r500 */ /* this object requires a surface when mapped - i.e. front buffer */ #define RADEON_TILING_SURFACE 0x10 #define RADEON_TILING_MICRO_SQUARE 0x20 -- 1.8.1.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] r600g, radeonsi: set/get the scanout flag using the set/get_tiling ioctls
--- src/gallium/drivers/r300/r300_state.c | 2 +- src/gallium/drivers/r300/r300_texture.c | 4 ++-- src/gallium/drivers/r600/r600_texture.c | 13 - src/gallium/drivers/radeonsi/r600_texture.c | 13 - src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 12 ++-- src/gallium/winsys/radeon/drm/radeon_winsys.h | 4 +++- 6 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index e69a605..dad3dc5 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -843,7 +843,7 @@ static void r300_tex_set_tiling_flags(struct r300_context *r300, tex->tex.macrotile[level]) { r300->rws->buffer_set_tiling(tex->buf, r300->cs, tex->tex.microtile, tex->tex.macrotile[level], -0, 0, 0, 0, 0, +0, 0, 0, 0, 0, FALSE, tex->tex.stride_in_bytes[0]); tex->surface_level = level; diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 13e9bc3..4b58f06 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -1059,7 +1059,7 @@ r300_texture_create_object(struct r300_screen *rscreen, rws->buffer_set_tiling(tex->buf, NULL, tex->tex.microtile, tex->tex.macrotile[0], -0, 0, 0, 0, 0, +0, 0, 0, 0, 0, FALSE, tex->tex.stride_in_bytes[0]); return tex; @@ -1115,7 +1115,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, if (!buffer) return NULL; -rws->buffer_get_tiling(buffer, µtile, ¯otile, NULL, NULL, NULL, NULL, NULL); +rws->buffer_get_tiling(buffer, µtile, ¯otile, NULL, NULL, NULL, NULL, NULL, NULL); /* Enforce a microtiled zbuffer. */ if (util_format_is_depth_or_stencil(base->format) && diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 742e982..f27d0dc 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -131,7 +131,7 @@ static int r600_init_surface(struct r600_screen *rscreen, struct radeon_surface *surface, const struct pipe_resource *ptex, unsigned array_mode, -bool is_flushed_depth) +bool is_flushed_depth, bool is_scanout) { const struct util_format_description *desc = util_format_description(ptex->format); @@ -205,7 +205,7 @@ static int r600_init_surface(struct r600_screen *rscreen, default: return -EINVAL; } - if (ptex->bind & PIPE_BIND_SCANOUT) { + if (is_scanout) { surface->flags |= RADEON_SURF_SCANOUT; } @@ -285,6 +285,7 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen, surface->tile_split, surface->stencil_tile_split, surface->mtilea, + (surface->flags & RADEON_SURF_SCANOUT) != 0, rtex->surface.level[0].pitch_bytes); return rscreen->ws->buffer_get_handle(resource->buf, @@ -624,7 +625,8 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen, } r = r600_init_surface(rscreen, &surface, templ, array_mode, - templ->flags & R600_RESOURCE_FLAG_FLUSHED_DEPTH); + (templ->flags & R600_RESOURCE_FLAG_FLUSHED_DEPTH) != 0, + (templ->bind & PIPE_BIND_SCANOUT) != 0); if (r) { return NULL; } @@ -689,6 +691,7 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, unsigned array_mode = 0; enum radeon_bo_layout micro, macro; struct radeon_surface surface; + boolean scanout; int r; /* Support only 2D textures without mipmaps */ @@ -704,7 +707,7 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, &surface.bankw, &surface.bankh, &surface.tile_split, &surface.stencil_tile_split, - &surface.mtilea); + &surface.mtilea, &scanout); if (macro == RADEON_LAYOUT_TILED) array_mode = V_0280A0_ARRAY_2D_TILED_THIN1; @@ -713,7 +716,7 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, else array_mode = V_038000_ARRAY_LINEAR_ALIGNED; - r = r600_init_surface(rscreen, &surface, templ, array_mode, false); + r
[PATCH] radeon/kms: set/get the scanout flag using the set/get_tiling ioctls
Basically just pass RADEON_TILING_R600_SCANOUT everywhere. Hopefully I didn't miss anything. This is only compile-tested. Signed-off-by: Marek Olšák --- src/drmmode_display.c | 44 +--- src/radeon_bo_helper.c | 11 +-- src/radeon_drm.h | 5 +++-- src/radeon_kms.c | 28 +++- 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 3a0187e..7c055d3 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -123,7 +123,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, surface->last_level = 0; surface->bpe = bpp / 8; surface->nsamples = 1; - surface->flags = RADEON_SURF_SCANOUT; + surface->flags = 0; /* we are requiring a recent enough libdrm version */ surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); @@ -136,6 +136,9 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, surface->flags = RADEON_SURF_CLR(surface->flags, MODE); surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); } + if (tiling & RADEON_TILING_R600_SCANOUT) { + surface->flags |= RADEON_SURF_SCANOUT; + } if (radeon_surface_best(info->surf_man, surface)) { return NULL; } @@ -313,6 +316,8 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, struct radeon_bo *bo; drmModeFBPtr fbcon; struct drm_gem_flink flink; + unsigned tiling = 0; + RADEONInfoPtr info = RADEONPTR(pScrn); fbcon = drmModeGetFB(drmmode->fd, fbcon_id); if (fbcon == NULL) @@ -337,9 +342,13 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, goto out_free_fb; } + if (info->ChipFamily >= CHIP_FAMILY_R600) { + tiling |= RADEON_TILING_R600_SCANOUT; + } + pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height, fbcon->depth, fbcon->bpp, - fbcon->pitch, 0, bo, NULL); + fbcon->pitch, tiling, bo, NULL); radeon_bo_unref(bo); out_free_fb: drmModeFreeFB(fbcon); @@ -399,6 +408,10 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) * info->pixel_bytes; + if (info->ChipFamily >= CHIP_FAMILY_R600) { + tiling_flags |= RADEON_TILING_R600_SCANOUT; + } + dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX, pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, pitch, @@ -1418,6 +1431,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) tiling_flags |= RADEON_TILING_MACRO; } + if (info->ChipFamily >= CHIP_FAMILY_R600) { + tiling_flags |= RADEON_TILING_R600_SCANOUT; + } + pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp; height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags)); screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE); @@ -1434,7 +1451,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) surface.last_level = 0; surface.bpe = cpp; surface.nsamples = 1; - surface.flags = RADEON_SURF_SCANOUT; + surface.flags = 0; /* we are requiring a recent enough libdrm version */ surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); @@ -1447,6 +1464,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) surface.flags = RADEON_SURF_CLR(surface.flags, MODE); surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); } + if (tiling_flags & RADEON_TILING_R600_SCANOUT) { + surface.flags |= RADEON_SURF_SCANOUT; + } if (radeon_surface_best(info->surf_man, &surface)) { return FALSE; } @@ -1456,7 +1476,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) screen_size = surface.bo_size; base_align = surface.bo_alignment; pitch = surface.level[0].
[PATCH] radeon: add RADEON_TILING_R600_SCANOUT to radeon_drm.h
--- include/drm/radeon_drm.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 86cef15..1e8713c 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -806,8 +806,9 @@ struct drm_radeon_gem_create { #define RADEON_TILING_MACRO0x1 #define RADEON_TILING_MICRO0x2 -#define RADEON_TILING_SWAP_16BIT 0x4 -#define RADEON_TILING_SWAP_32BIT 0x8 +#define RADEON_TILING_R600_SCANOUT 0x4 /* r600 and later */ +#define RADEON_TILING_SWAP_16BIT 0x4 /* r100-r500 */ +#define RADEON_TILING_SWAP_32BIT 0x8 /* r100-r500 */ /* this object requires a surface when mapped - i.e. front buffer */ #define RADEON_TILING_SURFACE 0x10 #define RADEON_TILING_MICRO_SQUARE 0x20 -- 1.8.1.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 67723] Resume from s2ram doesn't work with radeon.dpm=1
https://bugs.freedesktop.org/show_bug.cgi?id=67723 Bastian Triller changed: What|Removed |Added Summary|Resume from s2ram fails |Resume from s2ram doesn't |with [drm:r600_uvd_init]|work with radeon.dpm=1 |*ERROR* UVD not responding, | |trying to reset the VCPU!!! | -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 67723] Resume from s2ram doesn't work with radeon.dpm=1
https://bugs.freedesktop.org/show_bug.cgi?id=67723 --- Comment #5 from Alex Deucher --- You said in comment 3 that you also had the same failure with dpm disabled, but you just changed the summary to indicate that it happens with dpm enabled. Which is correct? Is it only an issue with dpm enabled or does it happen regardless of whether dpm is enabled? -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 67723] Resume from s2ram doesn't work with radeon.dpm=1
https://bugs.freedesktop.org/show_bug.cgi?id=67723 Bastian Triller changed: What|Removed |Added Status|RESOLVED|REOPENED Resolution|DUPLICATE |--- --- Comment #6 from Bastian Triller --- Wow, that was a fast answer. Resume with dpm=0 works. With dpm=1 only with power adapter attached. Screen stays black and laptop starts heating up and I have to force off the laptop. The laptop is pingable but SSH doesn't work, neither a new session nor an open one. It makes no difference if I suspend with or without power adapter. -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 50091] [BISECTED]GeForce 6150SE: system hangs on X-server start with garbled screen
https://bugzilla.kernel.org/show_bug.cgi?id=50091 Tom Wijsman changed: What|Removed |Added CC||ker...@gentoo.org --- Comment #32 from Tom Wijsman --- Similar downstream report at https://bugs.gentoo.org/show_bug.cgi?id=472200 -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 66425] "failed testing IB on ring 5" when suspending to disk
https://bugs.freedesktop.org/show_bug.cgi?id=66425 wuruxu changed: What|Removed |Added Hardware|x86-64 (AMD64) |x86 (IA32) Status|RESOLVED|REOPENED Resolution|FIXED |--- Priority|medium |high --- Comment #26 from wuruxu --- Hi I found that after enable radeon.dpm, this message [drm:radeon_ib_ring_tests] *ERROR* radeon: failed testing IB on ring 5 (-35). always show after suspend system to RAM. wait a minute, the X Server crash. the attachment is output of demsg -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 66425] "failed testing IB on ring 5" when suspending to disk
https://bugs.freedesktop.org/show_bug.cgi?id=66425 --- Comment #27 from wuruxu --- Hi I found that after enable radeon.dpm, this message [drm:radeon_ib_ring_tests] *ERROR* radeon: failed testing IB on ring 5 (-35). always show after suspend system to RAM. wait a minute, the X Server crash. the attachment is output of demsg. I test with radeon HD6310, linux 3.11 rc5, mesa9.2 git, -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 66425] "failed testing IB on ring 5" when suspending to disk
https://bugs.freedesktop.org/show_bug.cgi?id=66425 --- Comment #28 from Alex Deucher --- (In reply to comment #27) > Hi I found that after enable radeon.dpm, this message > [drm:radeon_ib_ring_tests] *ERROR* radeon: failed testing IB on ring 5 > (-35). always show after suspend system to RAM. wait a minute, the X Server > crash. the attachment is output of demsg. I test with radeon HD6310, linux > 3.11 rc5, mesa9.2 git, If you are having problems with dpm enabled, please open a new bug as it may be a different issue. -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 66425] "failed testing IB on ring 5" when suspending to disk
https://bugs.freedesktop.org/show_bug.cgi?id=66425 Alex Deucher changed: What|Removed |Added Status|REOPENED|RESOLVED Resolution|--- |FIXED -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 66425] "failed testing IB on ring 5" when suspending to disk
https://bugs.freedesktop.org/show_bug.cgi?id=66425 --- Comment #29 from Alex Deucher --- (In reply to comment #28) > If you are having problems with dpm enabled, please open a new bug as it may > be a different issue. Also check to see if you can reproduce the problem with dpm disabled. -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 66425] "failed testing IB on ring 5" when suspending to disk
https://bugs.freedesktop.org/show_bug.cgi?id=66425 --- Comment #30 from wuruxu --- Created attachment 83989 --> https://bugs.freedesktop.org/attachment.cgi?id=83989&action=edit dmesg 3.11rc5 [ 129.095684] [drm:r600_uvd_ib_test] *ERROR* radeon: fence wait failed (-35). [ 129.115566] [drm:radeon_ib_ring_tests] *ERROR* radeon: failed testing IB on ring 5 (-35). -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH] drm/exynos: Add missing includes
> -Original Message- > From: linux-samsung-soc-ow...@vger.kernel.org [mailto:linux-samsung-soc- > ow...@vger.kernel.org] On Behalf Of Mark Brown > Sent: Tuesday, August 13, 2013 8:47 AM > To: David Airlie > Cc: linux-samsung-...@vger.kernel.org; dri-devel@lists.freedesktop.org; > Mark Brown > Subject: [PATCH] drm/exynos: Add missing includes > > From: Mark Brown > > Ensure that all externally accessed functions are correctly prototyped > when defined in each file by making sure the headers with the protoypes > are included in the file with the definition. > I definitely missed it. sorry about that. Actually I was going to try to incur something such as compile warning. You mean that the warning could be incurred by compiler in case that a external module includes a header of Exynos drm but the prototype of the header file differs from the one of .c file? I will apply it to -next but I'd like to understand why this patch is needed surely. And it seems like that other drivers have same issue also. :) Thanks, Inki Dae > Signed-off-by: Mark Brown > --- > drivers/gpu/drm/exynos/exynos_drm_connector.c | 1 + > drivers/gpu/drm/exynos/exynos_drm_crtc.c | 1 + > drivers/gpu/drm/exynos/exynos_drm_dmabuf.c| 1 + > drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 1 + > drivers/gpu/drm/exynos/exynos_drm_fimc.c | 1 + > drivers/gpu/drm/exynos/exynos_drm_g2d.c | 1 + > drivers/gpu/drm/exynos/exynos_drm_gsc.c | 1 + > drivers/gpu/drm/exynos/exynos_drm_plane.c | 1 + > drivers/gpu/drm/exynos/exynos_drm_rotator.c | 1 + > drivers/gpu/drm/exynos/exynos_drm_vidi.c | 1 + > 10 files changed, 10 insertions(+) > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c > b/drivers/gpu/drm/exynos/exynos_drm_connector.c > index 02a8bc5..3f80673 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c > @@ -17,6 +17,7 @@ > #include > #include "exynos_drm_drv.h" > #include "exynos_drm_encoder.h" > +#include "exynos_drm_connector.h" > > #define to_exynos_connector(x) container_of(x, struct > exynos_drm_connector,\ > drm_connector) > diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c > b/drivers/gpu/drm/exynos/exynos_drm_crtc.c > index 9a35d17..6b836c1 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c > @@ -15,6 +15,7 @@ > #include > #include > > +#include "exynos_drm_crtc.h" > #include "exynos_drm_drv.h" > #include "exynos_drm_encoder.h" > #include "exynos_drm_plane.h" > diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c > b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c > index a0f997e..2b25ac8 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c > @@ -11,6 +11,7 @@ > > #include > #include > +#include "exynos_drm_dmabuf.h" > #include "exynos_drm_drv.h" > #include "exynos_drm_gem.h" > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c > b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c > index 8e60bd6..3199f5b 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c > @@ -19,6 +19,7 @@ > > #include "exynos_drm_drv.h" > #include "exynos_drm_fb.h" > +#include "exynos_drm_fbdev.h" > #include "exynos_drm_gem.h" > #include "exynos_drm_iommu.h" > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c > b/drivers/gpu/drm/exynos/exynos_drm_fimc.c > index 6e047bd..a8ab4a4 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c > @@ -21,6 +21,7 @@ > #include > #include > #include "regs-fimc.h" > +#include "exynos_drm_drv.h" > #include "exynos_drm_ipp.h" > #include "exynos_drm_fimc.h" > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c > b/drivers/gpu/drm/exynos/exynos_drm_g2d.c > index eddea49..1262434 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c > @@ -23,6 +23,7 @@ > #include > #include > #include "exynos_drm_drv.h" > +#include "exynos_drm_g2d.h" > #include "exynos_drm_gem.h" > #include "exynos_drm_iommu.h" > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c > b/drivers/gpu/drm/exynos/exynos_drm_gsc.c > index 90b8a1a..e69d1d2 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c > @@ -20,6 +20,7 @@ > #include > #include > #include "regs-gsc.h" > +#include "exynos_drm_drv.h" > #include "exynos_drm_ipp.h" > #include "exynos_drm_gsc.h" > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c > b/drivers/gpu/drm/exynos/exynos_drm_plane.c > index 6ee55e6..98eb1f7 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c > @@ -16,6 +16,7 @@ > #include "exynos_drm_encoder.h" > #include "exynos_drm_fb.h" > #include "exynos_drm_gem.h" > +#include "exynos_drm_plane.h" >
EDID modes unavailable when no connector/crtc available at boot
I am working on the HDMI driver for the i.MX6 as part of the larger DRM driver written by Sascha Hauer and need a little advice. I seem to be missing one important part of the subsystem that I haven't been able to resolve. In my testing, powering on the system with only a HDMI cable connected works perfectly. Resolution is set to 1920x1080 as requested (with the framebuffer console at the same resolution). If I boot up the system without an HDMI cable connected (or any other cable), I get the expected: [1.470273] imx_hdmi_connector_detect [1.470276] returned cable DISCONNECTED [1.470289] imx-drm imx-drm: No connectors reported connected with modes [1.470297] [drm] Cannot find any crtc or sizes - going 1024x768 When I connect the cable at a later time, all EDID detected modes are 'truncated' to '<= 1024x768', but because I have a video=xxx in bootargs, the driver still seems to initialize to 1920x1080, but with a framebuffer of 1024x768. I assume this is a mistake on my part, but I don't know what I'm missing that would cause it. I see in drm_crtc_helper.c:drm_helper_mode_fill_fb_struct that the width/height are set to the initialized mode. Later in drm_fb_helper.c:drm_fb_helper_hotplug_event, max_width if set to fb->width. This is what causes the modes to be truncated when the HDMI connector is finally connected (max_width is now limited to 1024). Suggestions appreciated. Regards Tony Prisk ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: EDID modes unavailable when no connector/crtc available at boot
On 11/08/13 20:42, Dave Airlie wrote: On Sun, Aug 11, 2013 at 2:41 PM, Tony Prisk wrote: I am working on the HDMI driver for the i.MX6 as part of the larger DRM driver written by Sascha Hauer and need a little advice. I seem to be missing one important part of the subsystem that I haven't been able to resolve. fbcon is limited by boot sizes as at least with dynamic memory management and how fbdev works resizing the allocation is nearly impossible to do race free, since fbdev will hand out mmaps to userspace and that stops you from ever moving anything once the device is open. But this is only for the fbdev emulation, a real kms application should be able to use a larger size no problems. Dave. It seems to be worse than just a fbcon issue as far as I can tell. I am making an assumption, but I believe '/sys/class/drm/card0-HDMI-A-1/modes' should list all the supported modes of the connector (regardless of fbcon). Using 'cat /sys/class/drm/card0-HDMI-A-1/modes', it appears the supported modes are being limited by fbcon 1) HDMI Cable connected at bootup (fb @ 1920x1080) cat /sys/class/drm/card0-HDMI-A-1/modes 1920x1080 1280x720 1280x720 720x576 720x480 640x480 2) HDMI Cable NOT connected at bootup (fb @ 1024x768), cable is then connected after userspace has started (still in console) cat /sys/class/drm/card0-HDMI-A-1/modes 720x576 720x480 640x480 Following back through the source: static struct drm_connector_funcs imx_hdmi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, ... }; static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = { .get_modes = imx_hdmi_connector_get_modes, .mode_valid = imx_hdmi_connector_mode_valid, ... }; It appears that only drm_helper_probe_single_connector_modes() calls .get_modes() and .mode_valid() .fill_modes() is called from drm_fb_helper_probe_connector_modes(), which is called from drm_fb_helper_hotplug_event() drm_fb_helper_hotplug_event() sets max_width to fb_helper->fb->width, and max_height to fb_helper->fb->height. fb->width is 1024 if booted without the cable connected, hence the clipping of the values. Regards Tony Prisk ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCHv2 1/5] drm/exynos: add device tree support for rotator
Hi Tomasz, > -Original Message- > From: Tomasz Figa [mailto:t.f...@samsung.com] > Sent: Friday, August 09, 2013 9:51 PM > To: Chanho Park > Cc: inki@samsung.com; kgene@samsung.com; dri- > de...@lists.freedesktop.org; kyungmin.p...@samsung.com; > mark.rutl...@arm.com; l.st...@pengutronix.de; s.nawro...@samsung.com; > tomasz.f...@gmail.com; linux-samsung-...@vger.kernel.org; linux-arm- > ker...@lists.infradead.org; devicet...@vger.kernel.org > Subject: Re: [PATCHv2 1/5] drm/exynos: add device tree support for > rotator > > Hi Chanho, > > On Friday 09 of August 2013 16:40:49 Chanho Park wrote: > > The exynos4 platform is only dt-based since 3.10, we should convert > > driver data and ids to dt-based parsing methods. The rotator driver > > has a limit table to get size limit of input picture. Each SoCs has > > slightly different limit value compared with any others. > > For example, exynos4210's max_size of RGB888 is 16k x 16k. But, others > > have 8k x 8k. Another example the exynos5250 should have multiple of 2 > > pixel size for its X/Y axis. Thus, we should keep different tables for > > each of them. > > > > Signed-off-by: Chanho Park > > Signed-off-by: Kyungmin Park > > --- > > drivers/gpu/drm/exynos/exynos_drm_rotator.c | 109 > > --- 1 file changed, 81 insertions(+), 28 > > deletions(-) > > > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c > > b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index 427640a..39b09e0 > > 100644 > > --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c > > +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c > > @@ -632,6 +632,73 @@ static int rotator_ippdrv_start(struct device > > *dev, enum drm_exynos_ipp_cmd cmd) return 0; } > > > > +static struct rot_limit_table rot_limit_tbl_4210 = { > > + .ycbcr420_2p = { > > + .min_w = 32, > > + .min_h = 32, > > + .max_w = SZ_64K, > > + .max_h = SZ_64K, > > + .align = 3, > > + }, > > + .rgb888 = { > > + .min_w = 8, > > + .min_h = 8, > > + .max_w = SZ_16K, > > + .max_h = SZ_16K, > > + .align = 2, > > + }, > > +}; > > + > > +static struct rot_limit_table rot_limit_tbl_4x12 = { > > + .ycbcr420_2p = { > > + .min_w = 32, > > + .min_h = 32, > > + .max_w = SZ_32K, > > + .max_h = SZ_32K, > > + .align = 3, > > + }, > > + .rgb888 = { > > + .min_w = 8, > > + .min_h = 8, > > + .max_w = SZ_8K, > > + .max_h = SZ_8K, > > + .align = 2, > > + }, > > +}; > > + > > +static struct rot_limit_table rot_limit_tbl_5250 = { > > + .ycbcr420_2p = { > > + .min_w = 32, > > + .min_h = 32, > > + .max_w = SZ_32K, > > + .max_h = SZ_32K, > > + .align = 3, > > + }, > > + .rgb888 = { > > + .min_w = 8, > > + .min_h = 8, > > + .max_w = SZ_8K, > > + .max_h = SZ_8K, > > + .align = 1, > > + }, > > +}; > > + > > +static const struct of_device_id exynos_rotator_match[] = { > > + { > > + .compatible = "samsung,exynos4210-rotator", > > + .data = &rot_limit_tbl_4210, > > + }, > > + { > > + .compatible = "samsung,exynos4212-rotator", > > + .data = &rot_limit_tbl_4x12, > > + }, > > + { > > + .compatible = "samsung,exynos5250-rotator", > > + .data = &rot_limit_tbl_5250, > > + }, > > + {}, > > +}; > > + > > static int rotator_probe(struct platform_device *pdev) { > > struct device *dev = &pdev->dev; > > @@ -645,8 +712,19 @@ static int rotator_probe(struct platform_device > > *pdev) return -ENOMEM; > > } > > > > - rot->limit_tbl = (struct rot_limit_table *) > > - platform_get_device_id(pdev)->driver_data; > > + if (dev->of_node) { > > + const struct of_device_id *match; > > + match = of_match_node(of_match_ptr(exynos_rotator_match), > > + dev->of_node); > > + if (match == NULL) { > > + dev_err(dev, "failed to match node\n"); > > + return -ENODEV; > > + } > > + rot->limit_tbl = (struct rot_limit_table *)match->data; > > + } else { > > + dev_err(dev, "cannot find binding\n"); > > What about having a check for !dev->of_node at the beginning of probe, > to not complicate further code? I agree with your comment. I'll move it at the beginning. > > Also the error message is confusing. It should be something closer to > "device does not have of_node". I'll change it to avoid confusing. Thanks. > > > + return -ENODEV; > > + } > > > > rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > rot->regs = devm_ioremap_resource(dev, rot->regs_res); @@ -718,31 > > +796,6 @@ static int rotator_remove(struct platform_device > > *pdev) return 0; > > } > > >
RE: [PATCHv2 2/5] ARM: dts: Add rotator node for exynos4210
Hi Tomasz, > -Original Message- > From: Tomasz Figa [mailto:t.f...@samsung.com] > Sent: Friday, August 09, 2013 9:57 PM > To: Chanho Park > Cc: inki@samsung.com; kgene@samsung.com; dri- > de...@lists.freedesktop.org; kyungmin.p...@samsung.com; > mark.rutl...@arm.com; l.st...@pengutronix.de; s.nawro...@samsung.com; > tomasz.f...@gmail.com; linux-samsung-...@vger.kernel.org; linux-arm- > ker...@lists.infradead.org; devicet...@vger.kernel.org; Thomas Abraham > Subject: Re: [PATCHv2 2/5] ARM: dts: Add rotator node for exynos4210 > > On Friday 09 of August 2013 16:40:50 Chanho Park wrote: > > This patch adds a rotator node for exynos4210. The exynos4210 has > > different limitation of image size compared with later chips. > > > > Signed-off-by: Chanho Park > > Cc: Thomas Abraham > > Cc: Kukjin Kim > > Cc: Inki Dae > > Signed-off-by: Kyungmin Park > > --- > > arch/arm/boot/dts/exynos4.dtsi |9 + > > 1 file changed, 9 insertions(+) > > > > diff --git a/arch/arm/boot/dts/exynos4.dtsi > > b/arch/arm/boot/dts/exynos4.dtsi index 597cfcf..002b2b8 100644 > > --- a/arch/arm/boot/dts/exynos4.dtsi > > +++ b/arch/arm/boot/dts/exynos4.dtsi > > @@ -243,6 +243,15 @@ > > status = "disabled"; > > }; > > > > + rotator: rotator@1281 { > > + compatible = "samsung,exynos4210-rotator"; > > + reg = <0x1281 0x1000>; > > + interrupts = <0 83 0>; > > + clocks = <&clock 278>; > > + clock-names = "rotator"; > > + status = "disabled"; > > Does the rotator need any board-specific information to work? If no, it > should not be disabled by default. Same comment goes to patch 4/5. It does not have any board-specific information. I'll remove the status node. Thanks. Best Regards, Chanho Park ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCHv2 5/5] ARM: dts: Add dt binding documentation for exynos rotator
Hi Tomasz, > -Original Message- > From: Tomasz Figa [mailto:t.f...@samsung.com] > Sent: Friday, August 09, 2013 10:16 PM > To: Chanho Park > Cc: inki@samsung.com; kgene@samsung.com; dri- > de...@lists.freedesktop.org; kyungmin.p...@samsung.com; > mark.rutl...@arm.com; l.st...@pengutronix.de; s.nawro...@samsung.com; > tomasz.f...@gmail.com; linux-samsung-...@vger.kernel.org; linux-arm- > ker...@lists.infradead.org; devicet...@vger.kernel.org; Thomas Abraham; > swar...@wwwdotorg.org; ian.campb...@citrix.com; rob.herr...@calxeda.com; > pawel.m...@arm.com > Subject: Re: [PATCHv2 5/5] ARM: dts: Add dt binding documentation for > exynos rotator > > Hi Chanho, > > On Friday 09 of August 2013 16:40:53 Chanho Park wrote: > > This patch describes each nodes of rotator and specifies a example how > > to bind it. > > > > Signed-off-by: Chanho Park > > Cc: Thomas Abraham > > Cc: Kukjin Kim > > Cc: Inki Dae > > Signed-off-by: Kyungmin Park > > --- > > .../devicetree/bindings/gpu/samsung-rotator.txt| 26 > > 1 file changed, 26 insertions(+) > > create mode 100644 > > Documentation/devicetree/bindings/gpu/samsung-rotator.txt > > > > diff --git a/Documentation/devicetree/bindings/gpu/samsung-rotator.txt > > b/Documentation/devicetree/bindings/gpu/samsung-rotator.txt new file > > mode 100644 index 000..31ee7b5 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/gpu/samsung-rotator.txt > > @@ -0,0 +1,26 @@ > > +* Samsung Image Rotator > > + > > +Required properties: > > + - compatible : value should be following: > > + (a) "samsung,exynos4210-rotator" for Rotator IP in Exynos4210 > > + (b) "samsung,exynos4212-rotator" for Rotator IP in Exynos4212/4412 > > + (c) "samsung,exynos5250-rotator" for Rotator IP in Exynos5250 > > + > > + - reg : Physical base address of the IP registers and length of > memory > > + mapped region. > > + > > + - interrupts : Interrupt number of Rotator > > What about: interrupt specifier for rotator interrupt, according to > format specific to interrupt parent. > > > + > > + - clocks : Clock number described in > > Documentations/devicetree/binding/clock. + > > Perhaps: clock specifier for rotator clock, according to generic clock > bindings. Become more clearly. Thanks. > > > + - clock-names : Clock name. > > Names of clocks specified in "clocks" property. For exynos rotator this > property should contain only one name: "rotator". > > > +Example: > > + rotator: rotator@1280 { > > I wonder if we shouldn't use a more generic name here, according to > ePAPR node naming recommendation. Hmm. I'm not sure what name is better than rotator. How about image-rotator@1281 > > > + compatible = "samsung,exynos4210-rotator"; > > + reg = <0x1281 0x1000>; > > Typo. Node has 1280 in unit-address suffix, but this property has > 1281 instead. Yes. It's typo. I'll correct it now. > > > + interrupts = <0 83 0>; > > + clocks = <&clock 278>; > > + clock-names = "rotator"; > > + status = "disabled"; > > Status property should be omitted from this example, as it's not a part > of this binding. I'll remove the property. Thanks. Best Regards, Chanho Park ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 03/25] drm/imx: kill firstopen callback
On Thu, Aug 08, 2013 at 03:41:13PM +0200, Daniel Vetter wrote: > This thing seems to do some kind of delayed setup. Really, real kms > drivers shouldn't do that at all. Either stuff needs to be dynamically > hotplugged or the driver setup sequence needs to be fixed. > > This patch here just moves the setup at the very end of the driver > load callback, with the locking adjusted accordingly. > > v2: Also move the corresponding put from ->lastclose to ->unload. > > Cc: Sascha Hauer > Cc: Greg Kroah-Hartman > Signed-off-by: Daniel Vetter > --- > > Note that this is already in the staging tree but due to the follow-up cleanup > it's probably best to merge it again through drm-next. > -Daniel That's fine with me: Acked-by: Greg Kroah-Hartman ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/exynos: Add missing includes
From: Mark Brown Ensure that all externally accessed functions are correctly prototyped when defined in each file by making sure the headers with the protoypes are included in the file with the definition. Signed-off-by: Mark Brown --- drivers/gpu/drm/exynos/exynos_drm_connector.c | 1 + drivers/gpu/drm/exynos/exynos_drm_crtc.c | 1 + drivers/gpu/drm/exynos/exynos_drm_dmabuf.c| 1 + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 1 + drivers/gpu/drm/exynos/exynos_drm_fimc.c | 1 + drivers/gpu/drm/exynos/exynos_drm_g2d.c | 1 + drivers/gpu/drm/exynos/exynos_drm_gsc.c | 1 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 1 + drivers/gpu/drm/exynos/exynos_drm_rotator.c | 1 + drivers/gpu/drm/exynos/exynos_drm_vidi.c | 1 + 10 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 02a8bc5..3f80673 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -17,6 +17,7 @@ #include #include "exynos_drm_drv.h" #include "exynos_drm_encoder.h" +#include "exynos_drm_connector.h" #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ drm_connector) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 9a35d17..6b836c1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -15,6 +15,7 @@ #include #include +#include "exynos_drm_crtc.h" #include "exynos_drm_drv.h" #include "exynos_drm_encoder.h" #include "exynos_drm_plane.h" diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index a0f997e..2b25ac8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -11,6 +11,7 @@ #include #include +#include "exynos_drm_dmabuf.h" #include "exynos_drm_drv.h" #include "exynos_drm_gem.h" diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 8e60bd6..3199f5b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -19,6 +19,7 @@ #include "exynos_drm_drv.h" #include "exynos_drm_fb.h" +#include "exynos_drm_fbdev.h" #include "exynos_drm_gem.h" #include "exynos_drm_iommu.h" diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index 6e047bd..a8ab4a4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -21,6 +21,7 @@ #include #include #include "regs-fimc.h" +#include "exynos_drm_drv.h" #include "exynos_drm_ipp.h" #include "exynos_drm_fimc.h" diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index eddea49..1262434 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -23,6 +23,7 @@ #include #include #include "exynos_drm_drv.h" +#include "exynos_drm_g2d.h" #include "exynos_drm_gem.h" #include "exynos_drm_iommu.h" diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 90b8a1a..e69d1d2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -20,6 +20,7 @@ #include #include #include "regs-gsc.h" +#include "exynos_drm_drv.h" #include "exynos_drm_ipp.h" #include "exynos_drm_gsc.h" diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 6ee55e6..98eb1f7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -16,6 +16,7 @@ #include "exynos_drm_encoder.h" #include "exynos_drm_fb.h" #include "exynos_drm_gem.h" +#include "exynos_drm_plane.h" #define to_exynos_plane(x) container_of(x, struct exynos_plane, base) diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index 49669aa..54b7360 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -21,6 +21,7 @@ #include #include "regs-rotator.h" #include "exynos_drm.h" +#include "exynos_drm_drv.h" #include "exynos_drm_ipp.h" /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index c57c565..4400330 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -23,6 +23,7 @@ #include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" #include "exynos_drm_encoder.h" +#include "exynos_drm_vidi.h" /* vidi has totally three virtual windows. */ #define WINDOWS_NR 3 -- 1.8.4.rc1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/lis
Re: [GIT PULL FOR v3.12] R-Car DU DRM support for R8A7790 SoC
On Sat, Aug 10, 2013 at 07:28:30AM +1000, Dave Airlie wrote: > On Sat, Aug 10, 2013 at 7:25 AM, Laurent Pinchart > wrote: > > Hi Dave, > > > > On Saturday 10 August 2013 06:45:05 Dave Airlie wrote: > >> On Thu, Aug 8, 2013 at 11:39 AM, Simon Horman wrote: > >> > On Thu, Aug 08, 2013 at 03:34:17AM +0200, Laurent Pinchart wrote: > >> >> Hi Dave, > >> >> > >> >> (CC'ing Simon Horman, the shmobile tree maintainer) > >> >> > >> >> On Thursday 08 August 2013 10:57:33 Dave Airlie wrote: > >> >> > On Thu, Aug 8, 2013 at 10:43 AM, Laurent Pinchart wrote: > >> >> > > Hi Dave, > >> >> > > > >> >> > > I've got a couple of arch/arm/ patches that depend on this series > >> >> > > and > >> >> > > that I would like to get merged in v3.12. They should go upstream > >> >> > > through the arm-soc tree. Would you be able to provide a stable > >> >> > > branch with this patch set based on one of the 3.11-rcX tags ? > >> >> > > Ideally that branch should have as little patches as possible other > >> >> > > than this set. > >> >> > > >> >> > Yeah that shouldn't be a problem, though is there any interface > >> >> > changes > >> >> > or things with this wrt drm-next? > >> >> > > >> >> > i.e. will this tree build on v3.11-rcX and drm-next? > >> >> > >> >> They depend on a fix that went in between -rc1 and -rc2. You can base > >> >> the > >> >> branch on any -rc >= 2. > >> > > >> > An rc2 or rc3 base would be ideal for me, but any rc would be fine. > >> > >> So the problem with making a stable branch is we have conflicts in other > >> places that have already been solved in drm-next, > >> > >> is there any problem with using Laurent's tree directly as the stable > >> point? > > > > As agreed on IRC, I've rebased the patches on top of v3.11-rc3 and pushed > > the > > result to > > > > git://linuxtv.org/pinchartl/fbdev.git drm/next/du > > > > b/drivers/gpu/drm/rcar-du/Kconfig |7 > > b/drivers/gpu/drm/rcar-du/Makefile | 10 - > > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c| 255 > > +- > > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h| 13 - > > b/drivers/gpu/drm/rcar-du/rcar_du_drv.c | 173 +++--- > > b/drivers/gpu/drm/rcar-du/rcar_du_drv.h | 63 +- > > b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 202 ++ > > b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h | 49 + > > b/drivers/gpu/drm/rcar-du/rcar_du_group.c | 187 > > b/drivers/gpu/drm/rcar-du/rcar_du_group.h | 50 + > > b/drivers/gpu/drm/rcar-du/rcar_du_kms.c | 165 ++ > > b/drivers/gpu/drm/rcar-du/rcar_du_kms.h | 29 --- > > b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 131 ++ > > b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h | 25 ++ > > b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 196 + > > b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 46 + > > b/drivers/gpu/drm/rcar-du/rcar_du_plane.c | 170 +- > > b/drivers/gpu/drm/rcar-du/rcar_du_plane.h | 26 ++ > > b/drivers/gpu/drm/rcar-du/rcar_du_regs.h| 94 -- > > b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 96 ++ > > b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h | 23 ++ > > b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h | 69 +++ > > b/include/linux/platform_data/rcar-du.h | 34 ++- > > drivers/gpu/drm/rcar-du/rcar_du_lvds.c | 216 --- > > drivers/gpu/drm/rcar-du/rcar_du_lvds.h | 24 -- > > drivers/gpu/drm/rcar-du/rcar_du_vga.c | 149 > > drivers/gpu/drm/rcar-du/rcar_du_vga.h | 24 -- > > 27 files changed, 1665 insertions(+), 861 deletions(-) > > > > Can you merge that into drm-next ? Simon, you can base the r8a7790 arch/ > > patches on top of this drm/next/du branch. > > Actually small change > > Simon can you use > > git://git.freedesktop.org/~airlied/linux drm-rcar-for-v3.12 > > as I've merged this tree with an S-o-b on the merge commit, so other > people will know it has gone via me. Thanks, got it. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCHv3 1/4] drm/exynos: add device tree support for rotator
The exynos4 platform is only dt-based since 3.10, we should convert driver data and ids to dt-based parsing methods. The rotator driver has a limit table to get size limit of input picture. Each SoCs has slightly different limit value compared with any others. For example, exynos4210's max_size of RGB888 is 16k x 16k. But, others have 8k x 8k. Another example the exynos5250 should have multiple of 2 pixel size for its X/Y axis. Thus, we should keep different tables for each of them. This patch also includes desciptions of each nodes for the rotator and specifies a example how to bind it. Signed-off-by: Chanho Park Cc: Inki Dae Signed-off-by: Kyungmin Park --- .../devicetree/bindings/gpu/samsung-rotator.txt| 27 + drivers/gpu/drm/exynos/exynos_drm_rotator.c| 108 +++- 2 files changed, 107 insertions(+), 28 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpu/samsung-rotator.txt diff --git a/Documentation/devicetree/bindings/gpu/samsung-rotator.txt b/Documentation/devicetree/bindings/gpu/samsung-rotator.txt new file mode 100644 index 000..82cd1ed --- /dev/null +++ b/Documentation/devicetree/bindings/gpu/samsung-rotator.txt @@ -0,0 +1,27 @@ +* Samsung Image Rotator + +Required properties: + - compatible : value should be one of the following: + (a) "samsung,exynos4210-rotator" for Rotator IP in Exynos4210 + (b) "samsung,exynos4212-rotator" for Rotator IP in Exynos4212/4412 + (c) "samsung,exynos5250-rotator" for Rotator IP in Exynos5250 + + - reg : Physical base address of the IP registers and length of memory + mapped region. + + - interrupts : Interrupt specifier for rotator interrupt, according to format +specific to interrupt parent. + + - clocks : Clock specifier for rotator clock, according to generic clock +bindings. (See Documentation/devicetree/bindings/clock/exynos*.txt) + + - clock-names : Names of clocks. For exynos rotator, it should be "rotator". + +Example: + rotator@1281 { + compatible = "samsung,exynos4210-rotator"; + reg = <0x1281 0x1000>; + interrupts = <0 83 0>; + clocks = <&clock 278>; + clock-names = "rotator"; + }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index 427640a..0485aea5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -632,21 +632,98 @@ static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) return 0; } +static struct rot_limit_table rot_limit_tbl_4210 = { + .ycbcr420_2p = { + .min_w = 32, + .min_h = 32, + .max_w = SZ_64K, + .max_h = SZ_64K, + .align = 3, + }, + .rgb888 = { + .min_w = 8, + .min_h = 8, + .max_w = SZ_16K, + .max_h = SZ_16K, + .align = 2, + }, +}; + +static struct rot_limit_table rot_limit_tbl_4x12 = { + .ycbcr420_2p = { + .min_w = 32, + .min_h = 32, + .max_w = SZ_32K, + .max_h = SZ_32K, + .align = 3, + }, + .rgb888 = { + .min_w = 8, + .min_h = 8, + .max_w = SZ_8K, + .max_h = SZ_8K, + .align = 2, + }, +}; + +static struct rot_limit_table rot_limit_tbl_5250 = { + .ycbcr420_2p = { + .min_w = 32, + .min_h = 32, + .max_w = SZ_32K, + .max_h = SZ_32K, + .align = 3, + }, + .rgb888 = { + .min_w = 8, + .min_h = 8, + .max_w = SZ_8K, + .max_h = SZ_8K, + .align = 1, + }, +}; + +static const struct of_device_id exynos_rotator_match[] = { + { + .compatible = "samsung,exynos4210-rotator", + .data = &rot_limit_tbl_4210, + }, + { + .compatible = "samsung,exynos4212-rotator", + .data = &rot_limit_tbl_4x12, + }, + { + .compatible = "samsung,exynos5250-rotator", + .data = &rot_limit_tbl_5250, + }, + {}, +}; + static int rotator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rot_context *rot; struct exynos_drm_ippdrv *ippdrv; + const struct of_device_id *match; int ret; + if (!dev->of_node) { + dev_err(dev, "cannot find of_node.\n"); + return -ENODEV; + } + rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL); if (!rot) { dev_err(dev, "failed to allocate rot\n"); return -ENOMEM; } - rot->limit_tbl = (struct rot_limit_table *) -
[PATCHv3 4/4] ARM: dts: Add rotator node for exynos5250
This patch adds a rotator node for exynos5250. It has different align value of image size compared with any other chips. So, we should define new compatible for the exynos5250. Signed-off-by: Chanho Park Cc: Thomas Abraham Cc: Kukjin Kim Cc: Inki Dae Signed-off-by: Kyungmin Park --- arch/arm/boot/dts/exynos5250.dtsi |8 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 6f356ce..f579546 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -570,6 +570,14 @@ }; }; + rotator@11C0 { + compatible = "samsung,exynos5250-rotator"; + reg = <0x11C0 0x1000>; + interrupts = <0 84 0>; + clocks = <&clock 269>; + clock-names = "rotator"; + }; + gsc_0: gsc@0x13e0 { compatible = "samsung,exynos5-gsc"; reg = <0x13e0 0x1000>; -- 1.7.9.5 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCHv3 0/4] device tree support for exynos rotator
This patchset includes device tree support for rotator of exynos4210/4x12/5250. Unfortunately, each of them has slightly different limitations of image size. The rotator can support several image formats(RGB888/555, YCbCr422/420_2/3p). For convinience, however, exynos drm rotator driver only support RGB888 and YCbCr420 2-Plane formats. For example, the exynos4210 has 16k x 16k maximum size . But rest of them has 8k x 8k. In addition, RGB888 X/Y pixel size of exynos5250 should be multiple of 2. But others are multiple of 4. Thus, we should define different compatibles and limit tables for each chipsets. This patchset is based on the Kukjin's dt-exynos tree. (git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git v3.12-next/dt-exynos) Changes from v2: - Remove unnecessary 'of_match_ptr' - Consolidate dt support code and documentation into one patch - Fix typo and remove status node. Changes from v1: - Added exynos5250 binding. - Move limit table into driver code from DT-nodes Chanho Park (4): drm/exynos: add device tree support for rotator ARM: dts: Add rotator node for exynos4210 ARM: dts: Add rotator node for exynos4x12 ARM: dts: Add rotator node for exynos5250 .../devicetree/bindings/gpu/samsung-rotator.txt| 27 + arch/arm/boot/dts/exynos4.dtsi |8 ++ arch/arm/boot/dts/exynos4x12.dtsi |4 + arch/arm/boot/dts/exynos5250.dtsi |8 ++ drivers/gpu/drm/exynos/exynos_drm_rotator.c| 108 +++- 5 files changed, 127 insertions(+), 28 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpu/samsung-rotator.txt -- 1.7.9.5 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCHv3 3/4] ARM: dts: Add rotator node for exynos4x12
This patch adds a rotator node for exynos4212 and 4412. These have different limitation of image size compared with the exynos4210. So, we should define new compatible to distinguish it from the exynos4210. Signed-off-by: Chanho Park Cc: Thomas Abraham Cc: Kukjin Kim Cc: Inki Dae Signed-off-by: Kyungmin Park --- arch/arm/boot/dts/exynos4x12.dtsi |4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi index 954628c..280c56f 100644 --- a/arch/arm/boot/dts/exynos4x12.dtsi +++ b/arch/arm/boot/dts/exynos4x12.dtsi @@ -176,4 +176,8 @@ }; }; }; + + rotator@1281 { + compatible = "samsung,exynos4212-rotator"; + }; }; -- 1.7.9.5 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCHv3 2/4] ARM: dts: Add rotator node for exynos4210
This patch adds a rotator node for exynos4210. The exynos4210 has different limitation of image size compared with later chips. Signed-off-by: Chanho Park Cc: Thomas Abraham Cc: Kukjin Kim Cc: Inki Dae Signed-off-by: Kyungmin Park --- arch/arm/boot/dts/exynos4.dtsi |8 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 597cfcf..baa3e56 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -243,6 +243,14 @@ status = "disabled"; }; + rotator@1281 { + compatible = "samsung,exynos4210-rotator"; + reg = <0x1281 0x1000>; + interrupts = <0 83 0>; + clocks = <&clock 278>; + clock-names = "rotator"; + }; + mfc: codec@1340 { compatible = "samsung,mfc-v5"; reg = <0x1340 0x1>; -- 1.7.9.5 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 67800] Computer freezes after idle for several hours (trinity)
https://bugs.freedesktop.org/show_bug.cgi?id=67800 --- Comment #8 from Kertesz Laszlo --- This bug seems to be gone now in this form after the aforementioned patches were installed. But now i have random freezes here and there when i am actually working on the computer. I had it happening during compilation (with 3/4 threads), using the browser (Firefox, Seamonkey) and playback (xv, mplayer). I never had it happen if i used something opengl related such as games (TF2, DoD) or xbmc. On the other hand xbmc exhibited severe memory leaks occasionally if i used vdpau. Thermals, at least the ones indicated by sensors dont seem to be a problem - i compiled for hours stuff on it and didnt freeze. And on other occasions it froze after a few minutes. Core temperature was 44C on the last occasion. Temperatures go up to 57C with 3-4 threads and nothing bad happens except thermal throttling (with fglrx i had up to 60C). -- You are receiving this mail because: You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 10/53] drm/radeon: switch CIK to use radeon_ucode.h
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 17 + drivers/gpu/drm/radeon/radeon_ucode.h | 14 ++ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 42b143e..2ceb900 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -30,22 +30,7 @@ #include "cikd.h" #include "atom.h" #include "cik_blit_shaders.h" - -/* GFX */ -#define CIK_PFP_UCODE_SIZE 2144 -#define CIK_ME_UCODE_SIZE 2144 -#define CIK_CE_UCODE_SIZE 2144 -/* compute */ -#define CIK_MEC_UCODE_SIZE 4192 -/* interrupts */ -#define BONAIRE_RLC_UCODE_SIZE 2048 -#define KB_RLC_UCODE_SIZE 2560 -#define KV_RLC_UCODE_SIZE 2560 -/* gddr controller */ -#define CIK_MC_UCODE_SIZE 7866 -/* sdma */ -#define CIK_SDMA_UCODE_SIZE 1050 -#define CIK_SDMA_UCODE_VERSION 64 +#include "radeon_ucode.h" MODULE_FIRMWARE("radeon/BONAIRE_pfp.bin"); MODULE_FIRMWARE("radeon/BONAIRE_me.bin"); diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index d8b05f7..fad27c0 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h @@ -35,6 +35,12 @@ #define SI_PFP_UCODE_SIZE2144 #define SI_PM4_UCODE_SIZE2144 #define SI_CE_UCODE_SIZE 2144 +#define CIK_PFP_UCODE_SIZE 2144 +#define CIK_ME_UCODE_SIZE2144 +#define CIK_CE_UCODE_SIZE2144 + +/* MEC */ +#define CIK_MEC_UCODE_SIZE 4192 /* RLC */ #define R600_RLC_UCODE_SIZE 768 @@ -43,12 +49,20 @@ #define CAYMAN_RLC_UCODE_SIZE1024 #define ARUBA_RLC_UCODE_SIZE 1536 #define SI_RLC_UCODE_SIZE2048 +#define BONAIRE_RLC_UCODE_SIZE 2048 +#define KB_RLC_UCODE_SIZE2560 +#define KV_RLC_UCODE_SIZE2560 /* MC */ #define BTC_MC_UCODE_SIZE6024 #define CAYMAN_MC_UCODE_SIZE 6037 #define SI_MC_UCODE_SIZE 7769 #define OLAND_MC_UCODE_SIZE 7863 +#define CIK_MC_UCODE_SIZE7866 + +/* SDMA */ +#define CIK_SDMA_UCODE_SIZE 1050 +#define CIK_SDMA_UCODE_VERSION 64 /* SMC */ #define RV770_SMC_UCODE_START0x0100 -- 1.8.3.1
[PATCH 11/53] drm/radeon/cik: add support for pcie gen1/2/3 switching
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 161 ++ drivers/gpu/drm/radeon/cikd.h | 57 +++ 2 files changed, 218 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 2ceb900..a30fb32 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -61,6 +61,7 @@ extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *m extern void si_rlc_fini(struct radeon_device *rdev); extern int si_rlc_init(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); +static void cik_pcie_gen3_enable(struct radeon_device *rdev); /* * Indirect registers accessor @@ -5949,6 +5950,9 @@ static int cik_startup(struct radeon_device *rdev) struct radeon_ring *ring; int r; + /* enable pcie gen2/3 link */ + cik_pcie_gen3_enable(rdev); + cik_mc_program(rdev); if (rdev->flags & RADEON_IS_IGP) { @@ -7051,3 +7055,160 @@ int cik_uvd_resume(struct radeon_device *rdev) return 0; } + +static void cik_pcie_gen3_enable(struct radeon_device *rdev) +{ + struct pci_dev *root = rdev->pdev->bus->self; + int bridge_pos, gpu_pos; + u32 speed_cntl, mask, current_data_rate; + int ret, i; + u16 tmp16; + + if (radeon_pcie_gen2 == 0) + return; + + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); + if (ret != 0) + return; + + if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) + return; + + speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); + current_data_rate = (speed_cntl & LC_CURRENT_DATA_RATE_MASK) >> + LC_CURRENT_DATA_RATE_SHIFT; + if (mask & DRM_PCIE_SPEED_80) { + if (current_data_rate == 2) { + DRM_INFO("PCIE gen 3 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 3 link speeds, disable with radeon.pcie_gen2=0\n"); + } else if (mask & DRM_PCIE_SPEED_50) { + if (current_data_rate == 1) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); + } + + bridge_pos = pci_pcie_cap(root); + if (!bridge_pos) + return; + + gpu_pos = pci_pcie_cap(rdev->pdev); + if (!gpu_pos) + return; + + if (mask & DRM_PCIE_SPEED_80) { + /* re-try equalization if gen3 is not already enabled */ + if (current_data_rate != 2) { + u16 bridge_cfg, gpu_cfg; + u16 bridge_cfg2, gpu_cfg2; + u32 max_lw, current_lw, tmp; + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg); + pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg); + + tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD; + pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16); + + tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD; + pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16); + + tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1); + max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT; + current_lw = (tmp & LC_OPERATING_LINK_WIDTH_MASK) >> LC_OPERATING_LINK_WIDTH_SHIFT; + + if (current_lw < max_lw) { + tmp = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); + if (tmp & LC_RENEGOTIATION_SUPPORT) { + tmp &= ~(LC_LINK_WIDTH_MASK | LC_UPCONFIGURE_DIS); + tmp |= (max_lw << LC_LINK_WIDTH_SHIFT); + tmp |= LC_UPCONFIGURE_SUPPORT | LC_RENEGOTIATE_EN | LC_RECONFIG_NOW; + WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, tmp); + } + } + + for (i = 0; i < 10; i++) { + /* check status */ + pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_DEVSTA, &tmp16); + if (tmp16 & PCI_EXP_DEVSTA_TRPND) + break; + + pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg); + pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu
[PATCH 13/53] drm/radeon/cik: restructure rlc setup
Restructure rlc setup to handle clock and power gating. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 84 +++ drivers/gpu/drm/radeon/cikd.h | 1 + drivers/gpu/drm/radeon/si.c | 2 +- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 0da9d67..e92a972 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -60,6 +60,7 @@ extern bool evergreen_is_display_hung(struct radeon_device *rdev); extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern void si_rlc_fini(struct radeon_device *rdev); extern int si_rlc_init(struct radeon_device *rdev); +extern void si_rlc_reset(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); static void cik_pcie_gen3_enable(struct radeon_device *rdev); static void cik_program_aspm(struct radeon_device *rdev); @@ -4728,31 +4729,34 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm * variety of functions, the most important of which is * the interrupt controller. */ -/** - * cik_rlc_stop - stop the RLC ME - * - * @rdev: radeon_device pointer - * - * Halt the RLC ME (MicroEngine) (CIK). - */ -static void cik_rlc_stop(struct radeon_device *rdev) +static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev, + bool enable) { - int i, j, k; - u32 mask, tmp; + u32 tmp = RREG32(CP_INT_CNTL_RING0); - tmp = RREG32(CP_INT_CNTL_RING0); - tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + if (enable) + tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + else + tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); WREG32(CP_INT_CNTL_RING0, tmp); +} - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); +static void cik_enable_lbpw(struct radeon_device *rdev, bool enable) +{ + u32 tmp; - tmp = RREG32(RLC_CGCG_CGLS_CTRL) & 0xfffc; - WREG32(RLC_CGCG_CGLS_CTRL, tmp); + tmp = RREG32(RLC_LB_CNTL); + if (enable) + tmp |= LOAD_BALANCE_ENABLE; + else + tmp &= ~LOAD_BALANCE_ENABLE; + WREG32(RLC_LB_CNTL, tmp); +} - WREG32(RLC_CNTL, 0); +static void cik_wait_for_rlc_serdes(struct radeon_device *rdev) +{ + u32 i, j, k; + u32 mask; for (i = 0; i < rdev->config.cik.max_shader_engines; i++) { for (j = 0; j < rdev->config.cik.max_sh_per_se; j++) { @@ -4775,6 +4779,32 @@ static void cik_rlc_stop(struct radeon_device *rdev) } /** + * cik_rlc_stop - stop the RLC ME + * + * @rdev: radeon_device pointer + * + * Halt the RLC ME (MicroEngine) (CIK). + */ +static void cik_rlc_stop(struct radeon_device *rdev) +{ + u32 tmp; + + cik_enable_gui_idle_interrupt(rdev, false); + + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + + tmp = RREG32(RLC_CGCG_CGLS_CTRL) & 0xfffc; + WREG32(RLC_CGCG_CGLS_CTRL, tmp); + + WREG32(RLC_CNTL, 0); + + cik_wait_for_rlc_serdes(rdev); +} + +/** * cik_rlc_start - start the RLC ME * * @rdev: radeon_device pointer @@ -4783,13 +4813,9 @@ static void cik_rlc_stop(struct radeon_device *rdev) */ static void cik_rlc_start(struct radeon_device *rdev) { - u32 tmp; - WREG32(RLC_CNTL, RLC_ENABLE); - tmp = RREG32(CP_INT_CNTL_RING0); - tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); - WREG32(CP_INT_CNTL_RING0, tmp); + cik_enable_gui_idle_interrupt(rdev, true); udelay(50); } @@ -4827,12 +4853,7 @@ static int cik_rlc_resume(struct radeon_device *rdev) cik_rlc_stop(rdev); - WREG32(GRBM_SOFT_RESET, SOFT_RESET_RLC); - RREG32(GRBM_SOFT_RESET); - udelay(50); - WREG32(GRBM_SOFT_RESET, 0); - RREG32(GRBM_SOFT_RESET); - udelay(50); + si_rlc_reset(rdev); WREG32(RLC_LB_CNTR_INIT, 0); WREG32(RLC_LB_CNTR_MAX, 0x8000); @@ -4851,6 +4872,9 @@ static int cik_rlc_resume(struct radeon_device *rdev) WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++)); WREG32(RLC_GPM_UCODE_ADDR, 0); + /* XXX - find out what chips support lbpw */ + cik_enable_lbpw(rdev, false); + /* XXX */ clear_state_info[0] = 0;//upper_32_bits(rdev->rlc.save_restore_gpu_addr); clear_state_info[1] = 0;//rdev->rlc.save_restore_gpu_addr; diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index d50593f..4742f3d 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -905,6 +905,7 @@ #define RLC_LB_CNTR_MAX 0xC348 #define RLC_LB_CNTL
[PATCH 12/53] drm/radeon: add support for ASPM on CIK asics
Enables PCIE ASPM (Active State Power Management) on CIK asics. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 151 ++ drivers/gpu/drm/radeon/cikd.h | 72 +++- 2 files changed, 222 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index a30fb32..0da9d67 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -62,6 +62,7 @@ extern void si_rlc_fini(struct radeon_device *rdev); extern int si_rlc_init(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); static void cik_pcie_gen3_enable(struct radeon_device *rdev); +static void cik_program_aspm(struct radeon_device *rdev); /* * Indirect registers accessor @@ -5952,6 +5953,8 @@ static int cik_startup(struct radeon_device *rdev) /* enable pcie gen2/3 link */ cik_pcie_gen3_enable(rdev); + /* enable aspm */ + cik_program_aspm(rdev); cik_mc_program(rdev); @@ -7212,3 +7215,151 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev) udelay(1); } } + +static void cik_program_aspm(struct radeon_device *rdev) +{ + u32 data, orig; + bool disable_l0s = false, disable_l1 = false, disable_plloff_in_l1 = false; + bool disable_clkreq = false; + + if (radeon_aspm == 0) + return; + + /* XXX double check IGPs */ + if (rdev->flags & RADEON_IS_IGP) + return; + + if (!(rdev->flags & RADEON_IS_PCIE)) + return; + + orig = data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL); + data &= ~LC_XMIT_N_FTS_MASK; + data |= LC_XMIT_N_FTS(0x24) | LC_XMIT_N_FTS_OVERRIDE_EN; + if (orig != data) + WREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL, data); + + orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL3); + data |= LC_GO_TO_RECOVERY; + if (orig != data) + WREG32_PCIE_PORT(PCIE_LC_CNTL3, data); + + orig = data = RREG32_PCIE_PORT(PCIE_P_CNTL); + data |= P_IGNORE_EDB_ERR; + if (orig != data) + WREG32_PCIE_PORT(PCIE_P_CNTL, data); + + orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL); + data &= ~(LC_L0S_INACTIVITY_MASK | LC_L1_INACTIVITY_MASK); + data |= LC_PMI_TO_L1_DIS; + if (!disable_l0s) + data |= LC_L0S_INACTIVITY(7); + + if (!disable_l1) { + data |= LC_L1_INACTIVITY(7); + data &= ~LC_PMI_TO_L1_DIS; + if (orig != data) + WREG32_PCIE_PORT(PCIE_LC_CNTL, data); + + if (!disable_plloff_in_l1) { + bool clk_req_support; + + orig = data = RREG32_PCIE_PORT(PB0_PIF_PWRDOWN_0); + data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK); + data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7); + if (orig != data) + WREG32_PCIE_PORT(PB0_PIF_PWRDOWN_0, data); + + orig = data = RREG32_PCIE_PORT(PB0_PIF_PWRDOWN_1); + data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK); + data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7); + if (orig != data) + WREG32_PCIE_PORT(PB0_PIF_PWRDOWN_1, data); + + orig = data = RREG32_PCIE_PORT(PB1_PIF_PWRDOWN_0); + data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK); + data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7); + if (orig != data) + WREG32_PCIE_PORT(PB1_PIF_PWRDOWN_0, data); + + orig = data = RREG32_PCIE_PORT(PB1_PIF_PWRDOWN_1); + data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK); + data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7); + if (orig != data) + WREG32_PCIE_PORT(PB1_PIF_PWRDOWN_1, data); + + orig = data = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); + data &= ~LC_DYN_LANES_PWR_STATE_MASK; + data |= LC_DYN_LANES_PWR_STATE(3); + if (orig != data) + WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data); + + if (!disable_clkreq) { + struct pci_dev *root = rdev->pdev->bus->self; + u32 lnkcap; + + clk_req_support = false; + pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap); + if (lnkcap & PCI_EXP_LNKCAP_CLKPM) +
[PATCH 14/53] drm/radeon: clean up sumo_rlc_init() for code sharing
This will eventually be shared with newer asics to reduce code duplication. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen.c | 221 +++-- 1 file changed, 113 insertions(+), 108 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index a5ab569..6178408 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -3910,131 +3910,136 @@ int sumo_rlc_init(struct radeon_device *rdev) dws = rdev->rlc.reg_list_size; cs_data = rdev->rlc.cs_data; - /* save restore block */ - if (rdev->rlc.save_restore_obj == NULL) { - r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true, -RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.save_restore_obj); + if (src_ptr) { + /* save restore block */ + if (rdev->rlc.save_restore_obj == NULL) { + r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true, +RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.save_restore_obj); + if (r) { + dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); + return r; + } + } + + r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); + if (unlikely(r != 0)) { + sumo_rlc_fini(rdev); + return r; + } + r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->rlc.save_restore_gpu_addr); if (r) { - dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); + radeon_bo_unreserve(rdev->rlc.save_restore_obj); + dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); + sumo_rlc_fini(rdev); return r; } - } - r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); - if (unlikely(r != 0)) { - sumo_rlc_fini(rdev); - return r; - } - r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, - &rdev->rlc.save_restore_gpu_addr); - if (r) { + r = radeon_bo_kmap(rdev->rlc.save_restore_obj, (void **)&rdev->rlc.sr_ptr); + if (r) { + dev_warn(rdev->dev, "(%d) map RLC sr bo failed\n", r); + sumo_rlc_fini(rdev); + return r; + } + /* write the sr buffer */ + dst_ptr = rdev->rlc.sr_ptr; + /* format: +* dw0: (reg2 << 16) | reg1 +* dw1: reg1 save space +* dw2: reg2 save space +*/ + for (i = 0; i < dws; i++) { + data = src_ptr[i] >> 2; + i++; + if (i < dws) + data |= (src_ptr[i] >> 2) << 16; + j = (((i - 1) * 3) / 2); + dst_ptr[j] = data; + } + j = ((i * 3) / 2); + dst_ptr[j] = RLC_SAVE_RESTORE_LIST_END_MARKER; + + radeon_bo_kunmap(rdev->rlc.save_restore_obj); radeon_bo_unreserve(rdev->rlc.save_restore_obj); - dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); - sumo_rlc_fini(rdev); - return r; - } - r = radeon_bo_kmap(rdev->rlc.save_restore_obj, (void **)&rdev->rlc.sr_ptr); - if (r) { - dev_warn(rdev->dev, "(%d) map RLC sr bo failed\n", r); - sumo_rlc_fini(rdev); - return r; - } - /* write the sr buffer */ - dst_ptr = rdev->rlc.sr_ptr; - /* format: -* dw0: (reg2 << 16) | reg1 -* dw1: reg1 save space -* dw2: reg2 save space -*/ - for (i = 0; i < dws; i++) { - data = src_ptr[i] >> 2; - i++; - if (i < dws) - data |= (src_ptr[i] >> 2) << 16; - j = (((i - 1) * 3) / 2); - dst_ptr[j] = data; } - j = ((i * 3) / 2); - dst_ptr[j] = RLC_SAVE_RESTORE_LIST_END_MARKER; - - radeon_bo_kunmap(rdev->rlc.save_restore_obj); - radeon_bo_unreserve(rdev->rlc.save_restore_obj); - /* clear state block */ - reg_list_num = 0; - dws = 0; - for (i = 0; cs_data[i].section != NULL; i++) { - for (j = 0; cs_data[i].section[j].extent != NULL; j++) { - reg_list_num++; - dws += cs_data[i].section[j].reg_count; + if (cs_data) { + /* clear state block */ + reg_list_num = 0; +
[PATCH 15/53] drm/radeon: convert SI,CIK to use sumo_rlc functions
and remove duplicate si_rlc functions. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 10 +- drivers/gpu/drm/radeon/clearstate_cayman.h| 2 +- drivers/gpu/drm/radeon/clearstate_evergreen.h | 2 +- drivers/gpu/drm/radeon/evergreen.c| 46 --- drivers/gpu/drm/radeon/ni.c | 6 +- drivers/gpu/drm/radeon/radeon.h | 4 +- drivers/gpu/drm/radeon/si.c | 174 ++ 7 files changed, 49 insertions(+), 195 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index e92a972..8389917 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -57,9 +57,9 @@ extern void r600_ih_ring_fini(struct radeon_device *rdev); extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); extern bool evergreen_is_display_hung(struct radeon_device *rdev); +extern void sumo_rlc_fini(struct radeon_device *rdev); +extern int sumo_rlc_init(struct radeon_device *rdev); extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); -extern void si_rlc_fini(struct radeon_device *rdev); -extern int si_rlc_init(struct radeon_device *rdev); extern void si_rlc_reset(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); static void cik_pcie_gen3_enable(struct radeon_device *rdev); @@ -6019,7 +6019,7 @@ static int cik_startup(struct radeon_device *rdev) cik_gpu_init(rdev); /* allocate rlc buffers */ - r = si_rlc_init(rdev); + r = sumo_rlc_init(rdev); if (r) { DRM_ERROR("Failed to init rlc BOs!\n"); return r; @@ -6343,7 +6343,7 @@ int cik_init(struct radeon_device *rdev) cik_cp_fini(rdev); cik_sdma_fini(rdev); cik_irq_fini(rdev); - si_rlc_fini(rdev); + sumo_rlc_fini(rdev); cik_mec_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -6379,7 +6379,7 @@ void cik_fini(struct radeon_device *rdev) cik_cp_fini(rdev); cik_sdma_fini(rdev); cik_irq_fini(rdev); - si_rlc_fini(rdev); + sumo_rlc_fini(rdev); cik_mec_fini(rdev); radeon_wb_fini(rdev); radeon_vm_manager_fini(rdev); diff --git a/drivers/gpu/drm/radeon/clearstate_cayman.h b/drivers/gpu/drm/radeon/clearstate_cayman.h index c003394..aa908c5 100644 --- a/drivers/gpu/drm/radeon/clearstate_cayman.h +++ b/drivers/gpu/drm/radeon/clearstate_cayman.h @@ -1073,7 +1073,7 @@ static const struct cs_extent_def SECT_CTRLCONST_defs[] = {SECT_CTRLCONST_def_1, 0xf3fc, 2 }, { 0, 0, 0 } }; -struct cs_section_def cayman_cs_data[] = { +static const struct cs_section_def cayman_cs_data[] = { { SECT_CONTEXT_defs, SECT_CONTEXT }, { SECT_CLEAR_defs, SECT_CLEAR }, { SECT_CTRLCONST_defs, SECT_CTRLCONST }, diff --git a/drivers/gpu/drm/radeon/clearstate_evergreen.h b/drivers/gpu/drm/radeon/clearstate_evergreen.h index 4791d85..63a1ffb 100644 --- a/drivers/gpu/drm/radeon/clearstate_evergreen.h +++ b/drivers/gpu/drm/radeon/clearstate_evergreen.h @@ -1072,7 +1072,7 @@ static const struct cs_extent_def SECT_CTRLCONST_defs[] = {SECT_CTRLCONST_def_1, 0xf3fc, 2 }, { 0, 0, 0 } }; -struct cs_section_def evergreen_cs_data[] = { +static const struct cs_section_def evergreen_cs_data[] = { { SECT_CONTEXT_defs, SECT_CONTEXT }, { SECT_CLEAR_defs, SECT_CLEAR }, { SECT_CTRLCONST_defs, SECT_CTRLCONST }, diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 6178408..6fc876a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -47,7 +47,7 @@ static const u32 crtc_offsets[6] = #include "clearstate_evergreen.h" -static u32 sumo_rlc_save_restore_register_list[] = +static const u32 sumo_rlc_save_restore_register_list[] = { 0x98fc, 0x9830, @@ -131,7 +131,6 @@ static u32 sumo_rlc_save_restore_register_list[] = 0x9150, 0x802c, }; -static u32 sumo_rlc_save_restore_register_list_size = ARRAY_SIZE(sumo_rlc_save_restore_register_list); static void evergreen_gpu_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); @@ -3898,12 +3897,12 @@ void sumo_rlc_fini(struct radeon_device *rdev) int sumo_rlc_init(struct radeon_device *rdev) { - u32 *src_ptr; + const u32 *src_ptr; volatile u32 *dst_ptr; u32 dws, data, i, j, k, reg_num; u32 reg_list_num, reg_list_hdr_blk_index, reg_list_blk_index; u64 reg_list_mc_addr; - struct cs_section_def *cs_data; + const struct cs_section_def *cs_data; int r; src_ptr = rdev->rlc.reg_list; @@ -3943,22 +3942,28 @@ int sumo_rlc_init(s
[PATCH 16/53] drm/radeon: implement clock and power gating for CIK (v3)
Only the APUs support power gating. v2: disable cgcg for now v3: workaround hw issue in mgcg Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 1475 +++- drivers/gpu/drm/radeon/cikd.h | 95 +- drivers/gpu/drm/radeon/clearstate_ci.h | 944 drivers/gpu/drm/radeon/evergreen.c | 57 +- drivers/gpu/drm/radeon/radeon.h| 14 + drivers/gpu/drm/radeon/radeon_asic.c |2 + drivers/gpu/drm/radeon/si.c|2 +- 7 files changed, 2565 insertions(+), 24 deletions(-) create mode 100644 drivers/gpu/drm/radeon/clearstate_ci.h diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 8389917..a36e98c 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -31,6 +31,7 @@ #include "atom.h" #include "cik_blit_shaders.h" #include "radeon_ucode.h" +#include "clearstate_ci.h" MODULE_FIRMWARE("radeon/BONAIRE_pfp.bin"); MODULE_FIRMWARE("radeon/BONAIRE_me.bin"); @@ -61,9 +62,12 @@ extern void sumo_rlc_fini(struct radeon_device *rdev); extern int sumo_rlc_init(struct radeon_device *rdev); extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern void si_rlc_reset(struct radeon_device *rdev); +extern void si_init_uvd_internal_cg(struct radeon_device *rdev); static void cik_rlc_stop(struct radeon_device *rdev); static void cik_pcie_gen3_enable(struct radeon_device *rdev); static void cik_program_aspm(struct radeon_device *rdev); +static void cik_init_pg(struct radeon_device *rdev); +static void cik_init_cg(struct radeon_device *rdev); /* * Indirect registers accessor @@ -86,6 +90,778 @@ void cik_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) (void)RREG32(PCIE_DATA); } +static const u32 spectre_rlc_save_restore_register_list[] = +{ + (0x0e00 << 16) | (0xc12c >> 2), + 0x, + (0x0e00 << 16) | (0xc140 >> 2), + 0x, + (0x0e00 << 16) | (0xc150 >> 2), + 0x, + (0x0e00 << 16) | (0xc15c >> 2), + 0x, + (0x0e00 << 16) | (0xc168 >> 2), + 0x, + (0x0e00 << 16) | (0xc170 >> 2), + 0x, + (0x0e00 << 16) | (0xc178 >> 2), + 0x, + (0x0e00 << 16) | (0xc204 >> 2), + 0x, + (0x0e00 << 16) | (0xc2b4 >> 2), + 0x, + (0x0e00 << 16) | (0xc2b8 >> 2), + 0x, + (0x0e00 << 16) | (0xc2bc >> 2), + 0x, + (0x0e00 << 16) | (0xc2c0 >> 2), + 0x, + (0x0e00 << 16) | (0x8228 >> 2), + 0x, + (0x0e00 << 16) | (0x829c >> 2), + 0x, + (0x0e00 << 16) | (0x869c >> 2), + 0x, + (0x0600 << 16) | (0x98f4 >> 2), + 0x, + (0x0e00 << 16) | (0x98f8 >> 2), + 0x, + (0x0e00 << 16) | (0x9900 >> 2), + 0x, + (0x0e00 << 16) | (0xc260 >> 2), + 0x, + (0x0e00 << 16) | (0x90e8 >> 2), + 0x, + (0x0e00 << 16) | (0x3c000 >> 2), + 0x, + (0x0e00 << 16) | (0x3c00c >> 2), + 0x, + (0x0e00 << 16) | (0x8c1c >> 2), + 0x, + (0x0e00 << 16) | (0x9700 >> 2), + 0x, + (0x0e00 << 16) | (0xcd20 >> 2), + 0x, + (0x4e00 << 16) | (0xcd20 >> 2), + 0x, + (0x5e00 << 16) | (0xcd20 >> 2), + 0x, + (0x6e00 << 16) | (0xcd20 >> 2), + 0x, + (0x7e00 << 16) | (0xcd20 >> 2), + 0x, + (0x8e00 << 16) | (0xcd20 >> 2), + 0x, + (0x9e00 << 16) | (0xcd20 >> 2), + 0x, + (0xae00 << 16) | (0xcd20 >> 2), + 0x, + (0xbe00 << 16) | (0xcd20 >> 2), + 0x, + (0x0e00 << 16) | (0x89bc >> 2), + 0x, + (0x0e00 << 16) | (0x8900 >> 2), + 0x, + 0x3, + (0x0e00 << 16) | (0xc130 >> 2), + 0x, + (0x0e00 << 16) | (0xc134 >> 2), + 0x, + (0x0e00 << 16) | (0xc1fc >> 2), + 0x, + (0x0e00 << 16) | (0xc208 >> 2), + 0x, + (0x0e00 << 16) | (0xc264 >> 2), + 0x, + (0x0e00 << 16) | (0xc268 >> 2), + 0x, + (0x0e00 << 16) | (0xc26c >> 2), + 0x, + (0x0e00 << 16) | (0xc270 >> 2), + 0x, + (0x0e00 << 16) | (0xc274 >> 2), + 0x, + (0x0e00 << 16) | (0xc278 >> 2), + 0x, + (0x0e00 << 16) | (0xc27c >> 2), + 0x, + (0x0e00 << 16) | (0xc280 >> 2), + 0x, + (0x0e00 << 16) | (0xc284 >> 2), + 0x, + (0x0e00 << 16) | (0xc288 >> 2), + 0x, + (0x0e00 << 16) | (0xc28c >> 2), + 0x, + (0x0e00 << 16) | (0xc290 >> 2), + 0x, + (0x0e00 << 16) | (0xc294 >> 2), + 0x
[PATCH 17/53] drm/radeon: add indirect accessors for dift registers on CIK
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik_reg.h | 3 +++ drivers/gpu/drm/radeon/radeon.h | 18 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik_reg.h b/drivers/gpu/drm/radeon/cik_reg.h index d71e46d..ca1bb61 100644 --- a/drivers/gpu/drm/radeon/cik_reg.h +++ b/drivers/gpu/drm/radeon/cik_reg.h @@ -24,6 +24,9 @@ #ifndef __CIK_REG_H__ #define __CIK_REG_H__ +#define CIK_DIDT_IND_INDEX0xca00 +#define CIK_DIDT_IND_DATA 0xca04 + #define CIK_DC_GPIO_HPD_MASK 0x65b0 #define CIK_DC_GPIO_HPD_A 0x65b4 #define CIK_DC_GPIO_HPD_EN0x65b8 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ed241d6..37b0fc4 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2141,6 +2141,8 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v); #define WREG32_PIF_PHY1(reg, v) eg_pif_phy1_wreg(rdev, (reg), (v)) #define RREG32_UVD_CTX(reg) r600_uvd_ctx_rreg(rdev, (reg)) #define WREG32_UVD_CTX(reg, v) r600_uvd_ctx_wreg(rdev, (reg), (v)) +#define RREG32_DIDT(reg) cik_didt_rreg(rdev, (reg)) +#define WREG32_DIDT(reg, v) cik_didt_wreg(rdev, (reg), (v)) #define WREG32_P(reg, val, mask) \ do {\ uint32_t tmp_ = RREG32(reg);\ @@ -2272,6 +2274,22 @@ static inline void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v) WREG32(R600_UVD_CTX_DATA, (v)); } + +static inline u32 cik_didt_rreg(struct radeon_device *rdev, u32 reg) +{ + u32 r; + + WREG32(CIK_DIDT_IND_INDEX, (reg)); + r = RREG32(CIK_DIDT_IND_DATA); + return r; +} + +static inline void cik_didt_wreg(struct radeon_device *rdev, u32 reg, u32 v) +{ + WREG32(CIK_DIDT_IND_INDEX, (reg)); + WREG32(CIK_DIDT_IND_DATA, (v)); +} + void r100_pll_errata_after_index(struct radeon_device *rdev); -- 1.8.3.1
[PATCH 18/53] drm/radeon/sumo add helper to go from vid7 to vid2
Needed for DPM on KB/KV. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/sumo_dpm.c | 14 ++ drivers/gpu/drm/radeon/sumo_dpm.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index c0a8503..2cefe59 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c @@ -1530,6 +1530,20 @@ u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; } +u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_7bit) +{ + u32 i; + + for (i = 0; i < vid_mapping_table->num_entries; i++) { + if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) + return vid_mapping_table->entries[i].vid_2bit; + } + + return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; +} + static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev, u32 vid_2bit) { diff --git a/drivers/gpu/drm/radeon/sumo_dpm.h b/drivers/gpu/drm/radeon/sumo_dpm.h index 07dda29..db1ea32 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.h +++ b/drivers/gpu/drm/radeon/sumo_dpm.h @@ -202,6 +202,9 @@ void sumo_construct_vid_mapping_table(struct radeon_device *rdev, u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, struct sumo_vid_mapping_table *vid_mapping_table, u32 vid_2bit); +u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_7bit); u32 sumo_get_sleep_divider_from_id(u32 id); u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev, u32 sclk, -- 1.8.3.1
[PATCH 19/53] drm/radeon: switch to pptable.h
Internally we switched to using a separate header for atombios pplib definitions. Switch over the open source driver. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios.h | 615 +- drivers/gpu/drm/radeon/pptable.h | 682 ++ 2 files changed, 685 insertions(+), 612 deletions(-) create mode 100644 drivers/gpu/drm/radeon/pptable.h diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 16b120c..af10f85 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -7661,618 +7661,6 @@ typedef struct _ATOM_POWERPLAY_INFO_V3 ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; }ATOM_POWERPLAY_INFO_V3; -/* New PPlib */ -/**/ -typedef struct _ATOM_PPLIB_THERMALCONTROLLER - -{ -UCHAR ucType; // one of ATOM_PP_THERMALCONTROLLER_* -UCHAR ucI2cLine;// as interpreted by DAL I2C -UCHAR ucI2cAddress; -UCHAR ucFanParameters; // Fan Control Parameters. -UCHAR ucFanMinRPM; // Fan Minimum RPM (hundreds) -- for display purposes only. -UCHAR ucFanMaxRPM; // Fan Maximum RPM (hundreds) -- for display purposes only. -UCHAR ucReserved; // -UCHAR ucFlags; // to be defined -} ATOM_PPLIB_THERMALCONTROLLER; - -#define ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f -#define ATOM_PP_FANPARAMETERS_NOFAN 0x80// No fan is connected to this controller. - -#define ATOM_PP_THERMALCONTROLLER_NONE 0 -#define ATOM_PP_THERMALCONTROLLER_LM63 1 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_ADM1032 2 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_ADM1030 3 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_MUA6649 4 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_LM64 5 -#define ATOM_PP_THERMALCONTROLLER_F753756 // Not used by PPLib -#define ATOM_PP_THERMALCONTROLLER_RV6xx 7 -#define ATOM_PP_THERMALCONTROLLER_RV770 8 -#define ATOM_PP_THERMALCONTROLLER_ADT7473 9 -#define ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO 11 -#define ATOM_PP_THERMALCONTROLLER_EVERGREEN 12 -#define ATOM_PP_THERMALCONTROLLER_EMC2103 13 /* 0x0D */ // Only fan control will be implemented, do NOT show this in PPGen. -#define ATOM_PP_THERMALCONTROLLER_SUMO 14 /* 0x0E */ // Sumo type, used internally -#define ATOM_PP_THERMALCONTROLLER_NISLANDS 15 -#define ATOM_PP_THERMALCONTROLLER_SISLANDS 16 -#define ATOM_PP_THERMALCONTROLLER_LM96163 17 -#define ATOM_PP_THERMALCONTROLLER_CISLANDS 18 - -// Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. -// We probably should reserve the bit 0x80 for this use. -// To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). -// The driver can pick the correct internal controller based on the ASIC. - -#define ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89// ADT7473 Fan Control + Internal Thermal Controller -#define ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D// EMC2103 Fan Control + Internal Thermal Controller - -typedef struct _ATOM_PPLIB_STATE -{ -UCHAR ucNonClockStateIndex; -UCHAR ucClockStateIndices[1]; // variable-sized -} ATOM_PPLIB_STATE; - - -typedef struct _ATOM_PPLIB_FANTABLE -{ -UCHAR ucFanTableFormat;// Change this if the table format changes or version changes so that the other fields are not the same. -UCHAR ucTHyst; // Temperature hysteresis. Integer. -USHORT usTMin; // The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. -USHORT usTMed; // The middle temperature where we change slopes. -USHORT usTHigh; // The high point above TMed for adjusting the second slope. -USHORT usPWMMin;// The minimum PWM value in percent (0.01% increments). -USHORT usPWMMed;// The PWM value (in percent) at TMed. -USHORT usPWMHigh; // The PWM value at THigh. -} ATOM_PPLIB_FANTABLE; - -typedef struct _ATOM_PPLIB_FANTABLE2 -{ -ATOM_PPLIB_FANTABLE basicTable; -USHORT usTMax; // The max temperature -} ATOM_PPLIB_FANTABLE2; - -typedef struct _ATOM_PPLIB_EXTENDEDHEADER -{ -USHORT usSize; -ULONG ulMaxEngineClock; // For Overdrive. -ULONG ulMaxMemoryClock; // For Overdrive. -// Add extra system parameters here, always adjust size to include all fields. -USHORT usVCETableOffset; //points to ATOM_PPLIB_VCE_Table -USHORT usUVDTableOffset; //points to ATOM_PPLIB_UVD_Table -USHORT usSAMUTableO
[PATCH 21/53] drm/radeon/cik: add rlc helpers for DPM
Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 29 + drivers/gpu/drm/radeon/cikd.h | 9 + 2 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index a36e98c..727c296 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -5587,6 +5587,35 @@ static u32 cik_halt_rlc(struct radeon_device *rdev) return orig; } +void cik_enter_rlc_safe_mode(struct radeon_device *rdev) +{ + u32 tmp, i, mask; + + tmp = REQ | MESSAGE(MSG_ENTER_RLC_SAFE_MODE); + WREG32(RLC_GPR_REG2, tmp); + + mask = GFX_POWER_STATUS | GFX_CLOCK_STATUS; + for (i = 0; i < rdev->usec_timeout; i++) { + if ((RREG32(RLC_GPM_STAT) & mask) == mask) + break; + udelay(1); + } + + for (i = 0; i < rdev->usec_timeout; i++) { + if ((RREG32(RLC_GPR_REG2) & REQ) == 0) + break; + udelay(1); + } +} + +void cik_exit_rlc_safe_mode(struct radeon_device *rdev) +{ + u32 tmp; + + tmp = REQ | MESSAGE(MSG_EXIT_RLC_SAFE_MODE); + WREG32(RLC_GPR_REG2, tmp); +} + /** * cik_rlc_stop - stop the RLC ME * diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 63955ab..116b313 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -952,6 +952,8 @@ #define RLC_GPM_STAT 0xC400 # define RLC_GPM_BUSY (1 << 0) +# define GFX_POWER_STATUS (1 << 1) +# define GFX_CLOCK_STATUS (1 << 2) #define RLC_PG_CNTL 0xC40C # define GFX_PG_ENABLE (1 << 0) @@ -1004,6 +1006,13 @@ #define RLC_GPM_SCRATCH_ADDR 0xC4B0 #define RLC_GPM_SCRATCH_DATA 0xC4B4 +#define RLC_GPR_REG2 0xC4E8 +#defineREQ 0x0001 +#defineMESSAGE(x) ((x) << 1) +#defineMESSAGE_MASK0x001e +#defineMSG_ENTER_RLC_SAFE_MODE 1 +#defineMSG_EXIT_RLC_SAFE_MODE 0 + #define CP_HPD_EOP_BASE_ADDR 0xC904 #define CP_HPD_EOP_BASE_ADDR_HI 0xC908 #define CP_HPD_EOP_VMID 0xC90C -- 1.8.3.1