aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/imx')
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c25
-rw-r--r--drivers/gpu/drm/imx/imx-drm.h6
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c151
-rw-r--r--drivers/gpu/drm/imx/ipuv3-crtc.c3
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c10
5 files changed, 104 insertions, 91 deletions
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 9f7dafce3a4c..438bac8fbc2b 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -16,7 +16,6 @@
16#include <linux/component.h> 16#include <linux/component.h>
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/dma-buf.h> 18#include <linux/dma-buf.h>
19#include <linux/fb.h>
20#include <linux/module.h> 19#include <linux/module.h>
21#include <linux/platform_device.h> 20#include <linux/platform_device.h>
22#include <linux/reservation.h> 21#include <linux/reservation.h>
@@ -58,12 +57,6 @@ static int legacyfb_depth = 16;
58module_param(legacyfb_depth, int, 0444); 57module_param(legacyfb_depth, int, 0444);
59#endif 58#endif
60 59
61unsigned int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
62{
63 return drm_crtc_index(crtc->crtc);
64}
65EXPORT_SYMBOL_GPL(imx_drm_crtc_id);
66
67static void imx_drm_driver_lastclose(struct drm_device *drm) 60static void imx_drm_driver_lastclose(struct drm_device *drm)
68{ 61{
69 struct imx_drm_device *imxdrm = drm->dev_private; 62 struct imx_drm_device *imxdrm = drm->dev_private;
@@ -90,24 +83,6 @@ static int imx_drm_driver_unload(struct drm_device *drm)
90 return 0; 83 return 0;
91} 84}
92 85
93int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
94{
95 return drm_crtc_vblank_get(imx_drm_crtc->crtc);
96}
97EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get);
98
99void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc)
100{
101 drm_crtc_vblank_put(imx_drm_crtc->crtc);
102}
103EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put);
104
105void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
106{
107 drm_crtc_handle_vblank(imx_drm_crtc->crtc);
108}
109EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
110
111static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe) 86static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe)
112{ 87{
113 struct imx_drm_device *imxdrm = drm->dev_private; 88 struct imx_drm_device *imxdrm = drm->dev_private;
diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h
index 07d33e45f90f..5a91cb16c8fa 100644
--- a/drivers/gpu/drm/imx/imx-drm.h
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -13,8 +13,6 @@ struct drm_plane;
13struct imx_drm_crtc; 13struct imx_drm_crtc;
14struct platform_device; 14struct platform_device;
15 15
16unsigned int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
17
18struct imx_crtc_state { 16struct imx_crtc_state {
19 struct drm_crtc_state base; 17 struct drm_crtc_state base;
20 u32 bus_format; 18 u32 bus_format;
@@ -44,10 +42,6 @@ int imx_drm_init_drm(struct platform_device *pdev,
44 int preferred_bpp); 42 int preferred_bpp);
45int imx_drm_exit_drm(void); 43int imx_drm_exit_drm(void);
46 44
47int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc);
48void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc);
49void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc);
50
51void imx_drm_mode_config_init(struct drm_device *drm); 45void imx_drm_mode_config_init(struct drm_device *drm);
52 46
53struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); 47struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index b03919ed60ba..4eed3a6addad 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -57,7 +57,11 @@ struct imx_ldb_channel {
57 struct imx_ldb *ldb; 57 struct imx_ldb *ldb;
58 struct drm_connector connector; 58 struct drm_connector connector;
59 struct drm_encoder encoder; 59 struct drm_encoder encoder;
60
61 /* Defines what is connected to the ldb, only one at a time */
60 struct drm_panel *panel; 62 struct drm_panel *panel;
63 struct drm_bridge *bridge;
64
61 struct device_node *child; 65 struct device_node *child;
62 struct i2c_adapter *ddc; 66 struct i2c_adapter *ddc;
63 int chno; 67 int chno;
@@ -66,6 +70,7 @@ struct imx_ldb_channel {
66 struct drm_display_mode mode; 70 struct drm_display_mode mode;
67 int mode_valid; 71 int mode_valid;
68 u32 bus_format; 72 u32 bus_format;
73 u32 bus_flags;
69}; 74};
70 75
71static inline struct imx_ldb_channel *con_to_imx_ldb_ch(struct drm_connector *c) 76static inline struct imx_ldb_channel *con_to_imx_ldb_ch(struct drm_connector *c)
@@ -251,11 +256,13 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder)
251 drm_panel_enable(imx_ldb_ch->panel); 256 drm_panel_enable(imx_ldb_ch->panel);
252} 257}
253 258
254static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, 259static void
255 struct drm_display_mode *orig_mode, 260imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder,
256 struct drm_display_mode *mode) 261 struct drm_crtc_state *crtc_state,
262 struct drm_connector_state *connector_state)
257{ 263{
258 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 264 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
265 struct drm_display_mode *mode = &crtc_state->adjusted_mode;
259 struct imx_ldb *ldb = imx_ldb_ch->ldb; 266 struct imx_ldb *ldb = imx_ldb_ch->ldb;
260 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; 267 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
261 unsigned long serial_clk; 268 unsigned long serial_clk;
@@ -297,17 +304,11 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
297 } 304 }
298 305
299 if (!bus_format) { 306 if (!bus_format) {
300 struct drm_connector *connector; 307 struct drm_connector *connector = connector_state->connector;
301 308 struct drm_display_info *di = &connector->display_info;
302 drm_for_each_connector(connector, encoder->dev) {
303 struct drm_display_info *di = &connector->display_info;
304 309
305 if (connector->encoder == encoder && 310 if (di->num_bus_formats)
306 di->num_bus_formats) { 311 bus_format = di->bus_formats[0];
307 bus_format = di->bus_formats[0];
308 break;
309 }
310 }
311 } 312 }
312 imx_ldb_ch_set_bus_format(imx_ldb_ch, bus_format); 313 imx_ldb_ch_set_bus_format(imx_ldb_ch, bus_format);
313} 314}
@@ -379,8 +380,13 @@ static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder,
379 u32 bus_format = imx_ldb_ch->bus_format; 380 u32 bus_format = imx_ldb_ch->bus_format;
380 381
381 /* Bus format description in DT overrides connector display info. */ 382 /* Bus format description in DT overrides connector display info. */
382 if (!bus_format && di->num_bus_formats) 383 if (!bus_format && di->num_bus_formats) {
383 bus_format = di->bus_formats[0]; 384 bus_format = di->bus_formats[0];
385 imx_crtc_state->bus_flags = di->bus_flags;
386 } else {
387 bus_format = imx_ldb_ch->bus_format;
388 imx_crtc_state->bus_flags = imx_ldb_ch->bus_flags;
389 }
384 switch (bus_format) { 390 switch (bus_format) {
385 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: 391 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
386 imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB666_1X18; 392 imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
@@ -420,7 +426,7 @@ static const struct drm_encoder_funcs imx_ldb_encoder_funcs = {
420}; 426};
421 427
422static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = { 428static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
423 .mode_set = imx_ldb_encoder_mode_set, 429 .atomic_mode_set = imx_ldb_encoder_atomic_mode_set,
424 .enable = imx_ldb_encoder_enable, 430 .enable = imx_ldb_encoder_enable,
425 .disable = imx_ldb_encoder_disable, 431 .disable = imx_ldb_encoder_disable,
426 .atomic_check = imx_ldb_encoder_atomic_check, 432 .atomic_check = imx_ldb_encoder_atomic_check,
@@ -466,10 +472,30 @@ static int imx_ldb_register(struct drm_device *drm,
466 drm_encoder_init(drm, encoder, &imx_ldb_encoder_funcs, 472 drm_encoder_init(drm, encoder, &imx_ldb_encoder_funcs,
467 DRM_MODE_ENCODER_LVDS, NULL); 473 DRM_MODE_ENCODER_LVDS, NULL);
468 474
469 drm_connector_helper_add(&imx_ldb_ch->connector, 475 if (imx_ldb_ch->bridge) {
470 &imx_ldb_connector_helper_funcs); 476 imx_ldb_ch->bridge->encoder = encoder;
471 drm_connector_init(drm, &imx_ldb_ch->connector, 477
472 &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS); 478 imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
479 ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
480 if (ret) {
481 DRM_ERROR("Failed to initialize bridge with drm\n");
482 return ret;
483 }
484 } else {
485 /*
486 * We want to add the connector whenever there is no bridge
487 * that brings its own, not only when there is a panel. For
488 * historical reasons, the ldb driver can also work without
489 * a panel.
490 */
491 drm_connector_helper_add(&imx_ldb_ch->connector,
492 &imx_ldb_connector_helper_funcs);
493 drm_connector_init(drm, &imx_ldb_ch->connector,
494 &imx_ldb_connector_funcs,
495 DRM_MODE_CONNECTOR_LVDS);
496 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
497 encoder);
498 }
473 499
474 if (imx_ldb_ch->panel) { 500 if (imx_ldb_ch->panel) {
475 ret = drm_panel_attach(imx_ldb_ch->panel, 501 ret = drm_panel_attach(imx_ldb_ch->panel,
@@ -478,8 +504,6 @@ static int imx_ldb_register(struct drm_device *drm,
478 return ret; 504 return ret;
479 } 505 }
480 506
481 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, encoder);
482
483 return 0; 507 return 0;
484} 508}
485 509
@@ -548,6 +572,46 @@ static const struct of_device_id imx_ldb_dt_ids[] = {
548}; 572};
549MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids); 573MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
550 574
575static int imx_ldb_panel_ddc(struct device *dev,
576 struct imx_ldb_channel *channel, struct device_node *child)
577{
578 struct device_node *ddc_node;
579 const u8 *edidp;
580 int ret;
581
582 ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
583 if (ddc_node) {
584 channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
585 of_node_put(ddc_node);
586 if (!channel->ddc) {
587 dev_warn(dev, "failed to get ddc i2c adapter\n");
588 return -EPROBE_DEFER;
589 }
590 }
591
592 if (!channel->ddc) {
593 /* if no DDC available, fallback to hardcoded EDID */
594 dev_dbg(dev, "no ddc available\n");
595
596 edidp = of_get_property(child, "edid",
597 &channel->edid_len);
598 if (edidp) {
599 channel->edid = kmemdup(edidp,
600 channel->edid_len,
601 GFP_KERNEL);
602 } else if (!channel->panel) {
603 /* fallback to display-timings node */
604 ret = of_get_drm_display_mode(child,
605 &channel->mode,
606 &channel->bus_flags,
607 OF_USE_NATIVE_MODE);
608 if (!ret)
609 channel->mode_valid = 1;
610 }
611 }
612 return 0;
613}
614
551static int imx_ldb_bind(struct device *dev, struct device *master, void *data) 615static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
552{ 616{
553 struct drm_device *drm = data; 617 struct drm_device *drm = data;
@@ -555,7 +619,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
555 const struct of_device_id *of_id = 619 const struct of_device_id *of_id =
556 of_match_device(imx_ldb_dt_ids, dev); 620 of_match_device(imx_ldb_dt_ids, dev);
557 struct device_node *child; 621 struct device_node *child;
558 const u8 *edidp;
559 struct imx_ldb *imx_ldb; 622 struct imx_ldb *imx_ldb;
560 int dual; 623 int dual;
561 int ret; 624 int ret;
@@ -605,7 +668,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
605 668
606 for_each_child_of_node(np, child) { 669 for_each_child_of_node(np, child) {
607 struct imx_ldb_channel *channel; 670 struct imx_ldb_channel *channel;
608 struct device_node *ddc_node;
609 struct device_node *ep; 671 struct device_node *ep;
610 int bus_format; 672 int bus_format;
611 673
@@ -638,46 +700,25 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
638 700
639 remote = of_graph_get_remote_port_parent(ep); 701 remote = of_graph_get_remote_port_parent(ep);
640 of_node_put(ep); 702 of_node_put(ep);
641 if (remote) 703 if (remote) {
642 channel->panel = of_drm_find_panel(remote); 704 channel->panel = of_drm_find_panel(remote);
643 else 705 channel->bridge = of_drm_find_bridge(remote);
706 } else
644 return -EPROBE_DEFER; 707 return -EPROBE_DEFER;
645 of_node_put(remote); 708 of_node_put(remote);
646 if (!channel->panel) {
647 dev_err(dev, "panel not found: %s\n",
648 remote->full_name);
649 return -EPROBE_DEFER;
650 }
651 }
652 709
653 ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0); 710 if (!channel->panel && !channel->bridge) {
654 if (ddc_node) { 711 dev_err(dev, "panel/bridge not found: %s\n",
655 channel->ddc = of_find_i2c_adapter_by_node(ddc_node); 712 remote->full_name);
656 of_node_put(ddc_node);
657 if (!channel->ddc) {
658 dev_warn(dev, "failed to get ddc i2c adapter\n");
659 return -EPROBE_DEFER; 713 return -EPROBE_DEFER;
660 } 714 }
661 } 715 }
662 716
663 if (!channel->ddc) { 717 /* panel ddc only if there is no bridge */
664 /* if no DDC available, fallback to hardcoded EDID */ 718 if (!channel->bridge) {
665 dev_dbg(dev, "no ddc available\n"); 719 ret = imx_ldb_panel_ddc(dev, channel, child);
666 720 if (ret)
667 edidp = of_get_property(child, "edid", 721 return ret;
668 &channel->edid_len);
669 if (edidp) {
670 channel->edid = kmemdup(edidp,
671 channel->edid_len,
672 GFP_KERNEL);
673 } else if (!channel->panel) {
674 /* fallback to display-timings node */
675 ret = of_get_drm_display_mode(child,
676 &channel->mode,
677 OF_USE_NATIVE_MODE);
678 if (!ret)
679 channel->mode_valid = 1;
680 }
681 } 722 }
682 723
683 bus_format = of_get_bus_format(dev, child); 724 bus_format = of_get_bus_format(dev, child);
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 08e188bc10fc..6e1dc902522c 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -21,7 +21,6 @@
21#include <drm/drm_atomic.h> 21#include <drm/drm_atomic.h>
22#include <drm/drm_atomic_helper.h> 22#include <drm/drm_atomic_helper.h>
23#include <drm/drm_crtc_helper.h> 23#include <drm/drm_crtc_helper.h>
24#include <linux/fb.h>
25#include <linux/clk.h> 24#include <linux/clk.h>
26#include <linux/errno.h> 25#include <linux/errno.h>
27#include <drm/drm_gem_cma_helper.h> 26#include <drm/drm_gem_cma_helper.h>
@@ -134,7 +133,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
134{ 133{
135 struct ipu_crtc *ipu_crtc = dev_id; 134 struct ipu_crtc *ipu_crtc = dev_id;
136 135
137 imx_drm_handle_vblank(ipu_crtc->imx_crtc); 136 drm_crtc_handle_vblank(&ipu_crtc->base);
138 137
139 return IRQ_HANDLED; 138 return IRQ_HANDLED;
140} 139}
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index 1dad297b01fd..74b0ac06fdab 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -33,6 +33,7 @@ struct imx_parallel_display {
33 void *edid; 33 void *edid;
34 int edid_len; 34 int edid_len;
35 u32 bus_format; 35 u32 bus_format;
36 u32 bus_flags;
36 struct drm_display_mode mode; 37 struct drm_display_mode mode;
37 struct drm_panel *panel; 38 struct drm_panel *panel;
38 struct drm_bridge *bridge; 39 struct drm_bridge *bridge;
@@ -80,6 +81,7 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
80 return -EINVAL; 81 return -EINVAL;
81 82
82 ret = of_get_drm_display_mode(np, &imxpd->mode, 83 ret = of_get_drm_display_mode(np, &imxpd->mode,
84 &imxpd->bus_flags,
83 OF_USE_NATIVE_MODE); 85 OF_USE_NATIVE_MODE);
84 if (ret) 86 if (ret)
85 return ret; 87 return ret;
@@ -125,11 +127,13 @@ static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder,
125 struct drm_display_info *di = &conn_state->connector->display_info; 127 struct drm_display_info *di = &conn_state->connector->display_info;
126 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); 128 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
127 129
128 imx_crtc_state->bus_flags = di->bus_flags; 130 if (!imxpd->bus_format && di->num_bus_formats) {
129 if (!imxpd->bus_format && di->num_bus_formats) 131 imx_crtc_state->bus_flags = di->bus_flags;
130 imx_crtc_state->bus_format = di->bus_formats[0]; 132 imx_crtc_state->bus_format = di->bus_formats[0];
131 else 133 } else {
134 imx_crtc_state->bus_flags = imxpd->bus_flags;
132 imx_crtc_state->bus_format = imxpd->bus_format; 135 imx_crtc_state->bus_format = imxpd->bus_format;
136 }
133 imx_crtc_state->di_hsync_pin = 2; 137 imx_crtc_state->di_hsync_pin = 2;
134 imx_crtc_state->di_vsync_pin = 3; 138 imx_crtc_state->di_vsync_pin = 3;
135 139