diff options
author | Dave Airlie <airlied@redhat.com> | 2016-07-02 02:21:35 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-07-02 02:21:35 -0400 |
commit | dac2c48ca5ac9bb2d6339aaa733c60d5b801ee86 (patch) | |
tree | 3b288b03448dc0e514de3101e9d9c4498947f084 | |
parent | 542d972221e024681b502033154f917c1455469f (diff) | |
parent | f5bce4309db6597003e683d28d12b1b4bc9408b0 (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.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h | 1 | ||||
-rw-r--r-- | include/drm/drm_fb_cma_helper.h | 1 |
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 | } |
598 | EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event); | 598 | EXPORT_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 | */ | ||
608 | void 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 | } | ||
613 | EXPORT_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 | ||
66 | static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) | 70 | 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 | { | 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 | ||
51 | static int fsl_dcu_drm_irq_init(struct drm_device *dev) | 51 | 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 | 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 | ||
279 | static const struct fsl_dcu_soc_data fsl_dcu_vf610_data = { | 301 | static 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 | ||
285 | static const struct of_device_id fsl_dcu_of_match[] = { | 308 | static 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 | ||
180 | struct fsl_dcu_drm_device { | 181 | struct 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 | ||
198 | void fsl_dcu_fbdev_init(struct drm_device *dev); | 200 | void 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 | ||
220 | void 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 | |||
220 | struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev) | 236 | struct 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 | ||
15 | void fsl_dcu_drm_init_planes(struct drm_device *dev); | ||
15 | struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev); | 16 | struct 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 | ||
24 | void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma); | 24 | void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma); |
25 | void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma); | 25 | void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma); |
26 | void drm_fbdev_cma_set_suspend(struct drm_fbdev_cma *fbdev_cma, int state); | ||
26 | int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper, | 27 | int 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); |