Icenowy Zheng | 9d75b8c | 2017-05-17 22:47:20 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) Icenowy Zheng <icenowy@aosc.io> |
| 3 | * |
| 4 | * Based on sun4i_layer.h, which is: |
| 5 | * Copyright (C) 2015 Free Electrons |
| 6 | * Copyright (C) 2015 NextThing Co |
| 7 | * |
| 8 | * Maxime Ripard <maxime.ripard@free-electrons.com> |
| 9 | * |
| 10 | * This program is free software; you can redistribute it and/or |
| 11 | * modify it under the terms of the GNU General Public License as |
| 12 | * published by the Free Software Foundation; either version 2 of |
| 13 | * the License, or (at your option) any later version. |
| 14 | */ |
| 15 | |
| 16 | #include <drm/drm_atomic_helper.h> |
| 17 | #include <drm/drm_plane_helper.h> |
| 18 | #include <drm/drmP.h> |
| 19 | |
| 20 | #include "sun8i_layer.h" |
| 21 | #include "sun8i_mixer.h" |
| 22 | |
| 23 | struct sun8i_plane_desc { |
| 24 | enum drm_plane_type type; |
| 25 | const uint32_t *formats; |
| 26 | uint32_t nformats; |
| 27 | }; |
| 28 | |
| 29 | static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane, |
| 30 | struct drm_plane_state *old_state) |
| 31 | { |
| 32 | struct sun8i_layer *layer = plane_to_sun8i_layer(plane); |
| 33 | struct sun8i_mixer *mixer = layer->mixer; |
| 34 | |
| 35 | sun8i_mixer_layer_enable(mixer, layer->id, false); |
| 36 | } |
| 37 | |
| 38 | static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane, |
| 39 | struct drm_plane_state *old_state) |
| 40 | { |
| 41 | struct sun8i_layer *layer = plane_to_sun8i_layer(plane); |
| 42 | struct sun8i_mixer *mixer = layer->mixer; |
| 43 | |
| 44 | sun8i_mixer_update_layer_coord(mixer, layer->id, plane); |
| 45 | sun8i_mixer_update_layer_formats(mixer, layer->id, plane); |
| 46 | sun8i_mixer_update_layer_buffer(mixer, layer->id, plane); |
| 47 | sun8i_mixer_layer_enable(mixer, layer->id, true); |
| 48 | } |
| 49 | |
| 50 | static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = { |
| 51 | .atomic_disable = sun8i_mixer_layer_atomic_disable, |
| 52 | .atomic_update = sun8i_mixer_layer_atomic_update, |
| 53 | }; |
| 54 | |
| 55 | static const struct drm_plane_funcs sun8i_mixer_layer_funcs = { |
| 56 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, |
| 57 | .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, |
| 58 | .destroy = drm_plane_cleanup, |
| 59 | .disable_plane = drm_atomic_helper_disable_plane, |
| 60 | .reset = drm_atomic_helper_plane_reset, |
| 61 | .update_plane = drm_atomic_helper_update_plane, |
| 62 | }; |
| 63 | |
| 64 | static const uint32_t sun8i_mixer_layer_formats[] = { |
| 65 | DRM_FORMAT_RGB888, |
| 66 | DRM_FORMAT_ARGB8888, |
| 67 | DRM_FORMAT_XRGB8888, |
| 68 | }; |
| 69 | |
| 70 | static const struct sun8i_plane_desc sun8i_mixer_planes[] = { |
| 71 | { |
| 72 | .type = DRM_PLANE_TYPE_PRIMARY, |
| 73 | .formats = sun8i_mixer_layer_formats, |
| 74 | .nformats = ARRAY_SIZE(sun8i_mixer_layer_formats), |
| 75 | }, |
| 76 | }; |
| 77 | |
| 78 | static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm, |
| 79 | struct sun8i_mixer *mixer, |
| 80 | const struct sun8i_plane_desc *plane) |
| 81 | { |
| 82 | struct sun8i_layer *layer; |
| 83 | int ret; |
| 84 | |
| 85 | layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL); |
| 86 | if (!layer) |
| 87 | return ERR_PTR(-ENOMEM); |
| 88 | |
| 89 | /* possible crtcs are set later */ |
| 90 | ret = drm_universal_plane_init(drm, &layer->plane, 0, |
| 91 | &sun8i_mixer_layer_funcs, |
| 92 | plane->formats, plane->nformats, |
Ben Widawsky | e6fc3b6 | 2017-07-23 20:46:38 -0700 | [diff] [blame^] | 93 | NULL, plane->type, NULL); |
Icenowy Zheng | 9d75b8c | 2017-05-17 22:47:20 +0800 | [diff] [blame] | 94 | if (ret) { |
| 95 | dev_err(drm->dev, "Couldn't initialize layer\n"); |
| 96 | return ERR_PTR(ret); |
| 97 | } |
| 98 | |
| 99 | drm_plane_helper_add(&layer->plane, |
| 100 | &sun8i_mixer_layer_helper_funcs); |
| 101 | layer->mixer = mixer; |
| 102 | |
| 103 | return layer; |
| 104 | } |
| 105 | |
| 106 | struct drm_plane **sun8i_layers_init(struct drm_device *drm, |
| 107 | struct sunxi_engine *engine) |
| 108 | { |
| 109 | struct drm_plane **planes; |
| 110 | struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); |
| 111 | int i; |
| 112 | |
| 113 | planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1, |
| 114 | sizeof(*planes), GFP_KERNEL); |
| 115 | if (!planes) |
| 116 | return ERR_PTR(-ENOMEM); |
| 117 | |
| 118 | for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) { |
| 119 | const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i]; |
| 120 | struct sun8i_layer *layer; |
| 121 | |
| 122 | layer = sun8i_layer_init_one(drm, mixer, plane); |
| 123 | if (IS_ERR(layer)) { |
| 124 | dev_err(drm->dev, "Couldn't initialize %s plane\n", |
| 125 | i ? "overlay" : "primary"); |
| 126 | return ERR_CAST(layer); |
| 127 | }; |
| 128 | |
| 129 | layer->id = i; |
| 130 | planes[i] = &layer->plane; |
| 131 | }; |
| 132 | |
| 133 | return planes; |
| 134 | } |