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