Commit | Line | Data |
---|---|---|
45d59d70 MV |
1 | /* |
2 | * Copyright (C) 2016 Marek Vasut <marex@denx.de> | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * as published by the Free Software Foundation; either version 2 | |
7 | * of the License, or (at your option) any later version. | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | */ | |
13 | ||
14 | #include <linux/of_graph.h> | |
15 | ||
16 | #include <drm/drm_atomic.h> | |
17 | #include <drm/drm_atomic_helper.h> | |
18 | #include <drm/drm_crtc.h> | |
45d59d70 MV |
19 | #include <drm/drm_fb_cma_helper.h> |
20 | #include <drm/drm_gem_cma_helper.h> | |
ebc94461 | 21 | #include <drm/drm_of.h> |
45d59d70 MV |
22 | #include <drm/drm_panel.h> |
23 | #include <drm/drm_plane_helper.h> | |
fcd70cd3 | 24 | #include <drm/drm_probe_helper.h> |
45d59d70 MV |
25 | #include <drm/drm_simple_kms_helper.h> |
26 | #include <drm/drmP.h> | |
27 | ||
28 | #include "mxsfb_drv.h" | |
29 | ||
30 | static struct mxsfb_drm_private * | |
31 | drm_connector_to_mxsfb_drm_private(struct drm_connector *connector) | |
32 | { | |
33 | return container_of(connector, struct mxsfb_drm_private, connector); | |
34 | } | |
35 | ||
36 | static int mxsfb_panel_get_modes(struct drm_connector *connector) | |
37 | { | |
38 | struct mxsfb_drm_private *mxsfb = | |
39 | drm_connector_to_mxsfb_drm_private(connector); | |
40 | ||
41 | if (mxsfb->panel) | |
42 | return mxsfb->panel->funcs->get_modes(mxsfb->panel); | |
43 | ||
44 | return 0; | |
45 | } | |
46 | ||
47 | static const struct | |
48 | drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = { | |
49 | .get_modes = mxsfb_panel_get_modes, | |
50 | }; | |
51 | ||
52 | static enum drm_connector_status | |
53 | mxsfb_panel_connector_detect(struct drm_connector *connector, bool force) | |
54 | { | |
55 | struct mxsfb_drm_private *mxsfb = | |
56 | drm_connector_to_mxsfb_drm_private(connector); | |
57 | ||
58 | if (mxsfb->panel) | |
59 | return connector_status_connected; | |
60 | ||
61 | return connector_status_disconnected; | |
62 | } | |
63 | ||
64 | static void mxsfb_panel_connector_destroy(struct drm_connector *connector) | |
65 | { | |
66 | struct mxsfb_drm_private *mxsfb = | |
67 | drm_connector_to_mxsfb_drm_private(connector); | |
68 | ||
69 | if (mxsfb->panel) | |
70 | drm_panel_detach(mxsfb->panel); | |
71 | ||
72 | drm_connector_unregister(connector); | |
73 | drm_connector_cleanup(connector); | |
74 | } | |
75 | ||
76 | static const struct drm_connector_funcs mxsfb_panel_connector_funcs = { | |
45d59d70 MV |
77 | .detect = mxsfb_panel_connector_detect, |
78 | .fill_modes = drm_helper_probe_single_connector_modes, | |
79 | .destroy = mxsfb_panel_connector_destroy, | |
80 | .reset = drm_atomic_helper_connector_reset, | |
81 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | |
82 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | |
83 | }; | |
84 | ||
ebc94461 | 85 | int mxsfb_create_output(struct drm_device *drm) |
45d59d70 MV |
86 | { |
87 | struct mxsfb_drm_private *mxsfb = drm->dev_private; | |
45d59d70 | 88 | struct drm_panel *panel; |
ebc94461 | 89 | int ret; |
45d59d70 | 90 | |
ebc94461 RH |
91 | ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, NULL); |
92 | if (ret) | |
93 | return ret; | |
45d59d70 MV |
94 | |
95 | mxsfb->connector.dpms = DRM_MODE_DPMS_OFF; | |
96 | mxsfb->connector.polled = 0; | |
97 | drm_connector_helper_add(&mxsfb->connector, | |
98 | &mxsfb_panel_connector_helper_funcs); | |
99 | ret = drm_connector_init(drm, &mxsfb->connector, | |
100 | &mxsfb_panel_connector_funcs, | |
101 | DRM_MODE_CONNECTOR_Unknown); | |
102 | if (!ret) | |
103 | mxsfb->panel = panel; | |
104 | ||
105 | return ret; | |
106 | } |