2 * Copyright (C) 2016 Broadcom
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
10 * DOC: VC4 firmware KMS module.
12 * As a hack to get us from the current closed source driver world
13 * toward a totally open stack, implement KMS on top of the Raspberry
14 * Pi's firmware display stack.
17 #include "drm/drm_atomic_helper.h"
18 #include "drm/drm_gem_framebuffer_helper.h"
19 #include "drm/drm_plane_helper.h"
20 #include "drm/drm_crtc_helper.h"
21 #include "drm/drm_fourcc.h"
22 #include "drm/drm_probe_helper.h"
23 #include "drm/drm_drv.h"
24 #include "drm/drm_vblank.h"
25 #include "linux/clk.h"
26 #include "linux/debugfs.h"
27 #include "drm/drm_fb_cma_helper.h"
28 #include "linux/component.h"
29 #include "linux/of_device.h"
32 #include "vc_image_types.h"
33 #include <soc/bcm2835/raspberrypi-firmware.h>
35 struct get_display_cfg {
36 u32 max_pixel_clock[2]; //Max pixel clock for each display
40 struct get_display_cfg cfg;
43 #define PLANES_PER_CRTC 3
57 u32 src_x; /* 16p16 */
58 u32 src_y; /* 16p16 */
60 u32 src_w; /* 16p16 */
61 u32 src_h; /* 16p16 */
74 u32 planes[4]; /* DMA address of each plane */
79 /* Values for the transform field */
80 #define TRANSFORM_NO_ROTATE 0
81 #define TRANSFORM_ROTATE_180 BIT(1)
82 #define TRANSFORM_FLIP_HRIZ BIT(16)
83 #define TRANSFORM_FLIP_VERT BIT(17)
85 #define SUPPORTED_ROTATIONS (DRM_MODE_ROTATE_0 | \
86 DRM_MODE_ROTATE_180 | \
87 DRM_MODE_REFLECT_X | \
90 struct mailbox_set_plane {
91 struct rpi_firmware_property_tag_header tag;
92 struct set_plane plane;
95 struct mailbox_blank_display {
96 struct rpi_firmware_property_tag_header tag1;
98 struct rpi_firmware_property_tag_header tag2;
102 struct mailbox_get_edid {
103 struct rpi_firmware_property_tag_header tag1;
114 u32 clock; /* in kHz */
135 #define TIMINGS_FLAGS_H_SYNC_POS BIT(0)
136 #define TIMINGS_FLAGS_H_SYNC_NEG 0
137 #define TIMINGS_FLAGS_V_SYNC_POS BIT(1)
138 #define TIMINGS_FLAGS_V_SYNC_NEG 0
139 #define TIMINGS_FLAGS_INTERLACE BIT(2)
141 #define TIMINGS_FLAGS_ASPECT_MASK GENMASK(7, 4)
142 #define TIMINGS_FLAGS_ASPECT_NONE (0 << 4)
143 #define TIMINGS_FLAGS_ASPECT_4_3 (1 << 4)
144 #define TIMINGS_FLAGS_ASPECT_16_9 (2 << 4)
145 #define TIMINGS_FLAGS_ASPECT_64_27 (3 << 4)
146 #define TIMINGS_FLAGS_ASPECT_256_135 (4 << 4)
148 /* Limited range RGB flag. Not set corresponds to full range. */
149 #define TIMINGS_FLAGS_RGB_LIMITED BIT(8)
150 /* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */
151 #define TIMINGS_FLAGS_DVI BIT(9)
154 struct mailbox_set_mode {
155 struct rpi_firmware_property_tag_header tag1;
156 struct set_timings timings;
159 static const struct vc_image_format {
160 u32 drm; /* DRM_FORMAT_* */
161 u32 vc_image; /* VC_IMAGE_* */
163 } vc_image_formats[] = {
165 .drm = DRM_FORMAT_XRGB8888,
166 .vc_image = VC_IMAGE_XRGB8888,
169 .drm = DRM_FORMAT_ARGB8888,
170 .vc_image = VC_IMAGE_ARGB8888,
173 * FIXME: Need to resolve which DRM format goes to which vc_image format
174 * for the remaining RGBA and RGBX formats.
176 * .drm = DRM_FORMAT_ABGR8888,
177 * .vc_image = VC_IMAGE_RGBA8888,
180 * .drm = DRM_FORMAT_XBGR8888,
181 * .vc_image = VC_IMAGE_RGBA8888,
185 .drm = DRM_FORMAT_RGB565,
186 .vc_image = VC_IMAGE_RGB565,
189 .drm = DRM_FORMAT_RGB888,
190 .vc_image = VC_IMAGE_BGR888,
193 .drm = DRM_FORMAT_BGR888,
194 .vc_image = VC_IMAGE_RGB888,
197 .drm = DRM_FORMAT_YUV422,
198 .vc_image = VC_IMAGE_YUV422PLANAR,
201 .drm = DRM_FORMAT_YUV420,
202 .vc_image = VC_IMAGE_YUV420,
205 .drm = DRM_FORMAT_YVU420,
206 .vc_image = VC_IMAGE_YUV420,
210 .drm = DRM_FORMAT_NV12,
211 .vc_image = VC_IMAGE_YUV420SP,
214 .drm = DRM_FORMAT_NV21,
215 .vc_image = VC_IMAGE_YUV420SP,
220 static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format)
224 for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) {
225 if (vc_image_formats[i].drm == drm_format)
226 return &vc_image_formats[i];
232 /* The firmware delivers a vblank interrupt to us through the SMI
233 * hardware, which has only this one register.
236 #define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11))
238 #define vc4_crtc vc4_kms_crtc
239 #define to_vc4_crtc to_vc4_kms_crtc
241 struct drm_crtc base;
242 struct drm_encoder *encoder;
243 struct drm_connector *connector;
246 struct drm_pending_vblank_event *event;
252 static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
254 return container_of(crtc, struct vc4_crtc, base);
257 struct vc4_fkms_encoder {
258 struct drm_encoder base;
262 static inline struct vc4_fkms_encoder *
263 to_vc4_fkms_encoder(struct drm_encoder *encoder)
265 return container_of(encoder, struct vc4_fkms_encoder, base);
268 /* VC4 FKMS connector KMS struct */
269 struct vc4_fkms_connector {
270 struct drm_connector base;
272 /* Since the connector is attached to just the one encoder,
273 * this is the reference to it so we can do the best_encoder()
276 struct drm_encoder *encoder;
277 struct vc4_dev *vc4_dev;
282 static inline struct vc4_fkms_connector *
283 to_vc4_fkms_connector(struct drm_connector *connector)
285 return container_of(connector, struct vc4_fkms_connector, base);
288 static u32 vc4_get_display_type(u32 display_number)
290 const u32 display_types[] = {
291 /* The firmware display (DispmanX) IDs map to specific types in
294 DRM_MODE_ENCODER_DSI, /* MAIN_LCD - DSI or DPI */
295 DRM_MODE_ENCODER_DSI, /* AUX_LCD */
296 DRM_MODE_ENCODER_TMDS, /* HDMI0 */
297 DRM_MODE_ENCODER_TVDAC, /* VEC */
298 DRM_MODE_ENCODER_NONE, /* FORCE_LCD */
299 DRM_MODE_ENCODER_NONE, /* FORCE_TV */
300 DRM_MODE_ENCODER_NONE, /* FORCE_OTHER */
301 DRM_MODE_ENCODER_TMDS, /* HDMI1 */
302 DRM_MODE_ENCODER_NONE, /* FORCE_TV2 */
304 return display_number > ARRAY_SIZE(display_types) - 1 ?
305 DRM_MODE_ENCODER_NONE : display_types[display_number];
308 /* Firmware's structure for making an FB mbox call. */
310 u32 xres, yres, xres_virtual, yres_virtual;
312 u32 xoffset, yoffset;
318 struct vc4_fkms_plane {
319 struct drm_plane base;
320 struct fbinfo_s *fbinfo;
321 dma_addr_t fbinfo_bus_addr;
323 struct mailbox_set_plane mb;
326 static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane)
328 return (struct vc4_fkms_plane *)plane;
331 static int vc4_plane_set_blank(struct drm_plane *plane, bool blank)
333 struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
334 struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
335 struct mailbox_set_plane blank_mb = {
336 .tag = { RPI_FIRMWARE_SET_PLANE, sizeof(struct set_plane), 0 },
338 .display = vc4_plane->mb.plane.display,
339 .plane_id = vc4_plane->mb.plane.plane_id,
342 static const char * const plane_types[] = {
349 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] %s plane %s",
350 plane->base.id, plane->name, plane_types[plane->type],
351 blank ? "blank" : "unblank");
354 ret = rpi_firmware_property_list(vc4->firmware, &blank_mb,
357 ret = rpi_firmware_property_list(vc4->firmware, &vc4_plane->mb,
358 sizeof(vc4_plane->mb));
360 WARN_ONCE(ret, "%s: firmware call failed. Please update your firmware",
365 static void vc4_plane_atomic_update(struct drm_plane *plane,
366 struct drm_plane_state *old_state)
368 struct drm_plane_state *state = plane->state;
369 struct drm_framebuffer *fb = state->fb;
370 struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
371 const struct drm_format_info *drm_fmt = fb->format;
372 const struct vc_image_format *vc_fmt =
373 vc4_get_vc_image_fmt(drm_fmt->format);
374 struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
375 struct mailbox_set_plane *mb = &vc4_plane->mb;
376 int num_planes = fb->format->num_planes;
377 struct drm_display_mode *mode = &state->crtc->mode;
378 unsigned int rotation = SUPPORTED_ROTATIONS;
380 mb->plane.vc_image_type = vc_fmt->vc_image;
381 mb->plane.width = fb->width;
382 mb->plane.height = fb->height;
383 mb->plane.pitch = fb->pitches[0];
384 mb->plane.src_w = state->src_w;
385 mb->plane.src_h = state->src_h;
386 mb->plane.src_x = state->src_x;
387 mb->plane.src_y = state->src_y;
388 mb->plane.dst_w = state->crtc_w;
389 mb->plane.dst_h = state->crtc_h;
390 mb->plane.dst_x = state->crtc_x;
391 mb->plane.dst_y = state->crtc_y;
392 mb->plane.alpha = state->alpha >> 8;
393 mb->plane.layer = state->normalized_zpos ?
394 state->normalized_zpos : -127;
395 mb->plane.num_planes = num_planes;
396 mb->plane.is_vu = vc_fmt->is_vu;
397 mb->plane.planes[0] = bo->paddr + fb->offsets[0];
399 rotation = drm_rotation_simplify(state->rotation, rotation);
403 case DRM_MODE_ROTATE_0:
404 mb->plane.transform = TRANSFORM_NO_ROTATE;
406 case DRM_MODE_ROTATE_180:
407 mb->plane.transform = TRANSFORM_ROTATE_180;
409 case DRM_MODE_REFLECT_X:
410 mb->plane.transform = TRANSFORM_FLIP_HRIZ;
412 case DRM_MODE_REFLECT_Y:
413 mb->plane.transform = TRANSFORM_FLIP_VERT;
417 /* FIXME: If the dest rect goes off screen then clip the src rect so we
418 * don't have off-screen pixels.
420 if (plane->type == DRM_PLANE_TYPE_CURSOR) {
421 /* There is no scaling on the cursor plane, therefore the calcs
422 * to alter the source crop as the cursor goes off the screen
425 if (mb->plane.dst_x + mb->plane.dst_w > mode->hdisplay) {
426 mb->plane.dst_w = mode->hdisplay - mb->plane.dst_x;
427 mb->plane.src_w = (mode->hdisplay - mb->plane.dst_x)
430 if (mb->plane.dst_y + mb->plane.dst_h > mode->vdisplay) {
431 mb->plane.dst_h = mode->vdisplay - mb->plane.dst_y;
432 mb->plane.src_h = (mode->vdisplay - mb->plane.dst_y)
437 if (num_planes > 1) {
438 /* Assume this must be YUV */
439 /* Makes assumptions on the stride for the chroma planes as we
440 * can't easily plumb in non-standard pitches.
442 mb->plane.planes[1] = bo->paddr + fb->offsets[1];
444 mb->plane.planes[2] = bo->paddr + fb->offsets[2];
446 mb->plane.planes[2] = 0;
448 /* Special case the YUV420 with U and V as line interleaved
449 * planes as we have special handling for that case.
451 if (num_planes == 3 &&
452 (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1])
453 mb->plane.vc_image_type = VC_IMAGE_YUV420_S;
455 mb->plane.planes[1] = 0;
456 mb->plane.planes[2] = 0;
458 mb->plane.planes[3] = 0;
460 switch (fb->modifier) {
461 case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
462 switch (mb->plane.vc_image_type) {
463 case VC_IMAGE_RGBX32:
464 mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32;
466 case VC_IMAGE_RGBA32:
467 mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32;
469 case VC_IMAGE_RGB565:
470 mb->plane.vc_image_type = VC_IMAGE_TF_RGB565;
474 case DRM_FORMAT_MOD_BROADCOM_SAND128:
475 mb->plane.vc_image_type = VC_IMAGE_YUV_UV;
476 mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier);
480 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n",
481 plane->base.id, plane->name,
484 mb->plane.vc_image_type,
498 state->normalized_zpos);
501 * Do NOT set now, as we haven't checked if the crtc is active or not.
502 * Set from vc4_plane_set_blank instead.
504 * If the CRTC is on (or going to be on) and we're enabled,
505 * then unblank. Otherwise, stay blank until CRTC enable.
507 if (state->crtc->state->active)
508 vc4_plane_set_blank(plane, false);
511 static void vc4_plane_atomic_disable(struct drm_plane *plane,
512 struct drm_plane_state *old_state)
514 //struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
515 struct drm_plane_state *state = plane->state;
516 struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
518 DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n",
519 plane->base.id, plane->name,
522 vc4_plane->mb.plane.vc_image_type,
525 vc4_plane_set_blank(plane, true);
528 static int vc4_plane_atomic_check(struct drm_plane *plane,
529 struct drm_plane_state *state)
534 static void vc4_plane_destroy(struct drm_plane *plane)
536 drm_plane_cleanup(plane);
539 static bool vc4_fkms_format_mod_supported(struct drm_plane *plane,
543 /* Support T_TILING for RGB formats only. */
545 case DRM_FORMAT_XRGB8888:
546 case DRM_FORMAT_ARGB8888:
547 case DRM_FORMAT_RGB565:
549 case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED:
550 case DRM_FORMAT_MOD_LINEAR:
551 case DRM_FORMAT_MOD_BROADCOM_UIF:
556 case DRM_FORMAT_NV12:
557 switch (fourcc_mod_broadcom_mod(modifier)) {
558 case DRM_FORMAT_MOD_LINEAR:
559 case DRM_FORMAT_MOD_BROADCOM_SAND128:
564 case DRM_FORMAT_NV21:
565 case DRM_FORMAT_RGB888:
566 case DRM_FORMAT_BGR888:
567 case DRM_FORMAT_YUV422:
568 case DRM_FORMAT_YUV420:
569 case DRM_FORMAT_YVU420:
571 return (modifier == DRM_FORMAT_MOD_LINEAR);
575 static const struct drm_plane_funcs vc4_plane_funcs = {
576 .update_plane = drm_atomic_helper_update_plane,
577 .disable_plane = drm_atomic_helper_disable_plane,
578 .destroy = vc4_plane_destroy,
579 .set_property = NULL,
580 .reset = drm_atomic_helper_plane_reset,
581 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
582 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
583 .format_mod_supported = vc4_fkms_format_mod_supported,
586 static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
587 .prepare_fb = drm_gem_fb_prepare_fb,
589 .atomic_check = vc4_plane_atomic_check,
590 .atomic_update = vc4_plane_atomic_update,
591 .atomic_disable = vc4_plane_atomic_disable,
594 static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev,
595 enum drm_plane_type type,
599 struct drm_plane *plane = NULL;
600 struct vc4_fkms_plane *vc4_plane;
601 u32 formats[ARRAY_SIZE(vc_image_formats)];
602 unsigned int default_zpos = 0;
605 static const uint64_t modifiers[] = {
606 DRM_FORMAT_MOD_LINEAR,
607 /* VC4_T_TILED should come after linear, because we
608 * would prefer to scan out linear (less bus traffic).
610 DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
611 DRM_FORMAT_MOD_BROADCOM_SAND128,
612 DRM_FORMAT_MOD_INVALID,
616 vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
623 for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++)
624 formats[num_formats++] = vc_image_formats[i].drm;
626 plane = &vc4_plane->base;
627 ret = drm_universal_plane_init(dev, plane, 0xff,
629 formats, num_formats, modifiers,
632 /* FIXME: Do we need to be checking return values from all these calls?
634 drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
636 drm_plane_create_alpha_property(plane);
637 drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
638 SUPPORTED_ROTATIONS);
641 * Default frame buffer setup is with FB on -127, and raspistill etc
642 * tend to drop overlays on layer 2. Cursor plane was on layer +127.
644 * For F-KMS the mailbox call allows for a s8.
645 * Remap zpos 0 to -127 for the background layer, but leave all the
646 * other layers as requested by KMS.
649 case DRM_PLANE_TYPE_PRIMARY:
652 case DRM_PLANE_TYPE_OVERLAY:
655 case DRM_PLANE_TYPE_CURSOR:
659 drm_plane_create_zpos_property(plane, default_zpos, 0, 127);
661 /* Prepare the static elements of the mailbox structure */
662 vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE;
663 vc4_plane->mb.tag.buf_size = sizeof(struct set_plane);
664 vc4_plane->mb.tag.req_resp_size = 0;
665 vc4_plane->mb.plane.display = display_num;
666 vc4_plane->mb.plane.plane_id = plane_id;
667 vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127;
672 vc4_plane_destroy(plane);
677 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
679 struct drm_device *dev = crtc->dev;
680 struct vc4_dev *vc4 = to_vc4_dev(dev);
681 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
682 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
683 struct vc4_fkms_encoder *vc4_encoder =
684 to_vc4_fkms_encoder(vc4_crtc->encoder);
685 struct mailbox_set_mode mb = {
686 .tag1 = { RPI_FIRMWARE_SET_TIMING,
687 sizeof(struct set_timings), 0},
689 union hdmi_infoframe frame;
692 ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, vc4_crtc->connector, mode);
694 DRM_ERROR("couldn't fill AVI infoframe\n");
698 DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u, flags 0x%04x\n",
699 vc4_crtc->display_number, mode->name, mode->clock,
700 mode->hdisplay, mode->hsync_start, mode->hsync_end,
701 mode->htotal, mode->hskew, mode->vdisplay,
702 mode->vsync_start, mode->vsync_end, mode->vtotal,
703 mode->vscan, mode->vrefresh, mode->picture_aspect_ratio,
705 mb.timings.display = vc4_crtc->display_number;
707 mb.timings.video_id_code = frame.avi.video_code;
709 mb.timings.clock = mode->clock;
710 mb.timings.hdisplay = mode->hdisplay;
711 mb.timings.hsync_start = mode->hsync_start;
712 mb.timings.hsync_end = mode->hsync_end;
713 mb.timings.htotal = mode->htotal;
714 mb.timings.hskew = mode->hskew;
715 mb.timings.vdisplay = mode->vdisplay;
716 mb.timings.vsync_start = mode->vsync_start;
717 mb.timings.vsync_end = mode->vsync_end;
718 mb.timings.vtotal = mode->vtotal;
719 mb.timings.vscan = mode->vscan;
720 mb.timings.vrefresh = 0;
721 mb.timings.flags = 0;
722 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
723 mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
724 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
725 mb.timings.flags |= TIMINGS_FLAGS_V_SYNC_POS;
727 switch (frame.avi.picture_aspect) {
729 case HDMI_PICTURE_ASPECT_NONE:
730 mb.timings.flags |= TIMINGS_FLAGS_ASPECT_NONE;
732 case HDMI_PICTURE_ASPECT_4_3:
733 mb.timings.flags |= TIMINGS_FLAGS_ASPECT_4_3;
735 case HDMI_PICTURE_ASPECT_16_9:
736 mb.timings.flags |= TIMINGS_FLAGS_ASPECT_16_9;
738 case HDMI_PICTURE_ASPECT_64_27:
739 mb.timings.flags |= TIMINGS_FLAGS_ASPECT_64_27;
741 case HDMI_PICTURE_ASPECT_256_135:
742 mb.timings.flags |= TIMINGS_FLAGS_ASPECT_256_135;
746 if (!vc4_encoder->hdmi_monitor)
747 mb.timings.flags |= TIMINGS_FLAGS_DVI;
748 else if (drm_default_rgb_quant_range(mode) ==
749 HDMI_QUANTIZATION_RANGE_LIMITED)
750 mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
754 switch(mode->flag & DRM_MODE_FLAG_3D_MASK) {
755 case DRM_MODE_FLAG_3D_NONE:
756 case DRM_MODE_FLAG_3D_FRAME_PACKING:
757 case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
758 case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
759 case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
760 case DRM_MODE_FLAG_3D_L_DEPTH:
761 case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
762 case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
763 case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
767 ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
770 static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
772 struct drm_plane *plane;
774 DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
776 drm_crtc_vblank_off(crtc);
778 /* Always turn the planes off on CRTC disable. In DRM, planes
779 * are enabled/disabled through the update/disable hooks
780 * above, and the CRTC enable/disable independently controls
781 * whether anything scans out at all, but the firmware doesn't
782 * give us a CRTC-level control for that.
785 drm_atomic_crtc_for_each_plane(plane, crtc)
786 vc4_plane_atomic_disable(plane, plane->state);
789 static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
791 struct drm_plane *plane;
793 DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
795 drm_crtc_vblank_on(crtc);
797 /* Unblank the planes (if they're supposed to be displayed). */
798 drm_atomic_crtc_for_each_plane(plane, crtc)
799 if (plane->state->fb)
800 vc4_plane_set_blank(plane, plane->state->visible);
803 static enum drm_mode_status
804 vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
806 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
807 struct drm_device *dev = crtc->dev;
808 struct vc4_dev *vc4 = to_vc4_dev(dev);
809 struct vc4_fkms *fkms = vc4->fkms;
811 /* Do not allow doublescan modes from user space */
812 if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
813 DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
815 return MODE_NO_DBLESCAN;
818 /* Limit the pixel clock based on the HDMI clock limits from the
821 switch (vc4_crtc->display_number) {
823 if (fkms->cfg.max_pixel_clock[0] &&
824 mode->clock > fkms->cfg.max_pixel_clock[0])
825 return MODE_CLOCK_HIGH;
828 if (fkms->cfg.max_pixel_clock[1] &&
829 mode->clock > fkms->cfg.max_pixel_clock[1])
830 return MODE_CLOCK_HIGH;
834 /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
837 if (mode->clock > 340000)
838 return MODE_CLOCK_HIGH;
843 static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
844 struct drm_crtc_state *state)
846 DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
851 static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
852 struct drm_crtc_state *old_state)
854 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
855 struct drm_device *dev = crtc->dev;
857 DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
859 if (crtc->state->event) {
862 crtc->state->event->pipe = drm_crtc_index(crtc);
864 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
866 spin_lock_irqsave(&dev->event_lock, flags);
867 vc4_crtc->event = crtc->state->event;
868 crtc->state->event = NULL;
869 spin_unlock_irqrestore(&dev->event_lock, flags);
873 static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
875 struct drm_crtc *crtc = &vc4_crtc->base;
876 struct drm_device *dev = crtc->dev;
879 spin_lock_irqsave(&dev->event_lock, flags);
880 if (vc4_crtc->event) {
881 drm_crtc_send_vblank_event(crtc, vc4_crtc->event);
882 vc4_crtc->event = NULL;
883 drm_crtc_vblank_put(crtc);
885 spin_unlock_irqrestore(&dev->event_lock, flags);
888 static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
890 struct vc4_crtc **crtc_list = data;
892 u32 stat = readl(crtc_list[0]->regs + SMICS);
893 irqreturn_t ret = IRQ_NONE;
895 if (stat & SMICS_INTERRUPTS) {
896 writel(0, crtc_list[0]->regs + SMICS);
898 for (i = 0; crtc_list[i]; i++) {
899 if (crtc_list[i]->vblank_enabled)
900 drm_crtc_handle_vblank(&crtc_list[i]->base);
901 vc4_crtc_handle_page_flip(crtc_list[i]);
909 static int vc4_page_flip(struct drm_crtc *crtc,
910 struct drm_framebuffer *fb,
911 struct drm_pending_vblank_event *event,
912 uint32_t flags, struct drm_modeset_acquire_ctx *ctx)
914 if (flags & DRM_MODE_PAGE_FLIP_ASYNC) {
915 DRM_ERROR("Async flips aren't allowed\n");
919 return drm_atomic_helper_page_flip(crtc, fb, event, flags, ctx);
922 static int vc4_fkms_enable_vblank(struct drm_crtc *crtc)
924 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
926 DRM_DEBUG_KMS("[CRTC:%d] enable_vblank.\n",
928 vc4_crtc->vblank_enabled = true;
933 static void vc4_fkms_disable_vblank(struct drm_crtc *crtc)
935 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
937 DRM_DEBUG_KMS("[CRTC:%d] disable_vblank.\n",
939 vc4_crtc->vblank_enabled = false;
942 static const struct drm_crtc_funcs vc4_crtc_funcs = {
943 .set_config = drm_atomic_helper_set_config,
944 .destroy = drm_crtc_cleanup,
945 .page_flip = vc4_page_flip,
946 .set_property = NULL,
947 .cursor_set = NULL, /* handled by drm_mode_cursor_universal */
948 .cursor_move = NULL, /* handled by drm_mode_cursor_universal */
949 .reset = drm_atomic_helper_crtc_reset,
950 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
951 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
952 .enable_vblank = vc4_fkms_enable_vblank,
953 .disable_vblank = vc4_fkms_disable_vblank,
956 static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
957 .mode_set_nofb = vc4_crtc_mode_set_nofb,
958 .mode_valid = vc4_crtc_mode_valid,
959 .atomic_check = vc4_crtc_atomic_check,
960 .atomic_flush = vc4_crtc_atomic_flush,
961 .atomic_enable = vc4_crtc_enable,
962 .atomic_disable = vc4_crtc_disable,
965 static const struct of_device_id vc4_firmware_kms_dt_match[] = {
966 { .compatible = "raspberrypi,rpi-firmware-kms" },
970 static enum drm_connector_status
971 vc4_fkms_connector_detect(struct drm_connector *connector, bool force)
973 DRM_DEBUG_KMS("connector detect.\n");
974 return connector_status_connected;
977 static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
980 struct vc4_fkms_connector *fkms_connector =
981 (struct vc4_fkms_connector *)data;
982 struct vc4_dev *vc4 = fkms_connector->vc4_dev;
983 struct mailbox_get_edid mb = {
984 .tag1 = { RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY,
987 .display_number = fkms_connector->display_number,
991 ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
994 memcpy(buf, mb.edid, len);
999 static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
1001 struct vc4_fkms_connector *fkms_connector =
1002 to_vc4_fkms_connector(connector);
1003 struct drm_encoder *encoder = fkms_connector->encoder;
1004 struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
1008 edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
1011 /* FIXME: Can we do CEC?
1012 * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
1017 vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
1019 drm_connector_update_edid_property(connector, edid);
1020 ret = drm_add_edid_modes(connector, edid);
1026 /* This is the DSI panel resolution. Use this as a default should the firmware
1027 * not respond to our request for the timings.
1029 static const struct drm_display_mode lcd_mode = {
1030 DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
1032 800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
1033 480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
1037 static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
1039 struct vc4_fkms_connector *fkms_connector =
1040 to_vc4_fkms_connector(connector);
1041 struct vc4_dev *vc4 = fkms_connector->vc4_dev;
1042 struct drm_display_mode *mode;
1043 struct mailbox_set_mode mb = {
1044 .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
1045 sizeof(struct set_timings), 0},
1046 .timings = { .display = fkms_connector->display_number },
1048 struct drm_display_mode fw_mode;
1051 ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
1053 /* Equivalent to DRM_MODE macro. */
1054 memset(&fw_mode, 0, sizeof(fw_mode));
1055 strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
1057 fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
1058 fw_mode.clock = mb.timings.clock;
1059 fw_mode.hdisplay = mb.timings.hdisplay;
1060 fw_mode.hsync_start = mb.timings.hsync_start;
1061 fw_mode.hsync_end = mb.timings.hsync_end;
1062 fw_mode.htotal = mb.timings.htotal;
1064 fw_mode.vdisplay = mb.timings.vdisplay;
1065 fw_mode.vsync_start = mb.timings.vsync_start;
1066 fw_mode.vsync_end = mb.timings.vsync_end;
1067 fw_mode.vtotal = mb.timings.vtotal;
1068 fw_mode.vscan = mb.timings.vscan;
1069 if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
1070 fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
1072 fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
1073 if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
1074 fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
1076 fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
1077 if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
1078 fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
1080 fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
1081 if (mb.timings.flags & TIMINGS_FLAGS_INTERLACE)
1082 fw_mode.flags |= DRM_MODE_FLAG_INTERLACE;
1084 mode = drm_mode_duplicate(connector->dev,
1087 mode = drm_mode_duplicate(connector->dev,
1092 DRM_ERROR("Failed to create a new display mode\n");
1096 drm_mode_probed_add(connector, mode);
1098 /* We have one mode */
1102 static struct drm_encoder *
1103 vc4_fkms_connector_best_encoder(struct drm_connector *connector)
1105 struct vc4_fkms_connector *fkms_connector =
1106 to_vc4_fkms_connector(connector);
1107 DRM_DEBUG_KMS("best_connector.\n");
1108 return fkms_connector->encoder;
1111 static void vc4_fkms_connector_destroy(struct drm_connector *connector)
1113 DRM_DEBUG_KMS("[CONNECTOR:%d] destroy.\n",
1114 connector->base.id);
1115 drm_connector_unregister(connector);
1116 drm_connector_cleanup(connector);
1119 static const struct drm_connector_funcs vc4_fkms_connector_funcs = {
1120 .detect = vc4_fkms_connector_detect,
1121 .fill_modes = drm_helper_probe_single_connector_modes,
1122 .destroy = vc4_fkms_connector_destroy,
1123 .reset = drm_atomic_helper_connector_reset,
1124 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1125 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1128 static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = {
1129 .get_modes = vc4_fkms_connector_get_modes,
1130 .best_encoder = vc4_fkms_connector_best_encoder,
1133 static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs = {
1134 .get_modes = vc4_fkms_lcd_connector_get_modes,
1135 .best_encoder = vc4_fkms_connector_best_encoder,
1138 static struct drm_connector *
1139 vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
1142 struct drm_connector *connector = NULL;
1143 struct vc4_fkms_connector *fkms_connector;
1144 struct vc4_dev *vc4_dev = to_vc4_dev(dev);
1147 DRM_DEBUG_KMS("connector_init, display_num %u\n", display_num);
1149 fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
1151 if (!fkms_connector) {
1155 connector = &fkms_connector->base;
1157 fkms_connector->encoder = encoder;
1158 fkms_connector->display_number = display_num;
1159 fkms_connector->display_type = vc4_get_display_type(display_num);
1160 fkms_connector->vc4_dev = vc4_dev;
1162 if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
1163 drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
1164 DRM_MODE_CONNECTOR_DSI);
1165 drm_connector_helper_add(connector,
1166 &vc4_fkms_lcd_conn_helper_funcs);
1167 connector->interlace_allowed = 0;
1168 } else if (fkms_connector->display_type == DRM_MODE_ENCODER_TVDAC) {
1169 drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
1170 DRM_MODE_CONNECTOR_Composite);
1171 drm_connector_helper_add(connector,
1172 &vc4_fkms_lcd_conn_helper_funcs);
1173 connector->interlace_allowed = 1;
1175 drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
1176 DRM_MODE_CONNECTOR_HDMIA);
1177 drm_connector_helper_add(connector,
1178 &vc4_fkms_connector_helper_funcs);
1179 connector->interlace_allowed = 0;
1182 connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
1183 DRM_CONNECTOR_POLL_DISCONNECT);
1185 connector->doublescan_allowed = 0;
1187 drm_connector_attach_encoder(connector, encoder);
1193 vc4_fkms_connector_destroy(connector);
1195 return ERR_PTR(ret);
1198 static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder)
1200 DRM_DEBUG_KMS("Encoder_destroy\n");
1201 drm_encoder_cleanup(encoder);
1204 static const struct drm_encoder_funcs vc4_fkms_encoder_funcs = {
1205 .destroy = vc4_fkms_encoder_destroy,
1208 static void vc4_fkms_encoder_enable(struct drm_encoder *encoder)
1210 DRM_DEBUG_KMS("Encoder_enable\n");
1213 static void vc4_fkms_encoder_disable(struct drm_encoder *encoder)
1215 DRM_DEBUG_KMS("Encoder_disable\n");
1218 static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = {
1219 .enable = vc4_fkms_encoder_enable,
1220 .disable = vc4_fkms_encoder_disable,
1223 static int vc4_fkms_create_screen(struct device *dev, struct drm_device *drm,
1224 int display_idx, int display_ref,
1225 struct vc4_crtc **ret_crtc)
1227 struct vc4_dev *vc4 = to_vc4_dev(drm);
1228 struct vc4_crtc *vc4_crtc;
1229 struct vc4_fkms_encoder *vc4_encoder;
1230 struct drm_crtc *crtc;
1231 struct drm_plane *primary_plane, *overlay_plane, *cursor_plane;
1232 struct drm_plane *destroy_plane, *temp;
1233 struct mailbox_blank_display blank = {
1234 .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
1235 .display = display_idx,
1236 .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_BLANK, 4, 0, },
1241 vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
1244 crtc = &vc4_crtc->base;
1246 vc4_crtc->display_number = display_ref;
1247 vc4_crtc->display_type = vc4_get_display_type(display_ref);
1249 /* Blank the firmware provided framebuffer */
1250 rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
1252 primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY,
1254 0 + (display_idx * PLANES_PER_CRTC)
1256 if (IS_ERR(primary_plane)) {
1257 dev_err(dev, "failed to construct primary plane\n");
1258 ret = PTR_ERR(primary_plane);
1262 overlay_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
1264 1 + (display_idx * PLANES_PER_CRTC)
1266 if (IS_ERR(overlay_plane)) {
1267 dev_err(dev, "failed to construct overlay plane\n");
1268 ret = PTR_ERR(overlay_plane);
1272 cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
1274 2 + (display_idx * PLANES_PER_CRTC)
1276 if (IS_ERR(cursor_plane)) {
1277 dev_err(dev, "failed to construct cursor plane\n");
1278 ret = PTR_ERR(cursor_plane);
1282 drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane,
1283 &vc4_crtc_funcs, NULL);
1284 drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
1286 vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL);
1289 vc4_crtc->encoder = &vc4_encoder->base;
1290 vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ;
1292 drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs,
1293 vc4_crtc->display_type, NULL);
1294 drm_encoder_helper_add(&vc4_encoder->base,
1295 &vc4_fkms_encoder_helper_funcs);
1297 vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
1299 if (IS_ERR(vc4_crtc->connector)) {
1300 ret = PTR_ERR(vc4_crtc->connector);
1301 goto err_destroy_encoder;
1304 *ret_crtc = vc4_crtc;
1308 err_destroy_encoder:
1309 vc4_fkms_encoder_destroy(vc4_crtc->encoder);
1310 list_for_each_entry_safe(destroy_plane, temp,
1311 &drm->mode_config.plane_list, head) {
1312 if (destroy_plane->possible_crtcs == 1 << drm_crtc_index(crtc))
1313 destroy_plane->funcs->destroy(destroy_plane);
1319 static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
1321 struct platform_device *pdev = to_platform_device(dev);
1322 struct drm_device *drm = dev_get_drvdata(master);
1323 struct vc4_dev *vc4 = to_vc4_dev(drm);
1324 struct device_node *firmware_node;
1325 struct vc4_crtc **crtc_list;
1326 u32 num_displays, display_num;
1327 struct vc4_fkms *fkms;
1331 vc4->firmware_kms = true;
1333 fkms = devm_kzalloc(dev, sizeof(*fkms), GFP_KERNEL);
1337 /* firmware kms doesn't have precise a scanoutpos implementation, so
1338 * we can't do the precise vblank timestamp mode.
1340 drm->driver->get_scanout_position = NULL;
1341 drm->driver->get_vblank_timestamp = NULL;
1343 firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
1344 vc4->firmware = rpi_firmware_get(firmware_node);
1345 if (!vc4->firmware) {
1346 DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n");
1347 return -EPROBE_DEFER;
1349 of_node_put(firmware_node);
1351 ret = rpi_firmware_property(vc4->firmware,
1352 RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
1353 &num_displays, sizeof(u32));
1355 /* If we fail to get the number of displays, then
1356 * assume old firmware that doesn't have the mailbox call, so just
1361 DRM_WARN("Unable to determine number of displays - assuming 1\n");
1365 ret = rpi_firmware_property(vc4->firmware,
1366 RPI_FIRMWARE_GET_DISPLAY_CFG,
1367 &fkms->cfg, sizeof(fkms->cfg));
1371 /* The firmware works in Hz. This will be compared against kHz, so div
1372 * 1000 now rather than multiple times later.
1374 fkms->cfg.max_pixel_clock[0] /= 1000;
1375 fkms->cfg.max_pixel_clock[1] /= 1000;
1377 /* Allocate a list, with space for a NULL on the end */
1378 crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
1383 for (display_num = 0; display_num < num_displays; display_num++) {
1384 display_id = display_num;
1385 ret = rpi_firmware_property(vc4->firmware,
1386 RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID,
1387 &display_id, sizeof(display_id));
1388 /* FIXME: Determine the correct error handling here.
1389 * Should we fail to create the one "screen" but keep the
1390 * others, or fail the whole thing?
1393 DRM_ERROR("Failed to get display id %u\n", display_num);
1395 ret = vc4_fkms_create_screen(dev, drm, display_num, display_id,
1396 &crtc_list[display_num]);
1398 DRM_ERROR("Oh dear, failed to create display %u\n",
1402 if (num_displays > 0) {
1403 /* Map the SMI interrupt reg */
1404 crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0);
1405 if (IS_ERR(crtc_list[0]->regs))
1406 DRM_ERROR("Oh dear, failed to map registers\n");
1408 writel(0, crtc_list[0]->regs + SMICS);
1409 ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
1410 vc4_crtc_irq_handler, 0,
1411 "vc4 firmware kms", crtc_list);
1413 DRM_ERROR("Oh dear, failed to register IRQ\n");
1415 DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
1420 platform_set_drvdata(pdev, crtc_list);
1425 static void vc4_fkms_unbind(struct device *dev, struct device *master,
1428 struct platform_device *pdev = to_platform_device(dev);
1429 struct vc4_crtc **crtc_list = dev_get_drvdata(dev);
1432 for (i = 0; crtc_list[i]; i++) {
1433 vc4_fkms_connector_destroy(crtc_list[i]->connector);
1434 vc4_fkms_encoder_destroy(crtc_list[i]->encoder);
1435 drm_crtc_cleanup(&crtc_list[i]->base);
1438 platform_set_drvdata(pdev, NULL);
1441 static const struct component_ops vc4_fkms_ops = {
1442 .bind = vc4_fkms_bind,
1443 .unbind = vc4_fkms_unbind,
1446 static int vc4_fkms_probe(struct platform_device *pdev)
1448 return component_add(&pdev->dev, &vc4_fkms_ops);
1451 static int vc4_fkms_remove(struct platform_device *pdev)
1453 component_del(&pdev->dev, &vc4_fkms_ops);
1457 struct platform_driver vc4_firmware_kms_driver = {
1458 .probe = vc4_fkms_probe,
1459 .remove = vc4_fkms_remove,
1461 .name = "vc4_firmware_kms",
1462 .of_match_table = vc4_firmware_kms_dt_match,