diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2014-12-02 14:22:49 -0500 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2015-03-31 06:44:50 -0400 |
commit | 5e501ed7253b369a8a9ec553c35238a3d6808f28 (patch) | |
tree | 06e52297f21c7c9c54e7c8ac0efd85aac6bc27f1 | |
parent | 3973aff06585309f6215c66ed9d11d74656a9fa6 (diff) |
drm/imx: imx-ldb: allow to determine bus format from the connected panel
This patch makes the fsl,data-width and fsl,data-mapping device tree
properties optional if a panel is connected to the ldb output port
via the of_graph bindings. The data mapping is determined from the
display_info.bus_format field provided by the panel.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-rw-r--r-- | drivers/gpu/drm/imx/imx-ldb.c | 116 |
1 files changed, 63 insertions, 53 deletions
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 544282bd4f7f..abacc8f67469 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c | |||
@@ -63,6 +63,7 @@ struct imx_ldb_channel { | |||
63 | int edid_len; | 63 | int edid_len; |
64 | struct drm_display_mode mode; | 64 | struct drm_display_mode mode; |
65 | int mode_valid; | 65 | int mode_valid; |
66 | int bus_format; | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | struct bus_mux { | 69 | struct bus_mux { |
@@ -96,7 +97,11 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) | |||
96 | 97 | ||
97 | if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs && | 98 | if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs && |
98 | imx_ldb_ch->panel->funcs->get_modes) { | 99 | imx_ldb_ch->panel->funcs->get_modes) { |
100 | struct drm_display_info *di = &connector->display_info; | ||
101 | |||
99 | num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel); | 102 | num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel); |
103 | if (!imx_ldb_ch->bus_format && di->num_bus_formats) | ||
104 | imx_ldb_ch->bus_format = di->bus_formats[0]; | ||
100 | if (num_modes > 0) | 105 | if (num_modes > 0) |
101 | return num_modes; | 106 | return num_modes; |
102 | } | 107 | } |
@@ -173,21 +178,33 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder) | |||
173 | { | 178 | { |
174 | struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); | 179 | struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); |
175 | struct imx_ldb *ldb = imx_ldb_ch->ldb; | 180 | struct imx_ldb *ldb = imx_ldb_ch->ldb; |
181 | int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; | ||
176 | u32 bus_format; | 182 | u32 bus_format; |
177 | 183 | ||
178 | switch (imx_ldb_ch->chno) { | 184 | switch (imx_ldb_ch->bus_format) { |
179 | case 0: | 185 | default: |
180 | bus_format = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH0_24) ? | 186 | dev_warn(ldb->dev, |
181 | MEDIA_BUS_FMT_RGB888_1X24 : MEDIA_BUS_FMT_RGB666_1X18; | 187 | "could not determine data mapping, default to 18-bit \"spwg\"\n"); |
188 | /* fallthrough */ | ||
189 | case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: | ||
190 | bus_format = MEDIA_BUS_FMT_RGB666_1X18; | ||
182 | break; | 191 | break; |
183 | case 1: | 192 | case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: |
184 | bus_format = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH1_24) ? | 193 | bus_format = MEDIA_BUS_FMT_RGB888_1X24; |
185 | MEDIA_BUS_FMT_RGB888_1X24 : MEDIA_BUS_FMT_RGB666_1X18; | 194 | if (imx_ldb_ch->chno == 0 || dual) |
195 | ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24; | ||
196 | if (imx_ldb_ch->chno == 1 || dual) | ||
197 | ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24; | ||
186 | break; | 198 | break; |
187 | default: | 199 | case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: |
188 | dev_err(ldb->dev, "unable to config di%d panel format\n", | ||
189 | imx_ldb_ch->chno); | ||
190 | bus_format = MEDIA_BUS_FMT_RGB888_1X24; | 200 | bus_format = MEDIA_BUS_FMT_RGB888_1X24; |
201 | if (imx_ldb_ch->chno == 0 || dual) | ||
202 | ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | | ||
203 | LDB_BIT_MAP_CH0_JEIDA; | ||
204 | if (imx_ldb_ch->chno == 1 || dual) | ||
205 | ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | | ||
206 | LDB_BIT_MAP_CH1_JEIDA; | ||
207 | break; | ||
191 | } | 208 | } |
192 | 209 | ||
193 | imx_drm_set_bus_format(encoder, bus_format); | 210 | imx_drm_set_bus_format(encoder, bus_format); |
@@ -426,25 +443,39 @@ enum { | |||
426 | LVDS_BIT_MAP_JEIDA | 443 | LVDS_BIT_MAP_JEIDA |
427 | }; | 444 | }; |
428 | 445 | ||
429 | static const char * const imx_ldb_bit_mappings[] = { | 446 | struct imx_ldb_bit_mapping { |
430 | [LVDS_BIT_MAP_SPWG] = "spwg", | 447 | u32 bus_format; |
431 | [LVDS_BIT_MAP_JEIDA] = "jeida", | 448 | u32 datawidth; |
449 | const char * const mapping; | ||
432 | }; | 450 | }; |
433 | 451 | ||
434 | static const int of_get_data_mapping(struct device_node *np) | 452 | static const struct imx_ldb_bit_mapping imx_ldb_bit_mappings[] = { |
453 | { MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, 18, "spwg" }, | ||
454 | { MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, 24, "spwg" }, | ||
455 | { MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, 24, "jeida" }, | ||
456 | }; | ||
457 | |||
458 | static u32 of_get_bus_format(struct device *dev, struct device_node *np) | ||
435 | { | 459 | { |
436 | const char *bm; | 460 | const char *bm; |
461 | u32 datawidth = 0; | ||
437 | int ret, i; | 462 | int ret, i; |
438 | 463 | ||
439 | ret = of_property_read_string(np, "fsl,data-mapping", &bm); | 464 | ret = of_property_read_string(np, "fsl,data-mapping", &bm); |
440 | if (ret < 0) | 465 | if (ret < 0) |
441 | return ret; | 466 | return ret; |
442 | 467 | ||
443 | for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++) | 468 | of_property_read_u32(np, "fsl,data-width", &datawidth); |
444 | if (!strcasecmp(bm, imx_ldb_bit_mappings[i])) | 469 | |
445 | return i; | 470 | for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++) { |
471 | if (!strcasecmp(bm, imx_ldb_bit_mappings[i].mapping) && | ||
472 | datawidth == imx_ldb_bit_mappings[i].datawidth) | ||
473 | return imx_ldb_bit_mappings[i].bus_format; | ||
474 | } | ||
475 | |||
476 | dev_err(dev, "invalid data mapping: %d-bit \"%s\"\n", datawidth, bm); | ||
446 | 477 | ||
447 | return -EINVAL; | 478 | return -ENOENT; |
448 | } | 479 | } |
449 | 480 | ||
450 | static struct bus_mux imx6q_lvds_mux[2] = { | 481 | static struct bus_mux imx6q_lvds_mux[2] = { |
@@ -481,8 +512,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) | |||
481 | struct device_node *child; | 512 | struct device_node *child; |
482 | const u8 *edidp; | 513 | const u8 *edidp; |
483 | struct imx_ldb *imx_ldb; | 514 | struct imx_ldb *imx_ldb; |
484 | int datawidth; | ||
485 | int mapping; | ||
486 | int dual; | 515 | int dual; |
487 | int ret; | 516 | int ret; |
488 | int i; | 517 | int i; |
@@ -583,39 +612,20 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) | |||
583 | channel->mode_valid = 1; | 612 | channel->mode_valid = 1; |
584 | } | 613 | } |
585 | 614 | ||
586 | ret = of_property_read_u32(child, "fsl,data-width", &datawidth); | 615 | channel->bus_format = of_get_bus_format(dev, child); |
587 | if (ret) | 616 | if (channel->bus_format == -EINVAL) { |
588 | datawidth = 0; | 617 | /* |
589 | else if (datawidth != 18 && datawidth != 24) | 618 | * If no bus format was specified in the device tree, |
590 | return -EINVAL; | 619 | * we can still get it from the connected panel later. |
591 | 620 | */ | |
592 | mapping = of_get_data_mapping(child); | 621 | if (channel->panel && channel->panel->funcs && |
593 | switch (mapping) { | 622 | channel->panel->funcs->get_modes) |
594 | case LVDS_BIT_MAP_SPWG: | 623 | channel->bus_format = 0; |
595 | if (datawidth == 24) { | 624 | } |
596 | if (i == 0 || dual) | 625 | if (channel->bus_format < 0) { |
597 | imx_ldb->ldb_ctrl |= | 626 | dev_err(dev, "could not determine data mapping: %d\n", |
598 | LDB_DATA_WIDTH_CH0_24; | 627 | channel->bus_format); |
599 | if (i == 1 || dual) | 628 | return channel->bus_format; |
600 | imx_ldb->ldb_ctrl |= | ||
601 | LDB_DATA_WIDTH_CH1_24; | ||
602 | } | ||
603 | break; | ||
604 | case LVDS_BIT_MAP_JEIDA: | ||
605 | if (datawidth == 18) { | ||
606 | dev_err(dev, "JEIDA standard only supported in 24 bit\n"); | ||
607 | return -EINVAL; | ||
608 | } | ||
609 | if (i == 0 || dual) | ||
610 | imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | | ||
611 | LDB_BIT_MAP_CH0_JEIDA; | ||
612 | if (i == 1 || dual) | ||
613 | imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | | ||
614 | LDB_BIT_MAP_CH1_JEIDA; | ||
615 | break; | ||
616 | default: | ||
617 | dev_err(dev, "data mapping not specified or invalid\n"); | ||
618 | return -EINVAL; | ||
619 | } | 629 | } |
620 | 630 | ||
621 | ret = imx_ldb_register(drm, channel); | 631 | ret = imx_ldb_register(drm, channel); |