diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2016-07-06 08:49:24 -0400 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2016-07-12 12:24:28 -0400 |
commit | 49f98bc4d44a4ee507737f8d5531d05539787319 (patch) | |
tree | f450326225bb4215a191bf10170cbbbae8b87b04 /drivers/gpu/drm/imx/parallel-display.c | |
parent | e41c5c2411bca56775663a4153e0c00ea8c8f130 (diff) |
drm/imx: store internal bus configuration in crtc state
The internal bus configuration is imx-drm specific crtc state. Store it
in imx_crtc_state and let the encoder atomic_check callbacks determine
bus_flags, bus_format and the sync pins, possibly taking into account
the mode and the connector display info.
The custom imx_drm_encoder structure can be replaced again with
drm_encoder.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm/imx/parallel-display.c')
-rw-r--r-- | drivers/gpu/drm/imx/parallel-display.c | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 4a2942ecec17..9da60df5efa7 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c | |||
@@ -27,19 +27,23 @@ | |||
27 | #include "imx-drm.h" | 27 | #include "imx-drm.h" |
28 | 28 | ||
29 | #define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) | 29 | #define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) |
30 | #define imx_enc_to_imxpd(x) \ | ||
31 | container_of(x, struct imx_parallel_display, imx_encoder) | ||
32 | 30 | ||
33 | struct imx_parallel_display { | 31 | struct imx_parallel_display { |
34 | struct drm_connector connector; | 32 | struct drm_connector connector; |
35 | struct imx_drm_encoder imx_encoder; | 33 | struct drm_encoder encoder; |
36 | struct device *dev; | 34 | struct device *dev; |
37 | void *edid; | 35 | void *edid; |
38 | int edid_len; | 36 | int edid_len; |
37 | u32 bus_format; | ||
39 | struct drm_display_mode mode; | 38 | struct drm_display_mode mode; |
40 | struct drm_panel *panel; | 39 | struct drm_panel *panel; |
41 | }; | 40 | }; |
42 | 41 | ||
42 | static inline struct imx_parallel_display *enc_to_imxpd(struct drm_encoder *e) | ||
43 | { | ||
44 | return container_of(e, struct imx_parallel_display, encoder); | ||
45 | } | ||
46 | |||
43 | static enum drm_connector_status imx_pd_connector_detect( | 47 | static enum drm_connector_status imx_pd_connector_detect( |
44 | struct drm_connector *connector, bool force) | 48 | struct drm_connector *connector, bool force) |
45 | { | 49 | { |
@@ -54,12 +58,7 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) | |||
54 | 58 | ||
55 | if (imxpd->panel && imxpd->panel->funcs && | 59 | if (imxpd->panel && imxpd->panel->funcs && |
56 | imxpd->panel->funcs->get_modes) { | 60 | imxpd->panel->funcs->get_modes) { |
57 | struct drm_display_info *di = &connector->display_info; | ||
58 | |||
59 | num_modes = imxpd->panel->funcs->get_modes(imxpd->panel); | 61 | num_modes = imxpd->panel->funcs->get_modes(imxpd->panel); |
60 | if (!imxpd->imx_encoder.bus_format && di->num_bus_formats) | ||
61 | imxpd->imx_encoder.bus_format = di->bus_formats[0]; | ||
62 | imxpd->imx_encoder.bus_flags = di->bus_flags; | ||
63 | if (num_modes > 0) | 62 | if (num_modes > 0) |
64 | return num_modes; | 63 | return num_modes; |
65 | } | 64 | } |
@@ -89,13 +88,12 @@ static struct drm_encoder *imx_pd_connector_best_encoder( | |||
89 | { | 88 | { |
90 | struct imx_parallel_display *imxpd = con_to_imxpd(connector); | 89 | struct imx_parallel_display *imxpd = con_to_imxpd(connector); |
91 | 90 | ||
92 | return &imxpd->imx_encoder.encoder; | 91 | return &imxpd->encoder; |
93 | } | 92 | } |
94 | 93 | ||
95 | static void imx_pd_encoder_enable(struct drm_encoder *encoder) | 94 | static void imx_pd_encoder_enable(struct drm_encoder *encoder) |
96 | { | 95 | { |
97 | struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); | 96 | struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); |
98 | struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); | ||
99 | 97 | ||
100 | drm_panel_prepare(imxpd->panel); | 98 | drm_panel_prepare(imxpd->panel); |
101 | drm_panel_enable(imxpd->panel); | 99 | drm_panel_enable(imxpd->panel); |
@@ -103,13 +101,31 @@ static void imx_pd_encoder_enable(struct drm_encoder *encoder) | |||
103 | 101 | ||
104 | static void imx_pd_encoder_disable(struct drm_encoder *encoder) | 102 | static void imx_pd_encoder_disable(struct drm_encoder *encoder) |
105 | { | 103 | { |
106 | struct imx_drm_encoder *imx_encoder = enc_to_imx_enc(encoder); | 104 | struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); |
107 | struct imx_parallel_display *imxpd = imx_enc_to_imxpd(imx_encoder); | ||
108 | 105 | ||
109 | drm_panel_disable(imxpd->panel); | 106 | drm_panel_disable(imxpd->panel); |
110 | drm_panel_unprepare(imxpd->panel); | 107 | drm_panel_unprepare(imxpd->panel); |
111 | } | 108 | } |
112 | 109 | ||
110 | static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder, | ||
111 | struct drm_crtc_state *crtc_state, | ||
112 | struct drm_connector_state *conn_state) | ||
113 | { | ||
114 | struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state); | ||
115 | struct drm_display_info *di = &conn_state->connector->display_info; | ||
116 | struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); | ||
117 | |||
118 | imx_crtc_state->bus_flags = di->bus_flags; | ||
119 | if (!imxpd->bus_format && di->num_bus_formats) | ||
120 | imx_crtc_state->bus_format = di->bus_formats[0]; | ||
121 | else | ||
122 | imx_crtc_state->bus_format = imxpd->bus_format; | ||
123 | imx_crtc_state->di_hsync_pin = 2; | ||
124 | imx_crtc_state->di_vsync_pin = 3; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
113 | static const struct drm_connector_funcs imx_pd_connector_funcs = { | 129 | static const struct drm_connector_funcs imx_pd_connector_funcs = { |
114 | .dpms = drm_atomic_helper_connector_dpms, | 130 | .dpms = drm_atomic_helper_connector_dpms, |
115 | .fill_modes = drm_helper_probe_single_connector_modes, | 131 | .fill_modes = drm_helper_probe_single_connector_modes, |
@@ -132,15 +148,16 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = { | |||
132 | static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { | 148 | static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { |
133 | .enable = imx_pd_encoder_enable, | 149 | .enable = imx_pd_encoder_enable, |
134 | .disable = imx_pd_encoder_disable, | 150 | .disable = imx_pd_encoder_disable, |
151 | .atomic_check = imx_pd_encoder_atomic_check, | ||
135 | }; | 152 | }; |
136 | 153 | ||
137 | static int imx_pd_register(struct drm_device *drm, | 154 | static int imx_pd_register(struct drm_device *drm, |
138 | struct imx_parallel_display *imxpd) | 155 | struct imx_parallel_display *imxpd) |
139 | { | 156 | { |
157 | struct drm_encoder *encoder = &imxpd->encoder; | ||
140 | int ret; | 158 | int ret; |
141 | 159 | ||
142 | ret = imx_drm_encoder_parse_of(drm, &imxpd->imx_encoder.encoder, | 160 | ret = imx_drm_encoder_parse_of(drm, encoder, imxpd->dev->of_node); |
143 | imxpd->dev->of_node); | ||
144 | if (ret) | 161 | if (ret) |
145 | return ret; | 162 | return ret; |
146 | 163 | ||
@@ -151,10 +168,9 @@ static int imx_pd_register(struct drm_device *drm, | |||
151 | */ | 168 | */ |
152 | imxpd->connector.dpms = DRM_MODE_DPMS_OFF; | 169 | imxpd->connector.dpms = DRM_MODE_DPMS_OFF; |
153 | 170 | ||
154 | drm_encoder_helper_add(&imxpd->imx_encoder.encoder, | 171 | drm_encoder_helper_add(encoder, &imx_pd_encoder_helper_funcs); |
155 | &imx_pd_encoder_helper_funcs); | 172 | drm_encoder_init(drm, encoder, &imx_pd_encoder_funcs, |
156 | drm_encoder_init(drm, &imxpd->imx_encoder.encoder, | 173 | DRM_MODE_ENCODER_NONE, NULL); |
157 | &imx_pd_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL); | ||
158 | 174 | ||
159 | drm_connector_helper_add(&imxpd->connector, | 175 | drm_connector_helper_add(&imxpd->connector, |
160 | &imx_pd_connector_helper_funcs); | 176 | &imx_pd_connector_helper_funcs); |
@@ -164,8 +180,7 @@ static int imx_pd_register(struct drm_device *drm, | |||
164 | if (imxpd->panel) | 180 | if (imxpd->panel) |
165 | drm_panel_attach(imxpd->panel, &imxpd->connector); | 181 | drm_panel_attach(imxpd->panel, &imxpd->connector); |
166 | 182 | ||
167 | drm_mode_connector_attach_encoder(&imxpd->connector, | 183 | drm_mode_connector_attach_encoder(&imxpd->connector, encoder); |
168 | &imxpd->imx_encoder.encoder); | ||
169 | 184 | ||
170 | return 0; | 185 | return 0; |
171 | } | 186 | } |
@@ -200,9 +215,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) | |||
200 | else if (!strcmp(fmt, "lvds666")) | 215 | else if (!strcmp(fmt, "lvds666")) |
201 | bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; | 216 | bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; |
202 | } | 217 | } |
203 | imxpd->imx_encoder.bus_format = bus_format; | 218 | imxpd->bus_format = bus_format; |
204 | imxpd->imx_encoder.di_hsync_pin = 2; | ||
205 | imxpd->imx_encoder.di_vsync_pin = 3; | ||
206 | 219 | ||
207 | /* port@1 is the output port */ | 220 | /* port@1 is the output port */ |
208 | ep = of_graph_get_endpoint_by_regs(np, 1, -1); | 221 | ep = of_graph_get_endpoint_by_regs(np, 1, -1); |
@@ -235,7 +248,7 @@ static void imx_pd_unbind(struct device *dev, struct device *master, | |||
235 | { | 248 | { |
236 | struct imx_parallel_display *imxpd = dev_get_drvdata(dev); | 249 | struct imx_parallel_display *imxpd = dev_get_drvdata(dev); |
237 | 250 | ||
238 | imxpd->imx_encoder.encoder.funcs->destroy(&imxpd->imx_encoder.encoder); | 251 | imxpd->encoder.funcs->destroy(&imxpd->encoder); |
239 | imxpd->connector.funcs->destroy(&imxpd->connector); | 252 | imxpd->connector.funcs->destroy(&imxpd->connector); |
240 | 253 | ||
241 | kfree(imxpd->edid); | 254 | kfree(imxpd->edid); |