Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
0004  * Copyright (C) 2013 Red Hat
0005  * Author: Rob Clark <robdclark@gmail.com>
0006  */
0007 
0008 #ifndef __MSM_KMS_H__
0009 #define __MSM_KMS_H__
0010 
0011 #include <linux/clk.h>
0012 #include <linux/regulator/consumer.h>
0013 
0014 #include "msm_drv.h"
0015 
0016 #define MAX_PLANE   4
0017 
0018 /* As there are different display controller blocks depending on the
0019  * snapdragon version, the kms support is split out and the appropriate
0020  * implementation is loaded at runtime.  The kms module is responsible
0021  * for constructing the appropriate planes/crtcs/encoders/connectors.
0022  */
0023 struct msm_kms_funcs {
0024     /* hw initialization: */
0025     int (*hw_init)(struct msm_kms *kms);
0026     /* irq handling: */
0027     void (*irq_preinstall)(struct msm_kms *kms);
0028     int (*irq_postinstall)(struct msm_kms *kms);
0029     void (*irq_uninstall)(struct msm_kms *kms);
0030     irqreturn_t (*irq)(struct msm_kms *kms);
0031     int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
0032     void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
0033 
0034     /*
0035      * Atomic commit handling:
0036      *
0037      * Note that in the case of async commits, the funcs which take
0038      * a crtc_mask (ie. ->flush_commit(), and ->complete_commit())
0039      * might not be evenly balanced with ->prepare_commit(), however
0040      * each crtc that effected by a ->prepare_commit() (potentially
0041      * multiple times) will eventually (at end of vsync period) be
0042      * flushed and completed.
0043      *
0044      * This has some implications about tracking of cleanup state,
0045      * for example SMP blocks to release after commit completes.  Ie.
0046      * cleanup state should be also duplicated in the various
0047      * duplicate_state() methods, as the current cleanup state at
0048      * ->complete_commit() time may have accumulated cleanup work
0049      * from multiple commits.
0050      */
0051 
0052     /**
0053      * Enable/disable power/clks needed for hw access done in other
0054      * commit related methods.
0055      *
0056      * If mdp4 is migrated to runpm, we could probably drop these
0057      * and use runpm directly.
0058      */
0059     void (*enable_commit)(struct msm_kms *kms);
0060     void (*disable_commit)(struct msm_kms *kms);
0061 
0062     /**
0063      * If the kms backend supports async commit, it should implement
0064      * this method to return the time of the next vsync.  This is
0065      * used to determine a time slightly before vsync, for the async
0066      * commit timer to run and complete an async commit.
0067      */
0068     ktime_t (*vsync_time)(struct msm_kms *kms, struct drm_crtc *crtc);
0069 
0070     /**
0071      * Prepare for atomic commit.  This is called after any previous
0072      * (async or otherwise) commit has completed.
0073      */
0074     void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
0075 
0076     /**
0077      * Flush an atomic commit.  This is called after the hardware
0078      * updates have already been pushed down to effected planes/
0079      * crtcs/encoders/connectors.
0080      */
0081     void (*flush_commit)(struct msm_kms *kms, unsigned crtc_mask);
0082 
0083     /**
0084      * Wait for any in-progress flush to complete on the specified
0085      * crtcs.  This should not block if there is no in-progress
0086      * commit (ie. don't just wait for a vblank), as it will also
0087      * be called before ->prepare_commit() to ensure any potential
0088      * "async" commit has completed.
0089      */
0090     void (*wait_flush)(struct msm_kms *kms, unsigned crtc_mask);
0091 
0092     /**
0093      * Clean up after commit is completed.  This is called after
0094      * ->wait_flush(), to give the backend a chance to do any
0095      * post-commit cleanup.
0096      */
0097     void (*complete_commit)(struct msm_kms *kms, unsigned crtc_mask);
0098 
0099     /*
0100      * Format handling:
0101      */
0102 
0103     /* get msm_format w/ optional format modifiers from drm_mode_fb_cmd2 */
0104     const struct msm_format *(*get_format)(struct msm_kms *kms,
0105                     const uint32_t format,
0106                     const uint64_t modifiers);
0107     /* do format checking on format modified through fb_cmd2 modifiers */
0108     int (*check_modified_format)(const struct msm_kms *kms,
0109             const struct msm_format *msm_fmt,
0110             const struct drm_mode_fb_cmd2 *cmd,
0111             struct drm_gem_object **bos);
0112 
0113     /* misc: */
0114     long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
0115             struct drm_encoder *encoder);
0116     int (*set_split_display)(struct msm_kms *kms,
0117             struct drm_encoder *encoder,
0118             struct drm_encoder *slave_encoder,
0119             bool is_cmd_mode);
0120     /* cleanup: */
0121     void (*destroy)(struct msm_kms *kms);
0122 
0123     /* snapshot: */
0124     void (*snapshot)(struct msm_disp_state *disp_state, struct msm_kms *kms);
0125 
0126 #ifdef CONFIG_DEBUG_FS
0127     /* debugfs: */
0128     int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor);
0129 #endif
0130 };
0131 
0132 struct msm_kms;
0133 
0134 /*
0135  * A per-crtc timer for pending async atomic flushes.  Scheduled to expire
0136  * shortly before vblank to flush pending async updates.
0137  */
0138 struct msm_pending_timer {
0139     struct msm_hrtimer_work work;
0140     struct kthread_worker *worker;
0141     struct msm_kms *kms;
0142     unsigned crtc_idx;
0143 };
0144 
0145 struct msm_kms {
0146     const struct msm_kms_funcs *funcs;
0147     struct drm_device *dev;
0148 
0149     /* irq number to be passed on to msm_irq_install */
0150     int irq;
0151     bool irq_requested;
0152 
0153     /* mapper-id used to request GEM buffer mapped for scanout: */
0154     struct msm_gem_address_space *aspace;
0155 
0156     /* disp snapshot support */
0157     struct kthread_worker *dump_worker;
0158     struct kthread_work dump_work;
0159     struct mutex dump_mutex;
0160 
0161     /*
0162      * For async commit, where ->flush_commit() and later happens
0163      * from the crtc's pending_timer close to end of the frame:
0164      */
0165     struct mutex commit_lock[MAX_CRTCS];
0166     unsigned pending_crtc_mask;
0167     struct msm_pending_timer pending_timers[MAX_CRTCS];
0168 };
0169 
0170 static inline int msm_kms_init(struct msm_kms *kms,
0171         const struct msm_kms_funcs *funcs)
0172 {
0173     unsigned i, ret;
0174 
0175     for (i = 0; i < ARRAY_SIZE(kms->commit_lock); i++)
0176         mutex_init(&kms->commit_lock[i]);
0177 
0178     kms->funcs = funcs;
0179 
0180     for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) {
0181         ret = msm_atomic_init_pending_timer(&kms->pending_timers[i], kms, i);
0182         if (ret) {
0183             return ret;
0184         }
0185     }
0186 
0187     return 0;
0188 }
0189 
0190 static inline void msm_kms_destroy(struct msm_kms *kms)
0191 {
0192     unsigned i;
0193 
0194     for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++)
0195         msm_atomic_destroy_pending_timer(&kms->pending_timers[i]);
0196 }
0197 
0198 #define for_each_crtc_mask(dev, crtc, crtc_mask) \
0199     drm_for_each_crtc(crtc, dev) \
0200         for_each_if (drm_crtc_mask(crtc) & (crtc_mask))
0201 
0202 #define for_each_crtc_mask_reverse(dev, crtc, crtc_mask) \
0203     drm_for_each_crtc_reverse(crtc, dev) \
0204         for_each_if (drm_crtc_mask(crtc) & (crtc_mask))
0205 
0206 #endif /* __MSM_KMS_H__ */