aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c')
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c93
1 files changed, 51 insertions, 42 deletions
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index 9b17a66cf0e1..53bfa56ca47a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -55,14 +55,12 @@ drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state)
* @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
* @event: pointer to the current page flip event
* @id: CRTC id (returned by drm_crtc_index)
- * @enabled: CRTC state
*/
struct atmel_hlcdc_crtc {
struct drm_crtc base;
struct atmel_hlcdc_dc *dc;
struct drm_pending_vblank_event *event;
int id;
- bool enabled;
};
static inline struct atmel_hlcdc_crtc *
@@ -158,9 +156,6 @@ static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
struct regmap *regmap = crtc->dc->hlcdc->regmap;
unsigned int status;
- if (!crtc->enabled)
- return;
-
drm_crtc_vblank_off(c);
pm_runtime_get_sync(dev->dev);
@@ -186,8 +181,6 @@ static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
pm_runtime_allow(dev->dev);
pm_runtime_put_sync(dev->dev);
-
- crtc->enabled = false;
}
static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
@@ -197,9 +190,6 @@ static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
struct regmap *regmap = crtc->dc->hlcdc->regmap;
unsigned int status;
- if (crtc->enabled)
- return;
-
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
@@ -226,29 +216,6 @@ static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
pm_runtime_put_sync(dev->dev);
drm_crtc_vblank_on(c);
-
- crtc->enabled = true;
-}
-
-void atmel_hlcdc_crtc_suspend(struct drm_crtc *c)
-{
- struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
-
- if (crtc->enabled) {
- atmel_hlcdc_crtc_disable(c);
- /* save enable state for resume */
- crtc->enabled = true;
- }
-}
-
-void atmel_hlcdc_crtc_resume(struct drm_crtc *c)
-{
- struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
-
- if (crtc->enabled) {
- crtc->enabled = false;
- atmel_hlcdc_crtc_enable(c);
- }
}
#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0)
@@ -434,6 +401,25 @@ static void atmel_hlcdc_crtc_destroy_state(struct drm_crtc *crtc,
kfree(state);
}
+static int atmel_hlcdc_crtc_enable_vblank(struct drm_crtc *c)
+{
+ struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+ struct regmap *regmap = crtc->dc->hlcdc->regmap;
+
+ /* Enable SOF (Start Of Frame) interrupt for vblank counting */
+ regmap_write(regmap, ATMEL_HLCDC_IER, ATMEL_HLCDC_SOF);
+
+ return 0;
+}
+
+static void atmel_hlcdc_crtc_disable_vblank(struct drm_crtc *c)
+{
+ struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+ struct regmap *regmap = crtc->dc->hlcdc->regmap;
+
+ regmap_write(regmap, ATMEL_HLCDC_IDR, ATMEL_HLCDC_SOF);
+}
+
static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
.page_flip = drm_atomic_helper_page_flip,
.set_config = drm_atomic_helper_set_config,
@@ -441,12 +427,14 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
.reset = atmel_hlcdc_crtc_reset,
.atomic_duplicate_state = atmel_hlcdc_crtc_duplicate_state,
.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
+ .enable_vblank = atmel_hlcdc_crtc_enable_vblank,
+ .disable_vblank = atmel_hlcdc_crtc_disable_vblank,
};
int atmel_hlcdc_crtc_create(struct drm_device *dev)
{
+ struct atmel_hlcdc_plane *primary = NULL, *cursor = NULL;
struct atmel_hlcdc_dc *dc = dev->dev_private;
- struct atmel_hlcdc_planes *planes = dc->planes;
struct atmel_hlcdc_crtc *crtc;
int ret;
int i;
@@ -457,20 +445,41 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
crtc->dc = dc;
- ret = drm_crtc_init_with_planes(dev, &crtc->base,
- &planes->primary->base,
- planes->cursor ? &planes->cursor->base : NULL,
- &atmel_hlcdc_crtc_funcs, NULL);
+ for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
+ if (!dc->layers[i])
+ continue;
+
+ switch (dc->layers[i]->desc->type) {
+ case ATMEL_HLCDC_BASE_LAYER:
+ primary = atmel_hlcdc_layer_to_plane(dc->layers[i]);
+ break;
+
+ case ATMEL_HLCDC_CURSOR_LAYER:
+ cursor = atmel_hlcdc_layer_to_plane(dc->layers[i]);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ ret = drm_crtc_init_with_planes(dev, &crtc->base, &primary->base,
+ &cursor->base, &atmel_hlcdc_crtc_funcs,
+ NULL);
if (ret < 0)
goto fail;
crtc->id = drm_crtc_index(&crtc->base);
- if (planes->cursor)
- planes->cursor->base.possible_crtcs = 1 << crtc->id;
+ for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
+ struct atmel_hlcdc_plane *overlay;
- for (i = 0; i < planes->noverlays; i++)
- planes->overlays[i]->base.possible_crtcs = 1 << crtc->id;
+ if (dc->layers[i] &&
+ dc->layers[i]->desc->type == ATMEL_HLCDC_OVERLAY_LAYER) {
+ overlay = atmel_hlcdc_layer_to_plane(dc->layers[i]);
+ overlay->base.possible_crtcs = 1 << crtc->id;
+ }
+ }
drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
drm_crtc_vblank_reset(&crtc->base);