xref: /OK3568_Linux_fs/external/recovery/minui/graphics_adf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2014 The Android Open Source Project
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun  * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun  * You may obtain a copy of the License at
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *      http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun  * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun  * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun  * limitations under the License.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <errno.h>
18*4882a593Smuzhiyun #include <fcntl.h>
19*4882a593Smuzhiyun #include <stdbool.h>
20*4882a593Smuzhiyun #include <stdio.h>
21*4882a593Smuzhiyun #include <stdlib.h>
22*4882a593Smuzhiyun #include <unistd.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include <sys/cdefs.h>
25*4882a593Smuzhiyun #include <sys/mman.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <adf/adf.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include "graphics.h"
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun struct adf_surface_pdata {
32*4882a593Smuzhiyun     GRSurface base;
33*4882a593Smuzhiyun     int fd;
34*4882a593Smuzhiyun     __u32 offset;
35*4882a593Smuzhiyun     __u32 pitch;
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun struct adf_pdata {
39*4882a593Smuzhiyun     minui_backend base;
40*4882a593Smuzhiyun     int intf_fd;
41*4882a593Smuzhiyun     adf_id_t eng_id;
42*4882a593Smuzhiyun     __u32 format;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun     unsigned int current_surface;
45*4882a593Smuzhiyun     unsigned int n_surfaces;
46*4882a593Smuzhiyun     struct adf_surface_pdata surfaces[2];
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun static gr_surface adf_flip(struct minui_backend *backend);
50*4882a593Smuzhiyun static void adf_blank(struct minui_backend *backend, bool blank);
51*4882a593Smuzhiyun 
adf_surface_init(struct adf_pdata * pdata,struct drm_mode_modeinfo * mode,struct adf_surface_pdata * surf)52*4882a593Smuzhiyun static int adf_surface_init(struct adf_pdata *pdata,
53*4882a593Smuzhiyun                             struct drm_mode_modeinfo *mode, struct adf_surface_pdata *surf)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun     memset(surf, 0, sizeof(*surf));
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun     surf->fd = adf_interface_simple_buffer_alloc(pdata->intf_fd, mode->hdisplay,
58*4882a593Smuzhiyun                                                  mode->vdisplay, pdata->format, &surf->offset, &surf->pitch);
59*4882a593Smuzhiyun     if (surf->fd < 0)
60*4882a593Smuzhiyun         return surf->fd;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun     surf->base.width = mode->hdisplay;
63*4882a593Smuzhiyun     surf->base.height = mode->vdisplay;
64*4882a593Smuzhiyun     surf->base.row_bytes = surf->pitch;
65*4882a593Smuzhiyun     surf->base.pixel_bytes = (pdata->format == DRM_FORMAT_RGB565) ? 2 : 4;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun     surf->base.data = mmap(NULL, surf->pitch * surf->base.height, PROT_WRITE,
68*4882a593Smuzhiyun                            MAP_SHARED, surf->fd, surf->offset);
69*4882a593Smuzhiyun     if (surf->base.data == MAP_FAILED) {
70*4882a593Smuzhiyun         close(surf->fd);
71*4882a593Smuzhiyun         return -errno;
72*4882a593Smuzhiyun     }
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun     return 0;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun 
adf_interface_init(struct adf_pdata * pdata)77*4882a593Smuzhiyun static int adf_interface_init(struct adf_pdata *pdata)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun     struct adf_interface_data intf_data;
80*4882a593Smuzhiyun     int ret = 0;
81*4882a593Smuzhiyun     int err;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun     err = adf_get_interface_data(pdata->intf_fd, &intf_data);
84*4882a593Smuzhiyun     if (err < 0)
85*4882a593Smuzhiyun         return err;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun     err = adf_surface_init(pdata, &intf_data.current_mode, &pdata->surfaces[0]);
88*4882a593Smuzhiyun     if (err < 0) {
89*4882a593Smuzhiyun         fprintf(stderr, "allocating surface 0 failed: %s\n", strerror(-err));
90*4882a593Smuzhiyun         ret = err;
91*4882a593Smuzhiyun         goto done;
92*4882a593Smuzhiyun     }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun     err = adf_surface_init(pdata, &intf_data.current_mode,
95*4882a593Smuzhiyun                            &pdata->surfaces[1]);
96*4882a593Smuzhiyun     if (err < 0) {
97*4882a593Smuzhiyun         fprintf(stderr, "allocating surface 1 failed: %s\n", strerror(-err));
98*4882a593Smuzhiyun         memset(&pdata->surfaces[1], 0, sizeof(pdata->surfaces[1]));
99*4882a593Smuzhiyun         pdata->n_surfaces = 1;
100*4882a593Smuzhiyun     } else {
101*4882a593Smuzhiyun         pdata->n_surfaces = 2;
102*4882a593Smuzhiyun     }
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun done:
105*4882a593Smuzhiyun     adf_free_interface_data(&intf_data);
106*4882a593Smuzhiyun     return ret;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
adf_device_init(struct adf_pdata * pdata,struct adf_device * dev)109*4882a593Smuzhiyun static int adf_device_init(struct adf_pdata *pdata, struct adf_device *dev)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun     adf_id_t intf_id;
112*4882a593Smuzhiyun     int intf_fd;
113*4882a593Smuzhiyun     int err;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun     err = adf_find_simple_post_configuration(dev, &pdata->format, 1, &intf_id,
116*4882a593Smuzhiyun                                              &pdata->eng_id);
117*4882a593Smuzhiyun     if (err < 0)
118*4882a593Smuzhiyun         return err;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun     err = adf_device_attach(dev, pdata->eng_id, intf_id);
121*4882a593Smuzhiyun     if (err < 0 && err != -EALREADY)
122*4882a593Smuzhiyun         return err;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun     pdata->intf_fd = adf_interface_open(dev, intf_id, O_RDWR);
125*4882a593Smuzhiyun     if (pdata->intf_fd < 0)
126*4882a593Smuzhiyun         return pdata->intf_fd;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun     err = adf_interface_init(pdata);
129*4882a593Smuzhiyun     if (err < 0) {
130*4882a593Smuzhiyun         close(pdata->intf_fd);
131*4882a593Smuzhiyun         pdata->intf_fd = -1;
132*4882a593Smuzhiyun     }
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun     return err;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
adf_init(minui_backend * backend)137*4882a593Smuzhiyun static gr_surface adf_init(minui_backend *backend)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun     struct adf_pdata *pdata = (struct adf_pdata *)backend;
140*4882a593Smuzhiyun     adf_id_t *dev_ids = NULL;
141*4882a593Smuzhiyun     ssize_t n_dev_ids, i;
142*4882a593Smuzhiyun     gr_surface ret;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun #if defined(RECOVERY_BGRA)
145*4882a593Smuzhiyun     pdata->format = DRM_FORMAT_BGRA8888;
146*4882a593Smuzhiyun #elif defined(RECOVERY_RGBX)
147*4882a593Smuzhiyun     pdata->format = DRM_FORMAT_RGBX8888;
148*4882a593Smuzhiyun #else
149*4882a593Smuzhiyun     pdata->format = DRM_FORMAT_RGB565;
150*4882a593Smuzhiyun #endif
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun     n_dev_ids = adf_devices(&dev_ids);
153*4882a593Smuzhiyun     if (n_dev_ids == 0) {
154*4882a593Smuzhiyun         return NULL;
155*4882a593Smuzhiyun     } else if (n_dev_ids < 0) {
156*4882a593Smuzhiyun         fprintf(stderr, "enumerating adf devices failed: %s\n",
157*4882a593Smuzhiyun                 strerror(-n_dev_ids));
158*4882a593Smuzhiyun         return NULL;
159*4882a593Smuzhiyun     }
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun     pdata->intf_fd = -1;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun     for (i = 0; i < n_dev_ids && pdata->intf_fd < 0; i++) {
164*4882a593Smuzhiyun         struct adf_device dev;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun         int err = adf_device_open(dev_ids[i], O_RDWR, &dev);
167*4882a593Smuzhiyun         if (err < 0) {
168*4882a593Smuzhiyun             fprintf(stderr, "opening adf device %u failed: %s\n", dev_ids[i],
169*4882a593Smuzhiyun                     strerror(-err));
170*4882a593Smuzhiyun             continue;
171*4882a593Smuzhiyun         }
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun         err = adf_device_init(pdata, &dev);
174*4882a593Smuzhiyun         if (err < 0)
175*4882a593Smuzhiyun             fprintf(stderr, "initializing adf device %u failed: %s\n",
176*4882a593Smuzhiyun                     dev_ids[i], strerror(-err));
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun         adf_device_close(&dev);
179*4882a593Smuzhiyun     }
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun     free(dev_ids);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun     if (pdata->intf_fd < 0)
184*4882a593Smuzhiyun         return NULL;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun     ret = adf_flip(backend);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun     adf_blank(backend, true);
189*4882a593Smuzhiyun     adf_blank(backend, false);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun     return ret;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
adf_flip(struct minui_backend * backend)194*4882a593Smuzhiyun static gr_surface adf_flip(struct minui_backend *backend)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun     struct adf_pdata *pdata = (struct adf_pdata *)backend;
197*4882a593Smuzhiyun     struct adf_surface_pdata *surf = &pdata->surfaces[pdata->current_surface];
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun     int fence_fd = adf_interface_simple_post(pdata->intf_fd, pdata->eng_id,
200*4882a593Smuzhiyun                                              surf->base.width, surf->base.height, pdata->format, surf->fd,
201*4882a593Smuzhiyun                                              surf->offset, surf->pitch, -1);
202*4882a593Smuzhiyun     if (fence_fd >= 0)
203*4882a593Smuzhiyun         close(fence_fd);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun     pdata->current_surface = (pdata->current_surface + 1) % pdata->n_surfaces;
206*4882a593Smuzhiyun     return &pdata->surfaces[pdata->current_surface].base;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
adf_blank(struct minui_backend * backend,bool blank)209*4882a593Smuzhiyun static void adf_blank(struct minui_backend *backend, bool blank)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun     struct adf_pdata *pdata = (struct adf_pdata *)backend;
212*4882a593Smuzhiyun     adf_interface_blank(pdata->intf_fd,
213*4882a593Smuzhiyun                         blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
adf_surface_destroy(struct adf_surface_pdata * surf)216*4882a593Smuzhiyun static void adf_surface_destroy(struct adf_surface_pdata *surf)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun     munmap(surf->base.data, surf->pitch * surf->base.height);
219*4882a593Smuzhiyun     close(surf->fd);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
adf_exit(struct minui_backend * backend)222*4882a593Smuzhiyun static void adf_exit(struct minui_backend *backend)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun     struct adf_pdata *pdata = (struct adf_pdata *)backend;
225*4882a593Smuzhiyun     unsigned int i;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun     for (i = 0; i < pdata->n_surfaces; i++)
228*4882a593Smuzhiyun         adf_surface_destroy(&pdata->surfaces[i]);
229*4882a593Smuzhiyun     if (pdata->intf_fd >= 0)
230*4882a593Smuzhiyun         close(pdata->intf_fd);
231*4882a593Smuzhiyun     free(pdata);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
open_adf()234*4882a593Smuzhiyun minui_backend *open_adf()
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun     struct adf_pdata *pdata = calloc(1, sizeof(*pdata));
237*4882a593Smuzhiyun     if (!pdata) {
238*4882a593Smuzhiyun         perror("allocating adf backend failed");
239*4882a593Smuzhiyun         return NULL;
240*4882a593Smuzhiyun     }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun     pdata->base.init = adf_init;
243*4882a593Smuzhiyun     pdata->base.flip = adf_flip;
244*4882a593Smuzhiyun     pdata->base.blank = adf_blank;
245*4882a593Smuzhiyun     pdata->base.exit = adf_exit;
246*4882a593Smuzhiyun     return &pdata->base;
247*4882a593Smuzhiyun }
248