| From 52add140c76c0a211ab340ced8e7e1ea8bef9c79 Mon Sep 17 00:00:00 2001 |
| From: Dave Stevenson <dave.stevenson@raspberrypi.org> |
| Date: Tue, 9 Apr 2019 18:23:41 +0100 |
| Subject: [PATCH] drm: vc4: FKMS reads the EDID from fw, and supports |
| mode setting |
| |
| This extends FKMS to read the EDID from the display, and support |
| requesting a particular mode via KMS. |
| |
| Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org> |
| --- |
| drivers/gpu/drm/vc4/vc4_firmware_kms.c | 334 ++++++++++++++++++--- |
| include/soc/bcm2835/raspberrypi-firmware.h | 2 + |
| 2 files changed, 302 insertions(+), 34 deletions(-) |
| |
| --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c |
| +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c |
| @@ -91,11 +91,60 @@ struct mailbox_blank_display { |
| u32 blank; |
| }; |
| |
| -struct mailbox_get_width_height { |
| +struct mailbox_get_edid { |
| struct rpi_firmware_property_tag_header tag1; |
| - u32 display; |
| - struct rpi_firmware_property_tag_header tag2; |
| - u32 wh[2]; |
| + u32 block; |
| + u32 display_number; |
| + u8 edid[128]; |
| +}; |
| + |
| +struct set_timings { |
| + u8 display; |
| + u8 padding; |
| + u16 video_id_code; |
| + |
| + u32 clock; /* in kHz */ |
| + |
| + u16 hdisplay; |
| + u16 hsync_start; |
| + |
| + u16 hsync_end; |
| + u16 htotal; |
| + |
| + u16 hskew; |
| + u16 vdisplay; |
| + |
| + u16 vsync_start; |
| + u16 vsync_end; |
| + |
| + u16 vtotal; |
| + u16 vscan; |
| + |
| + u16 vrefresh; |
| + u16 padding2; |
| + |
| + u32 flags; |
| +#define TIMINGS_FLAGS_H_SYNC_POS BIT(0) |
| +#define TIMINGS_FLAGS_H_SYNC_NEG 0 |
| +#define TIMINGS_FLAGS_V_SYNC_POS BIT(1) |
| +#define TIMINGS_FLAGS_V_SYNC_NEG 0 |
| + |
| +#define TIMINGS_FLAGS_ASPECT_MASK GENMASK(7, 4) |
| +#define TIMINGS_FLAGS_ASPECT_NONE (0 << 4) |
| +#define TIMINGS_FLAGS_ASPECT_4_3 (1 << 4) |
| +#define TIMINGS_FLAGS_ASPECT_16_9 (2 << 4) |
| +#define TIMINGS_FLAGS_ASPECT_64_27 (3 << 4) |
| +#define TIMINGS_FLAGS_ASPECT_256_135 (4 << 4) |
| + |
| +/* Limited range RGB flag. Not set corresponds to full range. */ |
| +#define TIMINGS_FLAGS_RGB_LIMITED BIT(8) |
| +/* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */ |
| +#define TIMINGS_FLAGS_DVI BIT(9) |
| +}; |
| + |
| +struct mailbox_set_mode { |
| + struct rpi_firmware_property_tag_header tag1; |
| + struct set_timings timings; |
| }; |
| |
| static const struct vc_image_format { |
| @@ -189,6 +238,7 @@ struct vc4_crtc { |
| u32 overscan[4]; |
| bool vblank_enabled; |
| u32 display_number; |
| + u32 display_type; |
| }; |
| |
| static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc) |
| @@ -198,6 +248,8 @@ static inline struct vc4_crtc *to_vc4_cr |
| |
| struct vc4_fkms_encoder { |
| struct drm_encoder base; |
| + bool hdmi_monitor; |
| + bool rgb_range_selectable; |
| }; |
| |
| static inline struct vc4_fkms_encoder * |
| @@ -215,7 +267,9 @@ struct vc4_fkms_connector { |
| * hook. |
| */ |
| struct drm_encoder *encoder; |
| - u32 display_idx; |
| + struct vc4_dev *vc4_dev; |
| + u32 display_number; |
| + u32 display_type; |
| }; |
| |
| static inline struct vc4_fkms_connector * |
| @@ -224,6 +278,26 @@ to_vc4_fkms_connector(struct drm_connect |
| return container_of(connector, struct vc4_fkms_connector, base); |
| } |
| |
| +static u32 vc4_get_display_type(u32 display_number) |
| +{ |
| + const u32 display_types[] = { |
| + /* The firmware display (DispmanX) IDs map to specific types in |
| + * a fixed manner. |
| + */ |
| + DRM_MODE_ENCODER_DSI, /* MAIN_LCD */ |
| + DRM_MODE_ENCODER_DSI, /* AUX_LCD */ |
| + DRM_MODE_ENCODER_TMDS, /* HDMI0 */ |
| + DRM_MODE_ENCODER_TVDAC, /* VEC */ |
| + DRM_MODE_ENCODER_NONE, /* FORCE_LCD */ |
| + DRM_MODE_ENCODER_NONE, /* FORCE_TV */ |
| + DRM_MODE_ENCODER_NONE, /* FORCE_OTHER */ |
| + DRM_MODE_ENCODER_TMDS, /* HDMI1 */ |
| + DRM_MODE_ENCODER_NONE, /* FORCE_TV2 */ |
| + }; |
| + return display_number > ARRAY_SIZE(display_types) - 1 ? |
| + DRM_MODE_ENCODER_NONE : display_types[display_number]; |
| +} |
| + |
| /* Firmware's structure for making an FB mbox call. */ |
| struct fbinfo_s { |
| u32 xres, yres, xres_virtual, yres_virtual; |
| @@ -258,10 +332,15 @@ static int vc4_plane_set_blank(struct dr |
| .plane_id = vc4_plane->mb.plane.plane_id, |
| } |
| }; |
| + static const char * const plane_types[] = { |
| + "overlay", |
| + "primary", |
| + "cursor" |
| + }; |
| int ret; |
| |
| - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s", |
| - plane->base.id, plane->name, |
| + DRM_DEBUG_ATOMIC("[PLANE:%d:%s] %s plane %s", |
| + plane->base.id, plane->name, plane_types[plane->type], |
| blank ? "blank" : "unblank"); |
| |
| if (blank) |
| @@ -595,13 +674,102 @@ fail: |
| |
| static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) |
| { |
| - /* Everyting is handled in the planes. */ |
| + struct drm_device *dev = crtc->dev; |
| + struct vc4_dev *vc4 = to_vc4_dev(dev); |
| + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); |
| + struct drm_display_mode *mode = &crtc->state->adjusted_mode; |
| + struct vc4_fkms_encoder *vc4_encoder = |
| + to_vc4_fkms_encoder(vc4_crtc->encoder); |
| + struct mailbox_set_mode mb = { |
| + .tag1 = { RPI_FIRMWARE_SET_TIMING, |
| + sizeof(struct set_timings), 0}, |
| + }; |
| + union hdmi_infoframe frame; |
| + int ret; |
| + |
| + ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, vc4_crtc->connector, mode); |
| + if (ret < 0) { |
| + DRM_ERROR("couldn't fill AVI infoframe\n"); |
| + return; |
| + } |
| + |
| + 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\n", |
| + vc4_crtc->display_number, mode->name, mode->clock, |
| + mode->hdisplay, mode->hsync_start, mode->hsync_end, |
| + mode->htotal, mode->hskew, mode->vdisplay, |
| + mode->vsync_start, mode->vsync_end, mode->vtotal, |
| + mode->vscan, mode->vrefresh, mode->picture_aspect_ratio); |
| + mb.timings.display = vc4_crtc->display_number; |
| + |
| + mb.timings.video_id_code = frame.avi.video_code; |
| + |
| + mb.timings.clock = mode->clock; |
| + mb.timings.hdisplay = mode->hdisplay; |
| + mb.timings.hsync_start = mode->hsync_start; |
| + mb.timings.hsync_end = mode->hsync_end; |
| + mb.timings.htotal = mode->htotal; |
| + mb.timings.hskew = mode->hskew; |
| + mb.timings.vdisplay = mode->vdisplay; |
| + mb.timings.vsync_start = mode->vsync_start; |
| + mb.timings.vsync_end = mode->vsync_end; |
| + mb.timings.vtotal = mode->vtotal; |
| + mb.timings.vscan = mode->vscan; |
| + mb.timings.vrefresh = 0; |
| + mb.timings.flags = 0; |
| + if (mode->flags & DRM_MODE_FLAG_PHSYNC) |
| + mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS; |
| + if (mode->flags & DRM_MODE_FLAG_PVSYNC) |
| + mb.timings.flags |= TIMINGS_FLAGS_V_SYNC_POS; |
| + |
| + switch (frame.avi.picture_aspect) { |
| + default: |
| + case HDMI_PICTURE_ASPECT_NONE: |
| + mode->flags |= TIMINGS_FLAGS_ASPECT_NONE; |
| + break; |
| + case HDMI_PICTURE_ASPECT_4_3: |
| + mode->flags |= TIMINGS_FLAGS_ASPECT_4_3; |
| + break; |
| + case HDMI_PICTURE_ASPECT_16_9: |
| + mode->flags |= TIMINGS_FLAGS_ASPECT_16_9; |
| + break; |
| + case HDMI_PICTURE_ASPECT_64_27: |
| + mode->flags |= TIMINGS_FLAGS_ASPECT_64_27; |
| + break; |
| + case HDMI_PICTURE_ASPECT_256_135: |
| + mode->flags |= TIMINGS_FLAGS_ASPECT_256_135; |
| + break; |
| + } |
| + |
| + if (!vc4_encoder->hdmi_monitor) |
| + mb.timings.flags |= TIMINGS_FLAGS_DVI; |
| + else if (drm_default_rgb_quant_range(mode) == |
| + HDMI_QUANTIZATION_RANGE_LIMITED) |
| + mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED; |
| + |
| + /* |
| + FIXME: To implement |
| + switch(mode->flag & DRM_MODE_FLAG_3D_MASK) { |
| + case DRM_MODE_FLAG_3D_NONE: |
| + case DRM_MODE_FLAG_3D_FRAME_PACKING: |
| + case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE: |
| + case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE: |
| + case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL: |
| + case DRM_MODE_FLAG_3D_L_DEPTH: |
| + case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH: |
| + case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: |
| + case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: |
| + } |
| + */ |
| + |
| + ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb)); |
| } |
| |
| static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) |
| { |
| struct drm_plane *plane; |
| |
| + DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n", |
| + crtc->base.id); |
| drm_crtc_vblank_off(crtc); |
| |
| /* Always turn the planes off on CRTC disable. In DRM, planes |
| @@ -619,6 +787,8 @@ static void vc4_crtc_enable(struct drm_c |
| { |
| struct drm_plane *plane; |
| |
| + DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n", |
| + crtc->base.id); |
| drm_crtc_vblank_on(crtc); |
| |
| /* Unblank the planes (if they're supposed to be displayed). */ |
| @@ -637,12 +807,20 @@ vc4_crtc_mode_valid(struct drm_crtc *crt |
| return MODE_NO_DBLESCAN; |
| } |
| |
| + /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling |
| + * working. |
| + */ |
| + if (mode->clock > 340000) |
| + return MODE_CLOCK_HIGH; |
| + |
| return MODE_OK; |
| } |
| |
| static int vc4_crtc_atomic_check(struct drm_crtc *crtc, |
| struct drm_crtc_state *state) |
| { |
| + DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n", |
| + crtc->base.id); |
| return 0; |
| } |
| |
| @@ -652,6 +830,8 @@ static void vc4_crtc_atomic_flush(struct |
| struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); |
| struct drm_device *dev = crtc->dev; |
| |
| + DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n", |
| + crtc->base.id); |
| if (crtc->state->event) { |
| unsigned long flags; |
| |
| @@ -719,6 +899,8 @@ static int vc4_fkms_enable_vblank(struct |
| { |
| struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); |
| |
| + DRM_DEBUG_KMS("[CRTC:%d] enable_vblank.\n", |
| + crtc->base.id); |
| vc4_crtc->vblank_enabled = true; |
| |
| return 0; |
| @@ -728,6 +910,8 @@ static void vc4_fkms_disable_vblank(stru |
| { |
| struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); |
| |
| + DRM_DEBUG_KMS("[CRTC:%d] disable_vblank.\n", |
| + crtc->base.id); |
| vc4_crtc->vblank_enabled = false; |
| } |
| |
| @@ -762,36 +946,92 @@ static const struct of_device_id vc4_fir |
| static enum drm_connector_status |
| vc4_fkms_connector_detect(struct drm_connector *connector, bool force) |
| { |
| + DRM_DEBUG_KMS("connector detect.\n"); |
| return connector_status_connected; |
| } |
| |
| -static int vc4_fkms_connector_get_modes(struct drm_connector *connector) |
| +static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block, |
| + size_t len) |
| { |
| - struct drm_device *dev = connector->dev; |
| struct vc4_fkms_connector *fkms_connector = |
| - to_vc4_fkms_connector(connector); |
| - struct vc4_dev *vc4 = to_vc4_dev(dev); |
| - struct drm_display_mode *mode; |
| - struct mailbox_get_width_height wh = { |
| - .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, }, |
| - .display = fkms_connector->display_idx, |
| - .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT, |
| - 8, 0, }, |
| + (struct vc4_fkms_connector *)data; |
| + struct vc4_dev *vc4 = fkms_connector->vc4_dev; |
| + struct mailbox_get_edid mb = { |
| + .tag1 = { RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY, |
| + 128 + 8, 0 }, |
| + .block = block, |
| + .display_number = fkms_connector->display_number, |
| }; |
| - int ret; |
| + int ret = 0; |
| + |
| + ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb)); |
| + |
| + if (!ret) |
| + memcpy(buf, mb.edid, len); |
| + |
| + return ret; |
| +} |
| + |
| +static int vc4_fkms_connector_get_modes(struct drm_connector *connector) |
| +{ |
| + struct vc4_fkms_connector *fkms_connector = |
| + to_vc4_fkms_connector(connector); |
| + struct drm_encoder *encoder = fkms_connector->encoder; |
| + struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder); |
| + int ret = 0; |
| + struct edid *edid; |
| + |
| + edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block, |
| + fkms_connector); |
| + |
| + /* FIXME: Can we do CEC? |
| + * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid); |
| + * if (!edid) |
| + * return -ENODEV; |
| + */ |
| + |
| + vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); |
| |
| - ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh)); |
| + if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { |
| + vc4_encoder->rgb_range_selectable = |
| + drm_rgb_quant_range_selectable(edid); |
| + } |
| + |
| + drm_connector_update_edid_property(connector, edid); |
| + ret = drm_add_edid_modes(connector, edid); |
| + kfree(edid); |
| + |
| + return ret; |
| +} |
| + |
| +/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */ |
| +static const struct drm_display_mode lcd_mode = { |
| + DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, |
| + 25979400 / 1000, |
| + 800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0, |
| + 480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0, |
| + DRM_MODE_FLAG_INTERLACE) |
| +}; |
| + |
| +static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector) |
| +{ |
| + //struct vc4_fkms_connector *fkms_connector = |
| + // to_vc4_fkms_connector(connector); |
| + //struct drm_encoder *encoder = fkms_connector->encoder; |
| + //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder); |
| + struct drm_display_mode *mode; |
| + //int ret = 0; |
| |
| - if (ret) { |
| - DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n", |
| - ret, wh.wh[0], wh.wh[1]); |
| - return 0; |
| + mode = drm_mode_duplicate(connector->dev, |
| + &lcd_mode); |
| + if (!mode) { |
| + DRM_ERROR("Failed to create a new display mode\n"); |
| + return -ENOMEM; |
| } |
| |
| - mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */, |
| - 0, 0, false); |
| drm_mode_probed_add(connector, mode); |
| |
| + /* We have one mode */ |
| return 1; |
| } |
| |
| @@ -800,11 +1040,14 @@ vc4_fkms_connector_best_encoder(struct d |
| { |
| struct vc4_fkms_connector *fkms_connector = |
| to_vc4_fkms_connector(connector); |
| + DRM_DEBUG_KMS("best_connector.\n"); |
| return fkms_connector->encoder; |
| } |
| |
| static void vc4_fkms_connector_destroy(struct drm_connector *connector) |
| { |
| + DRM_DEBUG_KMS("[CONNECTOR:%d] destroy.\n", |
| + connector->base.id); |
| drm_connector_unregister(connector); |
| drm_connector_cleanup(connector); |
| } |
| @@ -823,14 +1066,22 @@ static const struct drm_connector_helper |
| .best_encoder = vc4_fkms_connector_best_encoder, |
| }; |
| |
| +static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs = { |
| + .get_modes = vc4_fkms_lcd_connector_get_modes, |
| + .best_encoder = vc4_fkms_connector_best_encoder, |
| +}; |
| + |
| static struct drm_connector * |
| vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder, |
| - u32 display_idx) |
| + u32 display_num) |
| { |
| struct drm_connector *connector = NULL; |
| struct vc4_fkms_connector *fkms_connector; |
| + struct vc4_dev *vc4_dev = to_vc4_dev(dev); |
| int ret = 0; |
| |
| + DRM_DEBUG_KMS("connector_init, display_num %u\n", display_num); |
| + |
| fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector), |
| GFP_KERNEL); |
| if (!fkms_connector) { |
| @@ -840,11 +1091,21 @@ vc4_fkms_connector_init(struct drm_devic |
| connector = &fkms_connector->base; |
| |
| fkms_connector->encoder = encoder; |
| - fkms_connector->display_idx = display_idx; |
| - |
| - drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, |
| - DRM_MODE_CONNECTOR_HDMIA); |
| - drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs); |
| + fkms_connector->display_number = display_num; |
| + fkms_connector->display_type = vc4_get_display_type(display_num); |
| + fkms_connector->vc4_dev = vc4_dev; |
| + |
| + if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) { |
| + drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, |
| + DRM_MODE_CONNECTOR_DSI); |
| + drm_connector_helper_add(connector, |
| + &vc4_fkms_lcd_conn_helper_funcs); |
| + } else { |
| + drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, |
| + DRM_MODE_CONNECTOR_HDMIA); |
| + drm_connector_helper_add(connector, |
| + &vc4_fkms_connector_helper_funcs); |
| + } |
| |
| connector->polled = (DRM_CONNECTOR_POLL_CONNECT | |
| DRM_CONNECTOR_POLL_DISCONNECT); |
| @@ -865,6 +1126,7 @@ vc4_fkms_connector_init(struct drm_devic |
| |
| static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder) |
| { |
| + DRM_DEBUG_KMS("Encoder_destroy\n"); |
| drm_encoder_cleanup(encoder); |
| } |
| |
| @@ -874,10 +1136,12 @@ static const struct drm_encoder_funcs vc |
| |
| static void vc4_fkms_encoder_enable(struct drm_encoder *encoder) |
| { |
| + DRM_DEBUG_KMS("Encoder_enable\n"); |
| } |
| |
| static void vc4_fkms_encoder_disable(struct drm_encoder *encoder) |
| { |
| + DRM_DEBUG_KMS("Encoder_disable\n"); |
| } |
| |
| static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = { |
| @@ -909,6 +1173,7 @@ static int vc4_fkms_create_screen(struct |
| crtc = &vc4_crtc->base; |
| |
| vc4_crtc->display_number = display_ref; |
| + vc4_crtc->display_type = vc4_get_display_type(display_ref); |
| |
| /* Blank the firmware provided framebuffer */ |
| rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank)); |
| @@ -952,13 +1217,14 @@ static int vc4_fkms_create_screen(struct |
| return -ENOMEM; |
| vc4_crtc->encoder = &vc4_encoder->base; |
| vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ; |
| + |
| drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs, |
| - DRM_MODE_ENCODER_TMDS, NULL); |
| + vc4_crtc->display_type, NULL); |
| drm_encoder_helper_add(&vc4_encoder->base, |
| &vc4_fkms_encoder_helper_funcs); |
| |
| vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base, |
| - display_idx); |
| + display_ref); |
| if (IS_ERR(vc4_crtc->connector)) { |
| ret = PTR_ERR(vc4_crtc->connector); |
| goto err_destroy_encoder; |
| --- a/include/soc/bcm2835/raspberrypi-firmware.h |
| +++ b/include/soc/bcm2835/raspberrypi-firmware.h |
| @@ -75,6 +75,7 @@ enum rpi_firmware_property_tag { |
| RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, |
| RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, |
| RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, |
| + RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY = 0x00030023, |
| RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, |
| RPI_FIRMWARE_GET_THROTTLED = 0x00030046, |
| RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047, |
| @@ -149,6 +150,7 @@ enum rpi_firmware_property_tag { |
| RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, |
| |
| RPI_FIRMWARE_SET_PLANE = 0x00048015, |
| + RPI_FIRMWARE_SET_TIMING = 0x00048017, |
| |
| RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, |
| RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, |