Commit | Line | Data |
---|---|---|
d219673d BG |
1 | /* |
2 | * Copyright (C) STMicroelectronics SA 2014 | |
3 | * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | |
4 | * Fabien Dessenne <fabien.dessenne@st.com> | |
5 | * for STMicroelectronics. | |
6 | * License terms: GNU General Public License (GPL), version 2 | |
7 | */ | |
8 | ||
9 | #include <drm/drmP.h> | |
10 | #include <drm/drm_gem_cma_helper.h> | |
11 | #include <drm/drm_fb_cma_helper.h> | |
12 | ||
13 | #include "sti_compositor.h" | |
96006a77 | 14 | #include "sti_cursor.h" |
d219673d | 15 | #include "sti_gdp.h" |
4fdbc678 | 16 | #include "sti_hqvdp.h" |
d219673d BG |
17 | #include "sti_layer.h" |
18 | #include "sti_vid.h" | |
19 | ||
20 | const char *sti_layer_to_str(struct sti_layer *layer) | |
21 | { | |
22 | switch (layer->desc) { | |
23 | case STI_GDP_0: | |
24 | return "GDP0"; | |
25 | case STI_GDP_1: | |
26 | return "GDP1"; | |
27 | case STI_GDP_2: | |
28 | return "GDP2"; | |
29 | case STI_GDP_3: | |
30 | return "GDP3"; | |
31 | case STI_VID_0: | |
32 | return "VID0"; | |
33 | case STI_VID_1: | |
34 | return "VID1"; | |
35 | case STI_CURSOR: | |
36 | return "CURSOR"; | |
4fdbc678 BG |
37 | case STI_HQVDP_0: |
38 | return "HQVDP0"; | |
d219673d BG |
39 | default: |
40 | return "<UNKNOWN LAYER>"; | |
41 | } | |
42 | } | |
4e0cd681 | 43 | EXPORT_SYMBOL(sti_layer_to_str); |
d219673d BG |
44 | |
45 | struct sti_layer *sti_layer_create(struct device *dev, int desc, | |
46 | void __iomem *baseaddr) | |
47 | { | |
48 | ||
49 | struct sti_layer *layer = NULL; | |
50 | ||
51 | switch (desc & STI_LAYER_TYPE_MASK) { | |
52 | case STI_GDP: | |
53 | layer = sti_gdp_create(dev, desc); | |
54 | break; | |
55 | case STI_VID: | |
56 | layer = sti_vid_create(dev); | |
57 | break; | |
96006a77 BG |
58 | case STI_CUR: |
59 | layer = sti_cursor_create(dev); | |
60 | break; | |
4fdbc678 BG |
61 | case STI_VDP: |
62 | layer = sti_hqvdp_create(dev); | |
63 | break; | |
d219673d BG |
64 | } |
65 | ||
66 | if (!layer) { | |
67 | DRM_ERROR("Failed to create layer\n"); | |
68 | return NULL; | |
69 | } | |
70 | ||
71 | layer->desc = desc; | |
72 | layer->dev = dev; | |
73 | layer->regs = baseaddr; | |
74 | ||
75 | layer->ops->init(layer); | |
76 | ||
77 | DRM_DEBUG_DRIVER("%s created\n", sti_layer_to_str(layer)); | |
78 | ||
79 | return layer; | |
80 | } | |
4e0cd681 | 81 | EXPORT_SYMBOL(sti_layer_create); |
d219673d | 82 | |
4fdbc678 BG |
83 | int sti_layer_prepare(struct sti_layer *layer, |
84 | struct drm_crtc *crtc, | |
85 | struct drm_framebuffer *fb, | |
d219673d BG |
86 | struct drm_display_mode *mode, int mixer_id, |
87 | int dest_x, int dest_y, int dest_w, int dest_h, | |
88 | int src_x, int src_y, int src_w, int src_h) | |
89 | { | |
90 | int ret; | |
91 | unsigned int i; | |
92 | struct drm_gem_cma_object *cma_obj; | |
93 | ||
94 | if (!layer || !fb || !mode) { | |
95 | DRM_ERROR("Null fb, layer or mode\n"); | |
96 | return 1; | |
97 | } | |
98 | ||
99 | cma_obj = drm_fb_cma_get_gem_obj(fb, 0); | |
100 | if (!cma_obj) { | |
101 | DRM_ERROR("Can't get CMA GEM object for fb\n"); | |
102 | return 1; | |
103 | } | |
104 | ||
4fdbc678 | 105 | layer->crtc = crtc; |
d219673d BG |
106 | layer->fb = fb; |
107 | layer->mode = mode; | |
108 | layer->mixer_id = mixer_id; | |
109 | layer->dst_x = dest_x; | |
110 | layer->dst_y = dest_y; | |
111 | layer->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x); | |
112 | layer->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y); | |
113 | layer->src_x = src_x; | |
114 | layer->src_y = src_y; | |
115 | layer->src_w = src_w; | |
116 | layer->src_h = src_h; | |
117 | layer->format = fb->pixel_format; | |
96006a77 | 118 | layer->vaddr = cma_obj->vaddr; |
d219673d BG |
119 | layer->paddr = cma_obj->paddr; |
120 | for (i = 0; i < 4; i++) { | |
121 | layer->pitches[i] = fb->pitches[i]; | |
122 | layer->offsets[i] = fb->offsets[i]; | |
123 | } | |
124 | ||
125 | DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n", | |
126 | sti_layer_to_str(layer), | |
127 | layer->mixer_id); | |
128 | DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n", | |
129 | sti_layer_to_str(layer), | |
130 | layer->dst_w, layer->dst_h, layer->dst_x, layer->dst_y, | |
131 | layer->src_w, layer->src_h, layer->src_x, | |
132 | layer->src_y); | |
133 | ||
134 | DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, | |
135 | (char *)&layer->format, (unsigned long)layer->paddr); | |
136 | ||
137 | if (!layer->ops->prepare) | |
138 | goto err_no_prepare; | |
139 | ||
140 | ret = layer->ops->prepare(layer, !layer->enabled); | |
141 | if (!ret) | |
142 | layer->enabled = true; | |
143 | ||
144 | return ret; | |
145 | ||
146 | err_no_prepare: | |
147 | DRM_ERROR("Cannot prepare\n"); | |
148 | return 1; | |
149 | } | |
150 | ||
151 | int sti_layer_commit(struct sti_layer *layer) | |
152 | { | |
153 | if (!layer) | |
154 | return 1; | |
155 | ||
156 | if (!layer->ops->commit) | |
157 | goto err_no_commit; | |
158 | ||
159 | return layer->ops->commit(layer); | |
160 | ||
161 | err_no_commit: | |
162 | DRM_ERROR("Cannot commit\n"); | |
163 | return 1; | |
164 | } | |
165 | ||
166 | int sti_layer_disable(struct sti_layer *layer) | |
167 | { | |
168 | int ret; | |
169 | ||
170 | DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer)); | |
171 | if (!layer) | |
172 | return 1; | |
173 | ||
174 | if (!layer->enabled) | |
175 | return 0; | |
176 | ||
177 | if (!layer->ops->disable) | |
178 | goto err_no_disable; | |
179 | ||
180 | ret = layer->ops->disable(layer); | |
181 | if (!ret) | |
182 | layer->enabled = false; | |
183 | else | |
184 | DRM_ERROR("Disable failed\n"); | |
185 | ||
186 | return ret; | |
187 | ||
188 | err_no_disable: | |
189 | DRM_ERROR("Cannot disable\n"); | |
190 | return 1; | |
191 | } | |
192 | ||
193 | const uint32_t *sti_layer_get_formats(struct sti_layer *layer) | |
194 | { | |
195 | if (!layer) | |
196 | return NULL; | |
197 | ||
198 | if (!layer->ops->get_formats) | |
199 | return NULL; | |
200 | ||
201 | return layer->ops->get_formats(layer); | |
202 | } | |
203 | ||
204 | unsigned int sti_layer_get_nb_formats(struct sti_layer *layer) | |
205 | { | |
206 | if (!layer) | |
207 | return 0; | |
208 | ||
209 | if (!layer->ops->get_nb_formats) | |
210 | return 0; | |
211 | ||
212 | return layer->ops->get_nb_formats(layer); | |
213 | } |