0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <drm/drm_atomic.h>
0010 #include <drm/drm_atomic_helper.h>
0011 #include <drm/drm_blend.h>
0012 #include <drm/drm_gem_atomic_helper.h>
0013 #include <drm/drm_plane_helper.h>
0014
0015 #include "sun4i_backend.h"
0016 #include "sun4i_frontend.h"
0017 #include "sun4i_layer.h"
0018 #include "sunxi_engine.h"
0019
0020 static void sun4i_backend_layer_reset(struct drm_plane *plane)
0021 {
0022 struct sun4i_layer_state *state;
0023
0024 if (plane->state) {
0025 state = state_to_sun4i_layer_state(plane->state);
0026
0027 __drm_atomic_helper_plane_destroy_state(&state->state);
0028
0029 kfree(state);
0030 plane->state = NULL;
0031 }
0032
0033 state = kzalloc(sizeof(*state), GFP_KERNEL);
0034 if (state)
0035 __drm_atomic_helper_plane_reset(plane, &state->state);
0036 }
0037
0038 static struct drm_plane_state *
0039 sun4i_backend_layer_duplicate_state(struct drm_plane *plane)
0040 {
0041 struct sun4i_layer_state *orig = state_to_sun4i_layer_state(plane->state);
0042 struct sun4i_layer_state *copy;
0043
0044 copy = kzalloc(sizeof(*copy), GFP_KERNEL);
0045 if (!copy)
0046 return NULL;
0047
0048 __drm_atomic_helper_plane_duplicate_state(plane, ©->state);
0049 copy->uses_frontend = orig->uses_frontend;
0050
0051 return ©->state;
0052 }
0053
0054 static void sun4i_backend_layer_destroy_state(struct drm_plane *plane,
0055 struct drm_plane_state *state)
0056 {
0057 struct sun4i_layer_state *s_state = state_to_sun4i_layer_state(state);
0058
0059 __drm_atomic_helper_plane_destroy_state(state);
0060
0061 kfree(s_state);
0062 }
0063
0064 static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane,
0065 struct drm_atomic_state *state)
0066 {
0067 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
0068 plane);
0069 struct sun4i_layer_state *layer_state = state_to_sun4i_layer_state(old_state);
0070 struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
0071 struct sun4i_backend *backend = layer->backend;
0072
0073 sun4i_backend_layer_enable(backend, layer->id, false);
0074
0075 if (layer_state->uses_frontend) {
0076 unsigned long flags;
0077
0078 spin_lock_irqsave(&backend->frontend_lock, flags);
0079 backend->frontend_teardown = true;
0080 spin_unlock_irqrestore(&backend->frontend_lock, flags);
0081 }
0082 }
0083
0084 static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
0085 struct drm_atomic_state *state)
0086 {
0087 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
0088 plane);
0089 struct sun4i_layer_state *layer_state = state_to_sun4i_layer_state(new_state);
0090 struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
0091 struct sun4i_backend *backend = layer->backend;
0092 struct sun4i_frontend *frontend = backend->frontend;
0093
0094 sun4i_backend_cleanup_layer(backend, layer->id);
0095
0096 if (layer_state->uses_frontend) {
0097 sun4i_frontend_init(frontend);
0098 sun4i_frontend_update_coord(frontend, plane);
0099 sun4i_frontend_update_buffer(frontend, plane);
0100 sun4i_frontend_update_formats(frontend, plane,
0101 DRM_FORMAT_XRGB8888);
0102 sun4i_backend_update_layer_frontend(backend, layer->id,
0103 DRM_FORMAT_XRGB8888);
0104 sun4i_frontend_enable(frontend);
0105 } else {
0106 sun4i_backend_update_layer_formats(backend, layer->id, plane);
0107 sun4i_backend_update_layer_buffer(backend, layer->id, plane);
0108 }
0109
0110 sun4i_backend_update_layer_coord(backend, layer->id, plane);
0111 sun4i_backend_update_layer_zpos(backend, layer->id, plane);
0112 sun4i_backend_layer_enable(backend, layer->id, true);
0113 }
0114
0115 static bool sun4i_layer_format_mod_supported(struct drm_plane *plane,
0116 uint32_t format, uint64_t modifier)
0117 {
0118 struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
0119
0120 if (IS_ERR_OR_NULL(layer->backend->frontend))
0121 return sun4i_backend_format_is_supported(format, modifier);
0122
0123 return sun4i_backend_format_is_supported(format, modifier) ||
0124 sun4i_frontend_format_is_supported(format, modifier);
0125 }
0126
0127 static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
0128 .atomic_disable = sun4i_backend_layer_atomic_disable,
0129 .atomic_update = sun4i_backend_layer_atomic_update,
0130 };
0131
0132 static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
0133 .atomic_destroy_state = sun4i_backend_layer_destroy_state,
0134 .atomic_duplicate_state = sun4i_backend_layer_duplicate_state,
0135 .destroy = drm_plane_cleanup,
0136 .disable_plane = drm_atomic_helper_disable_plane,
0137 .reset = sun4i_backend_layer_reset,
0138 .update_plane = drm_atomic_helper_update_plane,
0139 .format_mod_supported = sun4i_layer_format_mod_supported,
0140 };
0141
0142 static const uint32_t sun4i_layer_formats[] = {
0143 DRM_FORMAT_ARGB8888,
0144 DRM_FORMAT_ARGB4444,
0145 DRM_FORMAT_ARGB1555,
0146 DRM_FORMAT_BGRX8888,
0147 DRM_FORMAT_RGBA5551,
0148 DRM_FORMAT_RGBA4444,
0149 DRM_FORMAT_RGB888,
0150 DRM_FORMAT_RGB565,
0151 DRM_FORMAT_NV12,
0152 DRM_FORMAT_NV16,
0153 DRM_FORMAT_NV21,
0154 DRM_FORMAT_NV61,
0155 DRM_FORMAT_UYVY,
0156 DRM_FORMAT_VYUY,
0157 DRM_FORMAT_XRGB8888,
0158 DRM_FORMAT_YUV411,
0159 DRM_FORMAT_YUV420,
0160 DRM_FORMAT_YUV422,
0161 DRM_FORMAT_YUV444,
0162 DRM_FORMAT_YUYV,
0163 DRM_FORMAT_YVU411,
0164 DRM_FORMAT_YVU420,
0165 DRM_FORMAT_YVU422,
0166 DRM_FORMAT_YVU444,
0167 DRM_FORMAT_YVYU,
0168 };
0169
0170 static const uint32_t sun4i_backend_layer_formats[] = {
0171 DRM_FORMAT_ARGB8888,
0172 DRM_FORMAT_ARGB4444,
0173 DRM_FORMAT_ARGB1555,
0174 DRM_FORMAT_RGBA5551,
0175 DRM_FORMAT_RGBA4444,
0176 DRM_FORMAT_RGB888,
0177 DRM_FORMAT_RGB565,
0178 DRM_FORMAT_UYVY,
0179 DRM_FORMAT_VYUY,
0180 DRM_FORMAT_XRGB8888,
0181 DRM_FORMAT_YUYV,
0182 DRM_FORMAT_YVYU,
0183 };
0184
0185 static const uint64_t sun4i_layer_modifiers[] = {
0186 DRM_FORMAT_MOD_LINEAR,
0187 DRM_FORMAT_MOD_ALLWINNER_TILED,
0188 DRM_FORMAT_MOD_INVALID
0189 };
0190
0191 static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
0192 struct sun4i_backend *backend,
0193 enum drm_plane_type type,
0194 unsigned int id)
0195 {
0196 const uint64_t *modifiers = sun4i_layer_modifiers;
0197 const uint32_t *formats = sun4i_layer_formats;
0198 unsigned int formats_len = ARRAY_SIZE(sun4i_layer_formats);
0199 struct sun4i_layer *layer;
0200 int ret;
0201
0202 layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
0203 if (!layer)
0204 return ERR_PTR(-ENOMEM);
0205
0206 layer->id = id;
0207 layer->backend = backend;
0208
0209 if (IS_ERR_OR_NULL(backend->frontend)) {
0210 formats = sun4i_backend_layer_formats;
0211 formats_len = ARRAY_SIZE(sun4i_backend_layer_formats);
0212 modifiers = NULL;
0213 }
0214
0215
0216 ret = drm_universal_plane_init(drm, &layer->plane, 0,
0217 &sun4i_backend_layer_funcs,
0218 formats, formats_len,
0219 modifiers, type, NULL);
0220 if (ret) {
0221 dev_err(drm->dev, "Couldn't initialize layer\n");
0222 return ERR_PTR(ret);
0223 }
0224
0225 drm_plane_helper_add(&layer->plane,
0226 &sun4i_backend_layer_helper_funcs);
0227
0228 drm_plane_create_alpha_property(&layer->plane);
0229 drm_plane_create_zpos_property(&layer->plane, layer->id,
0230 0, SUN4I_BACKEND_NUM_LAYERS - 1);
0231
0232 return layer;
0233 }
0234
0235 struct drm_plane **sun4i_layers_init(struct drm_device *drm,
0236 struct sunxi_engine *engine)
0237 {
0238 struct drm_plane **planes;
0239 struct sun4i_backend *backend = engine_to_sun4i_backend(engine);
0240 int i;
0241
0242
0243 planes = devm_kcalloc(drm->dev, SUN4I_BACKEND_NUM_LAYERS + 1,
0244 sizeof(*planes), GFP_KERNEL);
0245 if (!planes)
0246 return ERR_PTR(-ENOMEM);
0247
0248 for (i = 0; i < SUN4I_BACKEND_NUM_LAYERS; i++) {
0249 enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY;
0250 struct sun4i_layer *layer;
0251
0252 layer = sun4i_layer_init_one(drm, backend, type, i);
0253 if (IS_ERR(layer)) {
0254 dev_err(drm->dev, "Couldn't initialize %s plane\n",
0255 i ? "overlay" : "primary");
0256 return ERR_CAST(layer);
0257 }
0258
0259 planes[i] = &layer->plane;
0260 }
0261
0262 return planes;
0263 }