aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imx/imx-ldb.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-07-15 21:19:29 -0400
committerDave Airlie <airlied@redhat.com>2016-07-15 21:19:29 -0400
commitd3c35337fb01ed41c3aadfe73fe317b5b0741897 (patch)
tree7ef0fd006210a99cff39fecb55e9acbd31ca31e0 /drivers/gpu/drm/imx/imx-ldb.c
parentf82c13722275b6aca3a956a82846465ec789b367 (diff)
parentf140b0cc776f8771adfa45d2ef234da72662443d (diff)
Merge tag 'imx-drm-next-2016-07-14' of git://git.pengutronix.de/git/pza/linux into drm-next
imx-drm updates - atomic mode setting conversion - replace DMFC FIFO allocation mechanism with a fixed allocation that is good enough for all cases - support for external bridges connected to parallel-display - improved error handling in imx-ldb, imx-tve, and parallel-display - some code cleanup in imx-tve * tag 'imx-drm-next-2016-07-14' of git://git.pengutronix.de/git/pza/linux: drm/imx: parallel-display: add bridge support drm/imx: parallel-display: check return code from of_get_drm_display_mode() gpu: ipu-v3: ipu-dc: don't bug out on invalid bus_format drm/imx: imx-tve: fix the error message drm/imx: imx-tve: remove unneeded 'or' operation drm/imx: imx-tve: check the value returned by regulator_set_voltage() drm/imx: imx-ldb: check return code on panel attach drm/imx: turn remaining container_of macros into inline functions drm/imx: store internal bus configuration in crtc state drm/imx: remove empty mode_set encoder callbacks drm/imx: atomic phase 3 step 3: Advertise DRIVER_ATOMIC drm/imx: atomic phase 3 step 2: Legacy callback fixups drm/bridge: dw-hdmi: Remove the legacy drm_connector_funcs structure drm/imx: atomic phase 3 step 1: Use atomic configuration drm/imx: Remove encoders' ->prepare callbacks drm/imx: atomic phase 2 step 2: Track plane_state->fb correctly in ->page_flip drm/imx: atomic phase 2 step 1: Wire up state ->reset, ->duplicate and ->destroy drm/imx: atomic phase 1: Use transitional atomic CRTC and plane helpers gpu: ipu-v3: ipu-dmfc: Use static DMFC FIFO allocation mechanism drm/imx: ipuv3 plane: Check different types of plane separately
Diffstat (limited to 'drivers/gpu/drm/imx/imx-ldb.c')
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c192
1 files changed, 122 insertions, 70 deletions
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)