Skip to content

Commit

Permalink
staging: drm/omap: use omapdss low level API
Browse files Browse the repository at this point in the history
This patch changes the omapdrm KMS to bypass the omapdss "compat"
layer and use the core omapdss API directly.  This solves some layering
issues that would cause unpin confusion vs GO bit status, because we
would not know whether a particular pageflip or overlay update has hit
the screen or not.  Now instead we explicitly manage the GO bits in
dispc and handle the vblank/framedone interrupts ourself so that we
always know which buffers are being scanned out at any given time, and
so on.

As an added bonus, we no longer leave the last overlay buffer pinned
when the display is disabled, and have been able to add the previously
missing vblank event handling.

v1: original
v2: rebased on latest staging-next and omapdss patches from Tomi and
    review comments from Archit Taneja

Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Archit Taneja <archit@ti.com>
Reviewed-by: Sumit Semwal <sumit.semwal@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Rob Clark authored and Greg Kroah-Hartman committed Jan 7, 2013
1 parent 3c8c21e commit f5f9454
Show file tree
Hide file tree
Showing 9 changed files with 1,214 additions and 893 deletions.
1 change: 1 addition & 0 deletions drivers/staging/omapdrm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

ccflags-y := -Iinclude/drm -Werror
omapdrm-y := omap_drv.o \
omap_irq.o \
omap_debugfs.o \
omap_crtc.o \
omap_plane.o \
Expand Down
3 changes: 0 additions & 3 deletions drivers/staging/omapdrm/TODO
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ TODO
. Revisit GEM sync object infrastructure.. TTM has some framework for this
already. Possibly this could be refactored out and made more common?
There should be some way to do this with less wheel-reinvention.
. Review DSS vs KMS mismatches. The omap_dss_device is sort of part encoder,
part connector. Which results in a bit of duct tape to fwd calls from
encoder to connector. Possibly this could be done a bit better.
. Solve PM sequencing on resume. DMM/TILER must be reloaded before any
access is made from any component in the system. Which means on suspend
CRTC's should be disabled, and on resume the LUT should be reprogrammed
Expand Down
111 changes: 10 additions & 101 deletions drivers/staging/omapdrm/omap_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
struct omap_connector {
struct drm_connector base;
struct omap_dss_device *dssdev;
struct drm_encoder *encoder;
};

static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
void copy_timings_omap_to_drm(struct drm_display_mode *mode,
struct omap_video_timings *timings)
{
mode->clock = timings->pixel_clock;
Expand Down Expand Up @@ -64,7 +65,7 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
mode->flags |= DRM_MODE_FLAG_NVSYNC;
}

static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
void copy_timings_drm_to_omap(struct omap_video_timings *timings,
struct drm_display_mode *mode)
{
timings->pixel_clock = mode->clock;
Expand Down Expand Up @@ -96,48 +97,7 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
}

static void omap_connector_dpms(struct drm_connector *connector, int mode)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev = omap_connector->dssdev;
int old_dpms;

DBG("%s: %d", dssdev->name, mode);

old_dpms = connector->dpms;

/* from off to on, do from crtc to connector */
if (mode < old_dpms)
drm_helper_connector_dpms(connector, mode);

if (mode == DRM_MODE_DPMS_ON) {
/* store resume info for suspended displays */
switch (dssdev->state) {
case OMAP_DSS_DISPLAY_SUSPENDED:
dssdev->activate_after_resume = true;
break;
case OMAP_DSS_DISPLAY_DISABLED: {
int ret = dssdev->driver->enable(dssdev);
if (ret) {
DBG("%s: failed to enable: %d",
dssdev->name, ret);
dssdev->driver->disable(dssdev);
}
break;
}
default:
break;
}
} else {
/* TODO */
}

/* from on to off, do from connector to crtc */
if (mode > old_dpms)
drm_helper_connector_dpms(connector, mode);
}

enum drm_connector_status omap_connector_detect(
static enum drm_connector_status omap_connector_detect(
struct drm_connector *connector, bool force)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
Expand All @@ -164,8 +124,6 @@ static void omap_connector_destroy(struct drm_connector *connector)
struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev = omap_connector->dssdev;

dssdev->driver->disable(dssdev);

DBG("%s", omap_connector->dssdev->name);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
Expand Down Expand Up @@ -261,36 +219,12 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
struct drm_encoder *omap_connector_attached_encoder(
struct drm_connector *connector)
{
int i;
struct omap_connector *omap_connector = to_omap_connector(connector);

for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
struct drm_mode_object *obj;

if (connector->encoder_ids[i] == 0)
break;

obj = drm_mode_object_find(connector->dev,
connector->encoder_ids[i],
DRM_MODE_OBJECT_ENCODER);

if (obj) {
struct drm_encoder *encoder = obj_to_encoder(obj);
struct omap_overlay_manager *mgr =
omap_encoder_get_manager(encoder);
DBG("%s: found %s", omap_connector->dssdev->name,
mgr->name);
return encoder;
}
}

DBG("%s: no encoder", omap_connector->dssdev->name);

return NULL;
return omap_connector->encoder;
}

static const struct drm_connector_funcs omap_connector_funcs = {
.dpms = omap_connector_dpms,
.dpms = drm_helper_connector_dpms,
.detect = omap_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = omap_connector_destroy,
Expand All @@ -302,34 +236,6 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
.best_encoder = omap_connector_attached_encoder,
};

/* called from encoder when mode is set, to propagate settings to the dssdev */
void omap_connector_mode_set(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct drm_device *dev = connector->dev;
struct omap_connector *omap_connector = to_omap_connector(connector);
struct omap_dss_device *dssdev = omap_connector->dssdev;
struct omap_dss_driver *dssdrv = dssdev->driver;
struct omap_video_timings timings = {0};

copy_timings_drm_to_omap(&timings, mode);

DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
omap_connector->dssdev->name,
mode->base.id, mode->name, mode->vrefresh, mode->clock,
mode->hdisplay, mode->hsync_start,
mode->hsync_end, mode->htotal,
mode->vdisplay, mode->vsync_start,
mode->vsync_end, mode->vtotal, mode->type, mode->flags);

if (dssdrv->check_timings(dssdev, &timings)) {
dev_err(dev->dev, "could not set timings\n");
return;
}

dssdrv->set_timings(dssdev, &timings);
}

/* flush an area of the framebuffer (in case of manual update display that
* is not automatically flushed)
*/
Expand All @@ -344,7 +250,8 @@ void omap_connector_flush(struct drm_connector *connector,

/* initialize connector */
struct drm_connector *omap_connector_init(struct drm_device *dev,
int connector_type, struct omap_dss_device *dssdev)
int connector_type, struct omap_dss_device *dssdev,
struct drm_encoder *encoder)
{
struct drm_connector *connector = NULL;
struct omap_connector *omap_connector;
Expand All @@ -360,6 +267,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
}

omap_connector->dssdev = dssdev;
omap_connector->encoder = encoder;

connector = &omap_connector->base;

drm_connector_init(dev, connector, &omap_connector_funcs,
Expand Down
Loading

0 comments on commit f5f9454

Please sign in to comment.