73339fb3d040dd6c100d9e957d7fe08a5da684a9
[apps/home/charging-animation.git] / src / chg_drmd.c
1 /*
2 Copyright 2012  Samsung Electronics Co., Ltd
3
4 Licensed under the Flora License, Version 1.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.tizenopensource.org/license
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 #include <string.h>
18 #include <unistd.h>
19 #include "chg_common.h"
20 #include "chg_drmd.h"
21 #include "chg_env.h"
22
23 /*-----------------------------------------------------------------------------
24   find_connector()
25  ----------------------------------------------------------------------------*/
26 static int find_connector(st_drmdi *drmdi, int type)
27 {
28         int i;
29         int fd;
30         drmModeConnectorPtr connector=NULL;
31         drmModeEncoderPtr encoder=NULL;
32         drmModeCrtcPtr crtc;
33         drmModeResPtr res_mode;
34
35         if (drmdi == NULL)
36                 return -1;
37
38         fd = drmdi->fd;
39         res_mode = drmdi->res_mode;
40
41         for(i=0; i<res_mode->count_connectors; i++) {
42                 connector =drmModeGetConnector(fd, res_mode->connectors[i]);
43                 if(connector->connector_type == type)
44                         break;
45
46                 drmModeFreeConnector(connector);
47                 connector = NULL;
48         }
49
50         if(!connector) {
51                 LOGD("[find_connector] Cannot find connector:%d\n", type);
52                 return -1;
53         }
54
55         if(connector->connection != DRM_MODE_CONNECTED) {
56                 LOGD("[find_connector] connector is not connected (%d)\n",
57                         (int)connector->connection);
58                 return -1;
59         }
60
61         /* find default encoder */
62         encoder = drmModeGetEncoder(fd, connector->encoder_id);
63         if(!encoder) {
64                 LOGD("[find_connector] Cannot get encoder:%d\n", type);
65                 return -1;
66         }
67
68         /* find default crtc */
69         crtc = drmModeGetCrtc(fd, encoder->crtc_id);
70         if(!crtc) {
71                 LOGD("[find_connector] Cannot get CRTC\n");
72                 return -1;
73         }
74
75         drmdi->connector = connector;
76         drmdi->encoder = encoder;
77         drmdi->crtc = crtc;
78
79         return 0;
80 }
81
82 /*-----------------------------------------------------------------------------
83   create_framebuffer()
84  ----------------------------------------------------------------------------*/
85 static int create_framebuffer(st_drmdi *drmdi)
86 {
87         unsigned int attrs[]={
88                 KMS_WIDTH,   0,
89                 KMS_HEIGHT,  0,
90                 KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
91                 KMS_TERMINATE_PROP_LIST
92         };
93
94         /* Create kms bo */
95         attrs[1] = drmdi->connector->modes[0].hdisplay;
96         attrs[3] = drmdi->connector->modes[0].vdisplay;
97
98         if(kms_bo_create(drmdi->kms, attrs, &drmdi->bo)) {
99                 LOGD("[create_framebuffer] Cannot create kms bo\n");
100                 return -1;
101         }
102
103         drmdi->bo_width = drmdi->connector->modes[0].hdisplay;
104         drmdi->bo_height = drmdi->connector->modes[0].vdisplay;
105         kms_bo_get_prop(drmdi->bo, KMS_PITCH, &drmdi->bo_stride);
106         kms_bo_get_prop(drmdi->bo, KMS_HANDLE, &drmdi->bo_handle);
107
108         /* add drm framebuffer */
109         if(drmModeAddFB(drmdi->fd, drmdi->bo_width, drmdi->bo_height,
110                 32, 32, drmdi->bo_stride, drmdi->bo_handle, &drmdi->fb_id)) {
111                 LOGD("[create_framebuffer] Cannot add drm fb\n");
112                 return -1;
113         }
114
115         return 0;
116 }
117
118 /*-----------------------------------------------------------------------------
119   set_mode()
120  ----------------------------------------------------------------------------*/
121 static int set_drm_mode(st_drmdi *drmdi)
122 {
123         if(drmModeSetCrtc(drmdi->fd
124                         , drmdi->crtc->crtc_id
125                         , drmdi->fb_id
126                         , 0, 0
127                         , &drmdi->connector->connector_id, 1
128                         , drmdi->connector->modes)) {
129                 LOGD("[set_drm_mode] Cannot set drm mode\n");
130                 return -1;
131         }
132
133         return 0;
134 }
135
136 /*-----------------------------------------------------------------------------
137   init_drm()
138  ----------------------------------------------------------------------------*/
139 static void free_drm_res(st_drmdi *drmdi)
140 {
141         if(drmdi->connector)
142                 drmModeFreeConnector(drmdi->connector);
143
144         if(drmdi->encoder)
145                 drmModeFreeEncoder(drmdi->encoder);
146
147         if(drmdi->crtc)
148                 drmModeFreeCrtc(drmdi->crtc);
149
150         if(drmdi->res_mode)
151                 drmModeFreeResources(drmdi->res_mode);
152
153         if(drmdi->fb_id)
154                 drmModeRmFB(drmdi->fd, drmdi->fb_id);
155
156         if(drmdi->bo)
157                 kms_bo_destroy(&drmdi->bo);
158
159         if(drmdi->kms)
160                 kms_destroy(&drmdi->kms);
161
162         drmClose(drmdi->fd);
163 }
164
165 /*-----------------------------------------------------------------------------
166   drmd_open()
167  ----------------------------------------------------------------------------*/
168 int drmd_open(st_drmdi *drmdi)
169 {
170         drm_magic_t magic;
171         drmVBlank vbl;
172         void *ptr;
173         int ret;
174
175         if (drmdi == NULL) {
176                 LOGD("[drmd_open] drmdi is NULL\n");
177                 return -1;
178         }
179
180         memset(drmdi, 0x00, sizeof(st_drmdi));
181
182         drmdi->fd = drmOpen(chg_env_str[EN_ENV_DEV_DRM_NAME], NULL);
183         if(drmdi->fd<0) {
184                 LOGD("[drmd_open] Cannot open drm:%s\n",
185                         chg_env_str[EN_ENV_DEV_DRM_NAME]);
186                 return -1;
187         }
188
189         drmdi->driver_name = drmGetDeviceNameFromFd(drmdi->fd);
190         LOGD("[drmd_open] Init DRM(name:%s, fd:%d)...OK\n",
191                 drmdi->driver_name, drmdi->fd);
192
193         /* Auth DRM */
194         if(drmGetMagic(drmdi->fd, &magic)) {
195                 LOGD("[drmd_open] Cannot get magic\n");
196                 goto drm_err_exit;
197         }
198
199         if(drmAuthMagic(drmdi->fd, magic)) {
200                 LOGD("[drmd_open] Cannot auth magic\n");
201                 goto drm_err_exit;
202         }
203
204         /* Create KMS */
205         if(kms_create(drmdi->fd, &drmdi->kms)) {
206                 LOGD("[drmd_open] Cannot create kms\n");
207                 goto drm_err_exit;
208         }
209
210         /* Get drmmode resource */
211         drmdi->res_mode = drmModeGetResources(drmdi->fd);
212         if(!drmdi->res_mode) {
213                 LOGD("[drmd_open] Cannot get drmmode resources\n");
214                 goto drm_err_exit;
215         }
216
217         ret = find_connector(drmdi, DRM_MODE_CONNECTOR_LVDS);
218         if(ret < 0) {
219                 LOGD("[drmd_open] Cannot get default(LVDS) connector\n");
220                 goto drm_err_exit;
221         }
222
223         /* Create framebuffer */
224         ret = create_framebuffer(drmdi);
225         if(ret < 0) {
226                 LOGD("[drmd_open] Cannot create frame buffer\n");
227                 goto drm_err_exit;
228         }
229
230         if (kms_bo_map(drmdi->bo, &ptr)) {
231                 LOGD("[drmd_open] kms_bo_map() failed. \n");
232                 goto drm_err_exit;
233         }
234         drmdi->fb_buf = ptr;
235         drmdi->dpms_mode = DPMSModeOn;
236         memset(ptr, 0x00, drmdi->bo_stride * drmdi->bo_height);
237
238         /* Set mode */
239         ret = set_drm_mode(drmdi);
240         if(ret < 0) {
241                 LOGD("[drmd_open] Cannot set drm mode\n");
242                 goto drm_err_exit;
243         }
244
245         return 0;
246
247 drm_err_exit:
248         free_drm_res(drmdi);
249         return -1;
250 }
251
252 /*-----------------------------------------------------------------------------
253   drmd_close()
254  ----------------------------------------------------------------------------*/
255 void drmd_close(st_drmdi *drmdi)
256 {
257         kms_bo_unmap(drmdi->bo);
258         free_drm_res(drmdi);
259 }
260
261 /*-----------------------------------------------------------------------------
262   drmd_set_dpms_mode()
263  ----------------------------------------------------------------------------*/
264 static int drmd_set_dpms_mode(st_drmdi *drmdi, int dpms_mode)
265 {
266         int i;
267         drmModeConnectorPtr connector;
268
269         if (drmdi == NULL) {
270                 LOGD("[drmd_set_dpms_mode] drmdi is NULL\n");
271                 return -1;
272         }
273
274         connector = drmdi->connector;
275
276         if (dpms_mode == DPMSModeStandby || dpms_mode == DPMSModeSuspend) {
277                 LOGD("[drmd_set_dpms_mode] dmps_mode %s is not supported.\n",
278                         (dpms_mode == DPMSModeStandby)?
279                         "DPMSModeStandby":"DPMSModeSuspend");
280                 return -1;
281         }
282
283         for (i = 0; i < connector->count_props; i++) {
284                 drmModePropertyPtr props;
285                 props = drmModeGetProperty (drmdi->fd, connector->props[i]);
286                 if (!props)
287                         continue;
288
289                 if (!strcmp(props->name, "DPMS")) {
290                         int _tmp_dpms = dpms_mode;
291                         switch (dpms_mode) {
292                         case DPMSModeOn:
293                                 if (drmdi->dpms_mode == DPMSModeOn) {
294                                         drmModeFreeProperty (props);
295                                         return 0;
296                                 }
297
298                                 /* lcd on */
299                                 _tmp_dpms = DPMSModeOn;
300                                 drmdi->dpms_mode = DPMSModeOn;
301                                 break;
302
303                         case DPMSModeOff:
304                                 if (drmdi->dpms_mode == DPMSModeOff) {
305                                         drmModeFreeProperty(props);
306                                         return 0;
307                                 }
308
309                                 /* lcd off */
310                                 _tmp_dpms = DPMSModeOff;
311                                 drmdi->dpms_mode = DPMSModeOff;
312                                 break;
313                         default:
314                                 return -1;
315                         }
316
317                         drmModeConnectorSetProperty(drmdi->fd,
318                                 connector->connector_id,
319                                 props->prop_id,
320                                 _tmp_dpms);
321
322                         drmModeFreeProperty(props);
323                         return 0;
324                 }
325
326                 drmModeFreeProperty(props);
327         }
328
329         return -1;
330 }
331
332 /*-----------------------------------------------------------------------------
333   drmd_lcd_on()
334  ----------------------------------------------------------------------------*/
335 int drmd_lcd_on(st_drmdi *drmdi)
336 {
337         int ret;
338
339         ret = drmd_set_dpms_mode(drmdi, DPMSModeOn);
340         if (ret < 0) {
341                 LOGD("[drmd_lcd_on] drmd_set_dpms_mode() fail.\n");
342                 return -1;
343         }
344
345         return 0;
346 }
347
348 /*-----------------------------------------------------------------------------
349   drmd_lcd_off()
350  ----------------------------------------------------------------------------*/
351 int drmd_lcd_off(st_drmdi *drmdi)
352 {
353         int ret;
354
355         ret = drmd_set_dpms_mode(drmdi, DPMSModeOff);
356         if (ret < 0) {
357                 LOGD("[drmd_lcd_off] drmd_set_dpms_mode() fail.\n");
358                 return -1;
359         }
360
361         return 0;
362 }
363