Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+79 -30
+15
drivers/gpu/drm/drm_fb_cma_helper.c
··· 596 596 drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper); 597 597 } 598 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);
+6 -15
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
··· 44 44 struct drm_device *dev = crtc->dev; 45 45 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; 46 46 47 + drm_crtc_vblank_off(crtc); 48 + 47 49 regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, 48 50 DCU_MODE_DCU_MODE_MASK, 49 51 DCU_MODE_DCU_MODE(DCU_MODE_OFF)); ··· 63 61 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL)); 64 62 regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, 65 63 DCU_UPDATE_MODE_READREG); 64 + 65 + drm_crtc_vblank_on(crtc); 66 66 } 67 67 68 68 static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) ··· 141 137 { 142 138 struct drm_plane *primary; 143 139 struct drm_crtc *crtc = &fsl_dev->crtc; 144 - unsigned int i, j, reg_num; 145 140 int ret; 141 + 142 + fsl_dcu_drm_init_planes(fsl_dev->drm); 146 143 147 144 primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm); 148 145 if (!primary) ··· 157 152 } 158 153 159 154 drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs); 160 - 161 - if (!strcmp(fsl_dev->soc->name, "ls1021a")) 162 - reg_num = LS1021A_LAYER_REG_NUM; 163 - else 164 - reg_num = VF610_LAYER_REG_NUM; 165 - for (i = 0; i < fsl_dev->soc->total_layer; i++) { 166 - for (j = 1; j <= reg_num; j++) 167 - regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0); 168 - } 169 - regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, 170 - DCU_MODE_DCU_MODE_MASK, 171 - DCU_MODE_DCU_MODE(DCU_MODE_OFF)); 172 - regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, 173 - DCU_UPDATE_MODE_READREG); 174 155 175 156 return 0; 176 157 }
+38 -15
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
··· 11 11 12 12 #include <linux/clk.h> 13 13 #include <linux/clk-provider.h> 14 + #include <linux/console.h> 14 15 #include <linux/io.h> 15 16 #include <linux/mfd/syscon.h> 16 17 #include <linux/mm.h> ··· 23 22 #include <linux/regmap.h> 24 23 25 24 #include <drm/drmP.h> 25 + #include <drm/drm_atomic_helper.h> 26 26 #include <drm/drm_crtc_helper.h> 27 27 #include <drm/drm_fb_cma_helper.h> 28 28 #include <drm/drm_gem_cma_helper.h> ··· 44 42 .reg_bits = 32, 45 43 .reg_stride = 4, 46 44 .val_bits = 32, 47 - .cache_type = REGCACHE_FLAT, 48 45 49 46 .volatile_reg = fsl_dcu_drm_is_volatile_reg, 50 - .max_register = 0x11fc, 51 47 }; 52 48 53 49 static int fsl_dcu_drm_irq_init(struct drm_device *dev) ··· 229 229 if (!fsl_dev) 230 230 return 0; 231 231 232 + disable_irq(fsl_dev->irq); 232 233 drm_kms_helper_poll_disable(fsl_dev->drm); 233 - regcache_cache_only(fsl_dev->regmap, true); 234 - regcache_mark_dirty(fsl_dev->regmap); 235 - clk_disable(fsl_dev->clk); 236 - clk_unprepare(fsl_dev->clk); 234 + 235 + console_lock(); 236 + drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 1); 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 253 return 0; 239 254 } ··· 261 246 if (!fsl_dev) 262 247 return 0; 263 248 264 - ret = clk_enable(fsl_dev->clk); 249 + ret = clk_prepare_enable(fsl_dev->clk); 265 250 if (ret < 0) { 266 251 dev_err(dev, "failed to enable dcu clk\n"); 267 - clk_unprepare(fsl_dev->clk); 268 - return ret; 269 - } 270 - ret = clk_prepare(fsl_dev->clk); 271 - if (ret < 0) { 272 - dev_err(dev, "failed to prepare dcu clk\n"); 273 252 return ret; 274 253 } 275 254 255 + ret = clk_prepare_enable(fsl_dev->pix_clk); 256 + if (ret < 0) { 257 + dev_err(dev, "failed to enable pix clk\n"); 258 + return ret; 259 + } 260 + 261 + fsl_dcu_drm_init_planes(fsl_dev->drm); 262 + drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state); 263 + 264 + console_lock(); 265 + drm_fbdev_cma_set_suspend(fsl_dev->fbdev, 0); 266 + console_unlock(); 267 + 276 268 drm_kms_helper_poll_enable(fsl_dev->drm); 277 - regcache_cache_only(fsl_dev->regmap, false); 278 - regcache_sync(fsl_dev->regmap); 269 + enable_irq(fsl_dev->irq); 279 270 280 271 return 0; 281 272 } ··· 295 274 .name = "ls1021a", 296 275 .total_layer = 16, 297 276 .max_layer = 4, 277 + .layer_regs = LS1021A_LAYER_REG_NUM, 298 278 }; 299 279 300 280 static const struct fsl_dcu_soc_data fsl_dcu_vf610_data = { 301 281 .name = "vf610", 302 282 .total_layer = 64, 303 283 .max_layer = 6, 284 + .layer_regs = VF610_LAYER_REG_NUM, 304 285 }; 305 286 306 287 static const struct of_device_id fsl_dcu_of_match[] = {
+2
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
··· 175 175 unsigned int total_layer; 176 176 /*max layer number DCU supported*/ 177 177 unsigned int max_layer; 178 + unsigned int layer_regs; 178 179 }; 179 180 180 181 struct fsl_dcu_drm_device { ··· 194 193 struct drm_encoder encoder; 195 194 struct fsl_dcu_drm_connector connector; 196 195 const struct fsl_dcu_soc_data *soc; 196 + struct drm_atomic_state *state; 197 197 }; 198 198 199 199 void fsl_dcu_fbdev_init(struct drm_device *dev);
+16
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
··· 217 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 236 struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev) 221 237 { 222 238 struct drm_plane *primary;
+1
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
··· 12 12 #ifndef __FSL_DCU_DRM_PLANE_H__ 13 13 #define __FSL_DCU_DRM_PLANE_H__ 14 14 15 + void fsl_dcu_drm_init_planes(struct drm_device *dev); 15 16 struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev); 16 17 17 18 #endif /* __FSL_DCU_DRM_PLANE_H__ */
+1
include/drm/drm_fb_cma_helper.h
··· 23 23 24 24 void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma); 25 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 27 int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper, 27 28 struct drm_fb_helper_surface_size *sizes, 28 29 const struct drm_framebuffer_funcs *funcs);