static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_manager *manager = exynos_crtc->manager;
DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
drm_crtc_vblank_off(crtc);
}
- if (manager->ops->dpms)
- manager->ops->dpms(manager, mode);
+ if (exynos_crtc->ops->dpms)
+ exynos_crtc->ops->dpms(exynos_crtc, mode);
exynos_crtc->dpms = mode;
static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
{
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_manager *manager = exynos_crtc->manager;
struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary);
exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
- if (manager->ops->win_commit)
- manager->ops->win_commit(manager, exynos_plane->zpos);
+ if (exynos_crtc->ops->win_commit)
+ exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
- if (manager->ops->commit)
- manager->ops->commit(manager);
-
- exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
+ if (exynos_crtc->ops->commit)
+ exynos_crtc->ops->commit(exynos_crtc);
}
static bool
struct drm_display_mode *adjusted_mode)
{
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_manager *manager = exynos_crtc->manager;
- if (manager->ops->mode_fixup)
- return manager->ops->mode_fixup(manager, mode, adjusted_mode);
+ if (exynos_crtc->ops->mode_fixup)
+ return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
+ adjusted_mode);
return true;
}
struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb)
{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_manager *manager = exynos_crtc->manager;
struct drm_framebuffer *fb = crtc->primary->fb;
unsigned int crtc_w;
unsigned int crtc_h;
+ int ret;
/*
* copy the mode data adjusted by mode_fixup() into crtc->mode
*/
memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
+ ret = exynos_check_plane(crtc->primary, fb);
+ if (ret < 0)
+ return ret;
+
crtc_w = fb->width - x;
crtc_h = fb->height - y;
+ exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
+ crtc_w, crtc_h, x, y, crtc_w, crtc_h);
- if (manager->ops->mode_set)
- manager->ops->mode_set(manager, &crtc->mode);
-
- return exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
- crtc_w, crtc_h, x, y, crtc_w, crtc_h);
+ return 0;
}
static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
kfree(exynos_crtc);
}
-static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property,
- uint64_t val)
-{
- struct drm_device *dev = crtc->dev;
- struct exynos_drm_private *dev_priv = dev->dev_private;
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-
- if (property == dev_priv->crtc_mode_property) {
- enum exynos_crtc_mode mode = val;
-
- if (mode == exynos_crtc->mode)
- return 0;
-
- exynos_crtc->mode = mode;
-
- switch (mode) {
- case CRTC_MODE_NORMAL:
- exynos_drm_crtc_commit(crtc);
- break;
- case CRTC_MODE_BLANK:
- exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_OFF);
- break;
- default:
- break;
- }
-
- return 0;
- }
-
- return -EINVAL;
-}
-
static struct drm_crtc_funcs exynos_crtc_funcs = {
.set_config = drm_crtc_helper_set_config,
.page_flip = exynos_drm_crtc_page_flip,
.destroy = exynos_drm_crtc_destroy,
- .set_property = exynos_drm_crtc_set_property,
};
-static const struct drm_prop_enum_list mode_names[] = {
- { CRTC_MODE_NORMAL, "normal" },
- { CRTC_MODE_BLANK, "blank" },
-};
-
-static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct exynos_drm_private *dev_priv = dev->dev_private;
- struct drm_property *prop;
-
- prop = dev_priv->crtc_mode_property;
- if (!prop) {
- prop = drm_property_create_enum(dev, 0, "mode", mode_names,
- ARRAY_SIZE(mode_names));
- if (!prop)
- return;
-
- dev_priv->crtc_mode_property = prop;
- }
-
- drm_object_attach_property(&crtc->base, prop, 0);
-}
-
-int exynos_drm_crtc_create(struct exynos_drm_manager *manager,
- struct drm_device *drm_dev, int pipe,
- enum exynos_drm_output_type type)
+struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
+ int pipe,
+ enum exynos_drm_output_type type,
+ struct exynos_drm_crtc_ops *ops,
+ void *ctx)
{
struct exynos_drm_crtc *exynos_crtc;
struct drm_plane *plane;
exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
if (!exynos_crtc)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
init_waitqueue_head(&exynos_crtc->pending_flip_queue);
atomic_set(&exynos_crtc->pending_flip, 0);
exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
- exynos_crtc->manager = manager;
exynos_crtc->pipe = pipe;
exynos_crtc->type = type;
+ exynos_crtc->ops = ops;
+ exynos_crtc->ctx = ctx;
plane = exynos_plane_init(drm_dev, 1 << pipe,
DRM_PLANE_TYPE_PRIMARY);
if (IS_ERR(plane)) {
goto err_plane;
}
- manager->crtc = &exynos_crtc->base;
crtc = &exynos_crtc->base;
private->crtc[pipe] = crtc;
drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
- exynos_drm_crtc_attach_mode_property(crtc);
-
- return 0;
+ return exynos_crtc;
err_crtc:
plane->funcs->destroy(plane);
err_plane:
kfree(exynos_crtc);
- return ret;
+ return ERR_PTR(ret);
}
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
struct exynos_drm_private *private = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc =
to_exynos_crtc(private->crtc[pipe]);
- struct exynos_drm_manager *manager = exynos_crtc->manager;
if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
return -EPERM;
- if (manager->ops->enable_vblank)
- manager->ops->enable_vblank(manager);
+ if (exynos_crtc->ops->enable_vblank)
+ exynos_crtc->ops->enable_vblank(exynos_crtc);
return 0;
}
struct exynos_drm_private *private = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc =
to_exynos_crtc(private->crtc[pipe]);
- struct exynos_drm_manager *manager = exynos_crtc->manager;
if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
return;
- if (manager->ops->disable_vblank)
- manager->ops->disable_vblank(manager);
+ if (exynos_crtc->ops->disable_vblank)
+ exynos_crtc->ops->disable_vblank(exynos_crtc);
}
void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
{
- struct exynos_drm_manager *manager;
+ struct exynos_drm_crtc *exynos_crtc;
struct drm_device *dev = fb->dev;
struct drm_crtc *crtc;
* for all encoders.
*/
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- manager = to_exynos_crtc(crtc)->manager;
+ exynos_crtc = to_exynos_crtc(crtc);
/*
* wait for vblank interrupt
* - this makes sure that overlay data are updated to
* real hardware.
*/
- if (manager->ops->wait_for_vblank)
- manager->ops->wait_for_vblank(manager);
+ if (exynos_crtc->ops->wait_for_vblank)
+ exynos_crtc->ops->wait_for_vblank(exynos_crtc);
}
}
void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
{
- struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- if (manager->ops->te_handler)
- manager->ops->te_handler(manager);
+ if (exynos_crtc->ops->te_handler)
+ exynos_crtc->ops->te_handler(exynos_crtc);
}