1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * (C) COPYRIGHT 2018 ARM Limited. All rights reserved. |
4 | * Author: James.Qian.Wang <james.qian.wang@arm.com> |
5 | * |
6 | */ |
7 | #ifndef _KOMEDA_KMS_H_ |
8 | #define _KOMEDA_KMS_H_ |
9 | |
10 | #include <linux/list.h> |
11 | #include <drm/drm_atomic.h> |
12 | #include <drm/drm_atomic_helper.h> |
13 | #include <drm/drm_blend.h> |
14 | #include <drm/drm_device.h> |
15 | #include <drm/drm_writeback.h> |
16 | #include <drm/drm_print.h> |
17 | |
18 | /** |
19 | * struct komeda_plane - komeda instance of drm_plane |
20 | */ |
21 | struct komeda_plane { |
22 | /** @base: &drm_plane */ |
23 | struct drm_plane base; |
24 | /** |
25 | * @layer: |
26 | * |
27 | * represents available layer input pipelines for this plane. |
28 | * |
29 | * NOTE: |
30 | * the layer is not for a specific Layer, but indicate a group of |
31 | * Layers with same capabilities. |
32 | */ |
33 | struct komeda_layer *layer; |
34 | }; |
35 | |
36 | /** |
37 | * struct komeda_plane_state |
38 | * |
39 | * The plane_state can be split into two data flow (left/right) and handled |
40 | * by two layers &komeda_plane.layer and &komeda_plane.layer.right |
41 | */ |
42 | struct komeda_plane_state { |
43 | /** @base: &drm_plane_state */ |
44 | struct drm_plane_state base; |
45 | /** @zlist_node: zorder list node */ |
46 | struct list_head zlist_node; |
47 | |
48 | /** @layer_split: on/off layer_split */ |
49 | u8 layer_split : 1; |
50 | }; |
51 | |
52 | /** |
53 | * struct komeda_wb_connector |
54 | */ |
55 | struct komeda_wb_connector { |
56 | /** @base: &drm_writeback_connector */ |
57 | struct drm_writeback_connector base; |
58 | |
59 | /** @wb_layer: represents associated writeback pipeline of komeda */ |
60 | struct komeda_layer *wb_layer; |
61 | }; |
62 | |
63 | /** |
64 | * struct komeda_crtc |
65 | */ |
66 | struct komeda_crtc { |
67 | /** @base: &drm_crtc */ |
68 | struct drm_crtc base; |
69 | /** @master: only master has display output */ |
70 | struct komeda_pipeline *master; |
71 | /** |
72 | * @slave: optional |
73 | * |
74 | * Doesn't have its own display output, the handled data flow will |
75 | * merge into the master. |
76 | */ |
77 | struct komeda_pipeline *slave; |
78 | |
79 | /** @slave_planes: komeda slave planes mask */ |
80 | u32 slave_planes; |
81 | |
82 | /** @wb_conn: komeda write back connector */ |
83 | struct komeda_wb_connector *wb_conn; |
84 | |
85 | /** @disable_done: this flip_done is for tracing the disable */ |
86 | struct completion *disable_done; |
87 | |
88 | /** @encoder: encoder at the end of the pipeline */ |
89 | struct drm_encoder encoder; |
90 | }; |
91 | |
92 | /** |
93 | * struct komeda_crtc_state |
94 | */ |
95 | struct komeda_crtc_state { |
96 | /** @base: &drm_crtc_state */ |
97 | struct drm_crtc_state base; |
98 | |
99 | /* private properties */ |
100 | |
101 | /* computed state which are used by validate/check */ |
102 | /** |
103 | * @affected_pipes: |
104 | * the affected pipelines in once display instance |
105 | */ |
106 | u32 affected_pipes; |
107 | /** |
108 | * @active_pipes: |
109 | * the active pipelines in once display instance |
110 | */ |
111 | u32 active_pipes; |
112 | |
113 | /** @clock_ratio: ratio of (aclk << 32)/pxlclk */ |
114 | u64 clock_ratio; |
115 | |
116 | /** @max_slave_zorder: the maximum of slave zorder */ |
117 | u32 max_slave_zorder; |
118 | }; |
119 | |
120 | /** struct komeda_kms_dev - for gather KMS related things */ |
121 | struct komeda_kms_dev { |
122 | /** @base: &drm_device */ |
123 | struct drm_device base; |
124 | |
125 | /** @n_crtcs: valid numbers of crtcs in &komeda_kms_dev.crtcs */ |
126 | int n_crtcs; |
127 | /** @crtcs: crtcs list */ |
128 | struct komeda_crtc crtcs[KOMEDA_MAX_PIPELINES]; |
129 | }; |
130 | |
131 | #define to_kplane(p) container_of(p, struct komeda_plane, base) |
132 | #define to_kplane_st(p) container_of(p, struct komeda_plane_state, base) |
133 | #define to_kconn(p) container_of(p, struct komeda_wb_connector, base) |
134 | #define to_kcrtc(p) container_of(p, struct komeda_crtc, base) |
135 | #define to_kcrtc_st(p) container_of(p, struct komeda_crtc_state, base) |
136 | #define to_kdev(p) container_of(p, struct komeda_kms_dev, base) |
137 | #define to_wb_conn(x) container_of(x, struct drm_writeback_connector, base) |
138 | |
139 | static inline bool is_writeback_only(struct drm_crtc_state *st) |
140 | { |
141 | struct komeda_wb_connector *wb_conn = to_kcrtc(st->crtc)->wb_conn; |
142 | struct drm_connector *conn = wb_conn ? &wb_conn->base.base : NULL; |
143 | |
144 | return conn && (st->connector_mask == BIT(drm_connector_index(conn))); |
145 | } |
146 | |
147 | static inline bool |
148 | is_only_changed_connector(struct drm_crtc_state *st, struct drm_connector *conn) |
149 | { |
150 | struct drm_crtc_state *old_st; |
151 | u32 changed_connectors; |
152 | |
153 | old_st = drm_atomic_get_old_crtc_state(state: st->state, crtc: st->crtc); |
154 | changed_connectors = st->connector_mask ^ old_st->connector_mask; |
155 | |
156 | return BIT(drm_connector_index(conn)) == changed_connectors; |
157 | } |
158 | |
159 | static inline bool has_flip_h(u32 rot) |
160 | { |
161 | u32 rotation = drm_rotation_simplify(rotation: rot, |
162 | DRM_MODE_ROTATE_0 | |
163 | DRM_MODE_ROTATE_90 | |
164 | DRM_MODE_REFLECT_MASK); |
165 | |
166 | if (rotation & DRM_MODE_ROTATE_90) |
167 | return !!(rotation & DRM_MODE_REFLECT_Y); |
168 | else |
169 | return !!(rotation & DRM_MODE_REFLECT_X); |
170 | } |
171 | |
172 | void komeda_crtc_get_color_config(struct drm_crtc_state *crtc_st, |
173 | u32 *color_depths, u32 *color_formats); |
174 | unsigned long komeda_crtc_get_aclk(struct komeda_crtc_state *kcrtc_st); |
175 | |
176 | int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev); |
177 | |
178 | int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev); |
179 | int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev); |
180 | int komeda_kms_add_private_objs(struct komeda_kms_dev *kms, |
181 | struct komeda_dev *mdev); |
182 | int komeda_kms_add_wb_connectors(struct komeda_kms_dev *kms, |
183 | struct komeda_dev *mdev); |
184 | void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms); |
185 | |
186 | void komeda_crtc_handle_event(struct komeda_crtc *kcrtc, |
187 | struct komeda_events *evts); |
188 | void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, |
189 | struct completion *input_flip_done); |
190 | |
191 | struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev); |
192 | void komeda_kms_detach(struct komeda_kms_dev *kms); |
193 | void komeda_kms_shutdown(struct komeda_kms_dev *kms); |
194 | |
195 | #endif /*_KOMEDA_KMS_H_*/ |
196 | |