diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-05-31 15:09:14 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2018-09-03 09:13:29 -0400 |
commit | 90279e9518da8488982e9d5704b890fe0e34ad30 (patch) | |
tree | 4386b86cdc84177cd8c7b90c1a95820069721fbb /drivers/gpu/drm/omapdrm/omap_connector.c | |
parent | f006325cdc8008b015b47d830bce072adf40f313 (diff) |
drm/omap: Don't call EDID read operation recursively
Instead of calling the EDID read operation (.read_edid()) recursively
from the display device back to the first device that provides EDID read
support, iterate over the devices manually in the DRM connector code.
This moves the complexity to a single central location and simplifies
the logic in omap_dss_device drivers.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_connector.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_connector.c | 101 |
1 files changed, 58 insertions, 43 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 344414ef3962..5091991363d6 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c | |||
@@ -170,65 +170,80 @@ static void omap_connector_destroy(struct drm_connector *connector) | |||
170 | 170 | ||
171 | #define MAX_EDID 512 | 171 | #define MAX_EDID 512 |
172 | 172 | ||
173 | static int omap_connector_get_modes_edid(struct drm_connector *connector, | ||
174 | struct omap_dss_device *dssdev) | ||
175 | { | ||
176 | struct omap_connector *omap_connector = to_omap_connector(connector); | ||
177 | enum drm_connector_status status; | ||
178 | void *edid; | ||
179 | int n; | ||
180 | |||
181 | status = omap_connector_detect(connector, false); | ||
182 | if (status != connector_status_connected) | ||
183 | goto no_edid; | ||
184 | |||
185 | edid = kzalloc(MAX_EDID, GFP_KERNEL); | ||
186 | if (!edid) | ||
187 | goto no_edid; | ||
188 | |||
189 | if (dssdev->ops->read_edid(dssdev, edid, MAX_EDID) <= 0 || | ||
190 | !drm_edid_is_valid(edid)) { | ||
191 | kfree(edid); | ||
192 | goto no_edid; | ||
193 | } | ||
194 | |||
195 | drm_connector_update_edid_property(connector, edid); | ||
196 | n = drm_add_edid_modes(connector, edid); | ||
197 | |||
198 | omap_connector->hdmi_mode = drm_detect_hdmi_monitor(edid); | ||
199 | |||
200 | kfree(edid); | ||
201 | return n; | ||
202 | |||
203 | no_edid: | ||
204 | drm_connector_update_edid_property(connector, NULL); | ||
205 | return 0; | ||
206 | } | ||
207 | |||
173 | static int omap_connector_get_modes(struct drm_connector *connector) | 208 | static int omap_connector_get_modes(struct drm_connector *connector) |
174 | { | 209 | { |
175 | struct omap_connector *omap_connector = to_omap_connector(connector); | 210 | struct omap_connector *omap_connector = to_omap_connector(connector); |
176 | struct omap_dss_device *dssdev = omap_connector->dssdev; | 211 | struct omap_dss_device *dssdev; |
177 | struct drm_device *dev = connector->dev; | 212 | struct drm_display_mode *mode; |
178 | int n = 0; | 213 | struct videomode vm = {0}; |
179 | 214 | ||
180 | DBG("%s", omap_connector->dssdev->name); | 215 | DBG("%s", omap_connector->dssdev->name); |
181 | 216 | ||
182 | /* if display exposes EDID, then we parse that in the normal way to | 217 | /* |
183 | * build table of supported modes.. otherwise (ie. fixed resolution | 218 | * If display exposes EDID, then we parse that in the normal way to |
219 | * build table of supported modes. Otherwise (ie. fixed resolution | ||
184 | * LCD panels) we just return a single mode corresponding to the | 220 | * LCD panels) we just return a single mode corresponding to the |
185 | * currently configured timings: | 221 | * currently configured timings. |
186 | */ | 222 | */ |
187 | if (dssdev->ops->read_edid) { | 223 | dssdev = omap_connector_find_device(connector, |
188 | void *edid = kzalloc(MAX_EDID, GFP_KERNEL); | 224 | OMAP_DSS_DEVICE_OP_EDID); |
189 | 225 | if (dssdev) | |
190 | if (!edid) | 226 | return omap_connector_get_modes_edid(connector, dssdev); |
191 | return 0; | ||
192 | |||
193 | if ((dssdev->ops->read_edid(dssdev, edid, MAX_EDID) > 0) && | ||
194 | drm_edid_is_valid(edid)) { | ||
195 | drm_connector_update_edid_property( | ||
196 | connector, edid); | ||
197 | n = drm_add_edid_modes(connector, edid); | ||
198 | |||
199 | omap_connector->hdmi_mode = | ||
200 | drm_detect_hdmi_monitor(edid); | ||
201 | } else { | ||
202 | drm_connector_update_edid_property( | ||
203 | connector, NULL); | ||
204 | } | ||
205 | |||
206 | kfree(edid); | ||
207 | } else { | ||
208 | struct drm_display_mode *mode = drm_mode_create(dev); | ||
209 | struct videomode vm = {0}; | ||
210 | 227 | ||
211 | if (!mode) | 228 | mode = drm_mode_create(connector->dev); |
212 | return 0; | 229 | if (!mode) |
230 | return 0; | ||
213 | 231 | ||
214 | dssdev->ops->get_timings(dssdev, &vm); | 232 | dssdev = omap_connector->dssdev; |
233 | dssdev->ops->get_timings(dssdev, &vm); | ||
215 | 234 | ||
216 | drm_display_mode_from_videomode(&vm, mode); | 235 | drm_display_mode_from_videomode(&vm, mode); |
217 | 236 | ||
218 | mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; | 237 | mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; |
219 | drm_mode_set_name(mode); | 238 | drm_mode_set_name(mode); |
220 | drm_mode_probed_add(connector, mode); | 239 | drm_mode_probed_add(connector, mode); |
221 | 240 | ||
222 | if (dssdev->driver && dssdev->driver->get_size) { | 241 | if (dssdev->driver && dssdev->driver->get_size) |
223 | dssdev->driver->get_size(dssdev, | 242 | dssdev->driver->get_size(dssdev, |
224 | &connector->display_info.width_mm, | 243 | &connector->display_info.width_mm, |
225 | &connector->display_info.height_mm); | 244 | &connector->display_info.height_mm); |
226 | } | ||
227 | 245 | ||
228 | n = 1; | 246 | return 1; |
229 | } | ||
230 | |||
231 | return n; | ||
232 | } | 247 | } |
233 | 248 | ||
234 | static int omap_connector_mode_valid(struct drm_connector *connector, | 249 | static int omap_connector_mode_valid(struct drm_connector *connector, |