.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. |
---|
3 | 4 | * Copyright (C) 2013 Red Hat |
---|
4 | 5 | * Author: Rob Clark <robdclark@gmail.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms of the GNU General Public License version 2 as published by |
---|
8 | | - * the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | | - * more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License along with |
---|
16 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
---|
17 | 6 | */ |
---|
18 | 7 | |
---|
19 | 8 | #ifndef __MSM_KMS_H__ |
---|
.. | .. |
---|
41 | 30 | irqreturn_t (*irq)(struct msm_kms *kms); |
---|
42 | 31 | int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); |
---|
43 | 32 | void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); |
---|
44 | | - /* modeset, bracketing atomic_commit(): */ |
---|
| 33 | + |
---|
| 34 | + /* |
---|
| 35 | + * Atomic commit handling: |
---|
| 36 | + * |
---|
| 37 | + * Note that in the case of async commits, the funcs which take |
---|
| 38 | + * a crtc_mask (ie. ->flush_commit(), and ->complete_commit()) |
---|
| 39 | + * might not be evenly balanced with ->prepare_commit(), however |
---|
| 40 | + * each crtc that effected by a ->prepare_commit() (potentially |
---|
| 41 | + * multiple times) will eventually (at end of vsync period) be |
---|
| 42 | + * flushed and completed. |
---|
| 43 | + * |
---|
| 44 | + * This has some implications about tracking of cleanup state, |
---|
| 45 | + * for example SMP blocks to release after commit completes. Ie. |
---|
| 46 | + * cleanup state should be also duplicated in the various |
---|
| 47 | + * duplicate_state() methods, as the current cleanup state at |
---|
| 48 | + * ->complete_commit() time may have accumulated cleanup work |
---|
| 49 | + * from multiple commits. |
---|
| 50 | + */ |
---|
| 51 | + |
---|
| 52 | + /** |
---|
| 53 | + * Enable/disable power/clks needed for hw access done in other |
---|
| 54 | + * commit related methods. |
---|
| 55 | + * |
---|
| 56 | + * If mdp4 is migrated to runpm, we could probably drop these |
---|
| 57 | + * and use runpm directly. |
---|
| 58 | + */ |
---|
| 59 | + void (*enable_commit)(struct msm_kms *kms); |
---|
| 60 | + void (*disable_commit)(struct msm_kms *kms); |
---|
| 61 | + |
---|
| 62 | + /** |
---|
| 63 | + * If the kms backend supports async commit, it should implement |
---|
| 64 | + * this method to return the time of the next vsync. This is |
---|
| 65 | + * used to determine a time slightly before vsync, for the async |
---|
| 66 | + * commit timer to run and complete an async commit. |
---|
| 67 | + */ |
---|
| 68 | + ktime_t (*vsync_time)(struct msm_kms *kms, struct drm_crtc *crtc); |
---|
| 69 | + |
---|
| 70 | + /** |
---|
| 71 | + * Prepare for atomic commit. This is called after any previous |
---|
| 72 | + * (async or otherwise) commit has completed. |
---|
| 73 | + */ |
---|
45 | 74 | void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state); |
---|
46 | | - void (*commit)(struct msm_kms *kms, struct drm_atomic_state *state); |
---|
47 | | - void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state); |
---|
48 | | - /* functions to wait for atomic commit completed on each CRTC */ |
---|
49 | | - void (*wait_for_crtc_commit_done)(struct msm_kms *kms, |
---|
50 | | - struct drm_crtc *crtc); |
---|
| 75 | + |
---|
| 76 | + /** |
---|
| 77 | + * Flush an atomic commit. This is called after the hardware |
---|
| 78 | + * updates have already been pushed down to effected planes/ |
---|
| 79 | + * crtcs/encoders/connectors. |
---|
| 80 | + */ |
---|
| 81 | + void (*flush_commit)(struct msm_kms *kms, unsigned crtc_mask); |
---|
| 82 | + |
---|
| 83 | + /** |
---|
| 84 | + * Wait for any in-progress flush to complete on the specified |
---|
| 85 | + * crtcs. This should not block if there is no in-progress |
---|
| 86 | + * commit (ie. don't just wait for a vblank), as it will also |
---|
| 87 | + * be called before ->prepare_commit() to ensure any potential |
---|
| 88 | + * "async" commit has completed. |
---|
| 89 | + */ |
---|
| 90 | + void (*wait_flush)(struct msm_kms *kms, unsigned crtc_mask); |
---|
| 91 | + |
---|
| 92 | + /** |
---|
| 93 | + * Clean up after commit is completed. This is called after |
---|
| 94 | + * ->wait_flush(), to give the backend a chance to do any |
---|
| 95 | + * post-commit cleanup. |
---|
| 96 | + */ |
---|
| 97 | + void (*complete_commit)(struct msm_kms *kms, unsigned crtc_mask); |
---|
| 98 | + |
---|
| 99 | + /* |
---|
| 100 | + * Format handling: |
---|
| 101 | + */ |
---|
| 102 | + |
---|
51 | 103 | /* get msm_format w/ optional format modifiers from drm_mode_fb_cmd2 */ |
---|
52 | 104 | const struct msm_format *(*get_format)(struct msm_kms *kms, |
---|
53 | 105 | const uint32_t format, |
---|
.. | .. |
---|
57 | 109 | const struct msm_format *msm_fmt, |
---|
58 | 110 | const struct drm_mode_fb_cmd2 *cmd, |
---|
59 | 111 | struct drm_gem_object **bos); |
---|
| 112 | + |
---|
60 | 113 | /* misc: */ |
---|
61 | 114 | long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, |
---|
62 | 115 | struct drm_encoder *encoder); |
---|
.. | .. |
---|
67 | 120 | void (*set_encoder_mode)(struct msm_kms *kms, |
---|
68 | 121 | struct drm_encoder *encoder, |
---|
69 | 122 | bool cmd_mode); |
---|
70 | | - /* pm suspend/resume hooks */ |
---|
71 | | - int (*pm_suspend)(struct device *dev); |
---|
72 | | - int (*pm_resume)(struct device *dev); |
---|
73 | 123 | /* cleanup: */ |
---|
74 | 124 | void (*destroy)(struct msm_kms *kms); |
---|
75 | 125 | #ifdef CONFIG_DEBUG_FS |
---|
.. | .. |
---|
78 | 128 | #endif |
---|
79 | 129 | }; |
---|
80 | 130 | |
---|
| 131 | +struct msm_kms; |
---|
| 132 | + |
---|
| 133 | +/* |
---|
| 134 | + * A per-crtc timer for pending async atomic flushes. Scheduled to expire |
---|
| 135 | + * shortly before vblank to flush pending async updates. |
---|
| 136 | + */ |
---|
| 137 | +struct msm_pending_timer { |
---|
| 138 | + struct hrtimer timer; |
---|
| 139 | + struct work_struct work; |
---|
| 140 | + struct msm_kms *kms; |
---|
| 141 | + unsigned crtc_idx; |
---|
| 142 | +}; |
---|
| 143 | + |
---|
81 | 144 | struct msm_kms { |
---|
82 | 145 | const struct msm_kms_funcs *funcs; |
---|
| 146 | + struct drm_device *dev; |
---|
83 | 147 | |
---|
84 | 148 | /* irq number to be passed on to drm_irq_install */ |
---|
85 | 149 | int irq; |
---|
86 | 150 | |
---|
87 | 151 | /* mapper-id used to request GEM buffer mapped for scanout: */ |
---|
88 | 152 | struct msm_gem_address_space *aspace; |
---|
| 153 | + |
---|
| 154 | + /* |
---|
| 155 | + * For async commit, where ->flush_commit() and later happens |
---|
| 156 | + * from the crtc's pending_timer close to end of the frame: |
---|
| 157 | + */ |
---|
| 158 | + struct mutex commit_lock; |
---|
| 159 | + unsigned pending_crtc_mask; |
---|
| 160 | + struct msm_pending_timer pending_timers[MAX_CRTCS]; |
---|
89 | 161 | }; |
---|
90 | 162 | |
---|
91 | 163 | static inline void msm_kms_init(struct msm_kms *kms, |
---|
92 | 164 | const struct msm_kms_funcs *funcs) |
---|
93 | 165 | { |
---|
| 166 | + unsigned i; |
---|
| 167 | + |
---|
| 168 | + mutex_init(&kms->commit_lock); |
---|
94 | 169 | kms->funcs = funcs; |
---|
| 170 | + |
---|
| 171 | + for (i = 0; i < ARRAY_SIZE(kms->pending_timers); i++) |
---|
| 172 | + msm_atomic_init_pending_timer(&kms->pending_timers[i], kms, i); |
---|
95 | 173 | } |
---|
96 | 174 | |
---|
97 | 175 | struct msm_kms *mdp4_kms_init(struct drm_device *dev); |
---|
.. | .. |
---|
112 | 190 | int mdp5_mdss_init(struct drm_device *dev); |
---|
113 | 191 | int dpu_mdss_init(struct drm_device *dev); |
---|
114 | 192 | |
---|
| 193 | +#define for_each_crtc_mask(dev, crtc, crtc_mask) \ |
---|
| 194 | + drm_for_each_crtc(crtc, dev) \ |
---|
| 195 | + for_each_if (drm_crtc_mask(crtc) & (crtc_mask)) |
---|
| 196 | + |
---|
115 | 197 | #endif /* __MSM_KMS_H__ */ |
---|