Commit bddabbe174cfb6f944baaf13ed5b93c6ee89ec3d

Authored by Archit Taneja
Committed by Tomi Valkeinen
1 parent 581382e310

drm/omap: Make fixed resolution panels work

The omapdrm driver requires omapdss panel drivers to expose ops like detect,
set_timings and check_timings. These can be NULL for fixed panel DPI, DBI, DSI
and SDI drivers. At some places, there are no checks to see if the panel driver
has these ops or not, and that leads to a crash.

The following things are done to make fixed panels work:

- The omap_connector's detect function is modified such that it considers panel
  types which are generally fixed panels as always connected(provided the panel
  driver doesn't have a detect op). Hence, the connector corresponding to these
  panels is always in a 'connected' state.

- If a panel driver doesn't have a check_timings op, assume that it supports the
  mode passed to omap_connector_mode_valid(the 'mode_valid' drm helper function)

- The function omap_encoder_update shouldn't really do anything for fixed
  resolution panels, make sure that it calls set_timings only if the panel
  driver has one.

Signed-off-by: Archit Taneja <archit@ti.com>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

Showing 2 changed files with 40 additions and 4 deletions Side-by-side Diff

drivers/gpu/drm/omapdrm/omap_connector.c
... ... @@ -110,6 +110,11 @@
110 110 ret = connector_status_connected;
111 111 else
112 112 ret = connector_status_disconnected;
  113 + } else if (dssdev->type == OMAP_DISPLAY_TYPE_DPI ||
  114 + dssdev->type == OMAP_DISPLAY_TYPE_DBI ||
  115 + dssdev->type == OMAP_DISPLAY_TYPE_SDI ||
  116 + dssdev->type == OMAP_DISPLAY_TYPE_DSI) {
  117 + ret = connector_status_connected;
113 118 } else {
114 119 ret = connector_status_unknown;
115 120 }
116 121  
... ... @@ -189,12 +194,30 @@
189 194 struct omap_video_timings timings = {0};
190 195 struct drm_device *dev = connector->dev;
191 196 struct drm_display_mode *new_mode;
192   - int ret = MODE_BAD;
  197 + int r, ret = MODE_BAD;
193 198  
194 199 copy_timings_drm_to_omap(&timings, mode);
195 200 mode->vrefresh = drm_mode_vrefresh(mode);
196 201  
197   - if (!dssdrv->check_timings(dssdev, &timings)) {
  202 + /*
  203 + * if the panel driver doesn't have a check_timings, it's most likely
  204 + * a fixed resolution panel, check if the timings match with the
  205 + * panel's timings
  206 + */
  207 + if (dssdrv->check_timings) {
  208 + r = dssdrv->check_timings(dssdev, &timings);
  209 + } else {
  210 + struct omap_video_timings t = {0};
  211 +
  212 + dssdrv->get_timings(dssdev, &t);
  213 +
  214 + if (memcmp(&timings, &t, sizeof(struct omap_video_timings)))
  215 + r = -EINVAL;
  216 + else
  217 + r = 0;
  218 + }
  219 +
  220 + if (!r) {
198 221 /* check if vrefresh is still valid */
199 222 new_mode = drm_mode_duplicate(dev, mode);
200 223 new_mode->clock = timings.pixel_clock;
drivers/gpu/drm/omapdrm/omap_encoder.c
... ... @@ -128,13 +128,26 @@
128 128  
129 129 dssdev->output->manager = mgr;
130 130  
131   - ret = dssdrv->check_timings(dssdev, timings);
  131 + if (dssdrv->check_timings) {
  132 + ret = dssdrv->check_timings(dssdev, timings);
  133 + } else {
  134 + struct omap_video_timings t = {0};
  135 +
  136 + dssdrv->get_timings(dssdev, &t);
  137 +
  138 + if (memcmp(timings, &t, sizeof(struct omap_video_timings)))
  139 + ret = -EINVAL;
  140 + else
  141 + ret = 0;
  142 + }
  143 +
132 144 if (ret) {
133 145 dev_err(dev->dev, "could not set timings: %d\n", ret);
134 146 return ret;
135 147 }
136 148  
137   - dssdrv->set_timings(dssdev, timings);
  149 + if (dssdrv->set_timings)
  150 + dssdrv->set_timings(dssdev, timings);
138 151  
139 152 return 0;
140 153 }