aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi.c19
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c32
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c120
-rw-r--r--drivers/gpu/drm/imx/imx-drm.h21
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c192
-rw-r--r--drivers/gpu/drm/imx/imx-tve.c97
-rw-r--r--drivers/gpu/drm/imx/ipuv3-crtc.c400
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c548
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.h16
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c149
-rw-r--r--drivers/gpu/ipu-v3/ipu-dc.c9
-rw-r--r--drivers/gpu/ipu-v3/ipu-di.c3
-rw-r--r--drivers/gpu/ipu-v3/ipu-dmfc.c213
13 files changed, 781 insertions, 1038 deletions
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 70b1f7d4270b..77ab47341658 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1495,14 +1495,6 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
1495} 1495}
1496 1496
1497static const struct drm_connector_funcs dw_hdmi_connector_funcs = { 1497static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
1498 .dpms = drm_helper_connector_dpms,
1499 .fill_modes = drm_helper_probe_single_connector_modes,
1500 .detect = dw_hdmi_connector_detect,
1501 .destroy = dw_hdmi_connector_destroy,
1502 .force = dw_hdmi_connector_force,
1503};
1504
1505static const struct drm_connector_funcs dw_hdmi_atomic_connector_funcs = {
1506 .dpms = drm_atomic_helper_connector_dpms, 1498 .dpms = drm_atomic_helper_connector_dpms,
1507 .fill_modes = drm_helper_probe_single_connector_modes, 1499 .fill_modes = drm_helper_probe_single_connector_modes,
1508 .detect = dw_hdmi_connector_detect, 1500 .detect = dw_hdmi_connector_detect,
@@ -1634,14 +1626,9 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
1634 drm_connector_helper_add(&hdmi->connector, 1626 drm_connector_helper_add(&hdmi->connector,
1635 &dw_hdmi_connector_helper_funcs); 1627 &dw_hdmi_connector_helper_funcs);
1636 1628
1637 if (drm_core_check_feature(drm, DRIVER_ATOMIC)) 1629 drm_connector_init(drm, &hdmi->connector,
1638 drm_connector_init(drm, &hdmi->connector, 1630 &dw_hdmi_connector_funcs,
1639 &dw_hdmi_atomic_connector_funcs, 1631 DRM_MODE_CONNECTOR_HDMIA);
1640 DRM_MODE_CONNECTOR_HDMIA);
1641 else
1642 drm_connector_init(drm, &hdmi->connector,
1643 &dw_hdmi_connector_funcs,
1644 DRM_MODE_CONNECTOR_HDMIA);
1645 1632
1646 drm_mode_connector_attach_encoder(&hdmi->connector, encoder); 1633 drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
1647 1634
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index a24631fdf4ad..359cd2765552 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -28,6 +28,11 @@ struct imx_hdmi {
28 struct regmap *regmap; 28 struct regmap *regmap;
29}; 29};
30 30
31static inline struct imx_hdmi *enc_to_imx_hdmi(struct drm_encoder *e)
32{
33 return container_of(e, struct imx_hdmi, encoder);
34}
35
31static const struct dw_hdmi_mpll_config imx_mpll_cfg[] = { 36static const struct dw_hdmi_mpll_config imx_mpll_cfg[] = {
32 { 37 {
33 45250000, { 38 45250000, {
@@ -109,15 +114,9 @@ static void dw_hdmi_imx_encoder_disable(struct drm_encoder *encoder)
109{ 114{
110} 115}
111 116
112static void dw_hdmi_imx_encoder_mode_set(struct drm_encoder *encoder, 117static void dw_hdmi_imx_encoder_enable(struct drm_encoder *encoder)
113 struct drm_display_mode *mode,
114 struct drm_display_mode *adj_mode)
115{ 118{
116} 119 struct imx_hdmi *hdmi = enc_to_imx_hdmi(encoder);
117
118static void dw_hdmi_imx_encoder_commit(struct drm_encoder *encoder)
119{
120 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
121 int mux = drm_of_encoder_active_port_id(hdmi->dev->of_node, encoder); 120 int mux = drm_of_encoder_active_port_id(hdmi->dev->of_node, encoder);
122 121
123 regmap_update_bits(hdmi->regmap, IOMUXC_GPR3, 122 regmap_update_bits(hdmi->regmap, IOMUXC_GPR3,
@@ -125,16 +124,23 @@ static void dw_hdmi_imx_encoder_commit(struct drm_encoder *encoder)
125 mux << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT); 124 mux << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT);
126} 125}
127 126
128static void dw_hdmi_imx_encoder_prepare(struct drm_encoder *encoder) 127static int dw_hdmi_imx_atomic_check(struct drm_encoder *encoder,
128 struct drm_crtc_state *crtc_state,
129 struct drm_connector_state *conn_state)
129{ 130{
130 imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_RGB888_1X24); 131 struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
132
133 imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
134 imx_crtc_state->di_hsync_pin = 2;
135 imx_crtc_state->di_vsync_pin = 3;
136
137 return 0;
131} 138}
132 139
133static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = { 140static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = {
134 .mode_set = dw_hdmi_imx_encoder_mode_set, 141 .enable = dw_hdmi_imx_encoder_enable,
135 .prepare = dw_hdmi_imx_encoder_prepare,
136 .commit = dw_hdmi_imx_encoder_commit,
137 .disable = dw_hdmi_imx_encoder_disable, 142 .disable = dw_hdmi_imx_encoder_disable,
143 .atomic_check = dw_hdmi_imx_atomic_check,
138}; 144};
139 145
140static const struct drm_encoder_funcs dw_hdmi_imx_encoder_funcs = { 146static const struct drm_encoder_funcs dw_hdmi_imx_encoder_funcs = {
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 7746418a4c08..9f7dafce3a4c 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -15,10 +15,14 @@
15 */ 15 */
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/fb.h> 19#include <linux/fb.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/reservation.h>
21#include <drm/drmP.h> 23#include <drm/drmP.h>
24#include <drm/drm_atomic.h>
25#include <drm/drm_atomic_helper.h>
22#include <drm/drm_fb_helper.h> 26#include <drm/drm_fb_helper.h>
23#include <drm/drm_crtc_helper.h> 27#include <drm/drm_crtc_helper.h>
24#include <drm/drm_gem_cma_helper.h> 28#include <drm/drm_gem_cma_helper.h>
@@ -41,6 +45,7 @@ struct imx_drm_device {
41 struct imx_drm_crtc *crtc[MAX_CRTC]; 45 struct imx_drm_crtc *crtc[MAX_CRTC];
42 unsigned int pipes; 46 unsigned int pipes;
43 struct drm_fbdev_cma *fbhelper; 47 struct drm_fbdev_cma *fbhelper;
48 struct drm_atomic_state *state;
44}; 49};
45 50
46struct imx_drm_crtc { 51struct imx_drm_crtc {
@@ -85,45 +90,6 @@ static int imx_drm_driver_unload(struct drm_device *drm)
85 return 0; 90 return 0;
86} 91}
87 92
88static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
89{
90 struct imx_drm_device *imxdrm = crtc->dev->dev_private;
91 unsigned i;
92
93 for (i = 0; i < MAX_CRTC; i++)
94 if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc)
95 return imxdrm->crtc[i];
96
97 return NULL;
98}
99
100int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
101 int hsync_pin, int vsync_pin, u32 bus_flags)
102{
103 struct imx_drm_crtc_helper_funcs *helper;
104 struct imx_drm_crtc *imx_crtc;
105
106 imx_crtc = imx_drm_find_crtc(encoder->crtc);
107 if (!imx_crtc)
108 return -EINVAL;
109
110 helper = &imx_crtc->imx_drm_helper_funcs;
111 if (helper->set_interface_pix_fmt)
112 return helper->set_interface_pix_fmt(encoder->crtc,
113 bus_format, hsync_pin, vsync_pin,
114 bus_flags);
115 return 0;
116}
117EXPORT_SYMBOL_GPL(imx_drm_set_bus_config);
118
119int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format)
120{
121 return imx_drm_set_bus_config(encoder, bus_format, 2, 3,
122 DRM_BUS_FLAG_DE_HIGH |
123 DRM_BUS_FLAG_PIXDATA_NEGEDGE);
124}
125EXPORT_SYMBOL_GPL(imx_drm_set_bus_format);
126
127int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) 93int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
128{ 94{
129 return drm_crtc_vblank_get(imx_drm_crtc->crtc); 95 return drm_crtc_vblank_get(imx_drm_crtc->crtc);
@@ -208,6 +174,63 @@ static void imx_drm_output_poll_changed(struct drm_device *drm)
208static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = { 174static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
209 .fb_create = drm_fb_cma_create, 175 .fb_create = drm_fb_cma_create,
210 .output_poll_changed = imx_drm_output_poll_changed, 176 .output_poll_changed = imx_drm_output_poll_changed,
177 .atomic_check = drm_atomic_helper_check,
178 .atomic_commit = drm_atomic_helper_commit,
179};
180
181static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
182{
183 struct drm_device *dev = state->dev;
184 struct drm_crtc *crtc;
185 struct drm_crtc_state *crtc_state;
186 struct drm_plane_state *plane_state;
187 struct drm_gem_cma_object *cma_obj;
188 struct fence *excl;
189 unsigned shared_count;
190 struct fence **shared;
191 unsigned int i, j;
192 int ret;
193
194 /* Wait for fences. */
195 for_each_crtc_in_state(state, crtc, crtc_state, i) {
196 plane_state = crtc->primary->state;
197 if (plane_state->fb) {
198 cma_obj = drm_fb_cma_get_gem_obj(plane_state->fb, 0);
199 if (cma_obj->base.dma_buf) {
200 ret = reservation_object_get_fences_rcu(
201 cma_obj->base.dma_buf->resv, &excl,
202 &shared_count, &shared);
203 if (unlikely(ret))
204 DRM_ERROR("failed to get fences "
205 "for buffer\n");
206
207 if (excl) {
208 fence_wait(excl, false);
209 fence_put(excl);
210 }
211 for (j = 0; j < shared_count; i++) {
212 fence_wait(shared[j], false);
213 fence_put(shared[j]);
214 }
215 }
216 }
217 }
218
219 drm_atomic_helper_commit_modeset_disables(dev, state);
220
221 drm_atomic_helper_commit_planes(dev, state, true);
222
223 drm_atomic_helper_commit_modeset_enables(dev, state);
224
225 drm_atomic_helper_commit_hw_done(state);
226
227 drm_atomic_helper_wait_for_vblanks(dev, state);
228
229 drm_atomic_helper_cleanup_planes(dev, state);
230}
231
232static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
233 .atomic_commit_tail = imx_drm_atomic_commit_tail,
211}; 234};
212 235
213/* 236/*
@@ -249,6 +272,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
249 drm->mode_config.max_width = 4096; 272 drm->mode_config.max_width = 4096;
250 drm->mode_config.max_height = 4096; 273 drm->mode_config.max_height = 4096;
251 drm->mode_config.funcs = &imx_drm_mode_config_funcs; 274 drm->mode_config.funcs = &imx_drm_mode_config_funcs;
275 drm->mode_config.helper_private = &imx_drm_mode_config_helpers;
252 276
253 drm_mode_config_init(drm); 277 drm_mode_config_init(drm);
254 278
@@ -279,6 +303,8 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
279 } 303 }
280 } 304 }
281 305
306 drm_mode_config_reset(drm);
307
282 /* 308 /*
283 * All components are now initialised, so setup the fb helper. 309 * All components are now initialised, so setup the fb helper.
284 * The fb helper takes copies of key hardware information, so the 310 * The fb helper takes copies of key hardware information, so the
@@ -289,7 +315,6 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
289 dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); 315 dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n");
290 legacyfb_depth = 16; 316 legacyfb_depth = 16;
291 } 317 }
292 drm_helper_disable_unused_functions(drm);
293 imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth, 318 imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
294 drm->mode_config.num_crtc, MAX_CRTC); 319 drm->mode_config.num_crtc, MAX_CRTC);
295 if (IS_ERR(imxdrm->fbhelper)) { 320 if (IS_ERR(imxdrm->fbhelper)) {
@@ -403,7 +428,8 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = {
403}; 428};
404 429
405static struct drm_driver imx_drm_driver = { 430static struct drm_driver imx_drm_driver = {
406 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, 431 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
432 DRIVER_ATOMIC,
407 .load = imx_drm_driver_load, 433 .load = imx_drm_driver_load,
408 .unload = imx_drm_driver_unload, 434 .unload = imx_drm_driver_unload,
409 .lastclose = imx_drm_driver_lastclose, 435 .lastclose = imx_drm_driver_lastclose,
@@ -491,6 +517,7 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
491static int imx_drm_suspend(struct device *dev) 517static int imx_drm_suspend(struct device *dev)
492{ 518{
493 struct drm_device *drm_dev = dev_get_drvdata(dev); 519 struct drm_device *drm_dev = dev_get_drvdata(dev);
520 struct imx_drm_device *imxdrm;
494 521
495 /* The drm_dev is NULL before .load hook is called */ 522 /* The drm_dev is NULL before .load hook is called */
496 if (drm_dev == NULL) 523 if (drm_dev == NULL)
@@ -498,17 +525,26 @@ static int imx_drm_suspend(struct device *dev)
498 525
499 drm_kms_helper_poll_disable(drm_dev); 526 drm_kms_helper_poll_disable(drm_dev);
500 527
528 imxdrm = drm_dev->dev_private;
529 imxdrm->state = drm_atomic_helper_suspend(drm_dev);
530 if (IS_ERR(imxdrm->state)) {
531 drm_kms_helper_poll_enable(drm_dev);
532 return PTR_ERR(imxdrm->state);
533 }
534
501 return 0; 535 return 0;
502} 536}
503 537
504static int imx_drm_resume(struct device *dev) 538static int imx_drm_resume(struct device *dev)
505{ 539{
506 struct drm_device *drm_dev = dev_get_drvdata(dev); 540 struct drm_device *drm_dev = dev_get_drvdata(dev);
541 struct imx_drm_device *imx_drm;
507 542
508 if (drm_dev == NULL) 543 if (drm_dev == NULL)
509 return 0; 544 return 0;
510 545
511 drm_helper_resume_force_mode(drm_dev); 546 imx_drm = drm_dev->dev_private;
547 drm_atomic_helper_resume(drm_dev, imx_drm->state);
512 drm_kms_helper_poll_enable(drm_dev); 548 drm_kms_helper_poll_enable(drm_dev);
513 549
514 return 0; 550 return 0;
diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h
index 74320a1723b7..07d33e45f90f 100644
--- a/drivers/gpu/drm/imx/imx-drm.h
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -15,12 +15,22 @@ struct platform_device;
15 15
16unsigned int imx_drm_crtc_id(struct imx_drm_crtc *crtc); 16unsigned int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
17 17
18struct imx_crtc_state {
19 struct drm_crtc_state base;
20 u32 bus_format;
21 u32 bus_flags;
22 int di_hsync_pin;
23 int di_vsync_pin;
24};
25
26static inline struct imx_crtc_state *to_imx_crtc_state(struct drm_crtc_state *s)
27{
28 return container_of(s, struct imx_crtc_state, base);
29}
30
18struct imx_drm_crtc_helper_funcs { 31struct imx_drm_crtc_helper_funcs {
19 int (*enable_vblank)(struct drm_crtc *crtc); 32 int (*enable_vblank)(struct drm_crtc *crtc);
20 void (*disable_vblank)(struct drm_crtc *crtc); 33 void (*disable_vblank)(struct drm_crtc *crtc);
21 int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
22 u32 bus_format, int hsync_pin, int vsync_pin,
23 u32 bus_flags);
24 const struct drm_crtc_helper_funcs *crtc_helper_funcs; 34 const struct drm_crtc_helper_funcs *crtc_helper_funcs;
25 const struct drm_crtc_funcs *crtc_funcs; 35 const struct drm_crtc_funcs *crtc_funcs;
26}; 36};
@@ -42,11 +52,6 @@ void imx_drm_mode_config_init(struct drm_device *drm);
42 52
43struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb); 53struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
44 54
45int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
46 int hsync_pin, int vsync_pin, u32 bus_flags);
47int imx_drm_set_bus_format(struct drm_encoder *encoder,
48 u32 bus_format);
49
50int imx_drm_encoder_parse_of(struct drm_device *drm, 55int imx_drm_encoder_parse_of(struct drm_device *drm,
51 struct drm_encoder *encoder, struct device_node *np); 56 struct drm_encoder *encoder, struct device_node *np);
52 57
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index beff793bb717..5d2831dfb8b9 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -17,6 +17,8 @@
17#include <linux/clk.h> 17#include <linux/clk.h>
18#include <linux/component.h> 18#include <linux/component.h>
19#include <drm/drmP.h> 19#include <drm/drmP.h>
20#include <drm/drm_atomic.h>
21#include <drm/drm_atomic_helper.h>
20#include <drm/drm_fb_helper.h> 22#include <drm/drm_fb_helper.h>
21#include <drm/drm_crtc_helper.h> 23#include <drm/drm_crtc_helper.h>
22#include <drm/drm_of.h> 24#include <drm/drm_of.h>
@@ -49,9 +51,6 @@
49#define LDB_DI1_VS_POL_ACT_LOW (1 << 10) 51#define LDB_DI1_VS_POL_ACT_LOW (1 << 10)
50#define LDB_BGREF_RMODE_INT (1 << 15) 52#define LDB_BGREF_RMODE_INT (1 << 15)
51 53
52#define con_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, connector)
53#define enc_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, encoder)
54
55struct imx_ldb; 54struct imx_ldb;
56 55
57struct imx_ldb_channel { 56struct imx_ldb_channel {
@@ -66,9 +65,19 @@ struct imx_ldb_channel {
66 int edid_len; 65 int edid_len;
67 struct drm_display_mode mode; 66 struct drm_display_mode mode;
68 int mode_valid; 67 int mode_valid;
69 int bus_format; 68 u32 bus_format;
70}; 69};
71 70
71static inline struct imx_ldb_channel *con_to_imx_ldb_ch(struct drm_connector *c)
72{
73 return container_of(c, struct imx_ldb_channel, connector);
74}
75
76static inline struct imx_ldb_channel *enc_to_imx_ldb_ch(struct drm_encoder *e)
77{
78 return container_of(e, struct imx_ldb_channel, encoder);
79}
80
72struct bus_mux { 81struct bus_mux {
73 int reg; 82 int reg;
74 int shift; 83 int shift;
@@ -93,6 +102,32 @@ static enum drm_connector_status imx_ldb_connector_detect(
93 return connector_status_connected; 102 return connector_status_connected;
94} 103}
95 104
105static void imx_ldb_ch_set_bus_format(struct imx_ldb_channel *imx_ldb_ch,
106 u32 bus_format)
107{
108 struct imx_ldb *ldb = imx_ldb_ch->ldb;
109 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
110
111 switch (bus_format) {
112 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
113 break;
114 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
115 if (imx_ldb_ch->chno == 0 || dual)
116 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
117 if (imx_ldb_ch->chno == 1 || dual)
118 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24;
119 break;
120 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
121 if (imx_ldb_ch->chno == 0 || dual)
122 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
123 LDB_BIT_MAP_CH0_JEIDA;
124 if (imx_ldb_ch->chno == 1 || dual)
125 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
126 LDB_BIT_MAP_CH1_JEIDA;
127 break;
128 }
129}
130
96static int imx_ldb_connector_get_modes(struct drm_connector *connector) 131static int imx_ldb_connector_get_modes(struct drm_connector *connector)
97{ 132{
98 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); 133 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
@@ -100,11 +135,7 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
100 135
101 if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs && 136 if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs &&
102 imx_ldb_ch->panel->funcs->get_modes) { 137 imx_ldb_ch->panel->funcs->get_modes) {
103 struct drm_display_info *di = &connector->display_info;
104
105 num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel); 138 num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel);
106 if (!imx_ldb_ch->bus_format && di->num_bus_formats)
107 imx_ldb_ch->bus_format = di->bus_formats[0];
108 if (num_modes > 0) 139 if (num_modes > 0)
109 return num_modes; 140 return num_modes;
110 } 141 }
@@ -141,10 +172,6 @@ static struct drm_encoder *imx_ldb_connector_best_encoder(
141 return &imx_ldb_ch->encoder; 172 return &imx_ldb_ch->encoder;
142} 173}
143 174
144static void imx_ldb_encoder_dpms(struct drm_encoder *encoder, int mode)
145{
146}
147
148static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno, 175static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
149 unsigned long serial_clk, unsigned long di_clk) 176 unsigned long serial_clk, unsigned long di_clk)
150{ 177{
@@ -173,43 +200,7 @@ static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
173 chno); 200 chno);
174} 201}
175 202
176static void imx_ldb_encoder_prepare(struct drm_encoder *encoder) 203static void imx_ldb_encoder_enable(struct drm_encoder *encoder)
177{
178 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
179 struct imx_ldb *ldb = imx_ldb_ch->ldb;
180 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
181 u32 bus_format;
182
183 switch (imx_ldb_ch->bus_format) {
184 default:
185 dev_warn(ldb->dev,
186 "could not determine data mapping, default to 18-bit \"spwg\"\n");
187 /* fallthrough */
188 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
189 bus_format = MEDIA_BUS_FMT_RGB666_1X18;
190 break;
191 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
192 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
193 if (imx_ldb_ch->chno == 0 || dual)
194 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
195 if (imx_ldb_ch->chno == 1 || dual)
196 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24;
197 break;
198 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
199 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
200 if (imx_ldb_ch->chno == 0 || dual)
201 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
202 LDB_BIT_MAP_CH0_JEIDA;
203 if (imx_ldb_ch->chno == 1 || dual)
204 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
205 LDB_BIT_MAP_CH1_JEIDA;
206 break;
207 }
208
209 imx_drm_set_bus_format(encoder, bus_format);
210}
211
212static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
213{ 204{
214 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 205 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
215 struct imx_ldb *ldb = imx_ldb_ch->ldb; 206 struct imx_ldb *ldb = imx_ldb_ch->ldb;
@@ -219,8 +210,13 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
219 drm_panel_prepare(imx_ldb_ch->panel); 210 drm_panel_prepare(imx_ldb_ch->panel);
220 211
221 if (dual) { 212 if (dual) {
213 clk_set_parent(ldb->clk_sel[mux], ldb->clk[0]);
214 clk_set_parent(ldb->clk_sel[mux], ldb->clk[1]);
215
222 clk_prepare_enable(ldb->clk[0]); 216 clk_prepare_enable(ldb->clk[0]);
223 clk_prepare_enable(ldb->clk[1]); 217 clk_prepare_enable(ldb->clk[1]);
218 } else {
219 clk_set_parent(ldb->clk_sel[mux], ldb->clk[imx_ldb_ch->chno]);
224 } 220 }
225 221
226 if (imx_ldb_ch == &ldb->channel[0] || dual) { 222 if (imx_ldb_ch == &ldb->channel[0] || dual) {
@@ -265,6 +261,7 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
265 unsigned long serial_clk; 261 unsigned long serial_clk;
266 unsigned long di_clk = mode->clock * 1000; 262 unsigned long di_clk = mode->clock * 1000;
267 int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder); 263 int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder);
264 u32 bus_format = imx_ldb_ch->bus_format;
268 265
269 if (mode->clock > 170000) { 266 if (mode->clock > 170000) {
270 dev_warn(ldb->dev, 267 dev_warn(ldb->dev,
@@ -286,18 +283,36 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
286 } 283 }
287 284
288 /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */ 285 /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
289 if (imx_ldb_ch == &ldb->channel[0]) { 286 if (imx_ldb_ch == &ldb->channel[0] || dual) {
290 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 287 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
291 ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW; 288 ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW;
292 else if (mode->flags & DRM_MODE_FLAG_PVSYNC) 289 else if (mode->flags & DRM_MODE_FLAG_PVSYNC)
293 ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW; 290 ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW;
294 } 291 }
295 if (imx_ldb_ch == &ldb->channel[1]) { 292 if (imx_ldb_ch == &ldb->channel[1] || dual) {
296 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 293 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
297 ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW; 294 ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW;
298 else if (mode->flags & DRM_MODE_FLAG_PVSYNC) 295 else if (mode->flags & DRM_MODE_FLAG_PVSYNC)
299 ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW; 296 ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW;
300 } 297 }
298
299 if (!bus_format) {
300 struct drm_connector_state *conn_state;
301 struct drm_connector *connector;
302 int i;
303
304 for_each_connector_in_state(encoder->crtc->state->state,
305 connector, conn_state, i) {
306 struct drm_display_info *di = &connector->display_info;
307
308 if (conn_state->crtc == encoder->crtc &&
309 di->num_bus_formats) {
310 bus_format = di->bus_formats[0];
311 break;
312 }
313 }
314 }
315 imx_ldb_ch_set_bus_format(imx_ldb_ch, bus_format);
301} 316}
302 317
303static void imx_ldb_encoder_disable(struct drm_encoder *encoder) 318static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
@@ -357,11 +372,45 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
357 drm_panel_unprepare(imx_ldb_ch->panel); 372 drm_panel_unprepare(imx_ldb_ch->panel);
358} 373}
359 374
375static int imx_ldb_encoder_atomic_check(struct drm_encoder *encoder,
376 struct drm_crtc_state *crtc_state,
377 struct drm_connector_state *conn_state)
378{
379 struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
380 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
381 struct drm_display_info *di = &conn_state->connector->display_info;
382 u32 bus_format = imx_ldb_ch->bus_format;
383
384 /* Bus format description in DT overrides connector display info. */
385 if (!bus_format && di->num_bus_formats)
386 bus_format = di->bus_formats[0];
387 switch (bus_format) {
388 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
389 imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
390 break;
391 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
392 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
393 imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
394 break;
395 default:
396 return -EINVAL;
397 }
398
399 imx_crtc_state->di_hsync_pin = 2;
400 imx_crtc_state->di_vsync_pin = 3;
401
402 return 0;
403}
404
405
360static const struct drm_connector_funcs imx_ldb_connector_funcs = { 406static const struct drm_connector_funcs imx_ldb_connector_funcs = {
361 .dpms = drm_helper_connector_dpms, 407 .dpms = drm_atomic_helper_connector_dpms,
362 .fill_modes = drm_helper_probe_single_connector_modes, 408 .fill_modes = drm_helper_probe_single_connector_modes,
363 .detect = imx_ldb_connector_detect, 409 .detect = imx_ldb_connector_detect,
364 .destroy = imx_drm_connector_destroy, 410 .destroy = imx_drm_connector_destroy,
411 .reset = drm_atomic_helper_connector_reset,
412 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
413 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
365}; 414};
366 415
367static const struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = { 416static const struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
@@ -374,11 +423,10 @@ static const struct drm_encoder_funcs imx_ldb_encoder_funcs = {
374}; 423};
375 424
376static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = { 425static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
377 .dpms = imx_ldb_encoder_dpms,
378 .prepare = imx_ldb_encoder_prepare,
379 .commit = imx_ldb_encoder_commit,
380 .mode_set = imx_ldb_encoder_mode_set, 426 .mode_set = imx_ldb_encoder_mode_set,
427 .enable = imx_ldb_encoder_enable,
381 .disable = imx_ldb_encoder_disable, 428 .disable = imx_ldb_encoder_disable,
429 .atomic_check = imx_ldb_encoder_atomic_check,
382}; 430};
383 431
384static int imx_ldb_get_clk(struct imx_ldb *ldb, int chno) 432static int imx_ldb_get_clk(struct imx_ldb *ldb, int chno)
@@ -400,10 +448,10 @@ static int imx_ldb_register(struct drm_device *drm,
400 struct imx_ldb_channel *imx_ldb_ch) 448 struct imx_ldb_channel *imx_ldb_ch)
401{ 449{
402 struct imx_ldb *ldb = imx_ldb_ch->ldb; 450 struct imx_ldb *ldb = imx_ldb_ch->ldb;
451 struct drm_encoder *encoder = &imx_ldb_ch->encoder;
403 int ret; 452 int ret;
404 453
405 ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder, 454 ret = imx_drm_encoder_parse_of(drm, encoder, imx_ldb_ch->child);
406 imx_ldb_ch->child);
407 if (ret) 455 if (ret)
408 return ret; 456 return ret;
409 457
@@ -417,9 +465,8 @@ static int imx_ldb_register(struct drm_device *drm,
417 return ret; 465 return ret;
418 } 466 }
419 467
420 drm_encoder_helper_add(&imx_ldb_ch->encoder, 468 drm_encoder_helper_add(encoder, &imx_ldb_encoder_helper_funcs);
421 &imx_ldb_encoder_helper_funcs); 469 drm_encoder_init(drm, encoder, &imx_ldb_encoder_funcs,
422 drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
423 DRM_MODE_ENCODER_LVDS, NULL); 470 DRM_MODE_ENCODER_LVDS, NULL);
424 471
425 drm_connector_helper_add(&imx_ldb_ch->connector, 472 drm_connector_helper_add(&imx_ldb_ch->connector,
@@ -427,11 +474,14 @@ static int imx_ldb_register(struct drm_device *drm,
427 drm_connector_init(drm, &imx_ldb_ch->connector, 474 drm_connector_init(drm, &imx_ldb_ch->connector,
428 &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS); 475 &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
429 476
430 if (imx_ldb_ch->panel) 477 if (imx_ldb_ch->panel) {
431 drm_panel_attach(imx_ldb_ch->panel, &imx_ldb_ch->connector); 478 ret = drm_panel_attach(imx_ldb_ch->panel,
479 &imx_ldb_ch->connector);
480 if (ret)
481 return ret;
482 }
432 483
433 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, 484 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, encoder);
434 &imx_ldb_ch->encoder);
435 485
436 return 0; 486 return 0;
437} 487}
@@ -560,6 +610,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
560 struct imx_ldb_channel *channel; 610 struct imx_ldb_channel *channel;
561 struct device_node *ddc_node; 611 struct device_node *ddc_node;
562 struct device_node *ep; 612 struct device_node *ep;
613 int bus_format;
563 614
564 ret = of_property_read_u32(child, "reg", &i); 615 ret = of_property_read_u32(child, "reg", &i);
565 if (ret || i < 0 || i > 1) 616 if (ret || i < 0 || i > 1)
@@ -632,21 +683,22 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
632 } 683 }
633 } 684 }
634 685
635 channel->bus_format = of_get_bus_format(dev, child); 686 bus_format = of_get_bus_format(dev, child);
636 if (channel->bus_format == -EINVAL) { 687 if (bus_format == -EINVAL) {
637 /* 688 /*
638 * If no bus format was specified in the device tree, 689 * If no bus format was specified in the device tree,
639 * we can still get it from the connected panel later. 690 * we can still get it from the connected panel later.
640 */ 691 */
641 if (channel->panel && channel->panel->funcs && 692 if (channel->panel && channel->panel->funcs &&
642 channel->panel->funcs->get_modes) 693 channel->panel->funcs->get_modes)
643 channel->bus_format = 0; 694 bus_format = 0;
644 } 695 }
645 if (channel->bus_format < 0) { 696 if (bus_format < 0) {
646 dev_err(dev, "could not determine data mapping: %d\n", 697 dev_err(dev, "could not determine data mapping: %d\n",
647 channel->bus_format); 698 bus_format);
648 return channel->bus_format; 699 return bus_format;
649 } 700 }
701 channel->bus_format = bus_format;
650 702
651 ret = imx_ldb_register(drm, channel); 703 ret = imx_ldb_register(drm, channel);
652 if (ret) 704 if (ret)
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index baf788121287..5e875944ffa2 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -23,6 +23,7 @@
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/videodev2.h> 24#include <linux/videodev2.h>
25#include <drm/drmP.h> 25#include <drm/drmP.h>
26#include <drm/drm_atomic_helper.h>
26#include <drm/drm_fb_helper.h> 27#include <drm/drm_fb_helper.h>
27#include <drm/drm_crtc_helper.h> 28#include <drm/drm_crtc_helper.h>
28#include <video/imx-ipu-v3.h> 29#include <video/imx-ipu-v3.h>
@@ -97,9 +98,6 @@
97/* TVE_TST_MODE_REG */ 98/* TVE_TST_MODE_REG */
98#define TVE_TVDAC_TEST_MODE_MASK (0x7 << 0) 99#define TVE_TVDAC_TEST_MODE_MASK (0x7 << 0)
99 100
100#define con_to_tve(x) container_of(x, struct imx_tve, connector)
101#define enc_to_tve(x) container_of(x, struct imx_tve, encoder)
102
103enum { 101enum {
104 TVE_MODE_TVOUT, 102 TVE_MODE_TVOUT,
105 TVE_MODE_VGA, 103 TVE_MODE_VGA,
@@ -112,6 +110,8 @@ struct imx_tve {
112 spinlock_t lock; /* register lock */ 110 spinlock_t lock; /* register lock */
113 bool enabled; 111 bool enabled;
114 int mode; 112 int mode;
113 int di_hsync_pin;
114 int di_vsync_pin;
115 115
116 struct regmap *regmap; 116 struct regmap *regmap;
117 struct regulator *dac_reg; 117 struct regulator *dac_reg;
@@ -120,10 +120,18 @@ struct imx_tve {
120 struct clk *di_sel_clk; 120 struct clk *di_sel_clk;
121 struct clk_hw clk_hw_di; 121 struct clk_hw clk_hw_di;
122 struct clk *di_clk; 122 struct clk *di_clk;
123 int vsync_pin;
124 int hsync_pin;
125}; 123};
126 124
125static inline struct imx_tve *con_to_tve(struct drm_connector *c)
126{
127 return container_of(c, struct imx_tve, connector);
128}
129
130static inline struct imx_tve *enc_to_tve(struct drm_encoder *e)
131{
132 return container_of(e, struct imx_tve, encoder);
133}
134
127static void tve_lock(void *__tve) 135static void tve_lock(void *__tve)
128__acquires(&tve->lock) 136__acquires(&tve->lock)
129{ 137{
@@ -148,8 +156,7 @@ static void tve_enable(struct imx_tve *tve)
148 tve->enabled = true; 156 tve->enabled = true;
149 clk_prepare_enable(tve->clk); 157 clk_prepare_enable(tve->clk);
150 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, 158 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
151 TVE_IPU_CLK_EN | TVE_EN, 159 TVE_EN, TVE_EN);
152 TVE_IPU_CLK_EN | TVE_EN);
153 } 160 }
154 161
155 /* clear interrupt status register */ 162 /* clear interrupt status register */
@@ -172,7 +179,7 @@ static void tve_disable(struct imx_tve *tve)
172 if (tve->enabled) { 179 if (tve->enabled) {
173 tve->enabled = false; 180 tve->enabled = false;
174 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, 181 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
175 TVE_IPU_CLK_EN | TVE_EN, 0); 182 TVE_EN, 0);
176 clk_disable_unprepare(tve->clk); 183 clk_disable_unprepare(tve->clk);
177 } 184 }
178} 185}
@@ -275,36 +282,6 @@ static struct drm_encoder *imx_tve_connector_best_encoder(
275 return &tve->encoder; 282 return &tve->encoder;
276} 283}
277 284
278static void imx_tve_encoder_dpms(struct drm_encoder *encoder, int mode)
279{
280 struct imx_tve *tve = enc_to_tve(encoder);
281 int ret;
282
283 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
284 TVE_TV_OUT_MODE_MASK, TVE_TV_OUT_DISABLE);
285 if (ret < 0)
286 dev_err(tve->dev, "failed to disable TVOUT: %d\n", ret);
287}
288
289static void imx_tve_encoder_prepare(struct drm_encoder *encoder)
290{
291 struct imx_tve *tve = enc_to_tve(encoder);
292
293 tve_disable(tve);
294
295 switch (tve->mode) {
296 case TVE_MODE_VGA:
297 imx_drm_set_bus_config(encoder, MEDIA_BUS_FMT_GBR888_1X24,
298 tve->hsync_pin, tve->vsync_pin,
299 DRM_BUS_FLAG_DE_HIGH |
300 DRM_BUS_FLAG_PIXDATA_NEGEDGE);
301 break;
302 case TVE_MODE_TVOUT:
303 imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_YUV8_1X24);
304 break;
305 }
306}
307
308static void imx_tve_encoder_mode_set(struct drm_encoder *encoder, 285static void imx_tve_encoder_mode_set(struct drm_encoder *encoder,
309 struct drm_display_mode *orig_mode, 286 struct drm_display_mode *orig_mode,
310 struct drm_display_mode *mode) 287 struct drm_display_mode *mode)
@@ -333,6 +310,9 @@ static void imx_tve_encoder_mode_set(struct drm_encoder *encoder,
333 ret); 310 ret);
334 } 311 }
335 312
313 regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
314 TVE_IPU_CLK_EN, TVE_IPU_CLK_EN);
315
336 if (tve->mode == TVE_MODE_VGA) 316 if (tve->mode == TVE_MODE_VGA)
337 ret = tve_setup_vga(tve); 317 ret = tve_setup_vga(tve);
338 else 318 else
@@ -341,7 +321,7 @@ static void imx_tve_encoder_mode_set(struct drm_encoder *encoder,
341 dev_err(tve->dev, "failed to set configuration: %d\n", ret); 321 dev_err(tve->dev, "failed to set configuration: %d\n", ret);
342} 322}
343 323
344static void imx_tve_encoder_commit(struct drm_encoder *encoder) 324static void imx_tve_encoder_enable(struct drm_encoder *encoder)
345{ 325{
346 struct imx_tve *tve = enc_to_tve(encoder); 326 struct imx_tve *tve = enc_to_tve(encoder);
347 327
@@ -355,11 +335,28 @@ static void imx_tve_encoder_disable(struct drm_encoder *encoder)
355 tve_disable(tve); 335 tve_disable(tve);
356} 336}
357 337
338static int imx_tve_atomic_check(struct drm_encoder *encoder,
339 struct drm_crtc_state *crtc_state,
340 struct drm_connector_state *conn_state)
341{
342 struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
343 struct imx_tve *tve = enc_to_tve(encoder);
344
345 imx_crtc_state->bus_format = MEDIA_BUS_FMT_GBR888_1X24;
346 imx_crtc_state->di_hsync_pin = tve->di_hsync_pin;
347 imx_crtc_state->di_vsync_pin = tve->di_vsync_pin;
348
349 return 0;
350}
351
358static const struct drm_connector_funcs imx_tve_connector_funcs = { 352static const struct drm_connector_funcs imx_tve_connector_funcs = {
359 .dpms = drm_helper_connector_dpms, 353 .dpms = drm_atomic_helper_connector_dpms,
360 .fill_modes = drm_helper_probe_single_connector_modes, 354 .fill_modes = drm_helper_probe_single_connector_modes,
361 .detect = imx_tve_connector_detect, 355 .detect = imx_tve_connector_detect,
362 .destroy = imx_drm_connector_destroy, 356 .destroy = imx_drm_connector_destroy,
357 .reset = drm_atomic_helper_connector_reset,
358 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
359 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
363}; 360};
364 361
365static const struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = { 362static const struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
@@ -373,11 +370,10 @@ static const struct drm_encoder_funcs imx_tve_encoder_funcs = {
373}; 370};
374 371
375static const struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = { 372static const struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = {
376 .dpms = imx_tve_encoder_dpms,
377 .prepare = imx_tve_encoder_prepare,
378 .mode_set = imx_tve_encoder_mode_set, 373 .mode_set = imx_tve_encoder_mode_set,
379 .commit = imx_tve_encoder_commit, 374 .enable = imx_tve_encoder_enable,
380 .disable = imx_tve_encoder_disable, 375 .disable = imx_tve_encoder_disable,
376 .atomic_check = imx_tve_atomic_check,
381}; 377};
382 378
383static irqreturn_t imx_tve_irq_handler(int irq, void *data) 379static irqreturn_t imx_tve_irq_handler(int irq, void *data)
@@ -495,8 +491,7 @@ static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
495 encoder_type = tve->mode == TVE_MODE_VGA ? 491 encoder_type = tve->mode == TVE_MODE_VGA ?
496 DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC; 492 DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
497 493
498 ret = imx_drm_encoder_parse_of(drm, &tve->encoder, 494 ret = imx_drm_encoder_parse_of(drm, &tve->encoder, tve->dev->of_node);
499 tve->dev->of_node);
500 if (ret) 495 if (ret)
501 return ret; 496 return ret;
502 497
@@ -587,15 +582,15 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
587 582
588 if (tve->mode == TVE_MODE_VGA) { 583 if (tve->mode == TVE_MODE_VGA) {
589 ret = of_property_read_u32(np, "fsl,hsync-pin", 584 ret = of_property_read_u32(np, "fsl,hsync-pin",
590 &tve->hsync_pin); 585 &tve->di_hsync_pin);
591 586
592 if (ret < 0) { 587 if (ret < 0) {
593 dev_err(dev, "failed to get vsync pin\n"); 588 dev_err(dev, "failed to get hsync pin\n");
594 return ret; 589 return ret;
595 } 590 }
596 591
597 ret |= of_property_read_u32(np, "fsl,vsync-pin", 592 ret = of_property_read_u32(np, "fsl,vsync-pin",
598 &tve->vsync_pin); 593 &tve->di_vsync_pin);
599 594
600 if (ret < 0) { 595 if (ret < 0) {
601 dev_err(dev, "failed to get vsync pin\n"); 596 dev_err(dev, "failed to get vsync pin\n");
@@ -633,7 +628,9 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
633 628
634 tve->dac_reg = devm_regulator_get(dev, "dac"); 629 tve->dac_reg = devm_regulator_get(dev, "dac");
635 if (!IS_ERR(tve->dac_reg)) { 630 if (!IS_ERR(tve->dac_reg)) {
636 regulator_set_voltage(tve->dac_reg, 2750000, 2750000); 631 ret = regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
632 if (ret)
633 return ret;
637 ret = regulator_enable(tve->dac_reg); 634 ret = regulator_enable(tve->dac_reg);
638 if (ret) 635 if (ret)
639 return ret; 636 return ret;
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index fc040417e1e8..08e188bc10fc 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -18,12 +18,12 @@
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <drm/drmP.h> 20#include <drm/drmP.h>
21#include <drm/drm_atomic.h>
22#include <drm/drm_atomic_helper.h>
21#include <drm/drm_crtc_helper.h> 23#include <drm/drm_crtc_helper.h>
22#include <linux/fb.h> 24#include <linux/fb.h>
23#include <linux/clk.h> 25#include <linux/clk.h>
24#include <linux/errno.h> 26#include <linux/errno.h>
25#include <linux/reservation.h>
26#include <linux/dma-buf.h>
27#include <drm/drm_gem_cma_helper.h> 27#include <drm/drm_gem_cma_helper.h>
28#include <drm/drm_fb_cma_helper.h> 28#include <drm/drm_fb_cma_helper.h>
29 29
@@ -33,23 +33,6 @@
33 33
34#define DRIVER_DESC "i.MX IPUv3 Graphics" 34#define DRIVER_DESC "i.MX IPUv3 Graphics"
35 35
36enum ipu_flip_status {
37 IPU_FLIP_NONE,
38 IPU_FLIP_PENDING,
39 IPU_FLIP_SUBMITTED,
40};
41
42struct ipu_flip_work {
43 struct work_struct unref_work;
44 struct drm_gem_object *bo;
45 struct drm_pending_vblank_event *page_flip_event;
46 struct work_struct fence_work;
47 struct ipu_crtc *crtc;
48 struct fence *excl;
49 unsigned shared_count;
50 struct fence **shared;
51};
52
53struct ipu_crtc { 36struct ipu_crtc {
54 struct device *dev; 37 struct device *dev;
55 struct drm_crtc base; 38 struct drm_crtc base;
@@ -60,201 +43,166 @@ struct ipu_crtc {
60 43
61 struct ipu_dc *dc; 44 struct ipu_dc *dc;
62 struct ipu_di *di; 45 struct ipu_di *di;
63 int enabled;
64 enum ipu_flip_status flip_state;
65 struct workqueue_struct *flip_queue;
66 struct ipu_flip_work *flip_work;
67 int irq; 46 int irq;
68 u32 bus_format;
69 u32 bus_flags;
70 int di_hsync_pin;
71 int di_vsync_pin;
72}; 47};
73 48
74#define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base) 49static inline struct ipu_crtc *to_ipu_crtc(struct drm_crtc *crtc)
50{
51 return container_of(crtc, struct ipu_crtc, base);
52}
75 53
76static void ipu_fb_enable(struct ipu_crtc *ipu_crtc) 54static void ipu_crtc_enable(struct drm_crtc *crtc)
77{ 55{
56 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
78 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 57 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
79 58
80 if (ipu_crtc->enabled)
81 return;
82
83 ipu_dc_enable(ipu); 59 ipu_dc_enable(ipu);
84 ipu_plane_enable(ipu_crtc->plane[0]);
85 /* Start DC channel and DI after IDMAC */
86 ipu_dc_enable_channel(ipu_crtc->dc); 60 ipu_dc_enable_channel(ipu_crtc->dc);
87 ipu_di_enable(ipu_crtc->di); 61 ipu_di_enable(ipu_crtc->di);
88 drm_crtc_vblank_on(&ipu_crtc->base);
89
90 ipu_crtc->enabled = 1;
91} 62}
92 63
93static void ipu_fb_disable(struct ipu_crtc *ipu_crtc) 64static void ipu_crtc_disable(struct drm_crtc *crtc)
94{ 65{
66 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
95 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 67 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
96 68
97 if (!ipu_crtc->enabled)
98 return;
99
100 /* Stop DC channel and DI before IDMAC */
101 ipu_dc_disable_channel(ipu_crtc->dc); 69 ipu_dc_disable_channel(ipu_crtc->dc);
102 ipu_di_disable(ipu_crtc->di); 70 ipu_di_disable(ipu_crtc->di);
103 ipu_plane_disable(ipu_crtc->plane[0]);
104 ipu_dc_disable(ipu); 71 ipu_dc_disable(ipu);
105 drm_crtc_vblank_off(&ipu_crtc->base);
106 72
107 ipu_crtc->enabled = 0; 73 spin_lock_irq(&crtc->dev->event_lock);
74 if (crtc->state->event) {
75 drm_crtc_send_vblank_event(crtc, crtc->state->event);
76 crtc->state->event = NULL;
77 }
78 spin_unlock_irq(&crtc->dev->event_lock);
108} 79}
109 80
110static void ipu_crtc_dpms(struct drm_crtc *crtc, int mode) 81static void imx_drm_crtc_reset(struct drm_crtc *crtc)
111{ 82{
112 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 83 struct imx_crtc_state *state;
113 84
114 dev_dbg(ipu_crtc->dev, "%s mode: %d\n", __func__, mode); 85 if (crtc->state) {
115 86 if (crtc->state->mode_blob)
116 switch (mode) { 87 drm_property_unreference_blob(crtc->state->mode_blob);
117 case DRM_MODE_DPMS_ON: 88
118 ipu_fb_enable(ipu_crtc); 89 state = to_imx_crtc_state(crtc->state);
119 break; 90 memset(state, 0, sizeof(*state));
120 case DRM_MODE_DPMS_STANDBY: 91 } else {
121 case DRM_MODE_DPMS_SUSPEND: 92 state = kzalloc(sizeof(*state), GFP_KERNEL);
122 case DRM_MODE_DPMS_OFF: 93 if (!state)
123 ipu_fb_disable(ipu_crtc); 94 return;
124 break; 95 crtc->state = &state->base;
125 } 96 }
97
98 state->base.crtc = crtc;
126} 99}
127 100
128static void ipu_flip_unref_work_func(struct work_struct *__work) 101static struct drm_crtc_state *imx_drm_crtc_duplicate_state(struct drm_crtc *crtc)
129{ 102{
130 struct ipu_flip_work *work = 103 struct imx_crtc_state *state;
131 container_of(__work, struct ipu_flip_work, unref_work); 104
105 state = kzalloc(sizeof(*state), GFP_KERNEL);
106 if (!state)
107 return NULL;
132 108
133 drm_gem_object_unreference_unlocked(work->bo); 109 __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
134 kfree(work); 110
111 WARN_ON(state->base.crtc != crtc);
112 state->base.crtc = crtc;
113
114 return &state->base;
135} 115}
136 116
137static void ipu_flip_fence_work_func(struct work_struct *__work) 117static void imx_drm_crtc_destroy_state(struct drm_crtc *crtc,
118 struct drm_crtc_state *state)
138{ 119{
139 struct ipu_flip_work *work = 120 __drm_atomic_helper_crtc_destroy_state(state);
140 container_of(__work, struct ipu_flip_work, fence_work); 121 kfree(to_imx_crtc_state(state));
141 int i; 122}
142 123
143 /* wait for all fences attached to the FB obj to signal */ 124static const struct drm_crtc_funcs ipu_crtc_funcs = {
144 if (work->excl) { 125 .set_config = drm_atomic_helper_set_config,
145 fence_wait(work->excl, false); 126 .destroy = drm_crtc_cleanup,
146 fence_put(work->excl); 127 .page_flip = drm_atomic_helper_page_flip,
147 } 128 .reset = imx_drm_crtc_reset,
148 for (i = 0; i < work->shared_count; i++) { 129 .atomic_duplicate_state = imx_drm_crtc_duplicate_state,
149 fence_wait(work->shared[i], false); 130 .atomic_destroy_state = imx_drm_crtc_destroy_state,
150 fence_put(work->shared[i]); 131};
151 }
152 132
153 work->crtc->flip_state = IPU_FLIP_SUBMITTED; 133static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
134{
135 struct ipu_crtc *ipu_crtc = dev_id;
136
137 imx_drm_handle_vblank(ipu_crtc->imx_crtc);
138
139 return IRQ_HANDLED;
154} 140}
155 141
156static int ipu_page_flip(struct drm_crtc *crtc, 142static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc,
157 struct drm_framebuffer *fb, 143 const struct drm_display_mode *mode,
158 struct drm_pending_vblank_event *event, 144 struct drm_display_mode *adjusted_mode)
159 uint32_t page_flip_flags)
160{ 145{
161 struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
162 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 146 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
163 struct ipu_flip_work *flip_work; 147 struct videomode vm;
164 int ret; 148 int ret;
165 149
166 if (ipu_crtc->flip_state != IPU_FLIP_NONE) 150 drm_display_mode_to_videomode(adjusted_mode, &vm);
167 return -EBUSY;
168
169 ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc);
170 if (ret) {
171 dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n");
172 list_del(&event->base.link);
173
174 return ret;
175 }
176 151
177 flip_work = kzalloc(sizeof *flip_work, GFP_KERNEL); 152 ret = ipu_di_adjust_videomode(ipu_crtc->di, &vm);
178 if (!flip_work) { 153 if (ret)
179 ret = -ENOMEM; 154 return false;
180 goto put_vblank;
181 }
182 INIT_WORK(&flip_work->unref_work, ipu_flip_unref_work_func);
183 flip_work->page_flip_event = event;
184 155
185 /* get BO backing the old framebuffer and take a reference */ 156 if ((vm.vsync_len == 0) || (vm.hsync_len == 0))
186 flip_work->bo = &drm_fb_cma_get_gem_obj(crtc->primary->fb, 0)->base; 157 return false;
187 drm_gem_object_reference(flip_work->bo);
188 158
189 ipu_crtc->flip_work = flip_work; 159 drm_display_mode_from_videomode(&vm, adjusted_mode);
190 /*
191 * If the object has a DMABUF attached, we need to wait on its fences
192 * if there are any.
193 */
194 if (cma_obj->base.dma_buf) {
195 INIT_WORK(&flip_work->fence_work, ipu_flip_fence_work_func);
196 flip_work->crtc = ipu_crtc;
197 160
198 ret = reservation_object_get_fences_rcu( 161 return true;
199 cma_obj->base.dma_buf->resv, &flip_work->excl, 162}
200 &flip_work->shared_count, &flip_work->shared);
201 163
202 if (unlikely(ret)) { 164static int ipu_crtc_atomic_check(struct drm_crtc *crtc,
203 DRM_ERROR("failed to get fences for buffer\n"); 165 struct drm_crtc_state *state)
204 goto free_flip_work; 166{
205 } 167 u32 primary_plane_mask = 1 << drm_plane_index(crtc->primary);
206 168
207 /* No need to queue the worker if the are no fences */ 169 if (state->active && (primary_plane_mask & state->plane_mask) == 0)
208 if (!flip_work->excl && !flip_work->shared_count) { 170 return -EINVAL;
209 ipu_crtc->flip_state = IPU_FLIP_SUBMITTED;
210 } else {
211 ipu_crtc->flip_state = IPU_FLIP_PENDING;
212 queue_work(ipu_crtc->flip_queue,
213 &flip_work->fence_work);
214 }
215 } else {
216 ipu_crtc->flip_state = IPU_FLIP_SUBMITTED;
217 }
218 171
219 return 0; 172 return 0;
220
221free_flip_work:
222 drm_gem_object_unreference_unlocked(flip_work->bo);
223 kfree(flip_work);
224 ipu_crtc->flip_work = NULL;
225put_vblank:
226 imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);
227
228 return ret;
229} 173}
230 174
231static const struct drm_crtc_funcs ipu_crtc_funcs = { 175static void ipu_crtc_atomic_begin(struct drm_crtc *crtc,
232 .set_config = drm_crtc_helper_set_config, 176 struct drm_crtc_state *old_crtc_state)
233 .destroy = drm_crtc_cleanup, 177{
234 .page_flip = ipu_page_flip, 178 spin_lock_irq(&crtc->dev->event_lock);
235}; 179 if (crtc->state->event) {
180 WARN_ON(drm_crtc_vblank_get(crtc));
181 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
182 crtc->state->event = NULL;
183 }
184 spin_unlock_irq(&crtc->dev->event_lock);
185}
236 186
237static int ipu_crtc_mode_set(struct drm_crtc *crtc, 187static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc)
238 struct drm_display_mode *orig_mode,
239 struct drm_display_mode *mode,
240 int x, int y,
241 struct drm_framebuffer *old_fb)
242{ 188{
243 struct drm_device *dev = crtc->dev; 189 struct drm_device *dev = crtc->dev;
244 struct drm_encoder *encoder; 190 struct drm_encoder *encoder;
245 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 191 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
192 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
193 struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc->state);
246 struct ipu_di_signal_cfg sig_cfg = {}; 194 struct ipu_di_signal_cfg sig_cfg = {};
247 unsigned long encoder_types = 0; 195 unsigned long encoder_types = 0;
248 int ret;
249 196
250 dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, 197 dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
251 mode->hdisplay); 198 mode->hdisplay);
252 dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, 199 dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
253 mode->vdisplay); 200 mode->vdisplay);
254 201
255 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 202 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
256 if (encoder->crtc == crtc) 203 if (encoder->crtc == crtc)
257 encoder_types |= BIT(encoder->encoder_type); 204 encoder_types |= BIT(encoder->encoder_type);
205 }
258 206
259 dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n", 207 dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n",
260 __func__, encoder_types); 208 __func__, encoder_types);
@@ -272,114 +220,30 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
272 else 220 else
273 sig_cfg.clkflags = 0; 221 sig_cfg.clkflags = 0;
274 222
275 sig_cfg.enable_pol = !(ipu_crtc->bus_flags & DRM_BUS_FLAG_DE_LOW); 223 sig_cfg.enable_pol = !(imx_crtc_state->bus_flags & DRM_BUS_FLAG_DE_LOW);
276 /* Default to driving pixel data on negative clock edges */ 224 /* Default to driving pixel data on negative clock edges */
277 sig_cfg.clk_pol = !!(ipu_crtc->bus_flags & 225 sig_cfg.clk_pol = !!(imx_crtc_state->bus_flags &
278 DRM_BUS_FLAG_PIXDATA_POSEDGE); 226 DRM_BUS_FLAG_PIXDATA_POSEDGE);
279 sig_cfg.bus_format = ipu_crtc->bus_format; 227 sig_cfg.bus_format = imx_crtc_state->bus_format;
280 sig_cfg.v_to_h_sync = 0; 228 sig_cfg.v_to_h_sync = 0;
281 sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; 229 sig_cfg.hsync_pin = imx_crtc_state->di_hsync_pin;
282 sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; 230 sig_cfg.vsync_pin = imx_crtc_state->di_vsync_pin;
283 231
284 drm_display_mode_to_videomode(mode, &sig_cfg.mode); 232 drm_display_mode_to_videomode(mode, &sig_cfg.mode);
285 233
286 ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, 234 ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di,
287 mode->flags & DRM_MODE_FLAG_INTERLACE, 235 mode->flags & DRM_MODE_FLAG_INTERLACE,
288 ipu_crtc->bus_format, mode->hdisplay); 236 imx_crtc_state->bus_format, mode->hdisplay);
289 if (ret) { 237 ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg);
290 dev_err(ipu_crtc->dev,
291 "initializing display controller failed with %d\n",
292 ret);
293 return ret;
294 }
295
296 ret = ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg);
297 if (ret) {
298 dev_err(ipu_crtc->dev,
299 "initializing panel failed with %d\n", ret);
300 return ret;
301 }
302
303 return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode,
304 crtc->primary->fb,
305 0, 0, mode->hdisplay, mode->vdisplay,
306 x, y, mode->hdisplay, mode->vdisplay,
307 mode->flags & DRM_MODE_FLAG_INTERLACE);
308}
309
310static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc)
311{
312 unsigned long flags;
313 struct drm_device *drm = ipu_crtc->base.dev;
314 struct ipu_flip_work *work = ipu_crtc->flip_work;
315
316 spin_lock_irqsave(&drm->event_lock, flags);
317 if (work->page_flip_event)
318 drm_crtc_send_vblank_event(&ipu_crtc->base,
319 work->page_flip_event);
320 imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);
321 spin_unlock_irqrestore(&drm->event_lock, flags);
322}
323
324static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
325{
326 struct ipu_crtc *ipu_crtc = dev_id;
327
328 imx_drm_handle_vblank(ipu_crtc->imx_crtc);
329
330 if (ipu_crtc->flip_state == IPU_FLIP_SUBMITTED) {
331 struct ipu_plane *plane = ipu_crtc->plane[0];
332
333 ipu_plane_set_base(plane, ipu_crtc->base.primary->fb,
334 plane->x, plane->y);
335 ipu_crtc_handle_pageflip(ipu_crtc);
336 queue_work(ipu_crtc->flip_queue,
337 &ipu_crtc->flip_work->unref_work);
338 ipu_crtc->flip_state = IPU_FLIP_NONE;
339 }
340
341 return IRQ_HANDLED;
342}
343
344static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc,
345 const struct drm_display_mode *mode,
346 struct drm_display_mode *adjusted_mode)
347{
348 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
349 struct videomode vm;
350 int ret;
351
352 drm_display_mode_to_videomode(adjusted_mode, &vm);
353
354 ret = ipu_di_adjust_videomode(ipu_crtc->di, &vm);
355 if (ret)
356 return false;
357
358 drm_display_mode_from_videomode(&vm, adjusted_mode);
359
360 return true;
361}
362
363static void ipu_crtc_prepare(struct drm_crtc *crtc)
364{
365 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
366
367 ipu_fb_disable(ipu_crtc);
368}
369
370static void ipu_crtc_commit(struct drm_crtc *crtc)
371{
372 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
373
374 ipu_fb_enable(ipu_crtc);
375} 238}
376 239
377static const struct drm_crtc_helper_funcs ipu_helper_funcs = { 240static const struct drm_crtc_helper_funcs ipu_helper_funcs = {
378 .dpms = ipu_crtc_dpms,
379 .mode_fixup = ipu_crtc_mode_fixup, 241 .mode_fixup = ipu_crtc_mode_fixup,
380 .mode_set = ipu_crtc_mode_set, 242 .mode_set_nofb = ipu_crtc_mode_set_nofb,
381 .prepare = ipu_crtc_prepare, 243 .atomic_check = ipu_crtc_atomic_check,
382 .commit = ipu_crtc_commit, 244 .atomic_begin = ipu_crtc_atomic_begin,
245 .disable = ipu_crtc_disable,
246 .enable = ipu_crtc_enable,
383}; 247};
384 248
385static int ipu_enable_vblank(struct drm_crtc *crtc) 249static int ipu_enable_vblank(struct drm_crtc *crtc)
@@ -398,23 +262,9 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
398 disable_irq_nosync(ipu_crtc->irq); 262 disable_irq_nosync(ipu_crtc->irq);
399} 263}
400 264
401static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
402 u32 bus_format, int hsync_pin, int vsync_pin, u32 bus_flags)
403{
404 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
405
406 ipu_crtc->bus_format = bus_format;
407 ipu_crtc->bus_flags = bus_flags;
408 ipu_crtc->di_hsync_pin = hsync_pin;
409 ipu_crtc->di_vsync_pin = vsync_pin;
410
411 return 0;
412}
413
414static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = { 265static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
415 .enable_vblank = ipu_enable_vblank, 266 .enable_vblank = ipu_enable_vblank,
416 .disable_vblank = ipu_disable_vblank, 267 .disable_vblank = ipu_disable_vblank,
417 .set_interface_pix_fmt = ipu_set_interface_pix_fmt,
418 .crtc_funcs = &ipu_crtc_funcs, 268 .crtc_funcs = &ipu_crtc_funcs,
419 .crtc_helper_funcs = &ipu_helper_funcs, 269 .crtc_helper_funcs = &ipu_helper_funcs,
420}; 270};
@@ -496,8 +346,16 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
496 IPU_DP_FLOW_SYNC_FG, 346 IPU_DP_FLOW_SYNC_FG,
497 drm_crtc_mask(&ipu_crtc->base), 347 drm_crtc_mask(&ipu_crtc->base),
498 DRM_PLANE_TYPE_OVERLAY); 348 DRM_PLANE_TYPE_OVERLAY);
499 if (IS_ERR(ipu_crtc->plane[1])) 349 if (IS_ERR(ipu_crtc->plane[1])) {
500 ipu_crtc->plane[1] = NULL; 350 ipu_crtc->plane[1] = NULL;
351 } else {
352 ret = ipu_plane_get_resources(ipu_crtc->plane[1]);
353 if (ret) {
354 dev_err(ipu_crtc->dev, "getting plane 1 "
355 "resources failed with %d.\n", ret);
356 goto err_put_plane0_res;
357 }
358 }
501 } 359 }
502 360
503 ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]); 361 ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
@@ -505,16 +363,17 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
505 "imx_drm", ipu_crtc); 363 "imx_drm", ipu_crtc);
506 if (ret < 0) { 364 if (ret < 0) {
507 dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); 365 dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
508 goto err_put_plane_res; 366 goto err_put_plane1_res;
509 } 367 }
510 /* Only enable IRQ when we actually need it to trigger work. */ 368 /* Only enable IRQ when we actually need it to trigger work. */
511 disable_irq(ipu_crtc->irq); 369 disable_irq(ipu_crtc->irq);
512 370
513 ipu_crtc->flip_queue = create_singlethread_workqueue("ipu-crtc-flip");
514
515 return 0; 371 return 0;
516 372
517err_put_plane_res: 373err_put_plane1_res:
374 if (ipu_crtc->plane[1])
375 ipu_plane_put_resources(ipu_crtc->plane[1]);
376err_put_plane0_res:
518 ipu_plane_put_resources(ipu_crtc->plane[0]); 377 ipu_plane_put_resources(ipu_crtc->plane[0]);
519err_remove_crtc: 378err_remove_crtc:
520 imx_drm_remove_crtc(ipu_crtc->imx_crtc); 379 imx_drm_remove_crtc(ipu_crtc->imx_crtc);
@@ -553,9 +412,10 @@ static void ipu_drm_unbind(struct device *dev, struct device *master,
553 412
554 imx_drm_remove_crtc(ipu_crtc->imx_crtc); 413 imx_drm_remove_crtc(ipu_crtc->imx_crtc);
555 414
556 destroy_workqueue(ipu_crtc->flip_queue);
557 ipu_plane_put_resources(ipu_crtc->plane[0]);
558 ipu_put_resources(ipu_crtc); 415 ipu_put_resources(ipu_crtc);
416 if (ipu_crtc->plane[1])
417 ipu_plane_put_resources(ipu_crtc->plane[1]);
418 ipu_plane_put_resources(ipu_crtc->plane[0]);
559} 419}
560 420
561static const struct component_ops ipu_crtc_ops = { 421static const struct component_ops ipu_crtc_ops = {
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index a4bb44118d33..4ad67d015ec7 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -14,13 +14,19 @@
14 */ 14 */
15 15
16#include <drm/drmP.h> 16#include <drm/drmP.h>
17#include <drm/drm_atomic.h>
18#include <drm/drm_atomic_helper.h>
17#include <drm/drm_fb_cma_helper.h> 19#include <drm/drm_fb_cma_helper.h>
18#include <drm/drm_gem_cma_helper.h> 20#include <drm/drm_gem_cma_helper.h>
21#include <drm/drm_plane_helper.h>
19 22
20#include "video/imx-ipu-v3.h" 23#include "video/imx-ipu-v3.h"
21#include "ipuv3-plane.h" 24#include "ipuv3-plane.h"
22 25
23#define to_ipu_plane(x) container_of(x, struct ipu_plane, base) 26static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p)
27{
28 return container_of(p, struct ipu_plane, base);
29}
24 30
25static const uint32_t ipu_plane_formats[] = { 31static const uint32_t ipu_plane_formats[] = {
26 DRM_FORMAT_ARGB1555, 32 DRM_FORMAT_ARGB1555,
@@ -53,62 +59,67 @@ int ipu_plane_irq(struct ipu_plane *ipu_plane)
53 IPU_IRQ_EOF); 59 IPU_IRQ_EOF);
54} 60}
55 61
56static int calc_vref(struct drm_display_mode *mode) 62static inline unsigned long
63drm_plane_state_to_eba(struct drm_plane_state *state)
57{ 64{
58 unsigned long htotal, vtotal; 65 struct drm_framebuffer *fb = state->fb;
66 struct drm_gem_cma_object *cma_obj;
59 67
60 htotal = mode->htotal; 68 cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
61 vtotal = mode->vtotal; 69 BUG_ON(!cma_obj);
62 70
63 if (!htotal || !vtotal) 71 return cma_obj->paddr + fb->offsets[0] +
64 return 60; 72 fb->pitches[0] * (state->src_y >> 16) +
65 73 (fb->bits_per_pixel >> 3) * (state->src_x >> 16);
66 return DIV_ROUND_UP(mode->clock * 1000, vtotal * htotal);
67} 74}
68 75
69static inline int calc_bandwidth(int width, int height, unsigned int vref) 76static inline unsigned long
77drm_plane_state_to_ubo(struct drm_plane_state *state)
70{ 78{
71 return width * height * vref; 79 struct drm_framebuffer *fb = state->fb;
72} 80 struct drm_gem_cma_object *cma_obj;
81 unsigned long eba = drm_plane_state_to_eba(state);
73 82
74int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, 83 cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
75 int x, int y) 84 BUG_ON(!cma_obj);
76{
77 struct drm_gem_cma_object *cma_obj[3];
78 unsigned long eba, ubo, vbo;
79 int active, i;
80 85
81 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { 86 return cma_obj->paddr + fb->offsets[1] +
82 cma_obj[i] = drm_fb_cma_get_gem_obj(fb, i); 87 fb->pitches[1] * (state->src_y >> 16) / 2 +
83 if (!cma_obj[i]) { 88 (state->src_x >> 16) / 2 - eba;
84 DRM_DEBUG_KMS("plane %d entry is null.\n", i); 89}
85 return -EFAULT;
86 }
87 }
88 90
89 eba = cma_obj[0]->paddr + fb->offsets[0] + 91static inline unsigned long
90 fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x; 92drm_plane_state_to_vbo(struct drm_plane_state *state)
93{
94 struct drm_framebuffer *fb = state->fb;
95 struct drm_gem_cma_object *cma_obj;
96 unsigned long eba = drm_plane_state_to_eba(state);
91 97
92 if (eba & 0x7) { 98 cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
93 DRM_DEBUG_KMS("base address must be a multiple of 8.\n"); 99 BUG_ON(!cma_obj);
94 return -EINVAL;
95 }
96 100
97 if (fb->pitches[0] < 1 || fb->pitches[0] > 16384) { 101 return cma_obj->paddr + fb->offsets[2] +
98 DRM_DEBUG_KMS("pitches out of range.\n"); 102 fb->pitches[2] * (state->src_y >> 16) / 2 +
99 return -EINVAL; 103 (state->src_x >> 16) / 2 - eba;
100 } 104}
101 105
102 if (ipu_plane->enabled && fb->pitches[0] != ipu_plane->stride[0]) { 106static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane,
103 DRM_DEBUG_KMS("pitches must not change while plane is enabled.\n"); 107 struct drm_plane_state *old_state)
104 return -EINVAL; 108{
105 } 109 struct drm_plane *plane = &ipu_plane->base;
110 struct drm_plane_state *state = plane->state;
111 struct drm_framebuffer *fb = state->fb;
112 unsigned long eba, ubo, vbo;
113 int active;
106 114
107 ipu_plane->stride[0] = fb->pitches[0]; 115 eba = drm_plane_state_to_eba(state);
108 116
109 switch (fb->pixel_format) { 117 switch (fb->pixel_format) {
110 case DRM_FORMAT_YUV420: 118 case DRM_FORMAT_YUV420:
111 case DRM_FORMAT_YVU420: 119 case DRM_FORMAT_YVU420:
120 if (old_state->fb)
121 break;
122
112 /* 123 /*
113 * Multiplanar formats have to meet the following restrictions: 124 * Multiplanar formats have to meet the following restrictions:
114 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO 125 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
@@ -117,59 +128,28 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
117 * - Only EBA may be changed while scanout is active 128 * - Only EBA may be changed while scanout is active
118 * - The strides of U and V planes must be identical. 129 * - The strides of U and V planes must be identical.
119 */ 130 */
120 ubo = cma_obj[1]->paddr + fb->offsets[1] + 131 ubo = drm_plane_state_to_ubo(state);
121 fb->pitches[1] * y / 2 + x / 2 - eba; 132 vbo = drm_plane_state_to_vbo(state);
122 vbo = cma_obj[2]->paddr + fb->offsets[2] +
123 fb->pitches[2] * y / 2 + x / 2 - eba;
124 133
125 if ((ubo & 0x7) || (vbo & 0x7)) { 134 if (fb->pixel_format == DRM_FORMAT_YUV420)
126 DRM_DEBUG_KMS("U/V buffer offsets must be a multiple of 8.\n"); 135 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
127 return -EINVAL; 136 fb->pitches[1], ubo, vbo);
128 } 137 else
129 138 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
130 if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) { 139 fb->pitches[1], vbo, ubo);
131 DRM_DEBUG_KMS("U/V buffer offsets must be positive and not larger than 0xfffff8.\n");
132 return -EINVAL;
133 }
134
135 if (ipu_plane->enabled && ((ipu_plane->u_offset != ubo) ||
136 (ipu_plane->v_offset != vbo))) {
137 DRM_DEBUG_KMS("U/V buffer offsets must not change while plane is enabled.\n");
138 return -EINVAL;
139 }
140
141 if (fb->pitches[1] != fb->pitches[2]) {
142 DRM_DEBUG_KMS("U/V pitches must be identical.\n");
143 return -EINVAL;
144 }
145
146 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) {
147 DRM_DEBUG_KMS("U/V pitches out of range.\n");
148 return -EINVAL;
149 }
150
151 if (ipu_plane->enabled &&
152 (ipu_plane->stride[1] != fb->pitches[1])) {
153 DRM_DEBUG_KMS("U/V pitches must not change while plane is enabled.\n");
154 return -EINVAL;
155 }
156
157 ipu_plane->u_offset = ubo;
158 ipu_plane->v_offset = vbo;
159 ipu_plane->stride[1] = fb->pitches[1];
160 140
161 dev_dbg(ipu_plane->base.dev->dev, 141 dev_dbg(ipu_plane->base.dev->dev,
162 "phys = %pad %pad %pad, x = %d, y = %d", 142 "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
163 &cma_obj[0]->paddr, &cma_obj[1]->paddr, 143 state->src_x >> 16, state->src_y >> 16);
164 &cma_obj[2]->paddr, x, y);
165 break; 144 break;
166 default: 145 default:
167 dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d", 146 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
168 &cma_obj[0]->paddr, x, y); 147 eba, state->src_x >> 16, state->src_y >> 16);
148
169 break; 149 break;
170 } 150 }
171 151
172 if (ipu_plane->enabled) { 152 if (old_state->fb) {
173 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); 153 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
174 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); 154 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
175 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); 155 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
@@ -177,155 +157,6 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
177 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); 157 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
178 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); 158 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
179 } 159 }
180
181 /* cache offsets for subsequent pageflips */
182 ipu_plane->x = x;
183 ipu_plane->y = y;
184
185 return 0;
186}
187
188int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
189 struct drm_display_mode *mode,
190 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
191 unsigned int crtc_w, unsigned int crtc_h,
192 uint32_t src_x, uint32_t src_y,
193 uint32_t src_w, uint32_t src_h, bool interlaced)
194{
195 struct device *dev = ipu_plane->base.dev->dev;
196 int ret;
197
198 /* no scaling */
199 if (src_w != crtc_w || src_h != crtc_h)
200 return -EINVAL;
201
202 /* clip to crtc bounds */
203 if (crtc_x < 0) {
204 if (-crtc_x > crtc_w)
205 return -EINVAL;
206 src_x += -crtc_x;
207 src_w -= -crtc_x;
208 crtc_w -= -crtc_x;
209 crtc_x = 0;
210 }
211 if (crtc_y < 0) {
212 if (-crtc_y > crtc_h)
213 return -EINVAL;
214 src_y += -crtc_y;
215 src_h -= -crtc_y;
216 crtc_h -= -crtc_y;
217 crtc_y = 0;
218 }
219 if (crtc_x + crtc_w > mode->hdisplay) {
220 if (crtc_x > mode->hdisplay)
221 return -EINVAL;
222 crtc_w = mode->hdisplay - crtc_x;
223 src_w = crtc_w;
224 }
225 if (crtc_y + crtc_h > mode->vdisplay) {
226 if (crtc_y > mode->vdisplay)
227 return -EINVAL;
228 crtc_h = mode->vdisplay - crtc_y;
229 src_h = crtc_h;
230 }
231 /* full plane minimum width is 13 pixels */
232 if (crtc_w < 13 && (ipu_plane->dp_flow != IPU_DP_FLOW_SYNC_FG))
233 return -EINVAL;
234 if (crtc_h < 2)
235 return -EINVAL;
236
237 /*
238 * since we cannot touch active IDMAC channels, we do not support
239 * resizing the enabled plane or changing its format
240 */
241 if (ipu_plane->enabled) {
242 if (src_w != ipu_plane->w || src_h != ipu_plane->h ||
243 fb->pixel_format != ipu_plane->base.fb->pixel_format)
244 return -EINVAL;
245
246 return ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
247 }
248
249 switch (ipu_plane->dp_flow) {
250 case IPU_DP_FLOW_SYNC_BG:
251 ret = ipu_dp_setup_channel(ipu_plane->dp,
252 IPUV3_COLORSPACE_RGB,
253 IPUV3_COLORSPACE_RGB);
254 if (ret) {
255 dev_err(dev,
256 "initializing display processor failed with %d\n",
257 ret);
258 return ret;
259 }
260 ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
261 break;
262 case IPU_DP_FLOW_SYNC_FG:
263 ipu_dp_setup_channel(ipu_plane->dp,
264 ipu_drm_fourcc_to_colorspace(fb->pixel_format),
265 IPUV3_COLORSPACE_UNKNOWN);
266 ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y);
267 /* Enable local alpha on partial plane */
268 switch (fb->pixel_format) {
269 case DRM_FORMAT_ARGB1555:
270 case DRM_FORMAT_ABGR1555:
271 case DRM_FORMAT_RGBA5551:
272 case DRM_FORMAT_BGRA5551:
273 case DRM_FORMAT_ARGB4444:
274 case DRM_FORMAT_ARGB8888:
275 case DRM_FORMAT_ABGR8888:
276 case DRM_FORMAT_RGBA8888:
277 case DRM_FORMAT_BGRA8888:
278 ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);
279 break;
280 default:
281 break;
282 }
283 }
284
285 ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
286 calc_bandwidth(crtc_w, crtc_h,
287 calc_vref(mode)), 64);
288 if (ret) {
289 dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
290 return ret;
291 }
292
293 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, crtc_w);
294
295 ipu_cpmem_zero(ipu_plane->ipu_ch);
296 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h);
297 ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format);
298 if (ret < 0) {
299 dev_err(dev, "unsupported pixel format 0x%08x\n",
300 fb->pixel_format);
301 return ret;
302 }
303 ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
304 ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
305 ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
306
307 ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
308 if (ret < 0)
309 return ret;
310 if (interlaced)
311 ipu_cpmem_interlaced_scan(ipu_plane->ipu_ch, fb->pitches[0]);
312
313 if (fb->pixel_format == DRM_FORMAT_YUV420) {
314 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
315 ipu_plane->stride[1],
316 ipu_plane->u_offset,
317 ipu_plane->v_offset);
318 } else if (fb->pixel_format == DRM_FORMAT_YVU420) {
319 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
320 ipu_plane->stride[1],
321 ipu_plane->v_offset,
322 ipu_plane->u_offset);
323 }
324
325 ipu_plane->w = src_w;
326 ipu_plane->h = src_h;
327
328 return 0;
329} 160}
330 161
331void ipu_plane_put_resources(struct ipu_plane *ipu_plane) 162void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
@@ -372,7 +203,7 @@ err_out:
372 return ret; 203 return ret;
373} 204}
374 205
375void ipu_plane_enable(struct ipu_plane *ipu_plane) 206static void ipu_plane_enable(struct ipu_plane *ipu_plane)
376{ 207{
377 if (ipu_plane->dp) 208 if (ipu_plane->dp)
378 ipu_dp_enable(ipu_plane->ipu); 209 ipu_dp_enable(ipu_plane->ipu);
@@ -380,14 +211,10 @@ void ipu_plane_enable(struct ipu_plane *ipu_plane)
380 ipu_idmac_enable_channel(ipu_plane->ipu_ch); 211 ipu_idmac_enable_channel(ipu_plane->ipu_ch);
381 if (ipu_plane->dp) 212 if (ipu_plane->dp)
382 ipu_dp_enable_channel(ipu_plane->dp); 213 ipu_dp_enable_channel(ipu_plane->dp);
383
384 ipu_plane->enabled = true;
385} 214}
386 215
387void ipu_plane_disable(struct ipu_plane *ipu_plane) 216static void ipu_plane_disable(struct ipu_plane *ipu_plane)
388{ 217{
389 ipu_plane->enabled = false;
390
391 ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50); 218 ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
392 219
393 if (ipu_plane->dp) 220 if (ipu_plane->dp)
@@ -398,74 +225,225 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane)
398 ipu_dp_disable(ipu_plane->ipu); 225 ipu_dp_disable(ipu_plane->ipu);
399} 226}
400 227
401/* 228static int ipu_disable_plane(struct drm_plane *plane)
402 * drm_plane API
403 */
404
405static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
406 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
407 unsigned int crtc_w, unsigned int crtc_h,
408 uint32_t src_x, uint32_t src_y,
409 uint32_t src_w, uint32_t src_h)
410{ 229{
411 struct ipu_plane *ipu_plane = to_ipu_plane(plane); 230 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
412 int ret = 0;
413
414 DRM_DEBUG_KMS("plane - %p\n", plane);
415
416 if (!ipu_plane->enabled)
417 ret = ipu_plane_get_resources(ipu_plane);
418 if (ret < 0)
419 return ret;
420
421 ret = ipu_plane_mode_set(ipu_plane, crtc, &crtc->hwmode, fb,
422 crtc_x, crtc_y, crtc_w, crtc_h,
423 src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16,
424 false);
425 if (ret < 0) {
426 ipu_plane_put_resources(ipu_plane);
427 return ret;
428 }
429 231
430 if (crtc != plane->crtc) 232 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
431 dev_dbg(plane->dev->dev, "crtc change: %p -> %p\n",
432 plane->crtc, crtc);
433 233
434 if (!ipu_plane->enabled) 234 ipu_plane_disable(ipu_plane);
435 ipu_plane_enable(ipu_plane);
436 235
437 return 0; 236 return 0;
438} 237}
439 238
440static int ipu_disable_plane(struct drm_plane *plane) 239static void ipu_plane_destroy(struct drm_plane *plane)
441{ 240{
442 struct ipu_plane *ipu_plane = to_ipu_plane(plane); 241 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
443 242
444 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 243 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
445 244
446 if (ipu_plane->enabled) 245 ipu_disable_plane(plane);
447 ipu_plane_disable(ipu_plane); 246 drm_plane_cleanup(plane);
247 kfree(ipu_plane);
248}
448 249
449 ipu_plane_put_resources(ipu_plane); 250static const struct drm_plane_funcs ipu_plane_funcs = {
251 .update_plane = drm_atomic_helper_update_plane,
252 .disable_plane = drm_atomic_helper_disable_plane,
253 .destroy = ipu_plane_destroy,
254 .reset = drm_atomic_helper_plane_reset,
255 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
256 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
257};
258
259static int ipu_plane_atomic_check(struct drm_plane *plane,
260 struct drm_plane_state *state)
261{
262 struct drm_plane_state *old_state = plane->state;
263 struct drm_crtc_state *crtc_state;
264 struct device *dev = plane->dev->dev;
265 struct drm_framebuffer *fb = state->fb;
266 struct drm_framebuffer *old_fb = old_state->fb;
267 unsigned long eba, ubo, vbo, old_ubo, old_vbo;
268
269 /* Ok to disable */
270 if (!fb)
271 return 0;
272
273 if (!state->crtc)
274 return -EINVAL;
275
276 crtc_state =
277 drm_atomic_get_existing_crtc_state(state->state, state->crtc);
278 if (WARN_ON(!crtc_state))
279 return -EINVAL;
280
281 /* CRTC should be enabled */
282 if (!crtc_state->enable)
283 return -EINVAL;
284
285 /* no scaling */
286 if (state->src_w >> 16 != state->crtc_w ||
287 state->src_h >> 16 != state->crtc_h)
288 return -EINVAL;
289
290 switch (plane->type) {
291 case DRM_PLANE_TYPE_PRIMARY:
292 /* full plane doesn't support partial off screen */
293 if (state->crtc_x || state->crtc_y ||
294 state->crtc_w != crtc_state->adjusted_mode.hdisplay ||
295 state->crtc_h != crtc_state->adjusted_mode.vdisplay)
296 return -EINVAL;
297
298 /* full plane minimum width is 13 pixels */
299 if (state->crtc_w < 13)
300 return -EINVAL;
301 break;
302 case DRM_PLANE_TYPE_OVERLAY:
303 if (state->crtc_x < 0 || state->crtc_y < 0)
304 return -EINVAL;
305
306 if (state->crtc_x + state->crtc_w >
307 crtc_state->adjusted_mode.hdisplay)
308 return -EINVAL;
309 if (state->crtc_y + state->crtc_h >
310 crtc_state->adjusted_mode.vdisplay)
311 return -EINVAL;
312 break;
313 default:
314 dev_warn(dev, "Unsupported plane type\n");
315 return -EINVAL;
316 }
317
318 if (state->crtc_h < 2)
319 return -EINVAL;
320
321 /*
322 * since we cannot touch active IDMAC channels, we do not support
323 * resizing the enabled plane or changing its format
324 */
325 if (old_fb && (state->src_w != old_state->src_w ||
326 state->src_h != old_state->src_h ||
327 fb->pixel_format != old_fb->pixel_format))
328 return -EINVAL;
329
330 eba = drm_plane_state_to_eba(state);
331
332 if (eba & 0x7)
333 return -EINVAL;
334
335 if (fb->pitches[0] < 1 || fb->pitches[0] > 16384)
336 return -EINVAL;
337
338 if (old_fb && fb->pitches[0] != old_fb->pitches[0])
339 return -EINVAL;
340
341 switch (fb->pixel_format) {
342 case DRM_FORMAT_YUV420:
343 case DRM_FORMAT_YVU420:
344 /*
345 * Multiplanar formats have to meet the following restrictions:
346 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
347 * - EBA, UBO and VBO are a multiple of 8
348 * - UBO and VBO are unsigned and not larger than 0xfffff8
349 * - Only EBA may be changed while scanout is active
350 * - The strides of U and V planes must be identical.
351 */
352 ubo = drm_plane_state_to_ubo(state);
353 vbo = drm_plane_state_to_vbo(state);
354
355 if ((ubo & 0x7) || (vbo & 0x7))
356 return -EINVAL;
357
358 if ((ubo > 0xfffff8) || (vbo > 0xfffff8))
359 return -EINVAL;
360
361 if (old_fb) {
362 old_ubo = drm_plane_state_to_ubo(old_state);
363 old_vbo = drm_plane_state_to_vbo(old_state);
364 if (ubo != old_ubo || vbo != old_vbo)
365 return -EINVAL;
366 }
367
368 if (fb->pitches[1] != fb->pitches[2])
369 return -EINVAL;
370
371 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
372 return -EINVAL;
373
374 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
375 return -EINVAL;
376 }
450 377
451 return 0; 378 return 0;
452} 379}
453 380
454static void ipu_plane_destroy(struct drm_plane *plane) 381static void ipu_plane_atomic_disable(struct drm_plane *plane,
382 struct drm_plane_state *old_state)
383{
384 ipu_disable_plane(plane);
385}
386
387static void ipu_plane_atomic_update(struct drm_plane *plane,
388 struct drm_plane_state *old_state)
455{ 389{
456 struct ipu_plane *ipu_plane = to_ipu_plane(plane); 390 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
391 struct drm_plane_state *state = plane->state;
392 enum ipu_color_space ics;
457 393
458 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 394 if (old_state->fb) {
395 ipu_plane_atomic_set_base(ipu_plane, old_state);
396 return;
397 }
459 398
460 ipu_disable_plane(plane); 399 switch (ipu_plane->dp_flow) {
461 drm_plane_cleanup(plane); 400 case IPU_DP_FLOW_SYNC_BG:
462 kfree(ipu_plane); 401 ipu_dp_setup_channel(ipu_plane->dp,
402 IPUV3_COLORSPACE_RGB,
403 IPUV3_COLORSPACE_RGB);
404 ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
405 break;
406 case IPU_DP_FLOW_SYNC_FG:
407 ics = ipu_drm_fourcc_to_colorspace(state->fb->pixel_format);
408 ipu_dp_setup_channel(ipu_plane->dp, ics,
409 IPUV3_COLORSPACE_UNKNOWN);
410 ipu_dp_set_window_pos(ipu_plane->dp, state->crtc_x,
411 state->crtc_y);
412 /* Enable local alpha on partial plane */
413 switch (state->fb->pixel_format) {
414 case DRM_FORMAT_ARGB1555:
415 case DRM_FORMAT_ABGR1555:
416 case DRM_FORMAT_RGBA5551:
417 case DRM_FORMAT_BGRA5551:
418 case DRM_FORMAT_ARGB4444:
419 case DRM_FORMAT_ARGB8888:
420 case DRM_FORMAT_ABGR8888:
421 case DRM_FORMAT_RGBA8888:
422 case DRM_FORMAT_BGRA8888:
423 ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);
424 break;
425 default:
426 break;
427 }
428 }
429
430 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, state->crtc_w);
431
432 ipu_cpmem_zero(ipu_plane->ipu_ch);
433 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, state->src_w >> 16,
434 state->src_h >> 16);
435 ipu_cpmem_set_fmt(ipu_plane->ipu_ch, state->fb->pixel_format);
436 ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
437 ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
438 ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]);
439 ipu_plane_atomic_set_base(ipu_plane, old_state);
440 ipu_plane_enable(ipu_plane);
463} 441}
464 442
465static const struct drm_plane_funcs ipu_plane_funcs = { 443static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
466 .update_plane = ipu_update_plane, 444 .atomic_check = ipu_plane_atomic_check,
467 .disable_plane = ipu_disable_plane, 445 .atomic_disable = ipu_plane_atomic_disable,
468 .destroy = ipu_plane_destroy, 446 .atomic_update = ipu_plane_atomic_update,
469}; 447};
470 448
471struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, 449struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
@@ -498,5 +476,7 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
498 return ERR_PTR(ret); 476 return ERR_PTR(ret);
499 } 477 }
500 478
479 drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
480
501 return ipu_plane; 481 return ipu_plane;
502} 482}
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h
index 4448fd4ad4eb..338b88a74eb6 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.h
+++ b/drivers/gpu/drm/imx/ipuv3-plane.h
@@ -23,17 +23,6 @@ struct ipu_plane {
23 23
24 int dma; 24 int dma;
25 int dp_flow; 25 int dp_flow;
26
27 int x;
28 int y;
29 int w;
30 int h;
31
32 unsigned int u_offset;
33 unsigned int v_offset;
34 unsigned int stride[2];
35
36 bool enabled;
37}; 26};
38 27
39struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, 28struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
@@ -48,11 +37,6 @@ int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,
48 uint32_t src_x, uint32_t src_y, uint32_t src_w, 37 uint32_t src_x, uint32_t src_y, uint32_t src_w,
49 uint32_t src_h, bool interlaced); 38 uint32_t src_h, bool interlaced);
50 39
51void ipu_plane_enable(struct ipu_plane *plane);
52void ipu_plane_disable(struct ipu_plane *plane);
53int ipu_plane_set_base(struct ipu_plane *plane, struct drm_framebuffer *fb,
54 int x, int y);
55
56int ipu_plane_get_resources(struct ipu_plane *plane); 40int ipu_plane_get_resources(struct ipu_plane *plane);
57void ipu_plane_put_resources(struct ipu_plane *plane); 41void ipu_plane_put_resources(struct ipu_plane *plane);
58 42
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index 2d1fd02cd3d6..1dad297b01fd 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -16,6 +16,7 @@
16#include <linux/component.h> 16#include <linux/component.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <drm/drmP.h> 18#include <drm/drmP.h>
19#include <drm/drm_atomic_helper.h>
19#include <drm/drm_fb_helper.h> 20#include <drm/drm_fb_helper.h>
20#include <drm/drm_crtc_helper.h> 21#include <drm/drm_crtc_helper.h>
21#include <drm/drm_panel.h> 22#include <drm/drm_panel.h>
@@ -25,9 +26,6 @@
25 26
26#include "imx-drm.h" 27#include "imx-drm.h"
27 28
28#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector)
29#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder)
30
31struct imx_parallel_display { 29struct imx_parallel_display {
32 struct drm_connector connector; 30 struct drm_connector connector;
33 struct drm_encoder encoder; 31 struct drm_encoder encoder;
@@ -37,8 +35,19 @@ struct imx_parallel_display {
37 u32 bus_format; 35 u32 bus_format;
38 struct drm_display_mode mode; 36 struct drm_display_mode mode;
39 struct drm_panel *panel; 37 struct drm_panel *panel;
38 struct drm_bridge *bridge;
40}; 39};
41 40
41static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector *c)
42{
43 return container_of(c, struct imx_parallel_display, connector);
44}
45
46static inline struct imx_parallel_display *enc_to_imxpd(struct drm_encoder *e)
47{
48 return container_of(e, struct imx_parallel_display, encoder);
49}
50
42static enum drm_connector_status imx_pd_connector_detect( 51static enum drm_connector_status imx_pd_connector_detect(
43 struct drm_connector *connector, bool force) 52 struct drm_connector *connector, bool force)
44{ 53{
@@ -53,11 +62,7 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
53 62
54 if (imxpd->panel && imxpd->panel->funcs && 63 if (imxpd->panel && imxpd->panel->funcs &&
55 imxpd->panel->funcs->get_modes) { 64 imxpd->panel->funcs->get_modes) {
56 struct drm_display_info *di = &connector->display_info;
57
58 num_modes = imxpd->panel->funcs->get_modes(imxpd->panel); 65 num_modes = imxpd->panel->funcs->get_modes(imxpd->panel);
59 if (!imxpd->bus_format && di->num_bus_formats)
60 imxpd->bus_format = di->bus_formats[0];
61 if (num_modes > 0) 66 if (num_modes > 0)
62 return num_modes; 67 return num_modes;
63 } 68 }
@@ -69,10 +74,16 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
69 74
70 if (np) { 75 if (np) {
71 struct drm_display_mode *mode = drm_mode_create(connector->dev); 76 struct drm_display_mode *mode = drm_mode_create(connector->dev);
77 int ret;
72 78
73 if (!mode) 79 if (!mode)
74 return -EINVAL; 80 return -EINVAL;
75 of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE); 81
82 ret = of_get_drm_display_mode(np, &imxpd->mode,
83 OF_USE_NATIVE_MODE);
84 if (ret)
85 return ret;
86
76 drm_mode_copy(mode, &imxpd->mode); 87 drm_mode_copy(mode, &imxpd->mode);
77 mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 88 mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
78 drm_mode_probed_add(connector, mode); 89 drm_mode_probed_add(connector, mode);
@@ -90,24 +101,7 @@ static struct drm_encoder *imx_pd_connector_best_encoder(
90 return &imxpd->encoder; 101 return &imxpd->encoder;
91} 102}
92 103
93static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) 104static void imx_pd_encoder_enable(struct drm_encoder *encoder)
94{
95 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
96
97 if (mode != DRM_MODE_DPMS_ON)
98 drm_panel_disable(imxpd->panel);
99 else
100 drm_panel_enable(imxpd->panel);
101}
102
103static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
104{
105 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
106 imx_drm_set_bus_config(encoder, imxpd->bus_format, 2, 3,
107 imxpd->connector.display_info.bus_flags);
108}
109
110static void imx_pd_encoder_commit(struct drm_encoder *encoder)
111{ 105{
112 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); 106 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
113 107
@@ -115,12 +109,6 @@ static void imx_pd_encoder_commit(struct drm_encoder *encoder)
115 drm_panel_enable(imxpd->panel); 109 drm_panel_enable(imxpd->panel);
116} 110}
117 111
118static void imx_pd_encoder_mode_set(struct drm_encoder *encoder,
119 struct drm_display_mode *orig_mode,
120 struct drm_display_mode *mode)
121{
122}
123
124static void imx_pd_encoder_disable(struct drm_encoder *encoder) 112static void imx_pd_encoder_disable(struct drm_encoder *encoder)
125{ 113{
126 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); 114 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
@@ -129,11 +117,33 @@ static void imx_pd_encoder_disable(struct drm_encoder *encoder)
129 drm_panel_unprepare(imxpd->panel); 117 drm_panel_unprepare(imxpd->panel);
130} 118}
131 119
120static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder,
121 struct drm_crtc_state *crtc_state,
122 struct drm_connector_state *conn_state)
123{
124 struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
125 struct drm_display_info *di = &conn_state->connector->display_info;
126 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
127
128 imx_crtc_state->bus_flags = di->bus_flags;
129 if (!imxpd->bus_format && di->num_bus_formats)
130 imx_crtc_state->bus_format = di->bus_formats[0];
131 else
132 imx_crtc_state->bus_format = imxpd->bus_format;
133 imx_crtc_state->di_hsync_pin = 2;
134 imx_crtc_state->di_vsync_pin = 3;
135
136 return 0;
137}
138
132static const struct drm_connector_funcs imx_pd_connector_funcs = { 139static const struct drm_connector_funcs imx_pd_connector_funcs = {
133 .dpms = drm_helper_connector_dpms, 140 .dpms = drm_atomic_helper_connector_dpms,
134 .fill_modes = drm_helper_probe_single_connector_modes, 141 .fill_modes = drm_helper_probe_single_connector_modes,
135 .detect = imx_pd_connector_detect, 142 .detect = imx_pd_connector_detect,
136 .destroy = imx_drm_connector_destroy, 143 .destroy = imx_drm_connector_destroy,
144 .reset = drm_atomic_helper_connector_reset,
145 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
146 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
137}; 147};
138 148
139static const struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = { 149static const struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
@@ -146,20 +156,18 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = {
146}; 156};
147 157
148static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { 158static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
149 .dpms = imx_pd_encoder_dpms, 159 .enable = imx_pd_encoder_enable,
150 .prepare = imx_pd_encoder_prepare,
151 .commit = imx_pd_encoder_commit,
152 .mode_set = imx_pd_encoder_mode_set,
153 .disable = imx_pd_encoder_disable, 160 .disable = imx_pd_encoder_disable,
161 .atomic_check = imx_pd_encoder_atomic_check,
154}; 162};
155 163
156static int imx_pd_register(struct drm_device *drm, 164static int imx_pd_register(struct drm_device *drm,
157 struct imx_parallel_display *imxpd) 165 struct imx_parallel_display *imxpd)
158{ 166{
167 struct drm_encoder *encoder = &imxpd->encoder;
159 int ret; 168 int ret;
160 169
161 ret = imx_drm_encoder_parse_of(drm, &imxpd->encoder, 170 ret = imx_drm_encoder_parse_of(drm, encoder, imxpd->dev->of_node);
162 imxpd->dev->of_node);
163 if (ret) 171 if (ret)
164 return ret; 172 return ret;
165 173
@@ -170,19 +178,33 @@ static int imx_pd_register(struct drm_device *drm,
170 */ 178 */
171 imxpd->connector.dpms = DRM_MODE_DPMS_OFF; 179 imxpd->connector.dpms = DRM_MODE_DPMS_OFF;
172 180
173 drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs); 181 drm_encoder_helper_add(encoder, &imx_pd_encoder_helper_funcs);
174 drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs, 182 drm_encoder_init(drm, encoder, &imx_pd_encoder_funcs,
175 DRM_MODE_ENCODER_NONE, NULL); 183 DRM_MODE_ENCODER_NONE, NULL);
176 184
177 drm_connector_helper_add(&imxpd->connector, 185 if (!imxpd->bridge) {
178 &imx_pd_connector_helper_funcs); 186 drm_connector_helper_add(&imxpd->connector,
179 drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs, 187 &imx_pd_connector_helper_funcs);
180 DRM_MODE_CONNECTOR_VGA); 188 drm_connector_init(drm, &imxpd->connector,
189 &imx_pd_connector_funcs,
190 DRM_MODE_CONNECTOR_VGA);
191 }
181 192
182 if (imxpd->panel) 193 if (imxpd->panel)
183 drm_panel_attach(imxpd->panel, &imxpd->connector); 194 drm_panel_attach(imxpd->panel, &imxpd->connector);
184 195
185 drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder); 196 if (imxpd->bridge) {
197 imxpd->bridge->encoder = encoder;
198 encoder->bridge = imxpd->bridge;
199 ret = drm_bridge_attach(drm, imxpd->bridge);
200 if (ret < 0) {
201 dev_err(imxpd->dev, "failed to attach bridge: %d\n",
202 ret);
203 return ret;
204 }
205 } else {
206 drm_mode_connector_attach_encoder(&imxpd->connector, encoder);
207 }
186 208
187 return 0; 209 return 0;
188} 210}
@@ -195,6 +217,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
195 const u8 *edidp; 217 const u8 *edidp;
196 struct imx_parallel_display *imxpd; 218 struct imx_parallel_display *imxpd;
197 int ret; 219 int ret;
220 u32 bus_format = 0;
198 const char *fmt; 221 const char *fmt;
199 222
200 imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL); 223 imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
@@ -208,14 +231,15 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
208 ret = of_property_read_string(np, "interface-pix-fmt", &fmt); 231 ret = of_property_read_string(np, "interface-pix-fmt", &fmt);
209 if (!ret) { 232 if (!ret) {
210 if (!strcmp(fmt, "rgb24")) 233 if (!strcmp(fmt, "rgb24"))
211 imxpd->bus_format = MEDIA_BUS_FMT_RGB888_1X24; 234 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
212 else if (!strcmp(fmt, "rgb565")) 235 else if (!strcmp(fmt, "rgb565"))
213 imxpd->bus_format = MEDIA_BUS_FMT_RGB565_1X16; 236 bus_format = MEDIA_BUS_FMT_RGB565_1X16;
214 else if (!strcmp(fmt, "bgr666")) 237 else if (!strcmp(fmt, "bgr666"))
215 imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X18; 238 bus_format = MEDIA_BUS_FMT_RGB666_1X18;
216 else if (!strcmp(fmt, "lvds666")) 239 else if (!strcmp(fmt, "lvds666"))
217 imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; 240 bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
218 } 241 }
242 imxpd->bus_format = bus_format;
219 243
220 /* port@1 is the output port */ 244 /* port@1 is the output port */
221 ep = of_graph_get_endpoint_by_regs(np, 1, -1); 245 ep = of_graph_get_endpoint_by_regs(np, 1, -1);
@@ -223,13 +247,30 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
223 struct device_node *remote; 247 struct device_node *remote;
224 248
225 remote = of_graph_get_remote_port_parent(ep); 249 remote = of_graph_get_remote_port_parent(ep);
250 if (!remote) {
251 dev_warn(dev, "endpoint %s not connected\n",
252 ep->full_name);
253 of_node_put(ep);
254 return -ENODEV;
255 }
226 of_node_put(ep); 256 of_node_put(ep);
227 if (remote) { 257
228 imxpd->panel = of_drm_find_panel(remote); 258 imxpd->panel = of_drm_find_panel(remote);
229 of_node_put(remote); 259 if (imxpd->panel) {
260 dev_dbg(dev, "found panel %s\n", remote->full_name);
261 } else {
262 imxpd->bridge = of_drm_find_bridge(remote);
263 if (imxpd->bridge)
264 dev_dbg(dev, "found bridge %s\n",
265 remote->full_name);
230 } 266 }
231 if (!imxpd->panel) 267 if (!imxpd->panel && !imxpd->bridge) {
268 dev_dbg(dev, "waiting for panel or bridge %s\n",
269 remote->full_name);
270 of_node_put(remote);
232 return -EPROBE_DEFER; 271 return -EPROBE_DEFER;
272 }
273 of_node_put(remote);
233 } 274 }
234 275
235 imxpd->dev = dev; 276 imxpd->dev = dev;
diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 2f29780e7c68..659475c1e44a 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -150,6 +150,9 @@ static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
150static int ipu_bus_format_to_map(u32 fmt) 150static int ipu_bus_format_to_map(u32 fmt)
151{ 151{
152 switch (fmt) { 152 switch (fmt) {
153 default:
154 WARN_ON(1);
155 /* fall-through */
153 case MEDIA_BUS_FMT_RGB888_1X24: 156 case MEDIA_BUS_FMT_RGB888_1X24:
154 return IPU_DC_MAP_RGB24; 157 return IPU_DC_MAP_RGB24;
155 case MEDIA_BUS_FMT_RGB565_1X16: 158 case MEDIA_BUS_FMT_RGB565_1X16:
@@ -162,8 +165,6 @@ static int ipu_bus_format_to_map(u32 fmt)
162 return IPU_DC_MAP_LVDS666; 165 return IPU_DC_MAP_LVDS666;
163 case MEDIA_BUS_FMT_BGR888_1X24: 166 case MEDIA_BUS_FMT_BGR888_1X24:
164 return IPU_DC_MAP_BGR24; 167 return IPU_DC_MAP_BGR24;
165 default:
166 return -EINVAL;
167 } 168 }
168} 169}
169 170
@@ -178,10 +179,6 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
178 dc->di = ipu_di_get_num(di); 179 dc->di = ipu_di_get_num(di);
179 180
180 map = ipu_bus_format_to_map(bus_format); 181 map = ipu_bus_format_to_map(bus_format);
181 if (map < 0) {
182 dev_dbg(priv->dev, "IPU_DISP: No MAP\n");
183 return map;
184 }
185 182
186 /* 183 /*
187 * In interlaced mode we need more counters to create the asymmetric 184 * In interlaced mode we need more counters to create the asymmetric
diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 359268e3a166..a8d87ddd8a17 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -572,9 +572,6 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
572 dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n", 572 dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
573 di->id, sig->mode.hactive, sig->mode.vactive); 573 di->id, sig->mode.hactive, sig->mode.vactive);
574 574
575 if ((sig->mode.vsync_len == 0) || (sig->mode.hsync_len == 0))
576 return -EINVAL;
577
578 dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n", 575 dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
579 clk_get_rate(di->clk_ipu), 576 clk_get_rate(di->clk_ipu),
580 clk_get_rate(di->clk_di), 577 clk_get_rate(di->clk_di),
diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c
index 837b1ec22800..42705bb5aaa3 100644
--- a/drivers/gpu/ipu-v3/ipu-dmfc.c
+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
@@ -45,17 +45,6 @@
45#define DMFC_DP_CHAN_6B_24 16 45#define DMFC_DP_CHAN_6B_24 16
46#define DMFC_DP_CHAN_6F_29 24 46#define DMFC_DP_CHAN_6F_29 24
47 47
48#define DMFC_FIFO_SIZE_64 (3 << 3)
49#define DMFC_FIFO_SIZE_128 (2 << 3)
50#define DMFC_FIFO_SIZE_256 (1 << 3)
51#define DMFC_FIFO_SIZE_512 (0 << 3)
52
53#define DMFC_SEGMENT(x) ((x & 0x7) << 0)
54#define DMFC_BURSTSIZE_128 (0 << 6)
55#define DMFC_BURSTSIZE_64 (1 << 6)
56#define DMFC_BURSTSIZE_32 (2 << 6)
57#define DMFC_BURSTSIZE_16 (3 << 6)
58
59struct dmfc_channel_data { 48struct dmfc_channel_data {
60 int ipu_channel; 49 int ipu_channel;
61 unsigned long channel_reg; 50 unsigned long channel_reg;
@@ -104,9 +93,6 @@ struct ipu_dmfc_priv;
104 93
105struct dmfc_channel { 94struct dmfc_channel {
106 unsigned slots; 95 unsigned slots;
107 unsigned slotmask;
108 unsigned segment;
109 int burstsize;
110 struct ipu_soc *ipu; 96 struct ipu_soc *ipu;
111 struct ipu_dmfc_priv *priv; 97 struct ipu_dmfc_priv *priv;
112 const struct dmfc_channel_data *data; 98 const struct dmfc_channel_data *data;
@@ -117,7 +103,6 @@ struct ipu_dmfc_priv {
117 struct device *dev; 103 struct device *dev;
118 struct dmfc_channel channels[DMFC_NUM_CHANNELS]; 104 struct dmfc_channel channels[DMFC_NUM_CHANNELS];
119 struct mutex mutex; 105 struct mutex mutex;
120 unsigned long bandwidth_per_slot;
121 void __iomem *base; 106 void __iomem *base;
122 int use_count; 107 int use_count;
123}; 108};
@@ -172,184 +157,6 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
172} 157}
173EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel); 158EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
174 159
175static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
176 int segment, int burstsize)
177{
178 struct ipu_dmfc_priv *priv = dmfc->priv;
179 u32 val, field;
180
181 dev_dbg(priv->dev,
182 "dmfc: using %d slots starting from segment %d for IPU channel %d\n",
183 slots, segment, dmfc->data->ipu_channel);
184
185 switch (slots) {
186 case 1:
187 field = DMFC_FIFO_SIZE_64;
188 break;
189 case 2:
190 field = DMFC_FIFO_SIZE_128;
191 break;
192 case 4:
193 field = DMFC_FIFO_SIZE_256;
194 break;
195 case 8:
196 field = DMFC_FIFO_SIZE_512;
197 break;
198 default:
199 return -EINVAL;
200 }
201
202 switch (burstsize) {
203 case 16:
204 field |= DMFC_BURSTSIZE_16;
205 break;
206 case 32:
207 field |= DMFC_BURSTSIZE_32;
208 break;
209 case 64:
210 field |= DMFC_BURSTSIZE_64;
211 break;
212 case 128:
213 field |= DMFC_BURSTSIZE_128;
214 break;
215 }
216
217 field |= DMFC_SEGMENT(segment);
218
219 val = readl(priv->base + dmfc->data->channel_reg);
220
221 val &= ~(0xff << dmfc->data->shift);
222 val |= field << dmfc->data->shift;
223
224 writel(val, priv->base + dmfc->data->channel_reg);
225
226 dmfc->slots = slots;
227 dmfc->segment = segment;
228 dmfc->burstsize = burstsize;
229 dmfc->slotmask = ((1 << slots) - 1) << segment;
230
231 return 0;
232}
233
234static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv,
235 unsigned long bandwidth)
236{
237 int slots = 1;
238
239 while (slots * priv->bandwidth_per_slot < bandwidth)
240 slots *= 2;
241
242 return slots;
243}
244
245static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots)
246{
247 unsigned slotmask_need, slotmask_used = 0;
248 int i, segment = 0;
249
250 slotmask_need = (1 << slots) - 1;
251
252 for (i = 0; i < DMFC_NUM_CHANNELS; i++)
253 slotmask_used |= priv->channels[i].slotmask;
254
255 while (slotmask_need <= 0xff) {
256 if (!(slotmask_used & slotmask_need))
257 return segment;
258
259 slotmask_need <<= 1;
260 segment++;
261 }
262
263 return -EBUSY;
264}
265
266void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
267{
268 struct ipu_dmfc_priv *priv = dmfc->priv;
269 int i;
270
271 dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n",
272 dmfc->slots, dmfc->segment);
273
274 mutex_lock(&priv->mutex);
275
276 if (!dmfc->slots)
277 goto out;
278
279 dmfc->slotmask = 0;
280 dmfc->slots = 0;
281 dmfc->segment = 0;
282
283 for (i = 0; i < DMFC_NUM_CHANNELS; i++)
284 priv->channels[i].slotmask = 0;
285
286 for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
287 if (priv->channels[i].slots > 0) {
288 priv->channels[i].segment =
289 dmfc_find_slots(priv, priv->channels[i].slots);
290 priv->channels[i].slotmask =
291 ((1 << priv->channels[i].slots) - 1) <<
292 priv->channels[i].segment;
293 }
294 }
295
296 for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
297 if (priv->channels[i].slots > 0)
298 ipu_dmfc_setup_channel(&priv->channels[i],
299 priv->channels[i].slots,
300 priv->channels[i].segment,
301 priv->channels[i].burstsize);
302 }
303out:
304 mutex_unlock(&priv->mutex);
305}
306EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);
307
308int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
309 unsigned long bandwidth_pixel_per_second, int burstsize)
310{
311 struct ipu_dmfc_priv *priv = dmfc->priv;
312 int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second);
313 int segment = -1, ret = 0;
314
315 dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n",
316 bandwidth_pixel_per_second / 1000000,
317 dmfc->data->ipu_channel);
318
319 ipu_dmfc_free_bandwidth(dmfc);
320
321 mutex_lock(&priv->mutex);
322
323 if (slots > 8) {
324 ret = -EBUSY;
325 goto out;
326 }
327
328 /* For the MEM_BG channel, first try to allocate twice the slots */
329 if (dmfc->data->ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC)
330 segment = dmfc_find_slots(priv, slots * 2);
331 else if (slots < 2)
332 /* Always allocate at least 128*4 bytes (2 slots) */
333 slots = 2;
334
335 if (segment >= 0)
336 slots *= 2;
337 else
338 segment = dmfc_find_slots(priv, slots);
339 if (segment < 0) {
340 ret = -EBUSY;
341 goto out;
342 }
343
344 ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize);
345
346out:
347 mutex_unlock(&priv->mutex);
348
349 return ret;
350}
351EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);
352
353void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width) 160void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
354{ 161{
355 struct ipu_dmfc_priv *priv = dmfc->priv; 162 struct ipu_dmfc_priv *priv = dmfc->priv;
@@ -384,7 +191,6 @@ EXPORT_SYMBOL_GPL(ipu_dmfc_get);
384 191
385void ipu_dmfc_put(struct dmfc_channel *dmfc) 192void ipu_dmfc_put(struct dmfc_channel *dmfc)
386{ 193{
387 ipu_dmfc_free_bandwidth(dmfc);
388} 194}
389EXPORT_SYMBOL_GPL(ipu_dmfc_put); 195EXPORT_SYMBOL_GPL(ipu_dmfc_put);
390 196
@@ -412,20 +218,15 @@ int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
412 priv->channels[i].priv = priv; 218 priv->channels[i].priv = priv;
413 priv->channels[i].ipu = ipu; 219 priv->channels[i].ipu = ipu;
414 priv->channels[i].data = &dmfcdata[i]; 220 priv->channels[i].data = &dmfcdata[i];
415 }
416
417 writel(0x0, priv->base + DMFC_WR_CHAN);
418 writel(0x0, priv->base + DMFC_DP_CHAN);
419 221
420 /* 222 if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
421 * We have a total bandwidth of clkrate * 4pixel divided 223 dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
422 * into 8 slots. 224 dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
423 */ 225 priv->channels[i].slots = 2;
424 priv->bandwidth_per_slot = clk_get_rate(ipu_clk) * 4 / 8; 226 }
425
426 dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n",
427 priv->bandwidth_per_slot / 1000000);
428 227
228 writel(0x00000050, priv->base + DMFC_WR_CHAN);
229 writel(0x00005654, priv->base + DMFC_DP_CHAN);
429 writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF); 230 writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
430 writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF); 231 writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
431 writel(0x00000003, priv->base + DMFC_GENERAL1); 232 writel(0x00000003, priv->base + DMFC_GENERAL1);