8
8
#include <drm/drm_atomic_helper.h>
9
9
#include <drm/drm_gem_atomic_helper.h>
10
10
#include <drm/drm_plane_helper.h>
11
+ #include <drm/drm_fourcc.h>
11
12
12
13
#include "omap_dmm_tiler.h"
13
14
#include "omap_drv.h"
21
22
struct omap_plane_state {
22
23
/* Must be first. */
23
24
struct drm_plane_state base ;
25
+
26
+ struct omap_hw_overlay * overlay ;
24
27
};
25
28
26
29
#define to_omap_plane (x ) container_of(x, struct omap_plane, base)
27
30
28
31
struct omap_plane {
29
32
struct drm_plane base ;
30
33
enum omap_plane_id id ;
31
-
32
- struct omap_hw_overlay * overlay ;
33
34
};
34
35
35
36
static int omap_plane_prepare_fb (struct drm_plane * plane ,
@@ -54,13 +55,29 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
54
55
struct drm_atomic_state * state )
55
56
{
56
57
struct omap_drm_private * priv = plane -> dev -> dev_private ;
57
- struct omap_plane * omap_plane = to_omap_plane (plane );
58
58
struct drm_plane_state * new_state = drm_atomic_get_new_plane_state (state ,
59
59
plane );
60
- enum omap_plane_id ovl_id = omap_plane -> overlay -> id ;
60
+ struct drm_plane_state * old_state = drm_atomic_get_old_plane_state (state ,
61
+ plane );
62
+ struct omap_plane_state * new_omap_state ;
63
+ struct omap_plane_state * old_omap_state ;
61
64
struct omap_overlay_info info ;
65
+ enum omap_plane_id ovl_id ;
62
66
int ret ;
63
67
68
+ new_omap_state = to_omap_plane_state (new_state );
69
+ old_omap_state = to_omap_plane_state (old_state );
70
+
71
+ /* Cleanup previously held overlay if needed */
72
+ if (old_omap_state -> overlay )
73
+ omap_overlay_update_state (priv , old_omap_state -> overlay );
74
+
75
+ if (!new_omap_state -> overlay ) {
76
+ DBG ("[PLANE:%d:%s] no overlay attached" , plane -> base .id , plane -> name );
77
+ return ;
78
+ }
79
+
80
+ ovl_id = new_omap_state -> overlay -> id ;
64
81
DBG ("%s, crtc=%p fb=%p" , plane -> name , new_state -> crtc ,
65
82
new_state -> fb );
66
83
@@ -79,9 +96,9 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
79
96
/* update scanout: */
80
97
omap_framebuffer_update_scanout (new_state -> fb , new_state , & info );
81
98
82
- DBG ("%dx%d -> %dx%d (%d)" , info . width , info . height ,
83
- info .out_width , info .out_height ,
84
- info .screen_width );
99
+ DBG ("%s: % dx%d -> %dx%d (%d)" ,
100
+ new_omap_state -> overlay -> name , info .width , info .height ,
101
+ info .out_width , info . out_height , info . screen_width );
85
102
DBG ("%d,%d %pad %pad" , info .pos_x , info .pos_y ,
86
103
& info .paddr , & info .p_uv_addr );
87
104
@@ -102,16 +119,26 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
102
119
static void omap_plane_atomic_disable (struct drm_plane * plane ,
103
120
struct drm_atomic_state * state )
104
121
{
105
- struct drm_plane_state * new_state = drm_atomic_get_new_plane_state (state ,
106
- plane );
107
122
struct omap_drm_private * priv = plane -> dev -> dev_private ;
108
123
struct omap_plane * omap_plane = to_omap_plane (plane );
109
- enum omap_plane_id ovl_id = omap_plane -> overlay -> id ;
124
+ struct drm_plane_state * new_state = drm_atomic_get_new_plane_state (state ,
125
+ plane );
126
+ struct drm_plane_state * old_state = drm_atomic_get_old_plane_state (state ,
127
+ plane );
128
+ struct omap_plane_state * new_omap_state ;
129
+ struct omap_plane_state * old_omap_state ;
130
+
131
+ new_omap_state = to_omap_plane_state (new_state );
132
+ old_omap_state = to_omap_plane_state (old_state );
133
+
134
+ if (!old_omap_state -> overlay )
135
+ return ;
110
136
111
137
new_state -> rotation = DRM_MODE_ROTATE_0 ;
112
138
new_state -> zpos = plane -> type == DRM_PLANE_TYPE_PRIMARY ? 0 : omap_plane -> id ;
113
139
114
- dispc_ovl_enable (priv -> dispc , ovl_id , false);
140
+ omap_overlay_update_state (priv , old_omap_state -> overlay );
141
+ new_omap_state -> overlay = NULL ;
115
142
}
116
143
117
144
#define FRAC_16_16 (mult , div ) (((mult) << 16) / (div))
@@ -121,32 +148,37 @@ static int omap_plane_atomic_check(struct drm_plane *plane,
121
148
{
122
149
struct drm_plane_state * new_plane_state = drm_atomic_get_new_plane_state (state ,
123
150
plane );
151
+ struct drm_plane_state * old_plane_state = drm_atomic_get_old_plane_state (state ,
152
+ plane );
124
153
struct omap_drm_private * priv = plane -> dev -> dev_private ;
154
+ struct omap_plane_state * omap_state = to_omap_plane_state (new_plane_state );
155
+ struct omap_global_state * omap_overlay_global_state ;
125
156
struct drm_crtc_state * crtc_state ;
157
+ bool new_hw_overlay = false;
126
158
u32 max_width , max_height ;
159
+ struct drm_crtc * crtc ;
127
160
u16 width , height ;
161
+ u32 caps = 0 ;
162
+ u32 fourcc ;
128
163
int ret ;
129
164
130
- if (!new_plane_state -> fb )
131
- return 0 ;
165
+ omap_overlay_global_state = omap_get_global_state (state );
166
+ if (IS_ERR (omap_overlay_global_state ))
167
+ return PTR_ERR (omap_overlay_global_state );
132
168
133
169
dispc_ovl_get_max_size (priv -> dispc , & width , & height );
134
170
max_width = width << 16 ;
135
171
max_height = height << 16 ;
136
172
137
- /* crtc should only be NULL when disabling (i.e., ! new_plane_state->fb) */
138
- if (WARN_ON (! new_plane_state -> crtc ) )
173
+ crtc = new_plane_state -> crtc ? new_plane_state -> crtc : plane -> state -> crtc ;
174
+ if (! crtc )
139
175
return 0 ;
140
176
141
- crtc_state = drm_atomic_get_existing_crtc_state (state ,
142
- new_plane_state -> crtc );
177
+ crtc_state = drm_atomic_get_existing_crtc_state (state , crtc );
143
178
/* we should have a crtc state if the plane is attached to a crtc */
144
179
if (WARN_ON (!crtc_state ))
145
180
return 0 ;
146
181
147
- if (!crtc_state -> enable )
148
- return 0 ;
149
-
150
182
/*
151
183
* Note: these are just sanity checks to filter out totally bad scaling
152
184
* factors. The real limits must be calculated case by case, and
@@ -159,6 +191,15 @@ static int omap_plane_atomic_check(struct drm_plane *plane,
159
191
if (ret )
160
192
return ret ;
161
193
194
+ DBG ("%s: visible %d -> %d" , plane -> name ,
195
+ old_plane_state -> visible , new_plane_state -> visible );
196
+
197
+ if (!new_plane_state -> visible ) {
198
+ omap_overlay_release (state , omap_state -> overlay );
199
+ omap_state -> overlay = NULL ;
200
+ return 0 ;
201
+ }
202
+
162
203
if (new_plane_state -> crtc_x < 0 || new_plane_state -> crtc_y < 0 )
163
204
return - EINVAL ;
164
205
@@ -179,6 +220,43 @@ static int omap_plane_atomic_check(struct drm_plane *plane,
179
220
!omap_framebuffer_supports_rotation (new_plane_state -> fb ))
180
221
return - EINVAL ;
181
222
223
+ if ((new_plane_state -> src_w >> 16 ) != new_plane_state -> crtc_w ||
224
+ (new_plane_state -> src_h >> 16 ) != new_plane_state -> crtc_h )
225
+ caps |= OMAP_DSS_OVL_CAP_SCALE ;
226
+
227
+ fourcc = new_plane_state -> fb -> format -> format ;
228
+
229
+ /*
230
+ * (re)allocate hw overlay if we don't have one or
231
+ * there is a caps mismatch
232
+ */
233
+ if (!omap_state -> overlay || (caps & ~omap_state -> overlay -> caps )) {
234
+ new_hw_overlay = true;
235
+ } else {
236
+ /* check supported format */
237
+ if (!dispc_ovl_color_mode_supported (priv -> dispc , omap_state -> overlay -> id ,
238
+ fourcc ))
239
+ new_hw_overlay = true;
240
+ }
241
+
242
+ if (new_hw_overlay ) {
243
+ struct omap_hw_overlay * old_ovl = omap_state -> overlay ;
244
+ struct omap_hw_overlay * new_ovl = NULL ;
245
+
246
+ omap_overlay_release (state , old_ovl );
247
+
248
+ ret = omap_overlay_assign (state , plane , caps , fourcc , & new_ovl );
249
+ if (ret ) {
250
+ DBG ("%s: failed to assign hw_overlay" , plane -> name );
251
+ omap_state -> overlay = NULL ;
252
+ return ret ;
253
+ }
254
+
255
+ omap_state -> overlay = new_ovl ;
256
+ }
257
+
258
+ DBG ("plane: %s overlay_id: %d" , plane -> name , omap_state -> overlay -> id );
259
+
182
260
return 0 ;
183
261
}
184
262
@@ -252,17 +330,21 @@ static void omap_plane_reset(struct drm_plane *plane)
252
330
static struct drm_plane_state *
253
331
omap_plane_atomic_duplicate_state (struct drm_plane * plane )
254
332
{
255
- struct omap_plane_state * state ;
333
+ struct omap_plane_state * state , * current_state ;
256
334
257
335
if (WARN_ON (!plane -> state ))
258
336
return NULL ;
259
337
338
+ current_state = to_omap_plane_state (plane -> state );
339
+
260
340
state = kmalloc (sizeof (* state ), GFP_KERNEL );
261
341
if (!state )
262
342
return NULL ;
263
343
264
344
__drm_atomic_helper_plane_duplicate_state (plane , & state -> base );
265
345
346
+ state -> overlay = current_state -> overlay ;
347
+
266
348
return & state -> base ;
267
349
}
268
350
@@ -344,12 +426,11 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
344
426
return ERR_PTR (- ENOMEM );
345
427
346
428
omap_plane -> id = idx ;
347
- omap_plane -> overlay = priv -> overlays [idx ];
348
429
349
430
DBG ("%d: type=%d" , omap_plane -> id , type );
350
431
DBG (" crtc_mask: 0x%04x" , possible_crtcs );
351
432
352
- formats = dispc_ovl_get_color_modes (priv -> dispc , omap_plane -> overlay -> id );
433
+ formats = dispc_ovl_get_color_modes (priv -> dispc , omap_plane -> id );
353
434
for (nformats = 0 ; formats [nformats ]; ++ nformats )
354
435
;
355
436
0 commit comments