blob: 80e64d72b65b5cf0e73c048aed240f995f2a4383 [file] [log] [blame]
Ethan Yonker4ee5ad72014-02-18 18:41:17 -06001/*
2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#include <stdbool.h>
31#include <stdlib.h>
32#include <unistd.h>
33
34#include <errno.h>
35#include <fcntl.h>
36#include <stdio.h>
37
38#include <sys/ioctl.h>
39#include <sys/mman.h>
40#include <sys/types.h>
41
42#include <linux/fb.h>
43#include <linux/kd.h>
44
45#ifdef MSM_BSP
Dees Troy62b75ab2014-05-02 13:20:33 +000046#include <linux/msm_mdp.h>
47#include <linux/msm_ion.h>
Ethan Yonker4ee5ad72014-02-18 18:41:17 -060048#endif
49
50#include <pixelflinger/pixelflinger.h>
51
52#include "minui.h"
53
54#define MDP_V4_0 400
55
56#ifdef MSM_BSP
57#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
58
59typedef struct {
60 unsigned char *mem_buf;
61 int size;
62 int ion_fd;
63 int mem_fd;
64 struct ion_handle_data handle_data;
65} memInfo;
66
67//Left and right overlay id
68static int overlayL_id = MSMFB_NEW_REQUEST;
69static int overlayR_id = MSMFB_NEW_REQUEST;
70
71static memInfo mem_info;
72
73static int map_mdp_pixel_format()
74{
75 int format = MDP_RGB_565;
76#if defined(RECOVERY_BGRA)
77 format = MDP_BGRA_8888;
78#elif defined(RECOVERY_RGBX)
79 format = MDP_RGBA_8888;
80#endif
81 return format;
82}
Ethan Yonker4ee5ad72014-02-18 18:41:17 -060083
84static bool overlay_supported = false;
85static bool isMDP5 = false;
86
87bool target_has_overlay(char *version)
88{
Ethan Yonker4ee5ad72014-02-18 18:41:17 -060089 int mdp_version;
90
91 if (strlen(version) >= 8) {
92 if(!strncmp(version, "msmfb", strlen("msmfb"))) {
93 char str_ver[4];
94 memcpy(str_ver, version + strlen("msmfb"), 3);
95 str_ver[3] = '\0';
96 mdp_version = atoi(str_ver);
97 if (mdp_version >= MDP_V4_0) {
98 overlay_supported = true;
99 }
100 } else if (!strncmp(version, "mdssfb", strlen("mdssfb"))) {
101 overlay_supported = true;
102 isMDP5 = true;
103 }
104 }
Andrew Doddbb687f42014-06-29 18:24:35 -0400105 if (overlay_supported) printf("Using qcomm overlay\n");
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600106 return overlay_supported;
107}
108
109bool isTargetMdp5()
110{
111 if (isMDP5)
112 return true;
113
114 return false;
115}
116
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600117int free_ion_mem(void) {
118 if (!overlay_supported)
119 return -EINVAL;
120
121 int ret = 0;
122
123 if (mem_info.mem_buf)
124 munmap(mem_info.mem_buf, mem_info.size);
125
126 if (mem_info.ion_fd >= 0) {
127 ret = ioctl(mem_info.ion_fd, ION_IOC_FREE, &mem_info.handle_data);
128 if (ret < 0)
129 perror("free_mem failed ");
130 }
131
132 if (mem_info.mem_fd >= 0)
133 close(mem_info.mem_fd);
134 if (mem_info.ion_fd >= 0)
135 close(mem_info.ion_fd);
136
137 memset(&mem_info, 0, sizeof(mem_info));
138 mem_info.mem_fd = -1;
139 mem_info.ion_fd = -1;
140 return 0;
141}
142
143int alloc_ion_mem(unsigned int size)
144{
145 if (!overlay_supported)
146 return -EINVAL;
147 int result;
148 struct ion_fd_data fd_data;
149 struct ion_allocation_data ionAllocData;
150
151 mem_info.ion_fd = open("/dev/ion", O_RDWR|O_DSYNC);
152 if (mem_info.ion_fd < 0) {
153 perror("ERROR: Can't open ion ");
154 return -errno;
155 }
156
157 ionAllocData.flags = 0;
158 ionAllocData.len = size;
159 ionAllocData.align = sysconf(_SC_PAGESIZE);
Kra1o5de50c5f2015-04-23 21:46:36 +0200160#ifdef NEW_ION_HEAP
161 ionAllocData.heap_id_mask =
162#else
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600163 ionAllocData.heap_mask =
Kra1o5de50c5f2015-04-23 21:46:36 +0200164#endif
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600165 ION_HEAP(ION_IOMMU_HEAP_ID) |
166 ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID);
167
168 result = ioctl(mem_info.ion_fd, ION_IOC_ALLOC, &ionAllocData);
169 if(result){
170 perror("ION_IOC_ALLOC Failed ");
171 close(mem_info.ion_fd);
172 return result;
173 }
174
175 fd_data.handle = ionAllocData.handle;
176 mem_info.handle_data.handle = ionAllocData.handle;
177 result = ioctl(mem_info.ion_fd, ION_IOC_MAP, &fd_data);
178 if (result) {
179 perror("ION_IOC_MAP Failed ");
180 free_ion_mem();
181 return result;
182 }
183 mem_info.mem_buf = (unsigned char *)mmap(NULL, size, PROT_READ |
184 PROT_WRITE, MAP_SHARED, fd_data.fd, 0);
185 mem_info.mem_fd = fd_data.fd;
186
187 if (!mem_info.mem_buf) {
188 perror("ERROR: mem_buf MAP_FAILED ");
189 free_ion_mem();
190 return -ENOMEM;
191 }
192
193 return 0;
194}
195
196int allocate_overlay(int fd, GGLSurface gr_fb[])
197{
198 int ret = 0;
199
200 if (!overlay_supported)
201 return -EINVAL;
202
203 if (!isDisplaySplit()) {
204 // Check if overlay is already allocated
205 if (MSMFB_NEW_REQUEST == overlayL_id) {
206 struct mdp_overlay overlayL;
207
208 memset(&overlayL, 0 , sizeof (struct mdp_overlay));
209
210 /* Fill Overlay Data */
211 overlayL.src.width = ALIGN(gr_fb[0].width, 32);
212 overlayL.src.height = gr_fb[0].height;
213 overlayL.src.format = map_mdp_pixel_format();
214 overlayL.src_rect.w = gr_fb[0].width;
215 overlayL.src_rect.h = gr_fb[0].height;
216 overlayL.dst_rect.w = gr_fb[0].width;
217 overlayL.dst_rect.h = gr_fb[0].height;
218 overlayL.alpha = 0xFF;
219 overlayL.transp_mask = MDP_TRANSP_NOP;
220 overlayL.id = MSMFB_NEW_REQUEST;
221 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
222 if (ret < 0) {
223 perror("Overlay Set Failed");
224 return ret;
225 }
226 overlayL_id = overlayL.id;
227 }
228 } else {
229 float xres = getFbXres();
230 int lSplit = getLeftSplit();
231 float lSplitRatio = lSplit / xres;
232 float lCropWidth = gr_fb[0].width * lSplitRatio;
233 int lWidth = lSplit;
234 int rWidth = gr_fb[0].width - lSplit;
235 int height = gr_fb[0].height;
236
237 if (MSMFB_NEW_REQUEST == overlayL_id) {
238
239 struct mdp_overlay overlayL;
240
241 memset(&overlayL, 0 , sizeof (struct mdp_overlay));
242
243 /* Fill OverlayL Data */
244 overlayL.src.width = ALIGN(gr_fb[0].width, 32);
245 overlayL.src.height = gr_fb[0].height;
246 overlayL.src.format = map_mdp_pixel_format();
247 overlayL.src_rect.x = 0;
248 overlayL.src_rect.y = 0;
249 overlayL.src_rect.w = lCropWidth;
250 overlayL.src_rect.h = gr_fb[0].height;
251 overlayL.dst_rect.x = 0;
252 overlayL.dst_rect.y = 0;
253 overlayL.dst_rect.w = lWidth;
254 overlayL.dst_rect.h = height;
255 overlayL.alpha = 0xFF;
256 overlayL.transp_mask = MDP_TRANSP_NOP;
257 overlayL.id = MSMFB_NEW_REQUEST;
258 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
259 if (ret < 0) {
260 perror("OverlayL Set Failed");
261 return ret;
262 }
263 overlayL_id = overlayL.id;
264 }
265 if (MSMFB_NEW_REQUEST == overlayR_id) {
266 struct mdp_overlay overlayR;
267
268 memset(&overlayR, 0 , sizeof (struct mdp_overlay));
269
270 /* Fill OverlayR Data */
271 overlayR.src.width = ALIGN(gr_fb[0].width, 32);
272 overlayR.src.height = gr_fb[0].height;
273 overlayR.src.format = map_mdp_pixel_format();
274 overlayR.src_rect.x = lCropWidth;
275 overlayR.src_rect.y = 0;
276 overlayR.src_rect.w = gr_fb[0].width - lCropWidth;
277 overlayR.src_rect.h = gr_fb[0].height;
278 overlayR.dst_rect.x = 0;
279 overlayR.dst_rect.y = 0;
280 overlayR.dst_rect.w = rWidth;
281 overlayR.dst_rect.h = height;
282 overlayR.alpha = 0xFF;
283 overlayR.flags = MDSS_MDP_RIGHT_MIXER;
284 overlayR.transp_mask = MDP_TRANSP_NOP;
285 overlayR.id = MSMFB_NEW_REQUEST;
286 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayR);
287 if (ret < 0) {
288 perror("OverlayR Set Failed");
289 return ret;
290 }
291 overlayR_id = overlayR.id;
292 }
293
294 }
295 return 0;
296}
297
298int free_overlay(int fd)
299{
300 if (!overlay_supported)
301 return -EINVAL;
302
303 int ret = 0;
304 struct mdp_display_commit ext_commit;
305
306 if (!isDisplaySplit()) {
307 if (overlayL_id != MSMFB_NEW_REQUEST) {
308 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
309 if (ret) {
310 perror("Overlay Unset Failed");
311 overlayL_id = MSMFB_NEW_REQUEST;
312 return ret;
313 }
314 }
315 } else {
316
317 if (overlayL_id != MSMFB_NEW_REQUEST) {
318 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
319 if (ret) {
320 perror("OverlayL Unset Failed");
321 overlayL_id = MSMFB_NEW_REQUEST;
322 return ret;
323 }
324 }
325
326 if (overlayR_id != MSMFB_NEW_REQUEST) {
327 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayR_id);
328 if (ret) {
329 perror("OverlayR Unset Failed");
330 overlayR_id = MSMFB_NEW_REQUEST;
331 return ret;
332 }
333 }
334 }
335 memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
336 ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
337 ext_commit.wait_for_finish = 1;
338 ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
339 if (ret < 0) {
340 perror("ERROR: Clear MSMFB_DISPLAY_COMMIT failed!");
341 overlayL_id = MSMFB_NEW_REQUEST;
342 overlayR_id = MSMFB_NEW_REQUEST;
343 return ret;
344 }
345 overlayL_id = MSMFB_NEW_REQUEST;
346 overlayR_id = MSMFB_NEW_REQUEST;
347
348 return 0;
349}
350
351int overlay_display_frame(int fd, GGLubyte* data, size_t size)
352{
353 if (!overlay_supported)
354 return -EINVAL;
355
356 int ret = 0;
357 struct msmfb_overlay_data ovdataL, ovdataR;
358 struct mdp_display_commit ext_commit;
359
360 if (!isDisplaySplit()) {
361 if (overlayL_id == MSMFB_NEW_REQUEST) {
362 perror("display_frame failed, no overlay\n");
363 return -EINVAL;
364 }
365
366 memcpy(mem_info.mem_buf, data, size);
367
368 memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
369
370 ovdataL.id = overlayL_id;
371 ovdataL.data.flags = 0;
372 ovdataL.data.offset = 0;
373 ovdataL.data.memory_id = mem_info.mem_fd;
374 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
375 if (ret < 0) {
376 perror("overlay_display_frame failed, overlay play Failed\n");
377 return ret;
378 }
379 } else {
380
381 if (overlayL_id == MSMFB_NEW_REQUEST) {
382 perror("display_frame failed, no overlayL \n");
383 return -EINVAL;
384 }
385
386 memcpy(mem_info.mem_buf, data, size);
387
388 memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
389
390 ovdataL.id = overlayL_id;
391 ovdataL.data.flags = 0;
392 ovdataL.data.offset = 0;
393 ovdataL.data.memory_id = mem_info.mem_fd;
394 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
395 if (ret < 0) {
396 perror("overlay_display_frame failed, overlayL play Failed\n");
397 return ret;
398 }
399
400 if (overlayR_id == MSMFB_NEW_REQUEST) {
401 perror("display_frame failed, no overlayR \n");
402 return -EINVAL;
403 }
404 memset(&ovdataR, 0, sizeof(struct msmfb_overlay_data));
405
406 ovdataR.id = overlayR_id;
407 ovdataR.data.flags = 0;
408 ovdataR.data.offset = 0;
409 ovdataR.data.memory_id = mem_info.mem_fd;
410 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataR);
411 if (ret < 0) {
412 perror("overlay_display_frame failed, overlayR play Failed\n");
413 return ret;
414 }
415 }
416 memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
417 ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
418 ext_commit.wait_for_finish = 1;
419 ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
420 if (ret < 0) {
421 perror("overlay_display_frame failed, overlay commit Failed\n!");
422 }
423
424 return ret;
425}
426
427#else
428
Andrew Doddbb687f42014-06-29 18:24:35 -0400429bool target_has_overlay(char *version) {
430 return false;
431}
432
433bool isTargetMdp5() {
434 return false;
435}
436
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600437int free_ion_mem(void) {
438 return -EINVAL;
439}
440
441int alloc_ion_mem(unsigned int size)
442{
443 return -EINVAL;
444}
445
446int allocate_overlay(int fd, GGLSurface gr_fb[])
447{
448 return -EINVAL;
449}
450
451int free_overlay(int fd)
452{
453 return -EINVAL;
454}
455
456int overlay_display_frame(int fd, GGLubyte* data, size_t size)
457{
458 return -EINVAL;
459}
460
461#endif //#ifdef MSM_BSP