]>
Commit | Line | Data |
---|---|---|
c942fddf | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
45d59d70 MV |
2 | /* |
3 | * Copyright (C) 2016 Marek Vasut <marex@denx.de> | |
45d59d70 MV |
4 | */ |
5 | ||
6 | #include <linux/of_graph.h> | |
7 | ||
8 | #include <drm/drm_atomic.h> | |
9 | #include <drm/drm_atomic_helper.h> | |
10 | #include <drm/drm_crtc.h> | |
45d59d70 MV |
11 | #include <drm/drm_fb_cma_helper.h> |
12 | #include <drm/drm_gem_cma_helper.h> | |
ebc94461 | 13 | #include <drm/drm_of.h> |
45d59d70 MV |
14 | #include <drm/drm_panel.h> |
15 | #include <drm/drm_plane_helper.h> | |
fcd70cd3 | 16 | #include <drm/drm_probe_helper.h> |
45d59d70 | 17 | #include <drm/drm_simple_kms_helper.h> |
45d59d70 MV |
18 | |
19 | #include "mxsfb_drv.h" | |
20 | ||
21 | static struct mxsfb_drm_private * | |
22 | drm_connector_to_mxsfb_drm_private(struct drm_connector *connector) | |
23 | { | |
d0234043 RC |
24 | return container_of(connector, struct mxsfb_drm_private, |
25 | panel_connector); | |
45d59d70 MV |
26 | } |
27 | ||
28 | static int mxsfb_panel_get_modes(struct drm_connector *connector) | |
29 | { | |
30 | struct mxsfb_drm_private *mxsfb = | |
31 | drm_connector_to_mxsfb_drm_private(connector); | |
32 | ||
33 | if (mxsfb->panel) | |
06c4a9c2 | 34 | return drm_panel_get_modes(mxsfb->panel, connector); |
45d59d70 MV |
35 | |
36 | return 0; | |
37 | } | |
38 | ||
39 | static const struct | |
40 | drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = { | |
41 | .get_modes = mxsfb_panel_get_modes, | |
42 | }; | |
43 | ||
44 | static enum drm_connector_status | |
45 | mxsfb_panel_connector_detect(struct drm_connector *connector, bool force) | |
46 | { | |
47 | struct mxsfb_drm_private *mxsfb = | |
48 | drm_connector_to_mxsfb_drm_private(connector); | |
49 | ||
50 | if (mxsfb->panel) | |
51 | return connector_status_connected; | |
52 | ||
53 | return connector_status_disconnected; | |
54 | } | |
55 | ||
56 | static void mxsfb_panel_connector_destroy(struct drm_connector *connector) | |
57 | { | |
58 | struct mxsfb_drm_private *mxsfb = | |
59 | drm_connector_to_mxsfb_drm_private(connector); | |
60 | ||
61 | if (mxsfb->panel) | |
62 | drm_panel_detach(mxsfb->panel); | |
63 | ||
64 | drm_connector_unregister(connector); | |
65 | drm_connector_cleanup(connector); | |
66 | } | |
67 | ||
68 | static const struct drm_connector_funcs mxsfb_panel_connector_funcs = { | |
45d59d70 MV |
69 | .detect = mxsfb_panel_connector_detect, |
70 | .fill_modes = drm_helper_probe_single_connector_modes, | |
71 | .destroy = mxsfb_panel_connector_destroy, | |
72 | .reset = drm_atomic_helper_connector_reset, | |
73 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | |
74 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | |
75 | }; | |
76 | ||
ebc94461 | 77 | int mxsfb_create_output(struct drm_device *drm) |
45d59d70 MV |
78 | { |
79 | struct mxsfb_drm_private *mxsfb = drm->dev_private; | |
ebc94461 | 80 | int ret; |
45d59d70 | 81 | |
d0234043 RC |
82 | ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, |
83 | &mxsfb->panel, &mxsfb->bridge); | |
ebc94461 RH |
84 | if (ret) |
85 | return ret; | |
45d59d70 | 86 | |
d0234043 RC |
87 | if (mxsfb->panel) { |
88 | mxsfb->connector = &mxsfb->panel_connector; | |
89 | mxsfb->connector->dpms = DRM_MODE_DPMS_OFF; | |
90 | mxsfb->connector->polled = 0; | |
91 | drm_connector_helper_add(mxsfb->connector, | |
92 | &mxsfb_panel_connector_helper_funcs); | |
93 | ret = drm_connector_init(drm, mxsfb->connector, | |
94 | &mxsfb_panel_connector_funcs, | |
95 | DRM_MODE_CONNECTOR_Unknown); | |
96 | } | |
45d59d70 MV |
97 | |
98 | return ret; | |
99 | } |