Skip to content

Commit 06ec419

Browse files
author
Sinclair Yeh
committed
drm/vmwgfx: Add and connect CRTC helper functions
Atomic mode set requires us to refactor existing vmw_stdu_crtc_set_config code into sections that check the validity of the new mode, and sections that actually program the hardware state. vmw_du_crtc_atomic_check() takes CRTC-related checking code. In a later patch, vmw_du_primary_plane_atomic_check() will take framebuffer-related checking code. These helpers won't be called until we flip on the atomic support flag or set drm_crtc_funcs->set_config to using the atomic helper. v2: * The state->num_connector is actually the total number of potential connectors, not just the one associated with the display unit. The proper one to check is ->connector_mask. * Add the check to only allow plane state to be the same as crtc state (Thanks to mlankhorst) * Make sure to turn on SVGA mode before using VRAM. SVGA mode is disabled in master_drop if dbdev is not running. v3: * Moved dot clock override to crtc_atomic_check Signed-off-by: Sinclair Yeh <[email protected]> Signed-off-by: Thomas Hellstrom <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Acked-by: Daniel Vetter <[email protected]>
1 parent d7721ca commit 06ec419

File tree

5 files changed

+379
-0
lines changed

5 files changed

+379
-0
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_kms.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,61 @@ void vmw_du_primary_plane_destroy(struct drm_plane *plane)
390390
}
391391

392392

393+
int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
394+
struct drm_crtc_state *new_state)
395+
{
396+
struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc);
397+
int connector_mask = 1 << drm_connector_index(&du->connector);
398+
bool has_primary = new_state->plane_mask &
399+
BIT(drm_plane_index(crtc->primary));
400+
401+
/* We always want to have an active plane with an active CRTC */
402+
if (has_primary != new_state->enable)
403+
return -EINVAL;
404+
405+
406+
if (new_state->connector_mask != connector_mask &&
407+
new_state->connector_mask != 0) {
408+
DRM_ERROR("Invalid connectors configuration\n");
409+
return -EINVAL;
410+
}
411+
412+
/*
413+
* Our virtual device does not have a dot clock, so use the logical
414+
* clock value as the dot clock.
415+
*/
416+
if (new_state->mode.crtc_clock == 0)
417+
new_state->adjusted_mode.crtc_clock = new_state->mode.clock;
418+
419+
return 0;
420+
}
421+
422+
423+
void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
424+
struct drm_crtc_state *old_crtc_state)
425+
{
426+
}
427+
428+
429+
void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
430+
struct drm_crtc_state *old_crtc_state)
431+
{
432+
struct drm_pending_vblank_event *event = crtc->state->event;
433+
434+
if (event) {
435+
crtc->state->event = NULL;
436+
437+
spin_lock_irq(&crtc->dev->event_lock);
438+
if (drm_crtc_vblank_get(crtc) == 0)
439+
drm_crtc_arm_vblank_event(crtc, event);
440+
else
441+
drm_crtc_send_vblank_event(crtc, event);
442+
spin_unlock_irq(&crtc->dev->event_lock);
443+
}
444+
445+
}
446+
447+
393448
/**
394449
* vmw_du_crtc_duplicate_state - duplicate crtc state
395450
* @crtc: DRM crtc

drivers/gpu/drm/vmwgfx/vmwgfx_kms.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ struct vmw_crtc_state {
161161
* @surf Display surface for STDU
162162
* @dmabuf display dmabuf for SOU
163163
* @content_fb_type Used by STDU.
164+
* @dmabuf_size Size of the dmabuf, used by Screen Object Display Unit
164165
* @pinned pin count for STDU display surface
165166
*/
166167
struct vmw_plane_state {
@@ -169,6 +170,7 @@ struct vmw_plane_state {
169170
struct vmw_dma_buffer *dmabuf;
170171

171172
int content_fb_type;
173+
unsigned long dmabuf_size;
172174

173175
int pinned;
174176
};
@@ -342,10 +344,17 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
342344
uint32_t src_x, uint32_t src_y,
343345
uint32_t src_w, uint32_t src_h);
344346

347+
/* Atomic Helpers */
345348
void vmw_du_plane_reset(struct drm_plane *plane);
346349
struct drm_plane_state *vmw_du_plane_duplicate_state(struct drm_plane *plane);
347350
void vmw_du_plane_destroy_state(struct drm_plane *plane,
348351
struct drm_plane_state *state);
352+
int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
353+
struct drm_crtc_state *state);
354+
void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
355+
struct drm_crtc_state *old_crtc_state);
356+
void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
357+
struct drm_crtc_state *old_crtc_state);
349358
void vmw_du_crtc_reset(struct drm_crtc *crtc);
350359
struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
351360
void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,

drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
167167
if (vfb != ld->fb) {
168168
if (ld->fb && ld->fb->unpin)
169169
ld->fb->unpin(ld->fb);
170+
vmw_svga_enable(vmw_priv);
170171
if (vfb->pin)
171172
vfb->pin(vfb);
172173
ld->fb = vfb;
@@ -190,6 +191,68 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
190191
return 0;
191192
}
192193

194+
/**
195+
* vmw_ldu_crtc_mode_set_nofb - Enable svga
196+
*
197+
* @crtc: CRTC associated with the new screen
198+
*
199+
* For LDU, just enable the svga
200+
*/
201+
static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc)
202+
{
203+
}
204+
205+
/**
206+
* vmw_ldu_crtc_helper_prepare - Noop
207+
*
208+
* @crtc: CRTC associated with the new screen
209+
*
210+
* Prepares the CRTC for a mode set, but we don't need to do anything here.
211+
*
212+
*/
213+
static void vmw_ldu_crtc_helper_prepare(struct drm_crtc *crtc)
214+
{
215+
}
216+
217+
/**
218+
* vmw_ldu_crtc_helper_commit - Noop
219+
*
220+
* @crtc: CRTC associated with the new screen
221+
*
222+
* This is called after a mode set has been completed. Here's
223+
* usually a good place to call vmw_ldu_add_active/vmw_ldu_del_active
224+
* but since for LDU the display plane is closely tied to the
225+
* CRTC, it makes more sense to do those at plane update time.
226+
*/
227+
static void vmw_ldu_crtc_helper_commit(struct drm_crtc *crtc)
228+
{
229+
struct vmw_private *dev_priv;
230+
struct vmw_legacy_display_unit *ldu;
231+
struct vmw_framebuffer *vfb;
232+
struct drm_framebuffer *fb;
233+
234+
235+
ldu = vmw_crtc_to_ldu(crtc);
236+
dev_priv = vmw_priv(crtc->dev);
237+
fb = crtc->primary->fb;
238+
239+
vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
240+
241+
if (vfb)
242+
vmw_ldu_add_active(dev_priv, ldu, vfb);
243+
else
244+
vmw_ldu_del_active(dev_priv, ldu);
245+
}
246+
247+
/**
248+
* vmw_ldu_crtc_helper_disable - Turns off CRTC
249+
*
250+
* @crtc: CRTC to be turned off
251+
*/
252+
static void vmw_ldu_crtc_helper_disable(struct drm_crtc *crtc)
253+
{
254+
}
255+
193256
static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
194257
{
195258
struct vmw_private *dev_priv;
@@ -346,6 +409,20 @@ static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
346409
.atomic_destroy_state = vmw_du_plane_destroy_state,
347410
};
348411

412+
/*
413+
* Atomic Helpers
414+
*/
415+
static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = {
416+
.prepare = vmw_ldu_crtc_helper_prepare,
417+
.commit = vmw_ldu_crtc_helper_commit,
418+
.disable = vmw_ldu_crtc_helper_disable,
419+
.mode_set = drm_helper_crtc_mode_set,
420+
.mode_set_nofb = vmw_ldu_crtc_mode_set_nofb,
421+
.atomic_check = vmw_du_crtc_atomic_check,
422+
.atomic_begin = vmw_du_crtc_atomic_begin,
423+
.atomic_flush = vmw_du_crtc_atomic_flush,
424+
};
425+
349426

350427
static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
351428
{
@@ -445,6 +522,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
445522
goto err_free_unregister;
446523
}
447524

525+
drm_crtc_helper_add(crtc, &vmw_ldu_crtc_helper_funcs);
526+
448527
drm_mode_crtc_set_gamma_size(crtc, 256);
449528

450529
drm_object_attach_property(&connector->base,

drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,109 @@ static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
250250
return ret;
251251
}
252252

253+
/**
254+
* vmw_sou_crtc_mode_set_nofb - Create new screen
255+
*
256+
* @crtc: CRTC associated with the new screen
257+
*
258+
* This function creates/destroys a screen. This function cannot fail, so if
259+
* somehow we run into a failure, just do the best we can to get out.
260+
*/
261+
static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc)
262+
{
263+
struct vmw_private *dev_priv;
264+
struct vmw_screen_object_unit *sou;
265+
struct vmw_framebuffer *vfb;
266+
struct drm_framebuffer *fb;
267+
struct drm_plane_state *ps;
268+
struct vmw_plane_state *vps;
269+
int ret;
270+
271+
272+
sou = vmw_crtc_to_sou(crtc);
273+
dev_priv = vmw_priv(crtc->dev);
274+
ps = crtc->primary->state;
275+
fb = ps->fb;
276+
vps = vmw_plane_state_to_vps(ps);
277+
278+
vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
279+
280+
if (sou->defined) {
281+
ret = vmw_sou_fifo_destroy(dev_priv, sou);
282+
if (ret) {
283+
DRM_ERROR("Failed to destroy Screen Object\n");
284+
return;
285+
}
286+
}
287+
288+
if (vfb) {
289+
sou->buffer = vps->dmabuf;
290+
sou->buffer_size = vps->dmabuf_size;
291+
292+
ret = vmw_sou_fifo_create(dev_priv, sou, crtc->x, crtc->y,
293+
&crtc->mode);
294+
if (ret)
295+
DRM_ERROR("Failed to define Screen Object %dx%d\n",
296+
crtc->x, crtc->y);
297+
298+
vmw_kms_add_active(dev_priv, &sou->base, vfb);
299+
} else {
300+
sou->buffer = NULL;
301+
sou->buffer_size = 0;
302+
303+
vmw_kms_del_active(dev_priv, &sou->base);
304+
}
305+
}
306+
307+
/**
308+
* vmw_sou_crtc_helper_prepare - Noop
309+
*
310+
* @crtc: CRTC associated with the new screen
311+
*
312+
* Prepares the CRTC for a mode set, but we don't need to do anything here.
313+
*/
314+
static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc)
315+
{
316+
}
317+
318+
/**
319+
* vmw_sou_crtc_helper_commit - Noop
320+
*
321+
* @crtc: CRTC associated with the new screen
322+
*
323+
* This is called after a mode set has been completed.
324+
*/
325+
static void vmw_sou_crtc_helper_commit(struct drm_crtc *crtc)
326+
{
327+
}
328+
329+
/**
330+
* vmw_sou_crtc_helper_disable - Turns off CRTC
331+
*
332+
* @crtc: CRTC to be turned off
333+
*/
334+
static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc)
335+
{
336+
struct vmw_private *dev_priv;
337+
struct vmw_screen_object_unit *sou;
338+
int ret;
339+
340+
341+
if (!crtc) {
342+
DRM_ERROR("CRTC is NULL\n");
343+
return;
344+
}
345+
346+
sou = vmw_crtc_to_sou(crtc);
347+
dev_priv = vmw_priv(crtc->dev);
348+
349+
if (sou->defined) {
350+
ret = vmw_sou_fifo_destroy(dev_priv, sou);
351+
if (ret)
352+
DRM_ERROR("Failed to destroy Screen Object\n");
353+
}
354+
}
355+
253356
static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
254357
{
255358
struct vmw_private *dev_priv;
@@ -527,6 +630,20 @@ static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
527630
.atomic_destroy_state = vmw_du_plane_destroy_state,
528631
};
529632

633+
/*
634+
* Atomic Helpers
635+
*/
636+
static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = {
637+
.prepare = vmw_sou_crtc_helper_prepare,
638+
.commit = vmw_sou_crtc_helper_commit,
639+
.disable = vmw_sou_crtc_helper_disable,
640+
.mode_set = drm_helper_crtc_mode_set,
641+
.mode_set_nofb = vmw_sou_crtc_mode_set_nofb,
642+
.atomic_check = vmw_du_crtc_atomic_check,
643+
.atomic_begin = vmw_du_crtc_atomic_begin,
644+
.atomic_flush = vmw_du_crtc_atomic_flush,
645+
};
646+
530647

531648
static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
532649
{
@@ -626,6 +743,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
626743
goto err_free_unregister;
627744
}
628745

746+
drm_crtc_helper_add(crtc, &vmw_sou_crtc_helper_funcs);
747+
629748
drm_mode_crtc_set_gamma_size(crtc, 256);
630749

631750
drm_object_attach_property(&connector->base,

0 commit comments

Comments
 (0)