blob: 61d9ecf471eeb26ad344e576584cb2fd2940b5c8 [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{
89 int ret;
90 int mdp_version;
91
92 if (strlen(version) >= 8) {
93 if(!strncmp(version, "msmfb", strlen("msmfb"))) {
94 char str_ver[4];
95 memcpy(str_ver, version + strlen("msmfb"), 3);
96 str_ver[3] = '\0';
97 mdp_version = atoi(str_ver);
98 if (mdp_version >= MDP_V4_0) {
99 overlay_supported = true;
100 }
101 } else if (!strncmp(version, "mdssfb", strlen("mdssfb"))) {
102 overlay_supported = true;
103 isMDP5 = true;
104 }
105 }
Andrew Doddbb687f42014-06-29 18:24:35 -0400106 if (overlay_supported) printf("Using qcomm overlay\n");
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600107 return overlay_supported;
108}
109
110bool isTargetMdp5()
111{
112 if (isMDP5)
113 return true;
114
115 return false;
116}
117
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600118int free_ion_mem(void) {
119 if (!overlay_supported)
120 return -EINVAL;
121
122 int ret = 0;
123
124 if (mem_info.mem_buf)
125 munmap(mem_info.mem_buf, mem_info.size);
126
127 if (mem_info.ion_fd >= 0) {
128 ret = ioctl(mem_info.ion_fd, ION_IOC_FREE, &mem_info.handle_data);
129 if (ret < 0)
130 perror("free_mem failed ");
131 }
132
133 if (mem_info.mem_fd >= 0)
134 close(mem_info.mem_fd);
135 if (mem_info.ion_fd >= 0)
136 close(mem_info.ion_fd);
137
138 memset(&mem_info, 0, sizeof(mem_info));
139 mem_info.mem_fd = -1;
140 mem_info.ion_fd = -1;
141 return 0;
142}
143
144int alloc_ion_mem(unsigned int size)
145{
146 if (!overlay_supported)
147 return -EINVAL;
148 int result;
149 struct ion_fd_data fd_data;
150 struct ion_allocation_data ionAllocData;
151
152 mem_info.ion_fd = open("/dev/ion", O_RDWR|O_DSYNC);
153 if (mem_info.ion_fd < 0) {
154 perror("ERROR: Can't open ion ");
155 return -errno;
156 }
157
158 ionAllocData.flags = 0;
159 ionAllocData.len = size;
160 ionAllocData.align = sysconf(_SC_PAGESIZE);
Kra1o5de50c5f2015-04-23 21:46:36 +0200161#ifdef NEW_ION_HEAP
162 ionAllocData.heap_id_mask =
163#else
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600164 ionAllocData.heap_mask =
Kra1o5de50c5f2015-04-23 21:46:36 +0200165#endif
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600166 ION_HEAP(ION_IOMMU_HEAP_ID) |
167 ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID);
168
169 result = ioctl(mem_info.ion_fd, ION_IOC_ALLOC, &ionAllocData);
170 if(result){
171 perror("ION_IOC_ALLOC Failed ");
172 close(mem_info.ion_fd);
173 return result;
174 }
175
176 fd_data.handle = ionAllocData.handle;
177 mem_info.handle_data.handle = ionAllocData.handle;
178 result = ioctl(mem_info.ion_fd, ION_IOC_MAP, &fd_data);
179 if (result) {
180 perror("ION_IOC_MAP Failed ");
181 free_ion_mem();
182 return result;
183 }
184 mem_info.mem_buf = (unsigned char *)mmap(NULL, size, PROT_READ |
185 PROT_WRITE, MAP_SHARED, fd_data.fd, 0);
186 mem_info.mem_fd = fd_data.fd;
187
188 if (!mem_info.mem_buf) {
189 perror("ERROR: mem_buf MAP_FAILED ");
190 free_ion_mem();
191 return -ENOMEM;
192 }
193
194 return 0;
195}
196
197int allocate_overlay(int fd, GGLSurface gr_fb[])
198{
199 int ret = 0;
200
201 if (!overlay_supported)
202 return -EINVAL;
203
204 if (!isDisplaySplit()) {
205 // Check if overlay is already allocated
206 if (MSMFB_NEW_REQUEST == overlayL_id) {
207 struct mdp_overlay overlayL;
208
209 memset(&overlayL, 0 , sizeof (struct mdp_overlay));
210
211 /* Fill Overlay Data */
212 overlayL.src.width = ALIGN(gr_fb[0].width, 32);
213 overlayL.src.height = gr_fb[0].height;
214 overlayL.src.format = map_mdp_pixel_format();
215 overlayL.src_rect.w = gr_fb[0].width;
216 overlayL.src_rect.h = gr_fb[0].height;
217 overlayL.dst_rect.w = gr_fb[0].width;
218 overlayL.dst_rect.h = gr_fb[0].height;
219 overlayL.alpha = 0xFF;
220 overlayL.transp_mask = MDP_TRANSP_NOP;
221 overlayL.id = MSMFB_NEW_REQUEST;
222 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
223 if (ret < 0) {
224 perror("Overlay Set Failed");
225 return ret;
226 }
227 overlayL_id = overlayL.id;
228 }
229 } else {
230 float xres = getFbXres();
231 int lSplit = getLeftSplit();
232 float lSplitRatio = lSplit / xres;
233 float lCropWidth = gr_fb[0].width * lSplitRatio;
234 int lWidth = lSplit;
235 int rWidth = gr_fb[0].width - lSplit;
236 int height = gr_fb[0].height;
237
238 if (MSMFB_NEW_REQUEST == overlayL_id) {
239
240 struct mdp_overlay overlayL;
241
242 memset(&overlayL, 0 , sizeof (struct mdp_overlay));
243
244 /* Fill OverlayL Data */
245 overlayL.src.width = ALIGN(gr_fb[0].width, 32);
246 overlayL.src.height = gr_fb[0].height;
247 overlayL.src.format = map_mdp_pixel_format();
248 overlayL.src_rect.x = 0;
249 overlayL.src_rect.y = 0;
250 overlayL.src_rect.w = lCropWidth;
251 overlayL.src_rect.h = gr_fb[0].height;
252 overlayL.dst_rect.x = 0;
253 overlayL.dst_rect.y = 0;
254 overlayL.dst_rect.w = lWidth;
255 overlayL.dst_rect.h = height;
256 overlayL.alpha = 0xFF;
257 overlayL.transp_mask = MDP_TRANSP_NOP;
258 overlayL.id = MSMFB_NEW_REQUEST;
259 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
260 if (ret < 0) {
261 perror("OverlayL Set Failed");
262 return ret;
263 }
264 overlayL_id = overlayL.id;
265 }
266 if (MSMFB_NEW_REQUEST == overlayR_id) {
267 struct mdp_overlay overlayR;
268
269 memset(&overlayR, 0 , sizeof (struct mdp_overlay));
270
271 /* Fill OverlayR Data */
272 overlayR.src.width = ALIGN(gr_fb[0].width, 32);
273 overlayR.src.height = gr_fb[0].height;
274 overlayR.src.format = map_mdp_pixel_format();
275 overlayR.src_rect.x = lCropWidth;
276 overlayR.src_rect.y = 0;
277 overlayR.src_rect.w = gr_fb[0].width - lCropWidth;
278 overlayR.src_rect.h = gr_fb[0].height;
279 overlayR.dst_rect.x = 0;
280 overlayR.dst_rect.y = 0;
281 overlayR.dst_rect.w = rWidth;
282 overlayR.dst_rect.h = height;
283 overlayR.alpha = 0xFF;
284 overlayR.flags = MDSS_MDP_RIGHT_MIXER;
285 overlayR.transp_mask = MDP_TRANSP_NOP;
286 overlayR.id = MSMFB_NEW_REQUEST;
287 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayR);
288 if (ret < 0) {
289 perror("OverlayR Set Failed");
290 return ret;
291 }
292 overlayR_id = overlayR.id;
293 }
294
295 }
296 return 0;
297}
298
299int free_overlay(int fd)
300{
301 if (!overlay_supported)
302 return -EINVAL;
303
304 int ret = 0;
305 struct mdp_display_commit ext_commit;
306
307 if (!isDisplaySplit()) {
308 if (overlayL_id != MSMFB_NEW_REQUEST) {
309 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
310 if (ret) {
311 perror("Overlay Unset Failed");
312 overlayL_id = MSMFB_NEW_REQUEST;
313 return ret;
314 }
315 }
316 } else {
317
318 if (overlayL_id != MSMFB_NEW_REQUEST) {
319 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
320 if (ret) {
321 perror("OverlayL Unset Failed");
322 overlayL_id = MSMFB_NEW_REQUEST;
323 return ret;
324 }
325 }
326
327 if (overlayR_id != MSMFB_NEW_REQUEST) {
328 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayR_id);
329 if (ret) {
330 perror("OverlayR Unset Failed");
331 overlayR_id = MSMFB_NEW_REQUEST;
332 return ret;
333 }
334 }
335 }
336 memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
337 ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
338 ext_commit.wait_for_finish = 1;
339 ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
340 if (ret < 0) {
341 perror("ERROR: Clear MSMFB_DISPLAY_COMMIT failed!");
342 overlayL_id = MSMFB_NEW_REQUEST;
343 overlayR_id = MSMFB_NEW_REQUEST;
344 return ret;
345 }
346 overlayL_id = MSMFB_NEW_REQUEST;
347 overlayR_id = MSMFB_NEW_REQUEST;
348
349 return 0;
350}
351
352int overlay_display_frame(int fd, GGLubyte* data, size_t size)
353{
354 if (!overlay_supported)
355 return -EINVAL;
356
357 int ret = 0;
358 struct msmfb_overlay_data ovdataL, ovdataR;
359 struct mdp_display_commit ext_commit;
360
361 if (!isDisplaySplit()) {
362 if (overlayL_id == MSMFB_NEW_REQUEST) {
363 perror("display_frame failed, no overlay\n");
364 return -EINVAL;
365 }
366
367 memcpy(mem_info.mem_buf, data, size);
368
369 memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
370
371 ovdataL.id = overlayL_id;
372 ovdataL.data.flags = 0;
373 ovdataL.data.offset = 0;
374 ovdataL.data.memory_id = mem_info.mem_fd;
375 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
376 if (ret < 0) {
377 perror("overlay_display_frame failed, overlay play Failed\n");
378 return ret;
379 }
380 } else {
381
382 if (overlayL_id == MSMFB_NEW_REQUEST) {
383 perror("display_frame failed, no overlayL \n");
384 return -EINVAL;
385 }
386
387 memcpy(mem_info.mem_buf, data, size);
388
389 memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
390
391 ovdataL.id = overlayL_id;
392 ovdataL.data.flags = 0;
393 ovdataL.data.offset = 0;
394 ovdataL.data.memory_id = mem_info.mem_fd;
395 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
396 if (ret < 0) {
397 perror("overlay_display_frame failed, overlayL play Failed\n");
398 return ret;
399 }
400
401 if (overlayR_id == MSMFB_NEW_REQUEST) {
402 perror("display_frame failed, no overlayR \n");
403 return -EINVAL;
404 }
405 memset(&ovdataR, 0, sizeof(struct msmfb_overlay_data));
406
407 ovdataR.id = overlayR_id;
408 ovdataR.data.flags = 0;
409 ovdataR.data.offset = 0;
410 ovdataR.data.memory_id = mem_info.mem_fd;
411 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataR);
412 if (ret < 0) {
413 perror("overlay_display_frame failed, overlayR play Failed\n");
414 return ret;
415 }
416 }
417 memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
418 ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
419 ext_commit.wait_for_finish = 1;
420 ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
421 if (ret < 0) {
422 perror("overlay_display_frame failed, overlay commit Failed\n!");
423 }
424
425 return ret;
426}
427
428#else
429
Andrew Doddbb687f42014-06-29 18:24:35 -0400430bool target_has_overlay(char *version) {
431 return false;
432}
433
434bool isTargetMdp5() {
435 return false;
436}
437
Ethan Yonker4ee5ad72014-02-18 18:41:17 -0600438int free_ion_mem(void) {
439 return -EINVAL;
440}
441
442int alloc_ion_mem(unsigned int size)
443{
444 return -EINVAL;
445}
446
447int allocate_overlay(int fd, GGLSurface gr_fb[])
448{
449 return -EINVAL;
450}
451
452int free_overlay(int fd)
453{
454 return -EINVAL;
455}
456
457int overlay_display_frame(int fd, GGLubyte* data, size_t size)
458{
459 return -EINVAL;
460}
461
462#endif //#ifdef MSM_BSP