|
@@ -37,6 +37,7 @@
|
|
|
* @xstride: value to add to the pixel pointer between each line
|
|
* @xstride: value to add to the pixel pointer between each line
|
|
|
* @pstride: value to add to the pixel pointer between each pixel
|
|
* @pstride: value to add to the pixel pointer between each pixel
|
|
|
* @nplanes: number of planes (deduced from pixel_format)
|
|
* @nplanes: number of planes (deduced from pixel_format)
|
|
|
|
|
+ * @prepared: plane update has been prepared
|
|
|
*/
|
|
*/
|
|
|
struct atmel_hlcdc_plane_state {
|
|
struct atmel_hlcdc_plane_state {
|
|
|
struct drm_plane_state base;
|
|
struct drm_plane_state base;
|
|
@@ -64,6 +65,7 @@ struct atmel_hlcdc_plane_state {
|
|
|
int xstride[ATMEL_HLCDC_MAX_PLANES];
|
|
int xstride[ATMEL_HLCDC_MAX_PLANES];
|
|
|
int pstride[ATMEL_HLCDC_MAX_PLANES];
|
|
int pstride[ATMEL_HLCDC_MAX_PLANES];
|
|
|
int nplanes;
|
|
int nplanes;
|
|
|
|
|
+ bool prepared;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static inline struct atmel_hlcdc_plane_state *
|
|
static inline struct atmel_hlcdc_plane_state *
|
|
@@ -714,12 +716,54 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
|
|
|
static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
|
|
static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
|
|
|
const struct drm_plane_state *new_state)
|
|
const struct drm_plane_state *new_state)
|
|
|
{
|
|
{
|
|
|
|
|
+ /*
|
|
|
|
|
+ * FIXME: we should avoid this const -> non-const cast but it's
|
|
|
|
|
+ * currently the only solution we have to modify the ->prepared
|
|
|
|
|
+ * state and rollback the update request.
|
|
|
|
|
+ * Ideally, we should rework the code to attach all the resources
|
|
|
|
|
+ * to atmel_hlcdc_plane_state (including the DMA desc allocation),
|
|
|
|
|
+ * but this require a complete rework of the atmel_hlcdc_layer
|
|
|
|
|
+ * code.
|
|
|
|
|
+ */
|
|
|
|
|
+ struct drm_plane_state *s = (struct drm_plane_state *)new_state;
|
|
|
struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
|
|
struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
|
|
|
|
|
+ struct atmel_hlcdc_plane_state *state =
|
|
|
|
|
+ drm_plane_state_to_atmel_hlcdc_plane_state(s);
|
|
|
|
|
+ int ret;
|
|
|
|
|
|
|
|
- if (!new_state->fb)
|
|
|
|
|
- return 0;
|
|
|
|
|
|
|
+ ret = atmel_hlcdc_layer_update_start(&plane->layer);
|
|
|
|
|
+ if (!ret)
|
|
|
|
|
+ state->prepared = true;
|
|
|
|
|
+
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p,
|
|
|
|
|
+ const struct drm_plane_state *old_state)
|
|
|
|
|
+{
|
|
|
|
|
+ /*
|
|
|
|
|
+ * FIXME: we should avoid this const -> non-const cast but it's
|
|
|
|
|
+ * currently the only solution we have to modify the ->prepared
|
|
|
|
|
+ * state and rollback the update request.
|
|
|
|
|
+ * Ideally, we should rework the code to attach all the resources
|
|
|
|
|
+ * to atmel_hlcdc_plane_state (including the DMA desc allocation),
|
|
|
|
|
+ * but this require a complete rework of the atmel_hlcdc_layer
|
|
|
|
|
+ * code.
|
|
|
|
|
+ */
|
|
|
|
|
+ struct drm_plane_state *s = (struct drm_plane_state *)old_state;
|
|
|
|
|
+ struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
|
|
|
|
|
+ struct atmel_hlcdc_plane_state *state =
|
|
|
|
|
+ drm_plane_state_to_atmel_hlcdc_plane_state(s);
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * The Request has already been applied or cancelled, nothing to do
|
|
|
|
|
+ * here.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (!state->prepared)
|
|
|
|
|
+ return;
|
|
|
|
|
|
|
|
- return atmel_hlcdc_layer_update_start(&plane->layer);
|
|
|
|
|
|
|
+ atmel_hlcdc_layer_update_rollback(&plane->layer);
|
|
|
|
|
+ state->prepared = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
|
|
static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
|
|
@@ -844,6 +888,7 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
|
|
|
|
|
|
|
|
static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
|
|
static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
|
|
|
.prepare_fb = atmel_hlcdc_plane_prepare_fb,
|
|
.prepare_fb = atmel_hlcdc_plane_prepare_fb,
|
|
|
|
|
+ .cleanup_fb = atmel_hlcdc_plane_cleanup_fb,
|
|
|
.atomic_check = atmel_hlcdc_plane_atomic_check,
|
|
.atomic_check = atmel_hlcdc_plane_atomic_check,
|
|
|
.atomic_update = atmel_hlcdc_plane_atomic_update,
|
|
.atomic_update = atmel_hlcdc_plane_atomic_update,
|
|
|
.atomic_disable = atmel_hlcdc_plane_atomic_disable,
|
|
.atomic_disable = atmel_hlcdc_plane_atomic_disable,
|
|
@@ -883,6 +928,7 @@ atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p)
|
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
|
|
copy->disc_updated = false;
|
|
copy->disc_updated = false;
|
|
|
|
|
+ copy->prepared = false;
|
|
|
|
|
|
|
|
if (copy->base.fb)
|
|
if (copy->base.fb)
|
|
|
drm_framebuffer_reference(copy->base.fb);
|
|
drm_framebuffer_reference(copy->base.fb);
|