drm/tilcdc: use flip-work helper
Signed-off-by: Rob Clark <robdclark@gmail.com> Tested-by: Darren Etheridge <detheridge@ti.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kfifo.h>
|
#include "drm_flip_work.h"
|
||||||
|
|
||||||
#include "tilcdc_drv.h"
|
#include "tilcdc_drv.h"
|
||||||
#include "tilcdc_regs.h"
|
#include "tilcdc_regs.h"
|
||||||
@@ -35,21 +35,18 @@ struct tilcdc_crtc {
|
|||||||
struct drm_framebuffer *scanout[2];
|
struct drm_framebuffer *scanout[2];
|
||||||
|
|
||||||
/* for deferred fb unref's: */
|
/* for deferred fb unref's: */
|
||||||
DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *);
|
struct drm_flip_work unref_work;
|
||||||
struct work_struct work;
|
|
||||||
};
|
};
|
||||||
#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
|
#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
|
||||||
|
|
||||||
static void unref_worker(struct work_struct *work)
|
static void unref_worker(struct drm_flip_work *work, void *val)
|
||||||
{
|
{
|
||||||
struct tilcdc_crtc *tilcdc_crtc =
|
struct tilcdc_crtc *tilcdc_crtc =
|
||||||
container_of(work, struct tilcdc_crtc, work);
|
container_of(work, struct tilcdc_crtc, unref_work);
|
||||||
struct drm_device *dev = tilcdc_crtc->base.dev;
|
struct drm_device *dev = tilcdc_crtc->base.dev;
|
||||||
struct drm_framebuffer *fb;
|
|
||||||
|
|
||||||
mutex_lock(&dev->mode_config.mutex);
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb))
|
drm_framebuffer_unreference(val);
|
||||||
drm_framebuffer_unreference(fb);
|
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,19 +65,14 @@ static void set_scanout(struct drm_crtc *crtc, int n)
|
|||||||
};
|
};
|
||||||
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
|
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
|
||||||
struct drm_device *dev = crtc->dev;
|
struct drm_device *dev = crtc->dev;
|
||||||
|
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||||
|
|
||||||
pm_runtime_get_sync(dev->dev);
|
pm_runtime_get_sync(dev->dev);
|
||||||
tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
|
tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
|
||||||
tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
|
tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
|
||||||
if (tilcdc_crtc->scanout[n]) {
|
if (tilcdc_crtc->scanout[n]) {
|
||||||
if (kfifo_put(&tilcdc_crtc->unref_fifo,
|
drm_flip_work_queue(&tilcdc_crtc->unref_work, tilcdc_crtc->scanout[n]);
|
||||||
(const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) {
|
drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
|
||||||
struct tilcdc_drm_private *priv = dev->dev_private;
|
|
||||||
queue_work(priv->wq, &tilcdc_crtc->work);
|
|
||||||
} else {
|
|
||||||
dev_err(dev->dev, "unref fifo full!\n");
|
|
||||||
drm_framebuffer_unreference(tilcdc_crtc->scanout[n]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tilcdc_crtc->scanout[n] = crtc->fb;
|
tilcdc_crtc->scanout[n] = crtc->fb;
|
||||||
drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
|
drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
|
||||||
@@ -149,8 +141,8 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
|
|||||||
WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON);
|
WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON);
|
||||||
|
|
||||||
drm_crtc_cleanup(crtc);
|
drm_crtc_cleanup(crtc);
|
||||||
WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo));
|
drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
|
||||||
kfifo_free(&tilcdc_crtc->unref_fifo);
|
|
||||||
kfree(tilcdc_crtc);
|
kfree(tilcdc_crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,14 +663,13 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
|
|||||||
tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
|
tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
|
||||||
init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
|
init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
|
||||||
|
|
||||||
ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL);
|
ret = drm_flip_work_init(&tilcdc_crtc->unref_work, 16,
|
||||||
|
"unref", unref_worker);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev->dev, "could not allocate unref FIFO\n");
|
dev_err(dev->dev, "could not allocate unref FIFO\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_WORK(&tilcdc_crtc->work, unref_worker);
|
|
||||||
|
|
||||||
ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
|
ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|||||||
Reference in New Issue
Block a user