.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
---|
1 | 2 | /* |
---|
2 | 3 | * i.MX drm driver - LVDS display bridge |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2012 Sascha Hauer, Pengutronix |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of the GNU General Public License |
---|
8 | | - * as published by the Free Software Foundation; either version 2 |
---|
9 | | - * of the License, or (at your option) any later version. |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | 6 | */ |
---|
15 | 7 | |
---|
16 | | -#include <linux/module.h> |
---|
17 | 8 | #include <linux/clk.h> |
---|
18 | 9 | #include <linux/component.h> |
---|
19 | | -#include <drm/drmP.h> |
---|
20 | | -#include <drm/drm_atomic.h> |
---|
21 | | -#include <drm/drm_atomic_helper.h> |
---|
22 | | -#include <drm/drm_fb_helper.h> |
---|
23 | | -#include <drm/drm_crtc_helper.h> |
---|
24 | | -#include <drm/drm_of.h> |
---|
25 | | -#include <drm/drm_panel.h> |
---|
26 | 10 | #include <linux/mfd/syscon.h> |
---|
27 | 11 | #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> |
---|
| 12 | +#include <linux/module.h> |
---|
28 | 13 | #include <linux/of_device.h> |
---|
29 | 14 | #include <linux/of_graph.h> |
---|
30 | | -#include <video/of_display_timing.h> |
---|
31 | | -#include <video/of_videomode.h> |
---|
32 | 15 | #include <linux/regmap.h> |
---|
33 | 16 | #include <linux/videodev2.h> |
---|
| 17 | + |
---|
| 18 | +#include <video/of_display_timing.h> |
---|
| 19 | +#include <video/of_videomode.h> |
---|
| 20 | + |
---|
| 21 | +#include <drm/drm_atomic.h> |
---|
| 22 | +#include <drm/drm_atomic_helper.h> |
---|
| 23 | +#include <drm/drm_bridge.h> |
---|
| 24 | +#include <drm/drm_fb_helper.h> |
---|
| 25 | +#include <drm/drm_of.h> |
---|
| 26 | +#include <drm/drm_panel.h> |
---|
| 27 | +#include <drm/drm_print.h> |
---|
| 28 | +#include <drm/drm_probe_helper.h> |
---|
| 29 | +#include <drm/drm_simple_kms_helper.h> |
---|
34 | 30 | |
---|
35 | 31 | #include "imx-drm.h" |
---|
36 | 32 | |
---|
.. | .. |
---|
66 | 62 | struct i2c_adapter *ddc; |
---|
67 | 63 | int chno; |
---|
68 | 64 | void *edid; |
---|
69 | | - int edid_len; |
---|
70 | 65 | struct drm_display_mode mode; |
---|
71 | 66 | int mode_valid; |
---|
72 | 67 | u32 bus_format; |
---|
.. | .. |
---|
130 | 125 | static int imx_ldb_connector_get_modes(struct drm_connector *connector) |
---|
131 | 126 | { |
---|
132 | 127 | struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); |
---|
133 | | - int num_modes = 0; |
---|
| 128 | + int num_modes; |
---|
134 | 129 | |
---|
135 | | - if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs && |
---|
136 | | - imx_ldb_ch->panel->funcs->get_modes) { |
---|
137 | | - num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel); |
---|
138 | | - if (num_modes > 0) |
---|
139 | | - return num_modes; |
---|
140 | | - } |
---|
| 130 | + num_modes = drm_panel_get_modes(imx_ldb_ch->panel, connector); |
---|
| 131 | + if (num_modes > 0) |
---|
| 132 | + return num_modes; |
---|
141 | 133 | |
---|
142 | 134 | if (!imx_ldb_ch->edid && imx_ldb_ch->ddc) |
---|
143 | 135 | imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc); |
---|
.. | .. |
---|
161 | 153 | } |
---|
162 | 154 | |
---|
163 | 155 | return num_modes; |
---|
164 | | -} |
---|
165 | | - |
---|
166 | | -static struct drm_encoder *imx_ldb_connector_best_encoder( |
---|
167 | | - struct drm_connector *connector) |
---|
168 | | -{ |
---|
169 | | - struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); |
---|
170 | | - |
---|
171 | | - return &imx_ldb_ch->encoder; |
---|
172 | 156 | } |
---|
173 | 157 | |
---|
174 | 158 | static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno, |
---|
.. | .. |
---|
409 | 393 | |
---|
410 | 394 | static const struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = { |
---|
411 | 395 | .get_modes = imx_ldb_connector_get_modes, |
---|
412 | | - .best_encoder = imx_ldb_connector_best_encoder, |
---|
413 | | -}; |
---|
414 | | - |
---|
415 | | -static const struct drm_encoder_funcs imx_ldb_encoder_funcs = { |
---|
416 | | - .destroy = imx_drm_encoder_destroy, |
---|
417 | 396 | }; |
---|
418 | 397 | |
---|
419 | 398 | static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = { |
---|
.. | .. |
---|
460 | 439 | } |
---|
461 | 440 | |
---|
462 | 441 | drm_encoder_helper_add(encoder, &imx_ldb_encoder_helper_funcs); |
---|
463 | | - drm_encoder_init(drm, encoder, &imx_ldb_encoder_funcs, |
---|
464 | | - DRM_MODE_ENCODER_LVDS, NULL); |
---|
| 442 | + drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_LVDS); |
---|
465 | 443 | |
---|
466 | 444 | if (imx_ldb_ch->bridge) { |
---|
467 | 445 | ret = drm_bridge_attach(&imx_ldb_ch->encoder, |
---|
468 | | - imx_ldb_ch->bridge, NULL); |
---|
| 446 | + imx_ldb_ch->bridge, NULL, 0); |
---|
469 | 447 | if (ret) { |
---|
470 | 448 | DRM_ERROR("Failed to initialize bridge with drm\n"); |
---|
471 | 449 | return ret; |
---|
.. | .. |
---|
479 | 457 | */ |
---|
480 | 458 | drm_connector_helper_add(&imx_ldb_ch->connector, |
---|
481 | 459 | &imx_ldb_connector_helper_funcs); |
---|
482 | | - drm_connector_init(drm, &imx_ldb_ch->connector, |
---|
483 | | - &imx_ldb_connector_funcs, |
---|
484 | | - DRM_MODE_CONNECTOR_LVDS); |
---|
| 460 | + drm_connector_init_with_ddc(drm, &imx_ldb_ch->connector, |
---|
| 461 | + &imx_ldb_connector_funcs, |
---|
| 462 | + DRM_MODE_CONNECTOR_LVDS, |
---|
| 463 | + imx_ldb_ch->ddc); |
---|
485 | 464 | drm_connector_attach_encoder(&imx_ldb_ch->connector, encoder); |
---|
486 | | - } |
---|
487 | | - |
---|
488 | | - if (imx_ldb_ch->panel) { |
---|
489 | | - ret = drm_panel_attach(imx_ldb_ch->panel, |
---|
490 | | - &imx_ldb_ch->connector); |
---|
491 | | - if (ret) |
---|
492 | | - return ret; |
---|
493 | 465 | } |
---|
494 | 466 | |
---|
495 | 467 | return 0; |
---|
496 | 468 | } |
---|
497 | | - |
---|
498 | | -enum { |
---|
499 | | - LVDS_BIT_MAP_SPWG, |
---|
500 | | - LVDS_BIT_MAP_JEIDA |
---|
501 | | -}; |
---|
502 | 469 | |
---|
503 | 470 | struct imx_ldb_bit_mapping { |
---|
504 | 471 | u32 bus_format; |
---|
.. | .. |
---|
578 | 545 | } |
---|
579 | 546 | |
---|
580 | 547 | if (!channel->ddc) { |
---|
| 548 | + int edid_len; |
---|
| 549 | + |
---|
581 | 550 | /* if no DDC available, fallback to hardcoded EDID */ |
---|
582 | 551 | dev_dbg(dev, "no ddc available\n"); |
---|
583 | 552 | |
---|
584 | | - edidp = of_get_property(child, "edid", |
---|
585 | | - &channel->edid_len); |
---|
| 553 | + edidp = of_get_property(child, "edid", &edid_len); |
---|
586 | 554 | if (edidp) { |
---|
587 | | - channel->edid = kmemdup(edidp, |
---|
588 | | - channel->edid_len, |
---|
589 | | - GFP_KERNEL); |
---|
| 555 | + channel->edid = kmemdup(edidp, edid_len, GFP_KERNEL); |
---|
| 556 | + if (!channel->edid) |
---|
| 557 | + return -ENOMEM; |
---|
590 | 558 | } else if (!channel->panel) { |
---|
591 | 559 | /* fallback to display-timings node */ |
---|
592 | 560 | ret = of_get_drm_display_mode(child, |
---|
.. | .. |
---|
612 | 580 | int ret; |
---|
613 | 581 | int i; |
---|
614 | 582 | |
---|
615 | | - imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL); |
---|
616 | | - if (!imx_ldb) |
---|
617 | | - return -ENOMEM; |
---|
| 583 | + imx_ldb = dev_get_drvdata(dev); |
---|
| 584 | + memset(imx_ldb, 0, sizeof(*imx_ldb)); |
---|
618 | 585 | |
---|
619 | 586 | imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); |
---|
620 | 587 | if (IS_ERR(imx_ldb->regmap)) { |
---|
.. | .. |
---|
722 | 689 | } |
---|
723 | 690 | } |
---|
724 | 691 | |
---|
725 | | - dev_set_drvdata(dev, imx_ldb); |
---|
726 | | - |
---|
727 | 692 | return 0; |
---|
728 | 693 | |
---|
729 | 694 | free_child: |
---|
.. | .. |
---|
740 | 705 | for (i = 0; i < 2; i++) { |
---|
741 | 706 | struct imx_ldb_channel *channel = &imx_ldb->channel[i]; |
---|
742 | 707 | |
---|
743 | | - if (channel->panel) |
---|
744 | | - drm_panel_detach(channel->panel); |
---|
745 | | - |
---|
746 | 708 | kfree(channel->edid); |
---|
747 | 709 | i2c_put_adapter(channel->ddc); |
---|
748 | 710 | } |
---|
.. | .. |
---|
755 | 717 | |
---|
756 | 718 | static int imx_ldb_probe(struct platform_device *pdev) |
---|
757 | 719 | { |
---|
| 720 | + struct imx_ldb *imx_ldb; |
---|
| 721 | + |
---|
| 722 | + imx_ldb = devm_kzalloc(&pdev->dev, sizeof(*imx_ldb), GFP_KERNEL); |
---|
| 723 | + if (!imx_ldb) |
---|
| 724 | + return -ENOMEM; |
---|
| 725 | + |
---|
| 726 | + platform_set_drvdata(pdev, imx_ldb); |
---|
| 727 | + |
---|
758 | 728 | return component_add(&pdev->dev, &imx_ldb_ops); |
---|
759 | 729 | } |
---|
760 | 730 | |
---|