drm_crtc_cleanup(crtc);
}
-void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd)
+void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd, bool wait)
{
struct drm_framebuffer *fb = hdlcd->crtc.primary->fb;
struct hdlcd_bo *bo;
unsigned int depth, bpp;
dma_addr_t scanout_start;
+ int ret;
drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
bo = hdlcd->bo;
scanout_start = bo->dma_addr + fb->offsets[0] +
(hdlcd->crtc.y * fb->pitches[0]) + (hdlcd->crtc.x * bpp/8);
- if (scanout_start != hdlcd->scanout_buf) {
- hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
- hdlcd->scanout_buf = scanout_start;
+ hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
+
+ if (wait) {
+ drm_vblank_get(fb->dev, 0);
+ reinit_completion(&hdlcd->vsync_completion);
+ do {
+ ret = wait_for_completion_interruptible_timeout(&hdlcd->vsync_completion,
+ msecs_to_jiffies(1000));
+ } while (ret <= 0);
+ drm_vblank_put(fb->dev, 0);
}
}
unsigned long flags;
/* not active, update registers immediately */
- hdlcd_set_scanout(hdlcd);
+ hdlcd_set_scanout(hdlcd, false);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (event)
drm_send_vblank_event(crtc->dev, 0, event);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ } else {
+ hdlcd_set_scanout(hdlcd, true);
}
return 0;
/* This function gets called when the only change is the start of
the scanout buffer. Detect that and bail out early */
if (hdlcd->initialised && hdlcd_fb_mode_equal(oldfb, crtc->primary->fb)) {
- hdlcd_set_scanout(hdlcd);
+ hdlcd_set_scanout(hdlcd, true);
return 0;
}
clk_set_rate(hdlcd->clk, mode->crtc_clock * 1000);
clk_enable(hdlcd->clk);
- hdlcd_set_scanout(hdlcd);
+ hdlcd_set_scanout(hdlcd, false);
hdlcd->initialised = true;
return 0;
{
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
- hdlcd_set_scanout(hdlcd);
+ hdlcd_set_scanout(hdlcd, true);
return 0;
}
struct drm_pending_vblank_event *event;
unsigned long flags;
- hdlcd_set_scanout(hdlcd);
-
drm_handle_vblank(dev, 0);
spin_lock_irqsave(&dev->event_lock, flags);
drm_vblank_put(dev, 0);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
- complete(&hdlcd->vsync_completion);
+ complete_all(&hdlcd->vsync_completion);
}
/* acknowledge interrupt(s) */
struct clk *clk;
struct drm_fb_helper *fb_helper;
struct hdlcd_bo *bo;
- dma_addr_t scanout_buf;
struct drm_pending_vblank_event *event;
struct drm_crtc crtc;
struct device_node *slave_node;
}
#endif
-void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd);
+void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd, bool wait);
void hdlcd_drm_mode_config_init(struct drm_device *dev);
int hdlcd_fbdev_init(struct drm_device *dev);
struct hdlcd_drm_private *hdlcd = helper->dev->dev_private;
int ret;
- drm_crtc_vblank_on(&hdlcd->crtc);
- ret = wait_for_completion_interruptible_timeout(&hdlcd->vsync_completion,
- msecs_to_jiffies(100));
- drm_crtc_vblank_off(&hdlcd->crtc);
- if (ret)
+ drm_vblank_get(helper->dev, 0);
+ reinit_completion(&hdlcd->vsync_completion);
+ do {
+ ret = wait_for_completion_interruptible_timeout(&hdlcd->vsync_completion,
+ msecs_to_jiffies(1000));
+ } while (ret == -ERESTARTSYS);
+ drm_vblank_put(helper->dev, 0);
+ if (!ret)
return -ETIMEDOUT;
#endif
dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
- vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
+ vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP;
vm_size = vma->vm_end - vma->vm_start;
if (vm_size > bo->gem.size)
cmd.width = sizes->surface_width;
cmd.height = sizes->surface_height;
- cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+ cmd.pitches[0] = ALIGN(sizes->surface_width * bytes_per_pixel, 64);
cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
- size = cmd.pitches[0] * cmd.height * MAX_FRAMES;
+ size = PAGE_ALIGN(cmd.pitches[0] * cmd.height * MAX_FRAMES);
bo = hdlcd_fb_bo_create(helper->dev, size);
if (IS_ERR(bo))
int err;
struct drm_framebuffer *fb;
- dev_info(dev->dev, "Linux is here %s", __func__);
fb = kzalloc(sizeof(*fb), GFP_KERNEL);
if (!fb)
return ERR_PTR(-ENOMEM);