33
33
*
34
34
*/
35
35
36
+ static void hdlcd_crtc_cleanup (struct drm_crtc * crtc )
37
+ {
38
+ struct hdlcd_drm_private * hdlcd = crtc_to_hdlcd_priv (crtc );
39
+
40
+ /* stop the controller on cleanup */
41
+ hdlcd_write (hdlcd , HDLCD_REG_COMMAND , 0 );
42
+ drm_crtc_cleanup (crtc );
43
+ }
44
+
36
45
static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
37
- .destroy = drm_crtc_cleanup ,
46
+ .destroy = hdlcd_crtc_cleanup ,
38
47
.set_config = drm_atomic_helper_set_config ,
39
48
.page_flip = drm_atomic_helper_page_flip ,
40
49
.reset = drm_atomic_helper_crtc_reset ,
@@ -97,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
97
106
struct hdlcd_drm_private * hdlcd = crtc_to_hdlcd_priv (crtc );
98
107
struct drm_display_mode * m = & crtc -> state -> adjusted_mode ;
99
108
struct videomode vm ;
100
- unsigned int polarities , line_length , err ;
109
+ unsigned int polarities , err ;
101
110
102
111
vm .vfront_porch = m -> crtc_vsync_start - m -> crtc_vdisplay ;
103
112
vm .vback_porch = m -> crtc_vtotal - m -> crtc_vsync_end ;
@@ -113,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
113
122
if (m -> flags & DRM_MODE_FLAG_PVSYNC )
114
123
polarities |= HDLCD_POLARITY_VSYNC ;
115
124
116
- line_length = crtc -> primary -> state -> fb -> pitches [0 ];
117
-
118
125
/* Allow max number of outstanding requests and largest burst size */
119
126
hdlcd_write (hdlcd , HDLCD_REG_BUS_OPTIONS ,
120
127
HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16 );
121
128
122
- hdlcd_write (hdlcd , HDLCD_REG_FB_LINE_LENGTH , line_length );
123
- hdlcd_write (hdlcd , HDLCD_REG_FB_LINE_PITCH , line_length );
124
- hdlcd_write (hdlcd , HDLCD_REG_FB_LINE_COUNT , m -> crtc_vdisplay - 1 );
125
129
hdlcd_write (hdlcd , HDLCD_REG_V_DATA , m -> crtc_vdisplay - 1 );
126
130
hdlcd_write (hdlcd , HDLCD_REG_V_BACK_PORCH , vm .vback_porch - 1 );
127
131
hdlcd_write (hdlcd , HDLCD_REG_V_FRONT_PORCH , vm .vfront_porch - 1 );
128
132
hdlcd_write (hdlcd , HDLCD_REG_V_SYNC , vm .vsync_len - 1 );
133
+ hdlcd_write (hdlcd , HDLCD_REG_H_DATA , m -> crtc_hdisplay - 1 );
129
134
hdlcd_write (hdlcd , HDLCD_REG_H_BACK_PORCH , vm .hback_porch - 1 );
130
135
hdlcd_write (hdlcd , HDLCD_REG_H_FRONT_PORCH , vm .hfront_porch - 1 );
131
136
hdlcd_write (hdlcd , HDLCD_REG_H_SYNC , vm .hsync_len - 1 );
132
- hdlcd_write (hdlcd , HDLCD_REG_H_DATA , m -> crtc_hdisplay - 1 );
133
137
hdlcd_write (hdlcd , HDLCD_REG_POLARITIES , polarities );
134
138
135
139
err = hdlcd_set_pxl_fmt (crtc );
@@ -144,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
144
148
struct hdlcd_drm_private * hdlcd = crtc_to_hdlcd_priv (crtc );
145
149
146
150
clk_prepare_enable (hdlcd -> clk );
151
+ hdlcd_crtc_mode_set_nofb (crtc );
147
152
hdlcd_write (hdlcd , HDLCD_REG_COMMAND , 1 );
148
- drm_crtc_vblank_on (crtc );
149
153
}
150
154
151
155
static void hdlcd_crtc_disable (struct drm_crtc * crtc )
152
156
{
153
157
struct hdlcd_drm_private * hdlcd = crtc_to_hdlcd_priv (crtc );
154
158
155
- if (!crtc -> primary -> fb )
159
+ if (!crtc -> state -> active )
156
160
return ;
157
161
158
- clk_disable_unprepare (hdlcd -> clk );
159
162
hdlcd_write (hdlcd , HDLCD_REG_COMMAND , 0 );
160
- drm_crtc_vblank_off ( crtc );
163
+ clk_disable_unprepare ( hdlcd -> clk );
161
164
}
162
165
163
166
static int hdlcd_crtc_atomic_check (struct drm_crtc * crtc ,
@@ -179,20 +182,17 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
179
182
static void hdlcd_crtc_atomic_begin (struct drm_crtc * crtc ,
180
183
struct drm_crtc_state * state )
181
184
{
182
- struct hdlcd_drm_private * hdlcd = crtc_to_hdlcd_priv (crtc );
183
- unsigned long flags ;
184
-
185
- if (crtc -> state -> event ) {
186
- struct drm_pending_vblank_event * event = crtc -> state -> event ;
185
+ struct drm_pending_vblank_event * event = crtc -> state -> event ;
187
186
187
+ if (event ) {
188
188
crtc -> state -> event = NULL ;
189
- event -> pipe = drm_crtc_index (crtc );
190
-
191
- WARN_ON (drm_crtc_vblank_get (crtc ) != 0 );
192
189
193
- spin_lock_irqsave (& crtc -> dev -> event_lock , flags );
194
- list_add_tail (& event -> base .link , & hdlcd -> event_list );
195
- spin_unlock_irqrestore (& crtc -> dev -> event_lock , flags );
190
+ spin_lock_irq (& crtc -> dev -> event_lock );
191
+ if (drm_crtc_vblank_get (crtc ) == 0 )
192
+ drm_crtc_arm_vblank_event (crtc , event );
193
+ else
194
+ drm_crtc_send_vblank_event (crtc , event );
195
+ spin_unlock_irq (& crtc -> dev -> event_lock );
196
196
}
197
197
}
198
198
@@ -225,6 +225,15 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
225
225
static int hdlcd_plane_atomic_check (struct drm_plane * plane ,
226
226
struct drm_plane_state * state )
227
227
{
228
+ u32 src_w , src_h ;
229
+
230
+ src_w = state -> src_w >> 16 ;
231
+ src_h = state -> src_h >> 16 ;
232
+
233
+ /* we can't do any scaling of the plane source */
234
+ if ((src_w != state -> crtc_w ) || (src_h != state -> crtc_h ))
235
+ return - EINVAL ;
236
+
228
237
return 0 ;
229
238
}
230
239
@@ -233,20 +242,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
233
242
{
234
243
struct hdlcd_drm_private * hdlcd ;
235
244
struct drm_gem_cma_object * gem ;
245
+ unsigned int depth , bpp ;
246
+ u32 src_w , src_h , dest_w , dest_h ;
236
247
dma_addr_t scanout_start ;
237
248
238
- if (!plane -> state -> crtc || ! plane -> state -> fb )
249
+ if (!plane -> state -> fb )
239
250
return ;
240
251
241
- hdlcd = crtc_to_hdlcd_priv (plane -> state -> crtc );
252
+ drm_fb_get_bpp_depth (plane -> state -> fb -> pixel_format , & depth , & bpp );
253
+ src_w = plane -> state -> src_w >> 16 ;
254
+ src_h = plane -> state -> src_h >> 16 ;
255
+ dest_w = plane -> state -> crtc_w ;
256
+ dest_h = plane -> state -> crtc_h ;
242
257
gem = drm_fb_cma_get_gem_obj (plane -> state -> fb , 0 );
243
- scanout_start = gem -> paddr ;
258
+ scanout_start = gem -> paddr + plane -> state -> fb -> offsets [0 ] +
259
+ plane -> state -> crtc_y * plane -> state -> fb -> pitches [0 ] +
260
+ plane -> state -> crtc_x * bpp / 8 ;
261
+
262
+ hdlcd = plane -> dev -> dev_private ;
263
+ hdlcd_write (hdlcd , HDLCD_REG_FB_LINE_LENGTH , plane -> state -> fb -> pitches [0 ]);
264
+ hdlcd_write (hdlcd , HDLCD_REG_FB_LINE_PITCH , plane -> state -> fb -> pitches [0 ]);
265
+ hdlcd_write (hdlcd , HDLCD_REG_FB_LINE_COUNT , dest_h - 1 );
244
266
hdlcd_write (hdlcd , HDLCD_REG_FB_BASE , scanout_start );
245
267
}
246
268
247
269
static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
248
- .prepare_fb = NULL ,
249
- .cleanup_fb = NULL ,
250
270
.atomic_check = hdlcd_plane_atomic_check ,
251
271
.atomic_update = hdlcd_plane_atomic_update ,
252
272
};
@@ -294,16 +314,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
294
314
return plane ;
295
315
}
296
316
297
- void hdlcd_crtc_suspend (struct drm_crtc * crtc )
298
- {
299
- hdlcd_crtc_disable (crtc );
300
- }
301
-
302
- void hdlcd_crtc_resume (struct drm_crtc * crtc )
303
- {
304
- hdlcd_crtc_enable (crtc );
305
- }
306
-
307
317
int hdlcd_setup_crtc (struct drm_device * drm )
308
318
{
309
319
struct hdlcd_drm_private * hdlcd = drm -> dev_private ;
0 commit comments