@@ -63,6 +63,7 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
6363 [DRM_V3D_PARAM_V3D_CORE0_IDENT1 ] = V3D_CTL_IDENT1 ,
6464 [DRM_V3D_PARAM_V3D_CORE0_IDENT2 ] = V3D_CTL_IDENT2 ,
6565 };
66+ int ret ;
6667
6768 if (args -> pad != 0 )
6869 return - EINVAL ;
@@ -79,12 +80,19 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
7980 if (args -> value != 0 )
8081 return - EINVAL ;
8182
83+ ret = v3d_pm_runtime_get (v3d );
84+ if (ret )
85+ return ret ;
86+
8287 if (args -> param >= DRM_V3D_PARAM_V3D_CORE0_IDENT0 &&
8388 args -> param <= DRM_V3D_PARAM_V3D_CORE0_IDENT2 ) {
8489 args -> value = V3D_CORE_READ (0 , offset );
8590 } else {
8691 args -> value = V3D_READ (offset );
8792 }
93+
94+ v3d_pm_runtime_put (v3d );
95+
8896 return 0 ;
8997 }
9098
@@ -291,36 +299,6 @@ static const struct of_device_id v3d_of_match[] = {
291299};
292300MODULE_DEVICE_TABLE (of , v3d_of_match );
293301
294- static void
295- v3d_idle_sms (struct v3d_dev * v3d )
296- {
297- if (v3d -> ver < V3D_GEN_71 )
298- return ;
299-
300- V3D_SMS_WRITE (V3D_SMS_TEE_CS , V3D_SMS_CLEAR_POWER_OFF );
301-
302- if (wait_for ((V3D_GET_FIELD (V3D_SMS_READ (V3D_SMS_TEE_CS ),
303- V3D_SMS_STATE ) == V3D_SMS_IDLE ), 100 )) {
304- DRM_ERROR ("Failed to power up SMS\n" );
305- }
306-
307- v3d_reset_sms (v3d );
308- }
309-
310- static void
311- v3d_power_off_sms (struct v3d_dev * v3d )
312- {
313- if (v3d -> ver < V3D_GEN_71 )
314- return ;
315-
316- V3D_SMS_WRITE (V3D_SMS_TEE_CS , V3D_SMS_POWER_OFF );
317-
318- if (wait_for ((V3D_GET_FIELD (V3D_SMS_READ (V3D_SMS_TEE_CS ),
319- V3D_SMS_STATE ) == V3D_SMS_POWER_OFF_STATE ), 100 )) {
320- DRM_ERROR ("Failed to power off SMS\n" );
321- }
322- }
323-
324302static int
325303map_regs (struct v3d_dev * v3d , void __iomem * * regs , const char * name )
326304{
@@ -404,19 +382,26 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
404382 if (ret )
405383 goto dma_free ;
406384
407- ret = clk_prepare_enable (v3d -> clk );
408- if (ret ) {
409- dev_err (& pdev -> dev , "Couldn't enable the V3D clock\n" );
385+ ret = devm_pm_runtime_enable (dev );
386+ if (ret )
410387 goto gem_destroy ;
411- }
412388
413- v3d_idle_sms (v3d );
389+ ret = pm_runtime_resume_and_get (dev );
390+ if (ret )
391+ goto gem_destroy ;
392+
393+ /* If PM is disabled, we need to call v3d_power_resume() manually. */
394+ if (!IS_ENABLED (CONFIG_PM )) {
395+ ret = v3d_power_resume (dev );
396+ if (ret )
397+ goto gem_destroy ;
398+ }
414399
415400 mmu_debug = V3D_READ (V3D_MMU_DEBUG_INFO );
416401 mask = DMA_BIT_MASK (30 + V3D_GET_FIELD (mmu_debug , V3D_MMU_PA_WIDTH ));
417402 ret = dma_set_mask_and_coherent (dev , mask );
418403 if (ret )
419- goto clk_disable ;
404+ goto runtime_pm_put ;
420405
421406 dma_set_max_seg_size (& pdev -> dev , UINT_MAX );
422407
@@ -437,26 +422,27 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
437422 v3d -> rev = V3D_GET_FIELD (ident3 , V3D_HUB_IDENT3_IPREV );
438423
439424 v3d_init_hw_state (v3d );
440- v3d_mmu_set_page_table (v3d );
441- v3d_irq_enable (v3d );
425+
426+ pm_runtime_set_autosuspend_delay (dev , 50 );
427+ pm_runtime_use_autosuspend (dev );
442428
443429 ret = drm_dev_register (drm , 0 );
444430 if (ret )
445- goto irq_disable ;
431+ goto runtime_pm_put ;
446432
447433 ret = v3d_sysfs_init (dev );
448434 if (ret )
449435 goto drm_unregister ;
450436
437+ pm_runtime_mark_last_busy (dev );
438+ pm_runtime_put_autosuspend (dev );
439+
451440 return 0 ;
452441
453442drm_unregister :
454443 drm_dev_unregister (drm );
455- irq_disable :
456- v3d_irq_disable (v3d );
457- clk_disable :
458- v3d_power_off_sms (v3d );
459- clk_disable_unprepare (v3d -> clk );
444+ runtime_pm_put :
445+ pm_runtime_put_sync_suspend (dev );
460446gem_destroy :
461447 v3d_gem_destroy (drm );
462448dma_free :
@@ -474,21 +460,27 @@ static void v3d_platform_drm_remove(struct platform_device *pdev)
474460
475461 drm_dev_unregister (drm );
476462
477- v3d_power_off_sms ( v3d );
463+ pm_runtime_suspend ( dev );
478464
479- clk_disable_unprepare (v3d -> clk );
465+ /* If PM is disabled, we need to call v3d_power_suspend() manually. */
466+ if (!IS_ENABLED (CONFIG_PM ))
467+ v3d_power_suspend (dev );
480468
481469 v3d_gem_destroy (drm );
482470
483471 dma_free_wc (dev , 4096 , v3d -> mmu_scratch , v3d -> mmu_scratch_paddr );
484472}
485473
474+ static DEFINE_RUNTIME_DEV_PM_OPS (v3d_pm_ops , v3d_power_suspend ,
475+ v3d_power_resume , NULL) ;
476+
486477static struct platform_driver v3d_platform_driver = {
487478 .probe = v3d_platform_drm_probe ,
488479 .remove = v3d_platform_drm_remove ,
489480 .driver = {
490481 .name = "v3d" ,
491482 .of_match_table = v3d_of_match ,
483+ .pm = pm_ptr (& v3d_pm_ops ),
492484 },
493485};
494486
0 commit comments