Commit 049ec1b5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'drm-fixes-for-v4.7-rc2' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "A bunch of ARM drivers got into the fixes vibe this time around, so
  this contains a bunch of fixes for imx, atmel hlcdc, arm hdlcd (only
  so many combos of hlcd), mediatek and omap drm.

  Other than that there is one mgag200 fix and a few core drm regression
  fixes"

* tag 'drm-fixes-for-v4.7-rc2' of git://people.freedesktop.org/~airlied/linux: (34 commits)
  drm/omap: fix unused variable warning.
  drm: hdlcd: Add information about the underlying framebuffers in debugfs
  drm: hdlcd: Cleanup the atomic plane operations
  drm/hdlcd: Fix up crtc_state->event handling
  drm: hdlcd: Revamp runtime power management
  drm/mediatek: mtk_dsi: Remove spurious drm_connector_unregister
  drm/mediatek: mtk_dpi: remove invalid error message
  drm: atmel-hlcdc: fix a NULL check
  drm: atmel-hlcdc: fix atmel_hlcdc_crtc_reset() implementation
  drm/mgag200: Black screen fix for G200e rev 4
  drm: Wrap direct calls to driver->gem_free_object from CMA
  drm: fix fb refcount issue with atomic modesetting
  drm: make drm_atomic_set_mode_prop_for_crtc() more reliable
  drm/sti: remove extra mode fixup
  drm: add missing drm_mode_set_crtcinfo call
  drm/omap: include gpio/consumer.h where needed
  drm/omap: include linux/seq_file.h where needed
  Revert "drm/omap: no need to select OMAP2_DSS"
  drm/omap: Remove regulator API abuse
  OMAPDSS: HDMI5: Change DDC timings
  ...
parents f2c6b9e4 ab3ab684
...@@ -62,6 +62,7 @@ Required properties: ...@@ -62,6 +62,7 @@ Required properties:
display-timings are used instead. display-timings are used instead.
Optional properties (required if display-timings are used): Optional properties (required if display-timings are used):
- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
- display-timings : A node that describes the display timings as defined in - display-timings : A node that describes the display timings as defined in
Documentation/devicetree/bindings/display/display-timing.txt. Documentation/devicetree/bindings/display/display-timing.txt.
- fsl,data-mapping : should be "spwg" or "jeida" - fsl,data-mapping : should be "spwg" or "jeida"
......
...@@ -33,8 +33,17 @@ ...@@ -33,8 +33,17 @@
* *
*/ */
static void hdlcd_crtc_cleanup(struct drm_crtc *crtc)
{
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
/* stop the controller on cleanup */
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
drm_crtc_cleanup(crtc);
}
static const struct drm_crtc_funcs hdlcd_crtc_funcs = { static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
.destroy = drm_crtc_cleanup, .destroy = hdlcd_crtc_cleanup,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,
.reset = drm_atomic_helper_crtc_reset, .reset = drm_atomic_helper_crtc_reset,
...@@ -97,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc) ...@@ -97,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
struct drm_display_mode *m = &crtc->state->adjusted_mode; struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct videomode vm; struct videomode vm;
unsigned int polarities, line_length, err; unsigned int polarities, err;
vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay; vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end; vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
...@@ -113,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc) ...@@ -113,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
if (m->flags & DRM_MODE_FLAG_PVSYNC) if (m->flags & DRM_MODE_FLAG_PVSYNC)
polarities |= HDLCD_POLARITY_VSYNC; polarities |= HDLCD_POLARITY_VSYNC;
line_length = crtc->primary->state->fb->pitches[0];
/* Allow max number of outstanding requests and largest burst size */ /* Allow max number of outstanding requests and largest burst size */
hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS, hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16); HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1); hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1); hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1); hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1); hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1); hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1); hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1); hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities); hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);
err = hdlcd_set_pxl_fmt(crtc); err = hdlcd_set_pxl_fmt(crtc);
...@@ -144,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc) ...@@ -144,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
clk_prepare_enable(hdlcd->clk); clk_prepare_enable(hdlcd->clk);
hdlcd_crtc_mode_set_nofb(crtc);
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1); hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
drm_crtc_vblank_on(crtc);
} }
static void hdlcd_crtc_disable(struct drm_crtc *crtc) static void hdlcd_crtc_disable(struct drm_crtc *crtc)
{ {
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
if (!crtc->primary->fb) if (!crtc->state->active)
return; return;
clk_disable_unprepare(hdlcd->clk);
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0); hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
drm_crtc_vblank_off(crtc); clk_disable_unprepare(hdlcd->clk);
} }
static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
...@@ -179,20 +182,17 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, ...@@ -179,20 +182,17 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc, static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *state) struct drm_crtc_state *state)
{ {
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); struct drm_pending_vblank_event *event = crtc->state->event;
unsigned long flags;
if (crtc->state->event) {
struct drm_pending_vblank_event *event = crtc->state->event;
if (event) {
crtc->state->event = NULL; crtc->state->event = NULL;
event->pipe = drm_crtc_index(crtc);
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
spin_lock_irqsave(&crtc->dev->event_lock, flags); spin_lock_irq(&crtc->dev->event_lock);
list_add_tail(&event->base.link, &hdlcd->event_list); if (drm_crtc_vblank_get(crtc) == 0)
spin_unlock_irqrestore(&crtc->dev->event_lock, flags); drm_crtc_arm_vblank_event(crtc, event);
else
drm_crtc_send_vblank_event(crtc, event);
spin_unlock_irq(&crtc->dev->event_lock);
} }
} }
...@@ -225,6 +225,15 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { ...@@ -225,6 +225,15 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
static int hdlcd_plane_atomic_check(struct drm_plane *plane, static int hdlcd_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
u32 src_w, src_h;
src_w = state->src_w >> 16;
src_h = state->src_h >> 16;
/* we can't do any scaling of the plane source */
if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
return -EINVAL;
return 0; return 0;
} }
...@@ -233,20 +242,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, ...@@ -233,20 +242,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
{ {
struct hdlcd_drm_private *hdlcd; struct hdlcd_drm_private *hdlcd;
struct drm_gem_cma_object *gem; struct drm_gem_cma_object *gem;
unsigned int depth, bpp;
u32 src_w, src_h, dest_w, dest_h;
dma_addr_t scanout_start; dma_addr_t scanout_start;
if (!plane->state->crtc || !plane->state->fb) if (!plane->state->fb)
return; return;
hdlcd = crtc_to_hdlcd_priv(plane->state->crtc); drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
src_w = plane->state->src_w >> 16;
src_h = plane->state->src_h >> 16;
dest_w = plane->state->crtc_w;
dest_h = plane->state->crtc_h;
gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
scanout_start = gem->paddr; scanout_start = gem->paddr + plane->state->fb->offsets[0] +
plane->state->crtc_y * plane->state->fb->pitches[0] +
plane->state->crtc_x * bpp / 8;
hdlcd = plane->dev->dev_private;
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, plane->state->fb->pitches[0]);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start); hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
} }
static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = { static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
.prepare_fb = NULL,
.cleanup_fb = NULL,
.atomic_check = hdlcd_plane_atomic_check, .atomic_check = hdlcd_plane_atomic_check,
.atomic_update = hdlcd_plane_atomic_update, .atomic_update = hdlcd_plane_atomic_update,
}; };
...@@ -294,16 +314,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm) ...@@ -294,16 +314,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
return plane; return plane;
} }
void hdlcd_crtc_suspend(struct drm_crtc *crtc)
{
hdlcd_crtc_disable(crtc);
}
void hdlcd_crtc_resume(struct drm_crtc *crtc)
{
hdlcd_crtc_enable(crtc);
}
int hdlcd_setup_crtc(struct drm_device *drm) int hdlcd_setup_crtc(struct drm_device *drm)
{ {
struct hdlcd_drm_private *hdlcd = drm->dev_private; struct hdlcd_drm_private *hdlcd = drm->dev_private;
......
...@@ -49,8 +49,6 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags) ...@@ -49,8 +49,6 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
atomic_set(&hdlcd->dma_end_count, 0); atomic_set(&hdlcd->dma_end_count, 0);
#endif #endif
INIT_LIST_HEAD(&hdlcd->event_list);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hdlcd->mmio = devm_ioremap_resource(drm->dev, res); hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
if (IS_ERR(hdlcd->mmio)) { if (IS_ERR(hdlcd->mmio)) {
...@@ -84,11 +82,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags) ...@@ -84,11 +82,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
goto setup_fail; goto setup_fail;
} }
pm_runtime_enable(drm->dev);
pm_runtime_get_sync(drm->dev);
ret = drm_irq_install(drm, platform_get_irq(pdev, 0)); ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
pm_runtime_put_sync(drm->dev);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to install IRQ handler\n"); DRM_ERROR("failed to install IRQ handler\n");
goto irq_fail; goto irq_fail;
...@@ -164,24 +158,9 @@ static irqreturn_t hdlcd_irq(int irq, void *arg) ...@@ -164,24 +158,9 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
atomic_inc(&hdlcd->vsync_count); atomic_inc(&hdlcd->vsync_count);
#endif #endif
if (irq_status & HDLCD_INTERRUPT_VSYNC) { if (irq_status & HDLCD_INTERRUPT_VSYNC)
bool events_sent = false;
unsigned long flags;
struct drm_pending_vblank_event *e, *t;
drm_crtc_handle_vblank(&hdlcd->crtc); drm_crtc_handle_vblank(&hdlcd->crtc);
spin_lock_irqsave(&drm->event_lock, flags);
list_for_each_entry_safe(e, t, &hdlcd->event_list, base.link) {
list_del(&e->base.link);
drm_crtc_send_vblank_event(&hdlcd->crtc, e);
events_sent = true;
}
if (events_sent)
drm_crtc_vblank_put(&hdlcd->crtc);
spin_unlock_irqrestore(&drm->event_lock, flags);
}
/* acknowledge interrupt(s) */ /* acknowledge interrupt(s) */
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status); hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
...@@ -275,6 +254,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg) ...@@ -275,6 +254,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
static struct drm_info_list hdlcd_debugfs_list[] = { static struct drm_info_list hdlcd_debugfs_list[] = {
{ "interrupt_count", hdlcd_show_underrun_count, 0 }, { "interrupt_count", hdlcd_show_underrun_count, 0 },
{ "clocks", hdlcd_show_pxlclock, 0 }, { "clocks", hdlcd_show_pxlclock, 0 },
{ "fb", drm_fb_cma_debugfs_show, 0 },
}; };
static int hdlcd_debugfs_init(struct drm_minor *minor) static int hdlcd_debugfs_init(struct drm_minor *minor)
...@@ -357,6 +337,8 @@ static int hdlcd_drm_bind(struct device *dev) ...@@ -357,6 +337,8 @@ static int hdlcd_drm_bind(struct device *dev)
return -ENOMEM; return -ENOMEM;
drm->dev_private = hdlcd; drm->dev_private = hdlcd;
dev_set_drvdata(dev, drm);
hdlcd_setup_mode_config(drm); hdlcd_setup_mode_config(drm);
ret = hdlcd_load(drm, 0); ret = hdlcd_load(drm, 0);
if (ret) if (ret)
...@@ -366,14 +348,18 @@ static int hdlcd_drm_bind(struct device *dev) ...@@ -366,14 +348,18 @@ static int hdlcd_drm_bind(struct device *dev)
if (ret) if (ret)
goto err_unload; goto err_unload;
dev_set_drvdata(dev, drm);
ret = component_bind_all(dev, drm); ret = component_bind_all(dev, drm);
if (ret) { if (ret) {
DRM_ERROR("Failed to bind all components\n"); DRM_ERROR("Failed to bind all components\n");
goto err_unregister; goto err_unregister;
} }
ret = pm_runtime_set_active(dev);
if (ret)
goto err_pm_active;
pm_runtime_enable(dev);
ret = drm_vblank_init(drm, drm->mode_config.num_crtc); ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n"); DRM_ERROR("failed to initialise vblank\n");
...@@ -399,16 +385,16 @@ err_fbdev: ...@@ -399,16 +385,16 @@ err_fbdev:
drm_mode_config_cleanup(drm); drm_mode_config_cleanup(drm);
drm_vblank_cleanup(drm); drm_vblank_cleanup(drm);
err_vblank: err_vblank:
pm_runtime_disable(drm->dev);
err_pm_active:
component_unbind_all(dev, drm); component_unbind_all(dev, drm);
err_unregister: err_unregister:
drm_dev_unregister(drm); drm_dev_unregister(drm);
err_unload: err_unload:
pm_runtime_get_sync(drm->dev);
drm_irq_uninstall(drm); drm_irq_uninstall(drm);
pm_runtime_put_sync(drm->dev);
pm_runtime_disable(drm->dev);
of_reserved_mem_device_release(drm->dev); of_reserved_mem_device_release(drm->dev);
err_free: err_free:
dev_set_drvdata(dev, NULL);
drm_dev_unref(drm); drm_dev_unref(drm);
return ret; return ret;
...@@ -495,30 +481,34 @@ MODULE_DEVICE_TABLE(of, hdlcd_of_match); ...@@ -495,30 +481,34 @@ MODULE_DEVICE_TABLE(of, hdlcd_of_match);
static int __maybe_unused hdlcd_pm_suspend(struct device *dev) static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
{ {
struct drm_device *drm = dev_get_drvdata(dev); struct drm_device *drm = dev_get_drvdata(dev);
struct drm_crtc *crtc; struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
if (pm_runtime_suspended(dev)) if (!hdlcd)
return 0; return 0;
drm_modeset_lock_all(drm); drm_kms_helper_poll_disable(drm);
list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
hdlcd_crtc_suspend(crtc); hdlcd->state = drm_atomic_helper_suspend(drm);
drm_modeset_unlock_all(drm); if (IS_ERR(hdlcd->state)) {
drm_kms_helper_poll_enable(drm);
return PTR_ERR(hdlcd->state);
}
return 0; return 0;
} }
static int __maybe_unused hdlcd_pm_resume(struct device *dev) static int __maybe_unused hdlcd_pm_resume(struct device *dev)
{ {
struct drm_device *drm = dev_get_drvdata(dev); struct drm_device *drm = dev_get_drvdata(dev);
struct drm_crtc *crtc; struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
if (!pm_runtime_suspended(dev)) if (!hdlcd)
return 0; return 0;
drm_modeset_lock_all(drm); drm_atomic_helper_resume(drm, hdlcd->state);
list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) drm_kms_helper_poll_enable(drm);
hdlcd_crtc_resume(crtc); pm_runtime_set_active(dev);
drm_modeset_unlock_all(drm);
return 0; return 0;
} }
......
...@@ -9,10 +9,9 @@ struct hdlcd_drm_private { ...@@ -9,10 +9,9 @@ struct hdlcd_drm_private {
void __iomem *mmio; void __iomem *mmio;
struct clk *clk; struct clk *clk;
struct drm_fbdev_cma *fbdev; struct drm_fbdev_cma *fbdev;
struct drm_framebuffer *fb;
struct list_head event_list;
struct drm_crtc crtc; struct drm_crtc crtc;
struct drm_plane *plane; struct drm_plane *plane;
struct drm_atomic_state *state;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
atomic_t buffer_underrun_count; atomic_t buffer_underrun_count;
atomic_t bus_error_count; atomic_t bus_error_count;
...@@ -36,7 +35,5 @@ static inline u32 hdlcd_read(struct hdlcd_drm_private *hdlcd, unsigned int reg) ...@@ -36,7 +35,5 @@ static inline u32 hdlcd_read(struct hdlcd_drm_private *hdlcd, unsigned int reg)
int hdlcd_setup_crtc(struct drm_device *dev); int hdlcd_setup_crtc(struct drm_device *dev);
void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd); void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd);
void hdlcd_crtc_suspend(struct drm_crtc *crtc);
void hdlcd_crtc_resume(struct drm_crtc *crtc);
#endif /* __HDLCD_DRV_H__ */ #endif /* __HDLCD_DRV_H__ */
...@@ -391,12 +391,11 @@ void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc) ...@@ -391,12 +391,11 @@ void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc)
{ {
struct atmel_hlcdc_crtc_state *state; struct atmel_hlcdc_crtc_state *state;
if (crtc->state && crtc->state->mode_blob)
drm_property_unreference_blob(crtc->state->mode_blob);
if (crtc->state) { if (crtc->state) {
__drm_atomic_helper_crtc_destroy_state(crtc->state);
state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
kfree(state); kfree(state);
crtc->state = NULL;
} }
state = kzalloc(sizeof(*state), GFP_KERNEL); state = kzalloc(sizeof(*state), GFP_KERNEL);
...@@ -415,8 +414,9 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) ...@@ -415,8 +414,9 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
return NULL; return NULL;
state = kmalloc(sizeof(*state), GFP_KERNEL); state = kmalloc(sizeof(*state), GFP_KERNEL);
if (state) if (!state)
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); return NULL;
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
state->output_mode = cur->output_mode; state->output_mode = cur->output_mode;
......
...@@ -351,6 +351,8 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, ...@@ -351,6 +351,8 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
drm_property_unreference_blob(state->mode_blob); drm_property_unreference_blob(state->mode_blob);
state->mode_blob = NULL; state->mode_blob = NULL;
memset(&state->mode, 0, sizeof(state->mode));
if (blob) { if (blob) {
if (blob->length != sizeof(struct drm_mode_modeinfo) || if (blob->length != sizeof(struct drm_mode_modeinfo) ||
drm_mode_convert_umode(&state->mode, drm_mode_convert_umode(&state->mode,
...@@ -363,7 +365,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, ...@@ -363,7 +365,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n", DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
state->mode.name, state); state->mode.name, state);
} else { } else {
memset(&state->mode, 0, sizeof(state->mode));
state->enable = false; state->enable = false;
DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n", DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
state); state);
......
...@@ -2821,8 +2821,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, ...@@ -2821,8 +2821,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
goto out; goto out;
} }
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
/* /*
* Check whether the primary plane supports the fb pixel format. * Check whether the primary plane supports the fb pixel format.
* Drivers not implementing the universal planes API use a * Drivers not implementing the universal planes API use a
...@@ -4841,7 +4839,8 @@ bool drm_property_change_valid_get(struct drm_property *property, ...@@ -4841,7 +4839,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
if (value == 0) if (value == 0)
return true; return true;
return _object_find(property->dev, value, property->values[0]) != NULL; *ref = _object_find(property->dev, value, property->values[0]);
return *ref != NULL;
} }
for (i = 0; i < property->num_values; i++) for (i = 0; i < property->num_values; i++)
......
...@@ -445,7 +445,7 @@ err_cma_destroy: ...@@ -445,7 +445,7 @@ err_cma_destroy:
err_fb_info_destroy: err_fb_info_destroy:
drm_fb_helper_release_fbi(helper); drm_fb_helper_release_fbi(helper);
err_gem_free_object: err_gem_free_object:
dev->driver->gem_free_object(&obj->base); drm_gem_object_unreference_unlocked(&obj->base);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_fbdev_cma_create_with_funcs); EXPORT_SYMBOL(drm_fbdev_cma_create_with_funcs);
......
...@@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, ...@@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
return cma_obj; return cma_obj;
error: error:
drm->driver->gem_free_object(&cma_obj->base); drm_gem_object_unreference_unlocked(&cma_obj->base);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
EXPORT_SYMBOL_GPL(drm_gem_cma_create); EXPORT_SYMBOL_GPL(drm_gem_cma_create);
...@@ -162,18 +162,12 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv, ...@@ -162,18 +162,12 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
* and handle has the id what user can see. * and handle has the id what user can see.
*/ */
ret = drm_gem_handle_create(file_priv, gem_obj, handle);