diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_kms.h')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_kms.h | 140 |
1 files changed, 93 insertions, 47 deletions
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 1cbef6b200b7..8a7be7b854de 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -13,6 +13,8 @@ #include "msm_drv.h" +#ifdef CONFIG_DRM_MSM_KMS + #define MAX_PLANE 4 /* As there are different display controller blocks depending on the @@ -60,12 +62,11 @@ struct msm_kms_funcs { void (*disable_commit)(struct msm_kms *kms); /** - * If the kms backend supports async commit, it should implement - * this method to return the time of the next vsync. This is - * used to determine a time slightly before vsync, for the async - * commit timer to run and complete an async commit. + * @check_mode_changed: + * + * Verify if the commit requires a full modeset on one of CRTCs. */ - ktime_t (*vsync_time)(struct msm_kms *kms, struct drm_crtc *crtc); + int (*check_mode_changed)(struct msm_kms *kms, struct drm_atomic_state *state); /** * Prepare for atomic commit. This is called after any previous @@ -100,28 +101,15 @@ struct msm_kms_funcs { * Format handling: */ - /* 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); - /* 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); - /* misc: */ long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, struct drm_encoder *encoder); - int (*set_split_display)(struct msm_kms *kms, - struct drm_encoder *encoder, - struct drm_encoder *slave_encoder, - bool is_cmd_mode); - void (*set_encoder_mode)(struct msm_kms *kms, - struct drm_encoder *encoder, - bool cmd_mode); /* cleanup: */ void (*destroy)(struct msm_kms *kms); + + /* snapshot: */ + void (*snapshot)(struct msm_disp_state *disp_state, struct msm_kms *kms); + #ifdef CONFIG_DEBUG_FS /* debugfs: */ int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor); @@ -135,63 +123,121 @@ struct msm_kms; * shortly before vblank to flush pending async updates. */ struct msm_pending_timer { - struct hrtimer timer; - struct work_struct work; + struct msm_hrtimer_work work; + struct kthread_worker *worker; struct msm_kms *kms; unsigned crtc_idx; }; +/* Commit/Event thread specific structure */ +struct msm_drm_thread { + struct drm_device *dev; + struct kthread_worker *worker; +}; + struct msm_kms { const struct msm_kms_funcs *funcs; struct drm_device *dev; - /* irq number to be passed on to drm_irq_install */ + struct hdmi *hdmi; + + struct msm_dsi *dsi[MSM_DSI_CONTROLLER_COUNT]; + + struct msm_dp *dp[MSM_DP_CONTROLLER_COUNT]; + + /* irq number to be passed on to msm_irq_install */ int irq; + bool irq_requested; + + /* rate limit the snapshot capture to once per attach */ + atomic_t fault_snapshot_capture; /* mapper-id used to request GEM buffer mapped for scanout: */ - struct msm_gem_address_space *aspace; + struct drm_gpuvm *vm; + + /* disp snapshot support */ + struct kthread_worker *dump_worker; + struct kthread_work dump_work; + struct mutex dump_mutex; /* * For async commit, where ->flush_commit() and later happens * from the crtc's pending_timer close to end of the frame: */ - struct mutex commit_lock; + struct mutex commit_lock[MAX_CRTCS]; unsigned pending_crtc_mask; struct msm_pending_timer pending_timers[MAX_CRTCS]; + + struct workqueue_struct *wq; + struct msm_drm_thread event_thread[MAX_CRTCS]; }; -static inline void msm_kms_init(struct msm_kms *kms, +static inline int msm_kms_init(struct msm_kms *kms, const struct msm_kms_funcs *funcs) { - unsigned i; + unsigned i, ret; + + for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++) + mutex_init(&kms->commit_lock[i]); - mutex_init(&kms->commit_lock); kms->funcs = funcs; - for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) - msm_atomic_init_pending_timer(&kms->pending_timers[i], kms, i); -} + kms->wq = alloc_ordered_workqueue("msm", 0); + if (!kms->wq) + return -ENOMEM; -struct msm_kms *mdp4_kms_init(struct drm_device *dev); -struct msm_kms *mdp5_kms_init(struct drm_device *dev); -struct msm_kms *dpu_kms_init(struct drm_device *dev); + 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; + } + } -struct msm_mdss_funcs { - int (*enable)(struct msm_mdss *mdss); - int (*disable)(struct msm_mdss *mdss); - void (*destroy)(struct drm_device *dev); -}; + return 0; +} -struct msm_mdss { - struct drm_device *dev; - const struct msm_mdss_funcs *funcs; -}; +static inline void msm_kms_destroy(struct msm_kms *kms) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) + msm_atomic_destroy_pending_timer(&kms->pending_timers[i]); -int mdp5_mdss_init(struct drm_device *dev); -int dpu_mdss_init(struct drm_device *dev); + destroy_workqueue(kms->wq); +} #define for_each_crtc_mask(dev, crtc, crtc_mask) \ drm_for_each_crtc(crtc, dev) \ for_each_if (drm_crtc_mask(crtc) & (crtc_mask)) +#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)) + +int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv); +void msm_drm_kms_post_init(struct device *dev); +void msm_drm_kms_unregister(struct device *dev); +void msm_drm_kms_uninit(struct device *dev); + +#else /* ! CONFIG_DRM_MSM_KMS */ + +static inline int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) +{ + return -ENODEV; +} + +static inline void msm_drm_kms_post_init(struct device *dev) +{ +} + +static inline void msm_drm_kms_unregister(struct device *dev) +{ +} + +static inline void msm_drm_kms_uninit(struct device *dev) +{ +} + +#endif + #endif /* __MSM_KMS_H__ */ |
