Commit dac2c48c authored by Dave Airlie's avatar Dave Airlie

Merge branch 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu into drm-next

The patchset contains a new helper in drm_fb_cma_helper.c for suspend/
resume when using cma backed framebuffers.

* 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu:
  drm/fsl-dcu: disable vblank events on CRTC disable
  drm/fsl-dcu: implement suspend/resume using atomic helpers
  drm/fsl-dcu: use clk helpers
  drm/fsl-dcu: move layer initialization to plane file
  drm/fsl-dcu: store layer registers in soc_data
  drm/fb_cma_helper: add suspend helper
parents 542d9722 f5bce430
...@@ -596,3 +596,18 @@ void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma) ...@@ -596,3 +596,18 @@ void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma)
drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper); drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper);
} }
EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event); EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event);
/**
* drm_fbdev_cma_set_suspend - wrapper around drm_fb_helper_set_suspend
* @fbdev_cma: The drm_fbdev_cma struct, may be NULL
* @state: desired state, zero to resume, non-zero to suspend
*
* Calls drm_fb_helper_set_suspend, which is a wrapper around
* fb_set_suspend implemented by fbdev core.
*/
void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state)
{
if (fbdev_cma)
drm_fb_helper_set_suspend(&fbdev_cma->fb_helper, state);
}
EXPORT_SYMBOL(drm_fbdev_cma_set_suspend);
...@@ -44,6 +44,8 @@ static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc) ...@@ -44,6 +44,8 @@ static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
drm_crtc_vblank_off(crtc);
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK, DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_OFF)); DCU_MODE_DCU_MODE(DCU_MODE_OFF));
...@@ -61,6 +63,8 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc) ...@@ -61,6 +63,8 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
DCU_MODE_DCU_MODE(DCU_MODE_NORMAL)); DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG); DCU_UPDATE_MODE_READREG);
drm_crtc_vblank_on(crtc);
} }
static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
...@@ -137,9 +141,10 @@ int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev) ...@@ -137,9 +141,10 @@ int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
{ {
struct drm_plane *primary; struct drm_plane *primary;
struct drm_crtc *crtc = &fsl_dev->crtc; struct drm_crtc *crtc = &fsl_dev->crtc;
unsigned int i, j, reg_num;
int ret; int ret;
fsl_dcu_drm_init_planes(fsl_dev->drm);
primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm); primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm);
if (!primary) if (!primary)
return -ENOMEM; return -ENOMEM;
...@@ -153,19 +158,5 @@ int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev) ...@@ -153,19 +158,5 @@ int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs); drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
if (!strcmp(fsl_dev->soc->name, "ls1021a"))
reg_num = LS1021A_LAYER_REG_NUM;
else
reg_num = VF610_LAYER_REG_NUM;
for (i = 0; i < fsl_dev->soc->total_layer; i++) {
for (j = 1; j <= reg_num; j++)
regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
}
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_OFF));
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);
return 0; return 0;
} }
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/console.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -22,6 +23,7 @@ ...@@ -22,6 +23,7 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
...@@ -42,10 +44,8 @@ static const struct regmap_config fsl_dcu_regmap_config = { ...@@ -42,10 +44,8 @@ static const struct regmap_config fsl_dcu_regmap_config = {
.reg_bits = 32, .reg_bits = 32,
.reg_stride = 4, .reg_stride = 4,
.val_bits = 32, .val_bits = 32,
.cache_type = REGCACHE_FLAT,
.volatile_reg = fsl_dcu_drm_is_volatile_reg, .volatile_reg = fsl_dcu_drm_is_volatile_reg,
.max_register = 0x11fc,
}; };
static int fsl_dcu_drm_irq_init(struct drm_device *dev) static int fsl_dcu_drm_irq_init(struct drm_device *dev)
...@@ -229,11 +229,26 @@ static int fsl_dcu_drm_pm_suspend(struct device *dev) ...@@ -229,11 +229,26 @@ static int fsl_dcu_drm_pm_suspend(struct device *dev)
if (!fsl_dev) if (!fsl_dev)
return 0; return 0;
disable_irq(fsl_dev->irq);
drm_kms_helper_poll_disable(fsl_dev->drm); drm_kms_helper_poll_disable(fsl_dev->drm);
regcache_cache_only(fsl_dev->regmap, true);
regcache_mark_dirty(fsl_dev->regmap); console_lock();
clk_disable(fsl_dev->clk); drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 1);
clk_unprepare(fsl_dev->clk); console_unlock();
fsl_dev->state = drm_atomic_helper_suspend(fsl_dev->drm);
if (IS_ERR(fsl_dev->state)) {
console_lock();
drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 0);
console_unlock();
drm_kms_helper_poll_enable(fsl_dev->drm);
enable_irq(fsl_dev->irq);
return PTR_ERR(fsl_dev->state);
}
clk_disable_unprepare(fsl_dev->pix_clk);
clk_disable_unprepare(fsl_dev->clk);
return 0; return 0;
} }
...@@ -246,21 +261,27 @@ static int fsl_dcu_drm_pm_resume(struct device *dev) ...@@ -246,21 +261,27 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)
if (!fsl_dev) if (!fsl_dev)
return 0; return 0;
ret = clk_enable(fsl_dev->clk); ret = clk_prepare_enable(fsl_dev->clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to enable dcu clk\n"); dev_err(dev, "failed to enable dcu clk\n");
clk_unprepare(fsl_dev->clk);
return ret; return ret;
} }
ret = clk_prepare(fsl_dev->clk);
ret = clk_prepare_enable(fsl_dev->pix_clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to prepare dcu clk\n"); dev_err(dev, "failed to enable pix clk\n");
return ret; return ret;
} }
fsl_dcu_drm_init_planes(fsl_dev->drm);
drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state);
console_lock();
drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 0);
console_unlock();
drm_kms_helper_poll_enable(fsl_dev->drm); drm_kms_helper_poll_enable(fsl_dev->drm);
regcache_cache_only(fsl_dev->regmap, false); enable_irq(fsl_dev->irq);
regcache_sync(fsl_dev->regmap);
return 0; return 0;
} }
...@@ -274,12 +295,14 @@ static const struct fsl_dcu_soc_data fsl_dcu_ls1021a_data = { ...@@ -274,12 +295,14 @@ static const struct fsl_dcu_soc_data fsl_dcu_ls1021a_data = {
.name = "ls1021a", .name = "ls1021a",
.total_layer = 16, .total_layer = 16,
.max_layer = 4, .max_layer = 4,
.layer_regs = LS1021A_LAYER_REG_NUM,
}; };
static const struct fsl_dcu_soc_data fsl_dcu_vf610_data = { static const struct fsl_dcu_soc_data fsl_dcu_vf610_data = {
.name = "vf610", .name = "vf610",
.total_layer = 64, .total_layer = 64,
.max_layer = 6, .max_layer = 6,
.layer_regs = VF610_LAYER_REG_NUM,
}; };
static const struct of_device_id fsl_dcu_of_match[] = { static const struct of_device_id fsl_dcu_of_match[] = {
......
...@@ -175,6 +175,7 @@ struct fsl_dcu_soc_data { ...@@ -175,6 +175,7 @@ struct fsl_dcu_soc_data {
unsigned int total_layer; unsigned int total_layer;
/*max layer number DCU supported*/ /*max layer number DCU supported*/
unsigned int max_layer; unsigned int max_layer;
unsigned int layer_regs;
}; };
struct fsl_dcu_drm_device { struct fsl_dcu_drm_device {
...@@ -193,6 +194,7 @@ struct fsl_dcu_drm_device { ...@@ -193,6 +194,7 @@ struct fsl_dcu_drm_device {
struct drm_encoder encoder; struct drm_encoder encoder;
struct fsl_dcu_drm_connector connector; struct fsl_dcu_drm_connector connector;
const struct fsl_dcu_soc_data *soc; const struct fsl_dcu_soc_data *soc;
struct drm_atomic_state *state;
}; };
void fsl_dcu_fbdev_init(struct drm_device *dev); void fsl_dcu_fbdev_init(struct drm_device *dev);
......
...@@ -217,6 +217,22 @@ static const u32 fsl_dcu_drm_plane_formats[] = { ...@@ -217,6 +217,22 @@ static const u32 fsl_dcu_drm_plane_formats[] = {
DRM_FORMAT_YUV422, DRM_FORMAT_YUV422,
}; };
void fsl_dcu_drm_init_planes(struct drm_device *dev)
{
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
int i, j;
for (i = 0; i < fsl_dev->soc->total_layer; i++) {
for (j = 1; j <= fsl_dev->soc->layer_regs; j++)
regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
}
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_OFF));
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);
}
struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev) struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
{ {
struct drm_plane *primary; struct drm_plane *primary;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#ifndef __FSL_DCU_DRM_PLANE_H__ #ifndef __FSL_DCU_DRM_PLANE_H__
#define __FSL_DCU_DRM_PLANE_H__ #define __FSL_DCU_DRM_PLANE_H__
void fsl_dcu_drm_init_planes(struct drm_device *dev);
struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev); struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
#endif /* __FSL_DCU_DRM_PLANE_H__ */ #endif /* __FSL_DCU_DRM_PLANE_H__ */
...@@ -23,6 +23,7 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma); ...@@ -23,6 +23,7 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma);
void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma); void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma);
void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma); void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma);
void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state);
int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper, int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes, struct drm_fb_helper_surface_size *sizes,
const struct drm_framebuffer_funcs *funcs); const struct drm_framebuffer_funcs *funcs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment