aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_connector.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-05-31 15:09:14 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2018-09-03 09:13:29 -0400
commit90279e9518da8488982e9d5704b890fe0e34ad30 (patch)
tree4386b86cdc84177cd8c7b90c1a95820069721fbb /drivers/gpu/drm/omapdrm/omap_connector.c
parentf006325cdc8008b015b47d830bce072adf40f313 (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.c101
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
173static 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
203no_edid:
204 drm_connector_update_edid_property(connector, NULL);
205 return 0;
206}
207
173static int omap_connector_get_modes(struct drm_connector *connector) 208static 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
234static int omap_connector_mode_valid(struct drm_connector *connector, 249static int omap_connector_mode_valid(struct drm_connector *connector,