Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: rcar-du: Use the DRM panel API

Instead of parsing the panel device tree node manually, use the panel
API to delegate panel handling to a panel driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

+50 -44
+1
drivers/gpu/drm/rcar-du/Kconfig
··· 20 20 config DRM_RCAR_LVDS 21 21 bool "R-Car DU LVDS Encoder Support" 22 22 depends on DRM_RCAR_DU 23 + select DRM_PANEL 23 24 help 24 25 Enable support for the R-Car Display Unit embedded LVDS encoders. 25 26
+22
drivers/gpu/drm/rcar-du/rcar_du_encoder.c
··· 16 16 #include <drm/drmP.h> 17 17 #include <drm/drm_crtc.h> 18 18 #include <drm/drm_crtc_helper.h> 19 + #include <drm/drm_panel.h> 19 20 20 21 #include "rcar_du_drv.h" 21 22 #include "rcar_du_encoder.h" ··· 34 33 { 35 34 struct rcar_du_encoder *renc = to_rcar_encoder(encoder); 36 35 36 + if (renc->connector && renc->connector->panel) { 37 + drm_panel_disable(renc->connector->panel); 38 + drm_panel_unprepare(renc->connector->panel); 39 + } 40 + 37 41 if (renc->lvds) 38 42 rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false); 39 43 } ··· 49 43 50 44 if (renc->lvds) 51 45 rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true); 46 + 47 + if (renc->connector && renc->connector->panel) { 48 + drm_panel_prepare(renc->connector->panel); 49 + drm_panel_enable(renc->connector->panel); 50 + } 52 51 } 53 52 54 53 static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder, ··· 100 89 struct rcar_du_encoder *renc = to_rcar_encoder(encoder); 101 90 102 91 rcar_du_crtc_route_output(crtc_state->crtc, renc->output); 92 + 93 + if (!renc->lvds) { 94 + /* 95 + * The DU driver creates connectors only for the outputs of the 96 + * internal LVDS encoders. 97 + */ 98 + renc->connector = NULL; 99 + return; 100 + } 101 + 102 + renc->connector = to_rcar_connector(conn_state->connector); 103 103 } 104 104 105 105 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+3
drivers/gpu/drm/rcar-du/rcar_du_encoder.h
··· 17 17 #include <drm/drm_crtc.h> 18 18 #include <drm/drm_encoder.h> 19 19 20 + struct drm_panel; 20 21 struct rcar_du_device; 21 22 struct rcar_du_hdmienc; 22 23 struct rcar_du_lvdsenc; ··· 33 32 struct rcar_du_encoder { 34 33 struct drm_encoder base; 35 34 enum rcar_du_output output; 35 + struct rcar_du_connector *connector; 36 36 struct rcar_du_hdmienc *hdmi; 37 37 struct rcar_du_lvdsenc *lvds; 38 38 }; ··· 46 44 struct rcar_du_connector { 47 45 struct drm_connector connector; 48 46 struct rcar_du_encoder *encoder; 47 + struct drm_panel *panel; 49 48 }; 50 49 51 50 #define to_rcar_connector(c) \
+24 -44
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
··· 15 15 #include <drm/drm_atomic_helper.h> 16 16 #include <drm/drm_crtc.h> 17 17 #include <drm/drm_crtc_helper.h> 18 + #include <drm/drm_panel.h> 18 19 19 20 #include <video/display_timing.h> 20 21 #include <video/of_display_timing.h> ··· 26 25 #include "rcar_du_kms.h" 27 26 #include "rcar_du_lvdscon.h" 28 27 29 - struct rcar_du_lvds_connector { 30 - struct rcar_du_connector connector; 31 - 32 - struct { 33 - unsigned int width_mm; /* Panel width in mm */ 34 - unsigned int height_mm; /* Panel height in mm */ 35 - struct videomode mode; 36 - } panel; 37 - }; 38 - 39 - #define to_rcar_lvds_connector(c) \ 40 - container_of(c, struct rcar_du_lvds_connector, connector.connector) 41 - 42 28 static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector) 43 29 { 44 - struct rcar_du_lvds_connector *lvdscon = 45 - to_rcar_lvds_connector(connector); 46 - struct drm_display_mode *mode; 30 + struct rcar_du_connector *rcon = to_rcar_connector(connector); 47 31 48 - mode = drm_mode_create(connector->dev); 49 - if (mode == NULL) 50 - return 0; 51 - 52 - mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; 53 - 54 - drm_display_mode_from_videomode(&lvdscon->panel.mode, mode); 55 - 56 - drm_mode_probed_add(connector, mode); 57 - 58 - return 1; 32 + return drm_panel_get_modes(rcon->panel); 59 33 } 60 34 61 35 static const struct drm_connector_helper_funcs connector_helper_funcs = { 62 36 .get_modes = rcar_du_lvds_connector_get_modes, 63 37 }; 64 38 39 + static void rcar_du_lvds_connector_destroy(struct drm_connector *connector) 40 + { 41 + struct rcar_du_connector *rcon = to_rcar_connector(connector); 42 + 43 + drm_panel_detach(rcon->panel); 44 + drm_connector_cleanup(connector); 45 + } 46 + 65 47 static const struct drm_connector_funcs connector_funcs = { 66 48 .dpms = drm_atomic_helper_connector_dpms, 67 49 .reset = drm_atomic_helper_connector_reset, 68 50 .fill_modes = drm_helper_probe_single_connector_modes, 69 - .destroy = drm_connector_cleanup, 51 + .destroy = rcar_du_lvds_connector_destroy, 70 52 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 71 53 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 72 54 }; ··· 59 75 const struct device_node *np) 60 76 { 61 77 struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc); 62 - struct rcar_du_lvds_connector *lvdscon; 78 + struct rcar_du_connector *rcon; 63 79 struct drm_connector *connector; 64 - struct display_timing timing; 65 80 int ret; 66 81 67 - lvdscon = devm_kzalloc(rcdu->dev, sizeof(*lvdscon), GFP_KERNEL); 68 - if (lvdscon == NULL) 82 + rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL); 83 + if (rcon == NULL) 69 84 return -ENOMEM; 70 85 71 - ret = of_get_display_timing(np, "panel-timing", &timing); 72 - if (ret < 0) 73 - return ret; 86 + connector = &rcon->connector; 74 87 75 - videomode_from_timing(&timing, &lvdscon->panel.mode); 76 - 77 - of_property_read_u32(np, "width-mm", &lvdscon->panel.width_mm); 78 - of_property_read_u32(np, "height-mm", &lvdscon->panel.height_mm); 79 - 80 - connector = &lvdscon->connector.connector; 81 - connector->display_info.width_mm = lvdscon->panel.width_mm; 82 - connector->display_info.height_mm = lvdscon->panel.height_mm; 88 + rcon->panel = of_drm_find_panel(np); 89 + if (!rcon->panel) 90 + return -EPROBE_DEFER; 83 91 84 92 ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, 85 93 DRM_MODE_CONNECTOR_LVDS); ··· 88 112 if (ret < 0) 89 113 return ret; 90 114 91 - lvdscon->connector.encoder = renc; 115 + ret = drm_panel_attach(rcon->panel, connector); 116 + if (ret < 0) 117 + return ret; 118 + 119 + rcon->encoder = renc; 92 120 93 121 return 0; 94 122 }