1 // SPDX-License-Identifier: GPL-2.0 OR MIT
4 * Xen para-virtual DRM device
6 * Copyright (C) 2016-2018 EPAM Systems Inc.
8 * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
11 #include <drm/drm_atomic.h>
12 #include <drm/drm_atomic_helper.h>
13 #include <drm/drm_drv.h>
14 #include <drm/drm_fourcc.h>
15 #include <drm/drm_gem.h>
16 #include <drm/drm_gem_framebuffer_helper.h>
17 #include <drm/drm_probe_helper.h>
18 #include <drm/drm_vblank.h>
20 #include "xen_drm_front.h"
21 #include "xen_drm_front_conn.h"
22 #include "xen_drm_front_kms.h"
25 * Timeout in ms to wait for frame done event from the backend:
26 * must be a bit more than IO time-out
28 #define FRAME_DONE_TO_MS (XEN_DRM_FRONT_WAIT_BACK_MS + 100)
30 static struct xen_drm_front_drm_pipeline
*
31 to_xen_drm_pipeline(struct drm_simple_display_pipe
*pipe
)
33 return container_of(pipe
, struct xen_drm_front_drm_pipeline
, pipe
);
36 static void fb_destroy(struct drm_framebuffer
*fb
)
38 struct xen_drm_front_drm_info
*drm_info
= fb
->dev
->dev_private
;
41 if (drm_dev_enter(fb
->dev
, &idx
)) {
42 xen_drm_front_fb_detach(drm_info
->front_info
,
43 xen_drm_front_fb_to_cookie(fb
));
46 drm_gem_fb_destroy(fb
);
49 static const struct drm_framebuffer_funcs fb_funcs
= {
50 .destroy
= fb_destroy
,
53 static struct drm_framebuffer
*
54 fb_create(struct drm_device
*dev
, struct drm_file
*filp
,
55 const struct drm_mode_fb_cmd2
*mode_cmd
)
57 struct xen_drm_front_drm_info
*drm_info
= dev
->dev_private
;
58 struct drm_framebuffer
*fb
;
59 struct drm_gem_object
*gem_obj
;
62 fb
= drm_gem_fb_create_with_funcs(dev
, filp
, mode_cmd
, &fb_funcs
);
68 ret
= xen_drm_front_fb_attach(drm_info
->front_info
,
69 xen_drm_front_dbuf_to_cookie(gem_obj
),
70 xen_drm_front_fb_to_cookie(fb
),
71 fb
->width
, fb
->height
,
74 DRM_ERROR("Back failed to attach FB %p: %d\n", fb
, ret
);
81 drm_gem_fb_destroy(fb
);
85 static const struct drm_mode_config_funcs mode_config_funcs
= {
86 .fb_create
= fb_create
,
87 .atomic_check
= drm_atomic_helper_check
,
88 .atomic_commit
= drm_atomic_helper_commit
,
91 static void send_pending_event(struct xen_drm_front_drm_pipeline
*pipeline
)
93 struct drm_crtc
*crtc
= &pipeline
->pipe
.crtc
;
94 struct drm_device
*dev
= crtc
->dev
;
97 spin_lock_irqsave(&dev
->event_lock
, flags
);
98 if (pipeline
->pending_event
)
99 drm_crtc_send_vblank_event(crtc
, pipeline
->pending_event
);
100 pipeline
->pending_event
= NULL
;
101 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
104 static void display_enable(struct drm_simple_display_pipe
*pipe
,
105 struct drm_crtc_state
*crtc_state
,
106 struct drm_plane_state
*plane_state
)
108 struct xen_drm_front_drm_pipeline
*pipeline
=
109 to_xen_drm_pipeline(pipe
);
110 struct drm_crtc
*crtc
= &pipe
->crtc
;
111 struct drm_framebuffer
*fb
= plane_state
->fb
;
114 if (!drm_dev_enter(pipe
->crtc
.dev
, &idx
))
117 ret
= xen_drm_front_mode_set(pipeline
, crtc
->x
, crtc
->y
,
118 fb
->width
, fb
->height
,
119 fb
->format
->cpp
[0] * 8,
120 xen_drm_front_fb_to_cookie(fb
));
123 DRM_ERROR("Failed to enable display: %d\n", ret
);
124 pipeline
->conn_connected
= false;
130 static void display_disable(struct drm_simple_display_pipe
*pipe
)
132 struct xen_drm_front_drm_pipeline
*pipeline
=
133 to_xen_drm_pipeline(pipe
);
136 if (drm_dev_enter(pipe
->crtc
.dev
, &idx
)) {
137 ret
= xen_drm_front_mode_set(pipeline
, 0, 0, 0, 0, 0,
138 xen_drm_front_fb_to_cookie(NULL
));
142 DRM_ERROR("Failed to disable display: %d\n", ret
);
144 /* Make sure we can restart with enabled connector next time */
145 pipeline
->conn_connected
= true;
147 /* release stalled event if any */
148 send_pending_event(pipeline
);
151 void xen_drm_front_kms_on_frame_done(struct xen_drm_front_drm_pipeline
*pipeline
,
155 * This runs in interrupt context, e.g. under
156 * drm_info->front_info->io_lock, so we cannot call _sync version
159 cancel_delayed_work(&pipeline
->pflip_to_worker
);
161 send_pending_event(pipeline
);
164 static void pflip_to_worker(struct work_struct
*work
)
166 struct delayed_work
*delayed_work
= to_delayed_work(work
);
167 struct xen_drm_front_drm_pipeline
*pipeline
=
168 container_of(delayed_work
,
169 struct xen_drm_front_drm_pipeline
,
172 DRM_ERROR("Frame done timed-out, releasing");
173 send_pending_event(pipeline
);
176 static bool display_send_page_flip(struct drm_simple_display_pipe
*pipe
,
177 struct drm_plane_state
*old_plane_state
)
179 struct drm_plane_state
*plane_state
=
180 drm_atomic_get_new_plane_state(old_plane_state
->state
,
184 * If old_plane_state->fb is NULL and plane_state->fb is not,
185 * then this is an atomic commit which will enable display.
186 * If old_plane_state->fb is not NULL and plane_state->fb is,
187 * then this is an atomic commit which will disable display.
188 * Ignore these and do not send page flip as this framebuffer will be
189 * sent to the backend as a part of display_set_config call.
191 if (old_plane_state
->fb
&& plane_state
->fb
) {
192 struct xen_drm_front_drm_pipeline
*pipeline
=
193 to_xen_drm_pipeline(pipe
);
194 struct xen_drm_front_drm_info
*drm_info
= pipeline
->drm_info
;
197 schedule_delayed_work(&pipeline
->pflip_to_worker
,
198 msecs_to_jiffies(FRAME_DONE_TO_MS
));
200 ret
= xen_drm_front_page_flip(drm_info
->front_info
,
202 xen_drm_front_fb_to_cookie(plane_state
->fb
));
204 DRM_ERROR("Failed to send page flip request to backend: %d\n", ret
);
206 pipeline
->conn_connected
= false;
208 * Report the flip not handled, so pending event is
209 * sent, unblocking user-space.
214 * Signal that page flip was handled, pending event will be sent
215 * on frame done event from the backend.
223 static int display_check(struct drm_simple_display_pipe
*pipe
,
224 struct drm_plane_state
*plane_state
,
225 struct drm_crtc_state
*crtc_state
)
228 * Xen doesn't initialize vblanking via drm_vblank_init(), so
229 * DRM helpers assume that it doesn't handle vblanking and start
230 * sending out fake VBLANK events automatically.
232 * As xen contains it's own logic for sending out VBLANK events
233 * in send_pending_event(), disable no_vblank (i.e., the xen
234 * driver has vblanking support).
236 crtc_state
->no_vblank
= false;
241 static void display_update(struct drm_simple_display_pipe
*pipe
,
242 struct drm_plane_state
*old_plane_state
)
244 struct xen_drm_front_drm_pipeline
*pipeline
=
245 to_xen_drm_pipeline(pipe
);
246 struct drm_crtc
*crtc
= &pipe
->crtc
;
247 struct drm_pending_vblank_event
*event
;
250 event
= crtc
->state
->event
;
252 struct drm_device
*dev
= crtc
->dev
;
255 WARN_ON(pipeline
->pending_event
);
257 spin_lock_irqsave(&dev
->event_lock
, flags
);
258 crtc
->state
->event
= NULL
;
260 pipeline
->pending_event
= event
;
261 spin_unlock_irqrestore(&dev
->event_lock
, flags
);
264 if (!drm_dev_enter(pipe
->crtc
.dev
, &idx
)) {
265 send_pending_event(pipeline
);
270 * Send page flip request to the backend *after* we have event cached
271 * above, so on page flip done event from the backend we can
272 * deliver it and there is no race condition between this code and
273 * event from the backend.
274 * If this is not a page flip, e.g. no flip done event from the backend
275 * is expected, then send now.
277 if (!display_send_page_flip(pipe
, old_plane_state
))
278 send_pending_event(pipeline
);
283 static enum drm_mode_status
284 display_mode_valid(struct drm_simple_display_pipe
*pipe
,
285 const struct drm_display_mode
*mode
)
287 struct xen_drm_front_drm_pipeline
*pipeline
=
288 container_of(pipe
, struct xen_drm_front_drm_pipeline
,
291 if (mode
->hdisplay
!= pipeline
->width
)
294 if (mode
->vdisplay
!= pipeline
->height
)
300 static const struct drm_simple_display_pipe_funcs display_funcs
= {
301 .mode_valid
= display_mode_valid
,
302 .enable
= display_enable
,
303 .disable
= display_disable
,
304 .prepare_fb
= drm_gem_fb_simple_display_pipe_prepare_fb
,
305 .check
= display_check
,
306 .update
= display_update
,
309 static int display_pipe_init(struct xen_drm_front_drm_info
*drm_info
,
310 int index
, struct xen_drm_front_cfg_connector
*cfg
,
311 struct xen_drm_front_drm_pipeline
*pipeline
)
313 struct drm_device
*dev
= drm_info
->drm_dev
;
318 pipeline
->drm_info
= drm_info
;
319 pipeline
->index
= index
;
320 pipeline
->height
= cfg
->height
;
321 pipeline
->width
= cfg
->width
;
323 INIT_DELAYED_WORK(&pipeline
->pflip_to_worker
, pflip_to_worker
);
325 ret
= xen_drm_front_conn_init(drm_info
, &pipeline
->conn
);
329 formats
= xen_drm_front_conn_get_formats(&format_count
);
331 return drm_simple_display_pipe_init(dev
, &pipeline
->pipe
,
332 &display_funcs
, formats
,
337 int xen_drm_front_kms_init(struct xen_drm_front_drm_info
*drm_info
)
339 struct drm_device
*dev
= drm_info
->drm_dev
;
342 drm_mode_config_init(dev
);
344 dev
->mode_config
.min_width
= 0;
345 dev
->mode_config
.min_height
= 0;
346 dev
->mode_config
.max_width
= 4095;
347 dev
->mode_config
.max_height
= 2047;
348 dev
->mode_config
.funcs
= &mode_config_funcs
;
350 for (i
= 0; i
< drm_info
->front_info
->cfg
.num_connectors
; i
++) {
351 struct xen_drm_front_cfg_connector
*cfg
=
352 &drm_info
->front_info
->cfg
.connectors
[i
];
353 struct xen_drm_front_drm_pipeline
*pipeline
=
354 &drm_info
->pipeline
[i
];
356 ret
= display_pipe_init(drm_info
, i
, cfg
, pipeline
);
358 drm_mode_config_cleanup(dev
);
363 drm_mode_config_reset(dev
);
364 drm_kms_helper_poll_init(dev
);
368 void xen_drm_front_kms_fini(struct xen_drm_front_drm_info
*drm_info
)
372 for (i
= 0; i
< drm_info
->front_info
->cfg
.num_connectors
; i
++) {
373 struct xen_drm_front_drm_pipeline
*pipeline
=
374 &drm_info
->pipeline
[i
];
376 cancel_delayed_work_sync(&pipeline
->pflip_to_worker
);
378 send_pending_event(pipeline
);