From 255c35f8fe6a9c345320e512c681c03678f3e0b4 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Fri, 8 Jul 2016 17:40:56 +0800 Subject: drm/imx: atomic phase 2 step 1: Wire up state ->reset, ->duplicate and ->destroy Wire up CRTCs', planes' and connectors' ->reset, ->duplicate and ->destroy state hooks to use the default implementations from the atomic helper library. The helpers track each DRM object state. Signed-off-by: Liu Ying Acked-by: Daniel Vetter Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/imx/parallel-display.c') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 2d1fd02cd3d6..9fe88c9b4b0d 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,9 @@ static const struct drm_connector_funcs imx_pd_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = imx_pd_connector_detect, .destroy = imx_drm_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; static const struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = { -- cgit v1.2.2 From 032003c5cd744e8e0baf5430fc5b3fd5462208e4 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Fri, 8 Jul 2016 17:40:58 +0800 Subject: drm/imx: Remove encoders' ->prepare callbacks The main task of imx encoders' ->prepare callbacks is to set bus_format, bus_flags, di_vsync_pin and di_hsync_pin. We may create a structure named imx_encoder to cache them. The atomic encoder callback ->disable may replace ->prepare later, so let's remove ->prepare. Signed-off-by: Liu Ying Acked-by: Daniel Vetter Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 56 ++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/imx/parallel-display.c') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 9fe88c9b4b0d..7374d824a6d1 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -27,15 +27,15 @@ #include "imx-drm.h" #define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) -#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder) +#define imx_enc_to_imxpd(x) \ + container_of(x, struct imx_parallel_display, imx_encoder) struct imx_parallel_display { struct drm_connector connector; - struct drm_encoder encoder; + struct imx_drm_encoder imx_encoder; struct device *dev; void *edid; int edid_len; - u32 bus_format; struct drm_display_mode mode; struct drm_panel *panel; }; @@ -57,8 +57,9 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) struct drm_display_info *di = &connector->display_info; num_modes = imxpd->panel->funcs->get_modes(imxpd->panel); - if (!imxpd->bus_format && di->num_bus_formats) - imxpd->bus_format = di->bus_formats[0]; + if (!imxpd->imx_encoder.bus_format && di->num_bus_formats) + imxpd->imx_encoder.bus_format = di->bus_formats[0]; + imxpd->imx_encoder.bus_flags = di->bus_flags; if (num_modes > 0) return num_modes; } @@ -88,12 +89,13 @@ static struct drm_encoder *imx_pd_connector_best_encoder( { struct imx_parallel_display *imxpd = con_to_imxpd(connector); - return &imxpd->encoder; + return &imxpd->imx_encoder.encoder; } static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) { - struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); + struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); + struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); if (mode != DRM_MODE_DPMS_ON) drm_panel_disable(imxpd->panel); @@ -101,16 +103,10 @@ static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) drm_panel_enable(imxpd->panel); } -static void imx_pd_encoder_prepare(struct drm_encoder *encoder) -{ - struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); - imx_drm_set_bus_config(encoder, imxpd->bus_format, 2, 3, - imxpd->connector.display_info.bus_flags); -} - static void imx_pd_encoder_commit(struct drm_encoder *encoder) { - struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); + struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); + struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); drm_panel_prepare(imxpd->panel); drm_panel_enable(imxpd->panel); @@ -124,7 +120,8 @@ static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, static void imx_pd_encoder_disable(struct drm_encoder *encoder) { - struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); + struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); + struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); drm_panel_disable(imxpd->panel); drm_panel_unprepare(imxpd->panel); @@ -151,7 +148,6 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = { static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { .dpms = imx_pd_encoder_dpms, - .prepare = imx_pd_encoder_prepare, .commit = imx_pd_encoder_commit, .mode_set = imx_pd_encoder_mode_set, .disable = imx_pd_encoder_disable, @@ -162,7 +158,7 @@ static int imx_pd_register(struct drm_device *drm, { int ret; - ret = imx_drm_encoder_parse_of(drm, &imxpd->encoder, + ret = imx_drm_encoder_parse_of(drm, &imxpd->imx_encoder.encoder, imxpd->dev->of_node); if (ret) return ret; @@ -174,9 +170,10 @@ static int imx_pd_register(struct drm_device *drm, */ imxpd->connector.dpms = DRM_MODE_DPMS_OFF; - drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs); - drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs, - DRM_MODE_ENCODER_NONE, NULL); + drm_encoder_helper_add(&imxpd->imx_encoder.encoder, + &imx_pd_encoder_helper_funcs); + drm_encoder_init(drm, &imxpd->imx_encoder.encoder, + &imx_pd_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); drm_connector_helper_add(&imxpd->connector, &imx_pd_connector_helper_funcs); @@ -186,7 +183,8 @@ static int imx_pd_register(struct drm_device *drm, if (imxpd->panel) drm_panel_attach(imxpd->panel, &imxpd->connector); - drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder); + drm_mode_connector_attach_encoder(&imxpd->connector, + &imxpd->imx_encoder.encoder); return 0; } @@ -199,6 +197,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) const u8 *edidp; struct imx_parallel_display *imxpd; int ret; + u32 bus_format = 0; const char *fmt; imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL); @@ -212,14 +211,17 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) ret = of_property_read_string(np, "interface-pix-fmt", &fmt); if (!ret) { if (!strcmp(fmt, "rgb24")) - imxpd->bus_format = MEDIA_BUS_FMT_RGB888_1X24; + bus_format = MEDIA_BUS_FMT_RGB888_1X24; else if (!strcmp(fmt, "rgb565")) - imxpd->bus_format = MEDIA_BUS_FMT_RGB565_1X16; + bus_format = MEDIA_BUS_FMT_RGB565_1X16; else if (!strcmp(fmt, "bgr666")) - imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X18; + bus_format = MEDIA_BUS_FMT_RGB666_1X18; else if (!strcmp(fmt, "lvds666")) - imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; + bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; } + imxpd->imx_encoder.bus_format = bus_format; + imxpd->imx_encoder.di_hsync_pin = 2; + imxpd->imx_encoder.di_vsync_pin = 3; /* port@1 is the output port */ ep = of_graph_get_endpoint_by_regs(np, 1, -1); @@ -252,7 +254,7 @@ static void imx_pd_unbind(struct device *dev, struct device *master, { struct imx_parallel_display *imxpd = dev_get_drvdata(dev); - imxpd->encoder.funcs->destroy(&imxpd->encoder); + imxpd->imx_encoder.encoder.funcs->destroy(&imxpd->imx_encoder.encoder); imxpd->connector.funcs->destroy(&imxpd->connector); kfree(imxpd->edid); -- cgit v1.2.2 From f6e396e5096dec2523fade421bc27f3fae38e31d Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Fri, 8 Jul 2016 17:41:01 +0800 Subject: drm/imx: atomic phase 3 step 2: Legacy callback fixups Now that we can use atomic configurations, all the legacy callbacks of CRTCs, encoders and connectors can be switched to the atomic version. For the imx-ldb driver, there is a clock parent setting mismatch bewteen ->enable and ->disable after the switch, so a fixup is added. For the imx-tve driver, since the encoder's callback ->dpms is replaced by ->disable, we need to move the setting for the IPU_CLK_EN bit(in register TVE_COM_CONF_REG) from ->enable/->disable to ->mode_set, otherwise, the relevant CRTC cannot be disabled correctly with a warning on DC stop timeout. Signed-off-by: Liu Ying Acked-by: Daniel Vetter Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/imx/parallel-display.c') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 7374d824a6d1..bb5dbd66fea7 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -92,18 +92,7 @@ static struct drm_encoder *imx_pd_connector_best_encoder( return &imxpd->imx_encoder.encoder; } -static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); - struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); - - if (mode != DRM_MODE_DPMS_ON) - drm_panel_disable(imxpd->panel); - else - drm_panel_enable(imxpd->panel); -} - -static void imx_pd_encoder_commit(struct drm_encoder *encoder) +static void imx_pd_encoder_enable(struct drm_encoder *encoder) { struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); @@ -128,7 +117,7 @@ static void imx_pd_encoder_disable(struct drm_encoder *encoder) } static const struct drm_connector_funcs imx_pd_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .detect = imx_pd_connector_detect, .destroy = imx_drm_connector_destroy, @@ -147,9 +136,8 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = { }; static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { - .dpms = imx_pd_encoder_dpms, - .commit = imx_pd_encoder_commit, .mode_set = imx_pd_encoder_mode_set, + .enable = imx_pd_encoder_enable, .disable = imx_pd_encoder_disable, }; -- cgit v1.2.2 From e41c5c2411bca56775663a4153e0c00ea8c8f130 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 6 Jul 2016 13:40:13 +0200 Subject: drm/imx: remove empty mode_set encoder callbacks With atomic modeset support, these callbacks are optional. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/gpu/drm/imx/parallel-display.c') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index bb5dbd66fea7..4a2942ecec17 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -101,12 +101,6 @@ static void imx_pd_encoder_enable(struct drm_encoder *encoder) drm_panel_enable(imxpd->panel); } -static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *orig_mode, - struct drm_display_mode *mode) -{ -} - static void imx_pd_encoder_disable(struct drm_encoder *encoder) { struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); @@ -136,7 +130,6 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = { }; static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { - .mode_set = imx_pd_encoder_mode_set, .enable = imx_pd_encoder_enable, .disable = imx_pd_encoder_disable, }; -- cgit v1.2.2 From 49f98bc4d44a4ee507737f8d5531d05539787319 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 6 Jul 2016 14:49:24 +0200 Subject: drm/imx: store internal bus configuration in crtc state The internal bus configuration is imx-drm specific crtc state. Store it in imx_crtc_state and let the encoder atomic_check callbacks determine bus_flags, bus_format and the sync pins, possibly taking into account the mode and the connector display info. The custom imx_drm_encoder structure can be replaced again with drm_encoder. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 63 ++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/imx/parallel-display.c') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 4a2942ecec17..9da60df5efa7 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -27,19 +27,23 @@ #include "imx-drm.h" #define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) -#define imx_enc_to_imxpd(x) \ - container_of(x, struct imx_parallel_display, imx_encoder) struct imx_parallel_display { struct drm_connector connector; - struct imx_drm_encoder imx_encoder; + struct drm_encoder encoder; struct device *dev; void *edid; int edid_len; + u32 bus_format; struct drm_display_mode mode; struct drm_panel *panel; }; +static inline struct imx_parallel_display *enc_to_imxpd(struct drm_encoder *e) +{ + return container_of(e, struct imx_parallel_display, encoder); +} + static enum drm_connector_status imx_pd_connector_detect( struct drm_connector *connector, bool force) { @@ -54,12 +58,7 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) if (imxpd->panel && imxpd->panel->funcs && imxpd->panel->funcs->get_modes) { - struct drm_display_info *di = &connector->display_info; - num_modes = imxpd->panel->funcs->get_modes(imxpd->panel); - if (!imxpd->imx_encoder.bus_format && di->num_bus_formats) - imxpd->imx_encoder.bus_format = di->bus_formats[0]; - imxpd->imx_encoder.bus_flags = di->bus_flags; if (num_modes > 0) return num_modes; } @@ -89,13 +88,12 @@ static struct drm_encoder *imx_pd_connector_best_encoder( { struct imx_parallel_display *imxpd = con_to_imxpd(connector); - return &imxpd->imx_encoder.encoder; + return &imxpd->encoder; } static void imx_pd_encoder_enable(struct drm_encoder *encoder) { - struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); - struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); + struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); drm_panel_prepare(imxpd->panel); drm_panel_enable(imxpd->panel); @@ -103,13 +101,31 @@ static void imx_pd_encoder_enable(struct drm_encoder *encoder) static void imx_pd_encoder_disable(struct drm_encoder *encoder) { - struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); - struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); + struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); drm_panel_disable(imxpd->panel); drm_panel_unprepare(imxpd->panel); } +static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state); + struct drm_display_info *di = &conn_state->connector->display_info; + struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); + + imx_crtc_state->bus_flags = di->bus_flags; + if (!imxpd->bus_format && di->num_bus_formats) + imx_crtc_state->bus_format = di->bus_formats[0]; + else + imx_crtc_state->bus_format = imxpd->bus_format; + imx_crtc_state->di_hsync_pin = 2; + imx_crtc_state->di_vsync_pin = 3; + + return 0; +} + static const struct drm_connector_funcs imx_pd_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, @@ -132,15 +148,16 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = { static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { .enable = imx_pd_encoder_enable, .disable = imx_pd_encoder_disable, + .atomic_check = imx_pd_encoder_atomic_check, }; static int imx_pd_register(struct drm_device *drm, struct imx_parallel_display *imxpd) { + struct drm_encoder *encoder = &imxpd->encoder; int ret; - ret = imx_drm_encoder_parse_of(drm, &imxpd->imx_encoder.encoder, - imxpd->dev->of_node); + ret = imx_drm_encoder_parse_of(drm, encoder, imxpd->dev->of_node); if (ret) return ret; @@ -151,10 +168,9 @@ static int imx_pd_register(struct drm_device *drm, */ imxpd->connector.dpms = DRM_MODE_DPMS_OFF; - drm_encoder_helper_add(&imxpd->imx_encoder.encoder, - &imx_pd_encoder_helper_funcs); - drm_encoder_init(drm, &imxpd->imx_encoder.encoder, - &imx_pd_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); + drm_encoder_helper_add(encoder, &imx_pd_encoder_helper_funcs); + drm_encoder_init(drm, encoder, &imx_pd_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); drm_connector_helper_add(&imxpd->connector, &imx_pd_connector_helper_funcs); @@ -164,8 +180,7 @@ static int imx_pd_register(struct drm_device *drm, if (imxpd->panel) drm_panel_attach(imxpd->panel, &imxpd->connector); - drm_mode_connector_attach_encoder(&imxpd->connector, - &imxpd->imx_encoder.encoder); + drm_mode_connector_attach_encoder(&imxpd->connector, encoder); return 0; } @@ -200,9 +215,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) else if (!strcmp(fmt, "lvds666")) bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; } - imxpd->imx_encoder.bus_format = bus_format; - imxpd->imx_encoder.di_hsync_pin = 2; - imxpd->imx_encoder.di_vsync_pin = 3; + imxpd->bus_format = bus_format; /* port@1 is the output port */ ep = of_graph_get_endpoint_by_regs(np, 1, -1); @@ -235,7 +248,7 @@ static void imx_pd_unbind(struct device *dev, struct device *master, { struct imx_parallel_display *imxpd = dev_get_drvdata(dev); - imxpd->imx_encoder.encoder.funcs->destroy(&imxpd->imx_encoder.encoder); + imxpd->encoder.funcs->destroy(&imxpd->encoder); imxpd->connector.funcs->destroy(&imxpd->connector); kfree(imxpd->edid); -- cgit v1.2.2 From 3df0739052c23989b441883fa251a0988f75c0f3 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 6 Jul 2016 15:47:11 +0200 Subject: drm/imx: turn remaining container_of macros into inline functions This allows the compiler to do type checking. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/imx/parallel-display.c') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 9da60df5efa7..7b7bb3100831 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -26,8 +26,6 @@ #include "imx-drm.h" -#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) - struct imx_parallel_display { struct drm_connector connector; struct drm_encoder encoder; @@ -39,6 +37,11 @@ struct imx_parallel_display { struct drm_panel *panel; }; +static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector *c) +{ + return container_of(c, struct imx_parallel_display, connector); +} + static inline struct imx_parallel_display *enc_to_imxpd(struct drm_encoder *e) { return container_of(e, struct imx_parallel_display, encoder); -- cgit v1.2.2 From 76ecd9c9fb24b014a6f33fbb1287ede3be12158b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Tue, 12 Jul 2016 15:30:01 +0200 Subject: drm/imx: parallel-display: check return code from of_get_drm_display_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit of_get_drm_display_mode() may fail. Check its return code and bail out on error. Signed-off-by: Lothar Waßmann Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/imx/parallel-display.c') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 7b7bb3100831..4abac21c5c9b 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -73,10 +73,16 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) if (np) { struct drm_display_mode *mode = drm_mode_create(connector->dev); + int ret; if (!mode) return -EINVAL; - of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE); + + ret = of_get_drm_display_mode(np, &imxpd->mode, + OF_USE_NATIVE_MODE); + if (ret) + return ret; + drm_mode_copy(mode, &imxpd->mode); mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, drm_mode_probed_add(connector, mode); -- cgit v1.2.2 From f140b0cc776f8771adfa45d2ef234da72662443d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 27 Jun 2016 15:26:31 +0200 Subject: drm/imx: parallel-display: add bridge support Add support for bridge chips connected externally to the i.MX DISP0/DISP1 DPI interfaces. Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 50 ++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/imx/parallel-display.c') diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 4abac21c5c9b..1dad297b01fd 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -35,6 +35,7 @@ struct imx_parallel_display { u32 bus_format; struct drm_display_mode mode; struct drm_panel *panel; + struct drm_bridge *bridge; }; static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector *c) @@ -181,15 +182,29 @@ static int imx_pd_register(struct drm_device *drm, drm_encoder_init(drm, encoder, &imx_pd_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); - drm_connector_helper_add(&imxpd->connector, - &imx_pd_connector_helper_funcs); - drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs, - DRM_MODE_CONNECTOR_VGA); + if (!imxpd->bridge) { + drm_connector_helper_add(&imxpd->connector, + &imx_pd_connector_helper_funcs); + drm_connector_init(drm, &imxpd->connector, + &imx_pd_connector_funcs, + DRM_MODE_CONNECTOR_VGA); + } if (imxpd->panel) drm_panel_attach(imxpd->panel, &imxpd->connector); - drm_mode_connector_attach_encoder(&imxpd->connector, encoder); + if (imxpd->bridge) { + imxpd->bridge->encoder = encoder; + encoder->bridge = imxpd->bridge; + ret = drm_bridge_attach(drm, imxpd->bridge); + if (ret < 0) { + dev_err(imxpd->dev, "failed to attach bridge: %d\n", + ret); + return ret; + } + } else { + drm_mode_connector_attach_encoder(&imxpd->connector, encoder); + } return 0; } @@ -232,13 +247,30 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) struct device_node *remote; remote = of_graph_get_remote_port_parent(ep); + if (!remote) { + dev_warn(dev, "endpoint %s not connected\n", + ep->full_name); + of_node_put(ep); + return -ENODEV; + } of_node_put(ep); - if (remote) { - imxpd->panel = of_drm_find_panel(remote); - of_node_put(remote); + + imxpd->panel = of_drm_find_panel(remote); + if (imxpd->panel) { + dev_dbg(dev, "found panel %s\n", remote->full_name); + } else { + imxpd->bridge = of_drm_find_bridge(remote); + if (imxpd->bridge) + dev_dbg(dev, "found bridge %s\n", + remote->full_name); } - if (!imxpd->panel) + if (!imxpd->panel && !imxpd->bridge) { + dev_dbg(dev, "waiting for panel or bridge %s\n", + remote->full_name); + of_node_put(remote); return -EPROBE_DEFER; + } + of_node_put(remote); } imxpd->dev = dev; -- cgit v1.2.2