uterm: share drm dpms code
[platform/upstream/kmscon.git] / src / uterm_drm_shared.c
1 /*
2  * uterm - Linux User-Space Terminal
3  *
4  * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@googlemail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /*
27  * DRM shared functions
28  */
29
30 #include <errno.h>
31 #include <stdbool.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <xf86drm.h>
35 #include <xf86drmMode.h>
36 #include "log.h"
37 #include "uterm_drm_shared_internal.h"
38 #include "uterm_video.h"
39 #include "uterm_video_internal.h"
40
41 #define LOG_SUBSYSTEM "drm_shared"
42
43 int uterm_drm_mode_init(struct uterm_mode *mode)
44 {
45         struct uterm_drm_mode *m;
46
47         m = malloc(sizeof(*m));
48         if (!m)
49                 return -ENOMEM;
50         memset(m, 0, sizeof(*m));
51         mode->data = m;
52
53         return 0;
54 }
55
56 void uterm_drm_mode_destroy(struct uterm_mode *mode)
57 {
58         free(mode->data);
59 }
60
61 const char *uterm_drm_mode_get_name(const struct uterm_mode *mode)
62 {
63         struct uterm_drm_mode *m = mode->data;
64
65         return m->info.name;
66 }
67
68 unsigned int uterm_drm_mode_get_width(const struct uterm_mode *mode)
69 {
70         struct uterm_drm_mode *m = mode->data;
71
72         return m->info.hdisplay;
73 }
74
75 unsigned int uterm_drm_mode_get_height(const struct uterm_mode *mode)
76 {
77         struct uterm_drm_mode *m = mode->data;
78
79         return m->info.vdisplay;
80 }
81
82 void uterm_drm_mode_set(struct uterm_mode *mode, drmModeModeInfo *info)
83 {
84         struct uterm_drm_mode *m = mode->data;
85
86         m->info = *info;
87 }
88
89 const struct mode_ops uterm_drm_mode_ops = {
90         .init = uterm_drm_mode_init,
91         .destroy = uterm_drm_mode_destroy,
92         .get_name = uterm_drm_mode_get_name,
93         .get_width = uterm_drm_mode_get_width,
94         .get_height = uterm_drm_mode_get_height,
95 };
96
97 int uterm_drm_set_dpms(int fd, uint32_t conn_id, int state)
98 {
99         int i, ret, set;
100         drmModeConnector *conn;
101         drmModePropertyRes *prop;
102
103         switch (state) {
104         case UTERM_DPMS_ON:
105                 set = DRM_MODE_DPMS_ON;
106                 break;
107         case UTERM_DPMS_STANDBY:
108                 set = DRM_MODE_DPMS_STANDBY;
109                 break;
110         case UTERM_DPMS_SUSPEND:
111                 set = DRM_MODE_DPMS_SUSPEND;
112                 break;
113         case UTERM_DPMS_OFF:
114                 set = DRM_MODE_DPMS_OFF;
115                 break;
116         default:
117                 return -EINVAL;
118         }
119
120         conn = drmModeGetConnector(fd, conn_id);
121         if (!conn) {
122                 log_err("cannot get display connector");
123                 return -EFAULT;
124         }
125
126         ret = state;
127         for (i = 0; i < conn->count_props; ++i) {
128                 prop = drmModeGetProperty(fd, conn->props[i]);
129                 if (!prop) {
130                         log_error("cannot get DRM property (%d): %m", errno);
131                         continue;
132                 }
133
134                 if (!strcmp(prop->name, "DPMS")) {
135                         ret = drmModeConnectorSetProperty(fd, conn_id,
136                                                           prop->prop_id, set);
137                         if (ret) {
138                                 log_info("cannot set DPMS");
139                                 ret = -EFAULT;
140                         }
141                         drmModeFreeProperty(prop);
142                         break;
143                 }
144                 drmModeFreeProperty(prop);
145         }
146
147         if (i == conn->count_props) {
148                 log_warn("display does not support DPMS");
149                 ret = UTERM_DPMS_UNKNOWN;
150         }
151
152         drmModeFreeConnector(conn);
153         return ret;
154 }
155
156 int uterm_drm_get_dpms(int fd, drmModeConnector *conn)
157 {
158         int i, ret;
159         drmModePropertyRes *prop;
160
161         for (i = 0; i < conn->count_props; ++i) {
162                 prop = drmModeGetProperty(fd, conn->props[i]);
163                 if (!prop) {
164                         log_error("cannot get DRM property (%d): %m", errno);
165                         continue;
166                 }
167
168                 if (!strcmp(prop->name, "DPMS")) {
169                         switch (conn->prop_values[i]) {
170                         case DRM_MODE_DPMS_ON:
171                                 ret = UTERM_DPMS_ON;
172                                 break;
173                         case DRM_MODE_DPMS_STANDBY:
174                                 ret = UTERM_DPMS_STANDBY;
175                                 break;
176                         case DRM_MODE_DPMS_SUSPEND:
177                                 ret = UTERM_DPMS_SUSPEND;
178                                 break;
179                         case DRM_MODE_DPMS_OFF:
180                         default:
181                                 ret = UTERM_DPMS_OFF;
182                         }
183
184                         drmModeFreeProperty(prop);
185                         return ret;
186                 }
187                 drmModeFreeProperty(prop);
188         }
189
190         if (i == conn->count_props)
191                 log_warn("display does not support DPMS");
192         return UTERM_DPMS_UNKNOWN;
193 }