2019-06-03 07:44:50 +02:00
/* SPDX-License-Identifier: GPL-2.0-only */
2013-11-30 16:12:10 -05:00
/*
2018-06-27 15:26:09 -04:00
* Copyright ( c ) 2016 - 2018 , The Linux Foundation . All rights reserved .
2013-11-30 16:12:10 -05:00
* Copyright ( C ) 2013 Red Hat
* Author : Rob Clark < robdclark @ gmail . com >
*/
# ifndef __MSM_KMS_H__
# define __MSM_KMS_H__
# include <linux/clk.h>
# include <linux/regulator/consumer.h>
# include "msm_drv.h"
2014-12-08 10:48:57 -05:00
# define MAX_PLANE 4
2013-11-30 16:12:10 -05:00
/* As there are different display controller blocks depending on the
* snapdragon version , the kms support is split out and the appropriate
* implementation is loaded at runtime . The kms module is responsible
* for constructing the appropriate planes / crtcs / encoders / connectors .
*/
struct msm_kms_funcs {
/* hw initialization: */
int ( * hw_init ) ( struct msm_kms * kms ) ;
/* irq handling: */
void ( * irq_preinstall ) ( struct msm_kms * kms ) ;
int ( * irq_postinstall ) ( struct msm_kms * kms ) ;
void ( * irq_uninstall ) ( struct msm_kms * kms ) ;
irqreturn_t ( * irq ) ( struct msm_kms * kms ) ;
int ( * enable_vblank ) ( struct msm_kms * kms , struct drm_crtc * crtc ) ;
void ( * disable_vblank ) ( struct msm_kms * kms , struct drm_crtc * crtc ) ;
2019-08-29 09:45:14 -07:00
/*
* Atomic commit handling :
2019-08-29 09:45:16 -07:00
*
* Note that in the case of async commits , the funcs which take
* a crtc_mask ( ie . - > flush_commit ( ) , and - > complete_commit ( ) )
* might not be evenly balanced with - > prepare_commit ( ) , however
* each crtc that effected by a - > prepare_commit ( ) ( potentially
* multiple times ) will eventually ( at end of vsync period ) be
* flushed and completed .
*
* This has some implications about tracking of cleanup state ,
* for example SMP blocks to release after commit completes . Ie .
* cleanup state should be also duplicated in the various
* duplicate_state ( ) methods , as the current cleanup state at
* - > complete_commit ( ) time may have accumulated cleanup work
* from multiple commits .
2019-08-29 09:45:14 -07:00
*/
2019-08-29 09:45:15 -07:00
/**
* Enable / disable power / clks needed for hw access done in other
* commit related methods .
*
* If mdp4 is migrated to runpm , we could probably drop these
* and use runpm directly .
*/
void ( * enable_commit ) ( struct msm_kms * kms ) ;
void ( * disable_commit ) ( struct msm_kms * kms ) ;
2019-08-29 09:45:14 -07:00
/**
* Prepare for atomic commit . This is called after any previous
* ( async or otherwise ) commit has completed .
*/
2015-01-30 17:04:45 -05:00
void ( * prepare_commit ) ( struct msm_kms * kms , struct drm_atomic_state * state ) ;
2019-08-29 09:45:14 -07:00
/**
* Flush an atomic commit . This is called after the hardware
* updates have already been pushed down to effected planes /
* crtcs / encoders / connectors .
*/
void ( * flush_commit ) ( struct msm_kms * kms , unsigned crtc_mask ) ;
/**
* Wait for any in - progress flush to complete on the specified
* crtcs . This should not block if there is no in - progress
* commit ( ie . don ' t just wait for a vblank ) , as it will also
* be called before - > prepare_commit ( ) to ensure any potential
* " async " commit has completed .
*/
2019-08-29 09:45:12 -07:00
void ( * wait_flush ) ( struct msm_kms * kms , unsigned crtc_mask ) ;
2019-08-29 09:45:14 -07:00
/**
* Clean up after commit is completed . This is called after
* - > wait_flush ( ) , to give the backend a chance to do any
* post - commit cleanup .
*/
void ( * complete_commit ) ( struct msm_kms * kms , unsigned crtc_mask ) ;
/*
* Format handling :
*/
2018-02-13 12:42:44 -05:00
/* get msm_format w/ optional format modifiers from drm_mode_fb_cmd2 */
const struct msm_format * ( * get_format ) ( struct msm_kms * kms ,
const uint32_t format ,
const uint64_t modifiers ) ;
2018-06-27 15:26:09 -04:00
/* do format checking on format modified through fb_cmd2 modifiers */
int ( * check_modified_format ) ( const struct msm_kms * kms ,
const struct msm_format * msm_fmt ,
const struct drm_mode_fb_cmd2 * cmd ,
struct drm_gem_object * * bos ) ;
2019-08-29 09:45:14 -07:00
2013-11-30 16:12:10 -05:00
/* misc: */
long ( * round_pixclk ) ( struct msm_kms * kms , unsigned long rate ,
struct drm_encoder * encoder ) ;
2015-03-26 19:25:15 -04:00
int ( * set_split_display ) ( struct msm_kms * kms ,
struct drm_encoder * encoder ,
struct drm_encoder * slave_encoder ,
bool is_cmd_mode ) ;
2013-11-30 16:12:10 -05:00
/* cleanup: */
void ( * destroy ) ( struct msm_kms * kms ) ;
2021-04-16 13:57:23 -07:00
/* snapshot: */
2021-04-27 03:18:25 +03:00
void ( * snapshot ) ( struct msm_disp_state * disp_state , struct msm_kms * kms ) ;
2021-04-16 13:57:23 -07:00
2016-10-26 14:06:55 -04:00
# ifdef CONFIG_DEBUG_FS
/* debugfs: */
int ( * debugfs_init ) ( struct msm_kms * kms , struct drm_minor * minor ) ;
# endif
2013-11-30 16:12:10 -05:00
} ;
2019-08-29 09:45:16 -07:00
struct msm_kms ;
/*
* A per - crtc timer for pending async atomic flushes . Scheduled to expire
* shortly before vblank to flush pending async updates .
*/
struct msm_pending_timer {
2021-09-27 16:04:53 -07:00
struct msm_hrtimer_work work ;
2020-10-19 14:10:53 -07:00
struct kthread_worker * worker ;
2019-08-29 09:45:16 -07:00
struct msm_kms * kms ;
unsigned crtc_idx ;
} ;
2013-11-30 16:12:10 -05:00
struct msm_kms {
const struct msm_kms_funcs * funcs ;
2019-08-29 09:45:16 -07:00
struct drm_device * dev ;
2016-05-18 15:06:03 +05:30
2021-08-03 11:06:57 +02:00
/* irq number to be passed on to msm_irq_install */
2016-05-18 15:06:03 +05:30
int irq ;
2022-05-07 04:00:20 +03:00
bool irq_requested ;
2017-06-13 10:22:37 -04:00
/* mapper-id used to request GEM buffer mapped for scanout: */
struct msm_gem_address_space * aspace ;
2019-08-29 09:45:16 -07:00
2021-04-27 03:18:26 +03:00
/* disp snapshot support */
struct kthread_worker * dump_worker ;
struct kthread_work dump_work ;
struct mutex dump_mutex ;
2021-04-16 13:57:20 -07:00
2019-08-29 09:45:16 -07:00
/*
* For async commit , where - > flush_commit ( ) and later happens
* from the crtc ' s pending_timer close to end of the frame :
*/
2020-10-16 19:40:43 +05:30
struct mutex commit_lock [ MAX_CRTCS ] ;
2019-08-29 09:45:16 -07:00
unsigned pending_crtc_mask ;
struct msm_pending_timer pending_timers [ MAX_CRTCS ] ;
2013-11-30 16:12:10 -05:00
} ;
2020-10-19 14:10:52 -07:00
static inline int msm_kms_init ( struct msm_kms * kms ,
2013-11-30 17:24:22 -05:00
const struct msm_kms_funcs * funcs )
{
2020-10-19 14:10:53 -07:00
unsigned i , ret ;
2019-08-29 09:45:16 -07:00
2021-02-11 14:40:58 -08:00
for ( i = 0 ; i < ARRAY_SIZE ( kms - > commit_lock ) ; i + + )
mutex_init ( & kms - > commit_lock [ i ] ) ;
2020-10-16 19:40:43 +05:30
2013-11-30 17:24:22 -05:00
kms - > funcs = funcs ;
2019-08-29 09:45:16 -07:00
2020-10-19 14:10:53 -07:00
for ( i = 0 ; i < ARRAY_SIZE ( kms - > pending_timers ) ; i + + ) {
ret = msm_atomic_init_pending_timer ( & kms - > pending_timers [ i ] , kms , i ) ;
if ( ret ) {
return ret ;
}
}
2020-10-19 14:10:52 -07:00
return 0 ;
}
static inline void msm_kms_destroy ( struct msm_kms * kms )
{
2020-10-19 14:10:53 -07:00
unsigned i ;
for ( i = 0 ; i < ARRAY_SIZE ( kms - > pending_timers ) ; i + + )
msm_atomic_destroy_pending_timer ( & kms - > pending_timers [ i ] ) ;
2013-11-30 17:24:22 -05:00
}
2019-08-29 09:45:12 -07:00
# define for_each_crtc_mask(dev, crtc, crtc_mask) \
drm_for_each_crtc ( crtc , dev ) \
for_each_if ( drm_crtc_mask ( crtc ) & ( crtc_mask ) )
2020-10-20 15:26:00 -07:00
# define for_each_crtc_mask_reverse(dev, crtc, crtc_mask) \
drm_for_each_crtc_reverse ( crtc , dev ) \
for_each_if ( drm_crtc_mask ( crtc ) & ( crtc_mask ) )
2013-11-30 16:12:10 -05:00
# endif /* __MSM_KMS_H__ */