aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-07-02 02:21:35 -0400
committerDave Airlie <airlied@redhat.com>2016-07-02 02:21:35 -0400
commitdac2c48ca5ac9bb2d6339aaa733c60d5b801ee86 (patch)
tree3b288b03448dc0e514de3101e9d9c4498947f084
parent542d972221e024681b502033154f917c1455469f (diff)
parentf5bce4309db6597003e683d28d12b1b4bc9408b0 (diff)
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
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c15
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c21
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c47
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h2
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c16
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h1
-rw-r--r--include/drm/drm_fb_cma_helper.h1
7 files changed, 76 insertions, 27 deletions
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index c0b0c718994a..1fd6eac1400c 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -596,3 +596,18 @@ void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma)
596 drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper); 596 drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper);
597} 597}
598EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event); 598EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event);
599
600/**
601 * drm_fbdev_cma_set_suspend - wrapper around drm_fb_helper_set_suspend
602 * @fbdev_cma: The drm_fbdev_cma struct, may be NULL
603 * @state: desired state, zero to resume, non-zero to suspend
604 *
605 * Calls drm_fb_helper_set_suspend, which is a wrapper around
606 * fb_set_suspend implemented by fbdev core.
607 */
608void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state)
609{
610 if (fbdev_cma)
611 drm_fb_helper_set_suspend(&fbdev_cma->fb_helper, state);
612}
613EXPORT_SYMBOL(drm_fbdev_cma_set_suspend);
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
index 706de3278f1c..3371635cd4d7 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
@@ -44,6 +44,8 @@ static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
44 struct drm_device *dev = crtc->dev; 44 struct drm_device *dev = crtc->dev;
45 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; 45 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
46 46
47 drm_crtc_vblank_off(crtc);
48
47 regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, 49 regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
48 DCU_MODE_DCU_MODE_MASK, 50 DCU_MODE_DCU_MODE_MASK,
49 DCU_MODE_DCU_MODE(DCU_MODE_OFF)); 51 DCU_MODE_DCU_MODE(DCU_MODE_OFF));
@@ -61,6 +63,8 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
61 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL)); 63 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
62 regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, 64 regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
63 DCU_UPDATE_MODE_READREG); 65 DCU_UPDATE_MODE_READREG);
66
67 drm_crtc_vblank_on(crtc);
64} 68}
65 69
66static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) 70static 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{ 141{
138 struct drm_plane *primary; 142 struct drm_plane *primary;
139 struct drm_crtc *crtc = &fsl_dev->crtc; 143 struct drm_crtc *crtc = &fsl_dev->crtc;
140 unsigned int i, j, reg_num;
141 int ret; 144 int ret;
142 145
146 fsl_dcu_drm_init_planes(fsl_dev->drm);
147
143 primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm); 148 primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm);
144 if (!primary) 149 if (!primary)
145 return -ENOMEM; 150 return -ENOMEM;
@@ -153,19 +158,5 @@ int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
153 158
154 drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs); 159 drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
155 160
156 if (!strcmp(fsl_dev->soc->name, "ls1021a"))
157 reg_num = LS1021A_LAYER_REG_NUM;
158 else
159 reg_num = VF610_LAYER_REG_NUM;
160 for (i = 0; i < fsl_dev->soc->total_layer; i++) {
161 for (j = 1; j <= reg_num; j++)
162 regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
163 }
164 regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
165 DCU_MODE_DCU_MODE_MASK,
166 DCU_MODE_DCU_MODE(DCU_MODE_OFF));
167 regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
168 DCU_UPDATE_MODE_READREG);
169
170 return 0; 161 return 0;
171} 162}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index 7655c8c62c65..7882387f9bff 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -11,6 +11,7 @@
11 11
12#include <linux/clk.h> 12#include <linux/clk.h>
13#include <linux/clk-provider.h> 13#include <linux/clk-provider.h>
14#include <linux/console.h>
14#include <linux/io.h> 15#include <linux/io.h>
15#include <linux/mfd/syscon.h> 16#include <linux/mfd/syscon.h>
16#include <linux/mm.h> 17#include <linux/mm.h>
@@ -22,6 +23,7 @@
22#include <linux/regmap.h> 23#include <linux/regmap.h>
23 24
24#include <drm/drmP.h> 25#include <drm/drmP.h>
26#include <drm/drm_atomic_helper.h>
25#include <drm/drm_crtc_helper.h> 27#include <drm/drm_crtc_helper.h>
26#include <drm/drm_fb_cma_helper.h> 28#include <drm/drm_fb_cma_helper.h>
27#include <drm/drm_gem_cma_helper.h> 29#include <drm/drm_gem_cma_helper.h>
@@ -42,10 +44,8 @@ static const struct regmap_config fsl_dcu_regmap_config = {
42 .reg_bits = 32, 44 .reg_bits = 32,
43 .reg_stride = 4, 45 .reg_stride = 4,
44 .val_bits = 32, 46 .val_bits = 32,
45 .cache_type = REGCACHE_FLAT,
46 47
47 .volatile_reg = fsl_dcu_drm_is_volatile_reg, 48 .volatile_reg = fsl_dcu_drm_is_volatile_reg,
48 .max_register = 0x11fc,
49}; 49};
50 50
51static int fsl_dcu_drm_irq_init(struct drm_device *dev) 51static 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 if (!fsl_dev) 229 if (!fsl_dev)
230 return 0; 230 return 0;
231 231
232 disable_irq(fsl_dev->irq);
232 drm_kms_helper_poll_disable(fsl_dev->drm); 233 drm_kms_helper_poll_disable(fsl_dev->drm);
233 regcache_cache_only(fsl_dev->regmap, true); 234
234 regcache_mark_dirty(fsl_dev->regmap); 235 console_lock();
235 clk_disable(fsl_dev->clk); 236 drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 1);
236 clk_unprepare(fsl_dev->clk); 237 console_unlock();
238
239 fsl_dev->state = drm_atomic_helper_suspend(fsl_dev->drm);
240 if (IS_ERR(fsl_dev->state)) {
241 console_lock();
242 drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 0);
243 console_unlock();
244
245 drm_kms_helper_poll_enable(fsl_dev->drm);
246 enable_irq(fsl_dev->irq);
247 return PTR_ERR(fsl_dev->state);
248 }
249
250 clk_disable_unprepare(fsl_dev->pix_clk);
251 clk_disable_unprepare(fsl_dev->clk);
237 252
238 return 0; 253 return 0;
239} 254}
@@ -246,21 +261,27 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)
246 if (!fsl_dev) 261 if (!fsl_dev)
247 return 0; 262 return 0;
248 263
249 ret = clk_enable(fsl_dev->clk); 264 ret = clk_prepare_enable(fsl_dev->clk);
250 if (ret < 0) { 265 if (ret < 0) {
251 dev_err(dev, "failed to enable dcu clk\n"); 266 dev_err(dev, "failed to enable dcu clk\n");
252 clk_unprepare(fsl_dev->clk);
253 return ret; 267 return ret;
254 } 268 }
255 ret = clk_prepare(fsl_dev->clk); 269
270 ret = clk_prepare_enable(fsl_dev->pix_clk);
256 if (ret < 0) { 271 if (ret < 0) {
257 dev_err(dev, "failed to prepare dcu clk\n"); 272 dev_err(dev, "failed to enable pix clk\n");
258 return ret; 273 return ret;
259 } 274 }
260 275
276 fsl_dcu_drm_init_planes(fsl_dev->drm);
277 drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state);
278
279 console_lock();
280 drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 0);
281 console_unlock();
282
261 drm_kms_helper_poll_enable(fsl_dev->drm); 283 drm_kms_helper_poll_enable(fsl_dev->drm);
262 regcache_cache_only(fsl_dev->regmap, false); 284 enable_irq(fsl_dev->irq);
263 regcache_sync(fsl_dev->regmap);
264 285
265 return 0; 286 return 0;
266} 287}
@@ -274,12 +295,14 @@ static const struct fsl_dcu_soc_data fsl_dcu_ls1021a_data = {
274 .name = "ls1021a", 295 .name = "ls1021a",
275 .total_layer = 16, 296 .total_layer = 16,
276 .max_layer = 4, 297 .max_layer = 4,
298 .layer_regs = LS1021A_LAYER_REG_NUM,
277}; 299};
278 300
279static const struct fsl_dcu_soc_data fsl_dcu_vf610_data = { 301static const struct fsl_dcu_soc_data fsl_dcu_vf610_data = {
280 .name = "vf610", 302 .name = "vf610",
281 .total_layer = 64, 303 .total_layer = 64,
282 .max_layer = 6, 304 .max_layer = 6,
305 .layer_regs = VF610_LAYER_REG_NUM,
283}; 306};
284 307
285static const struct of_device_id fsl_dcu_of_match[] = { 308static const struct of_device_id fsl_dcu_of_match[] = {
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
index c275f900ff23..3b371fe7491e 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
@@ -175,6 +175,7 @@ struct fsl_dcu_soc_data {
175 unsigned int total_layer; 175 unsigned int total_layer;
176 /*max layer number DCU supported*/ 176 /*max layer number DCU supported*/
177 unsigned int max_layer; 177 unsigned int max_layer;
178 unsigned int layer_regs;
178}; 179};
179 180
180struct fsl_dcu_drm_device { 181struct fsl_dcu_drm_device {
@@ -193,6 +194,7 @@ struct fsl_dcu_drm_device {
193 struct drm_encoder encoder; 194 struct drm_encoder encoder;
194 struct fsl_dcu_drm_connector connector; 195 struct fsl_dcu_drm_connector connector;
195 const struct fsl_dcu_soc_data *soc; 196 const struct fsl_dcu_soc_data *soc;
197 struct drm_atomic_state *state;
196}; 198};
197 199
198void fsl_dcu_fbdev_init(struct drm_device *dev); 200void fsl_dcu_fbdev_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
index 274558b3b32b..e50467a0deb0 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -217,6 +217,22 @@ static const u32 fsl_dcu_drm_plane_formats[] = {
217 DRM_FORMAT_YUV422, 217 DRM_FORMAT_YUV422,
218}; 218};
219 219
220void fsl_dcu_drm_init_planes(struct drm_device *dev)
221{
222 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
223 int i, j;
224
225 for (i = 0; i < fsl_dev->soc->total_layer; i++) {
226 for (j = 1; j <= fsl_dev->soc->layer_regs; j++)
227 regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
228 }
229 regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
230 DCU_MODE_DCU_MODE_MASK,
231 DCU_MODE_DCU_MODE(DCU_MODE_OFF));
232 regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
233 DCU_UPDATE_MODE_READREG);
234}
235
220struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev) 236struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
221{ 237{
222 struct drm_plane *primary; 238 struct drm_plane *primary;
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
index d657f088d859..8ee45f813ee8 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
@@ -12,6 +12,7 @@
12#ifndef __FSL_DCU_DRM_PLANE_H__ 12#ifndef __FSL_DCU_DRM_PLANE_H__
13#define __FSL_DCU_DRM_PLANE_H__ 13#define __FSL_DCU_DRM_PLANE_H__
14 14
15void fsl_dcu_drm_init_planes(struct drm_device *dev);
15struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev); 16struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
16 17
17#endif /* __FSL_DCU_DRM_PLANE_H__ */ 18#endif /* __FSL_DCU_DRM_PLANE_H__ */
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index fd0dde9f0a6d..f313211f8ed5 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -23,6 +23,7 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma);
23 23
24void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma); 24void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma);
25void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma); 25void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma);
26void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state);
26int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper, 27int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper,
27 struct drm_fb_helper_surface_size *sizes, 28 struct drm_fb_helper_surface_size *sizes,
28 const struct drm_framebuffer_funcs *funcs); 29 const struct drm_framebuffer_funcs *funcs);