blob: bd78a1c59207235040329e8befca7a79efd9013d [file] [log] [blame]
limin.tian20df7d42023-02-10 10:05:52 +08001/*
2 * Copyright (c) 2023 Amlogic, Inc. All rights reserved.
3 *
4 * This source code is subject to the terms and conditions defined in the
5 * file 'LICENSE' which is part of this source code package.
6 *
7 * Description:
8 */
9#include <stdio.h>
10#include <stdlib.h>
11#include <fcntl.h>
12#include <unistd.h>
13#include <errno.h>
14#include <xf86drm.h>
15#include <xf86drmMode.h>
16#include <linux/string.h>
17#include "libdrm_meson_connector.h"
18#include "libdrm_meson_property.h"
19#include "meson_drm_settings.h"
20
21
22#define DEFAULT_CARD "/dev/dri/card0"
23#define PROP_NAME_MAX_LEN 50
24static int meson_drm_get_crtc_prop_value( int drmFd, MESON_CONNECTOR_TYPE connType,
25 char* name, uint32_t* prop_value );
26static int meson_drm_get_conn_prop_value( int drmFd, MESON_CONNECTOR_TYPE connType,
27 char* name, uint32_t* propValue );
28static int meson_drm_get_prop_value(int drmFd, MESON_CONNECTOR_TYPE connType,
29 uint32_t objType, char* name, uint32_t* propValue );
30
31static struct mesonConnector* get_current_connector(int drmFd, MESON_CONNECTOR_TYPE connType);
32static int meson_drm_set_property(int drmFd, drmModeAtomicReq *req, uint32_t objId,
33 uint32_t objType, char* name, uint64_t value);
34
35static int meson_drm_get_prop_value(int drmFd, MESON_CONNECTOR_TYPE connType, uint32_t objType, char* name, uint32_t* propValue )
36{
37 int ret = -1;
38 int objID = -1;
39 struct mesonConnector* conn = NULL;
40 if ( drmFd < 0 || name == NULL || propValue == NULL)
41 {
42 printf("\n%s %d drmfd invalid, or property name invalid\n",__FUNCTION__,__LINE__);
43 goto out;
44 }
45 conn = get_current_connector(drmFd, connType);
46 if ( conn == NULL )
47 {
48 printf("\n%s %d get_current_connector fail\n",__FUNCTION__,__LINE__);
49 goto out;
50 }
51 objID = mesonConnectorGetId(conn);
52 if (objType == DRM_MODE_OBJECT_CRTC)
53 objID = mesonConnectorGetCRTCId(conn);
54 struct mesonProperty* meson_prop = NULL;
55 meson_prop = mesonPropertyCreate(drmFd, objID, objType, name);
56 if (!meson_prop) {
57 printf("\n meson_prop create fail\n");
58 goto out;
59 }
60 uint64_t value = mesonPropertyGetValue(meson_prop);
61 *propValue = (uint32_t)value;
62 printf("\n prop value:%llu objID:%d,name:%s\n",value, objID,name);
63 mesonPropertyDestroy(meson_prop);
64 ret = 0;
65out:
66 if (conn)
67 mesonConnectorDestroy(drmFd,conn);
68 return ret;
69}
70
71static int meson_drm_get_conn_prop_value( int drmFd, MESON_CONNECTOR_TYPE conn_type, char* name, uint32_t* prop_value )
72{
73 return meson_drm_get_prop_value( drmFd, conn_type, DRM_MODE_OBJECT_CONNECTOR, name, prop_value );
74}
75
76static int meson_drm_get_crtc_prop_value( int drmFd, MESON_CONNECTOR_TYPE conn_type, char* name, uint32_t* prop_value )
77{
78 return meson_drm_get_prop_value( drmFd, conn_type, DRM_MODE_OBJECT_CRTC, name, prop_value );
79}
80
81static struct mesonConnector* get_current_connector(int drmFd, MESON_CONNECTOR_TYPE connType)
82{
83 struct mesonConnector* connector = NULL;
84 int drmConnType = DRM_MODE_CONNECTOR_HDMIA;
85 if (drmFd < 0) {
86 printf("\n %s %d invalid drmFd return\n",__FUNCTION__,__LINE__);
87 return NULL;
88 }
89 switch (connType)
90 {
91 case MESON_CONNECTOR_HDMIA:
92 drmConnType = DRM_MODE_CONNECTOR_HDMIA;
93 break;
94 case MESON_CONNECTOR_HDMIB:
95 drmConnType = DRM_MODE_CONNECTOR_HDMIB;
96 break;
97 case MESON_CONNECTOR_LVDS:
98 drmConnType = DRM_MODE_CONNECTOR_LVDS;
99 break;
100 case MESON_CONNECTOR_CVBS:
101 drmConnType = DRM_MODE_CONNECTOR_TV;
102 default :
103 drmConnType = DRM_MODE_CONNECTOR_HDMIA;
104 break;
105 }
106 connector = mesonConnectorCreate(drmFd, drmConnType);
107 return connector;
108}
109int meson_open_drm()
110{
111 int ret_fd = -1;
112 const char *card;
113 int ret = -1;
114 card= getenv("WESTEROS_DRM_CARD");
115 if ( !card ) {
116 card = DEFAULT_CARD;
117 }
118 ret_fd = open(card, O_RDONLY|O_CLOEXEC);
119 if ( ret_fd < 0 )
120 printf("\n meson_open_drm drm card:%s open fail\n",card);
121 else
122 drmDropMaster(ret_fd);
123 ret = drmSetClientCap(ret_fd, DRM_CLIENT_CAP_ATOMIC, 1);
124 if (ret < 0)
125 printf("Unable to set DRM atomic capability\n");
126 ret = drmSetClientCap(ret_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
127 if (ret < 0)
128 printf("Unable to set UNIVERSAL_PLANES\n");
129 return ret_fd;
130}
131void meson_close_drm(int drmFd)
132{
133 if (drmFd >= 0)
134 close(drmFd);
135}
136static int meson_drm_set_property(int drmFd, drmModeAtomicReq *req, uint32_t objId,
137 uint32_t objType, char* name, uint64_t value)
138{
139 uint32_t propId;
140 int rc = -1;
141 if (drmFd < 0 || req == NULL) {
142 printf("\n %s %d invalid parameter return\n",__FUNCTION__,__LINE__);
143 return rc;
144 }
145 struct mesonProperty *prop = NULL;
146 prop = mesonPropertyCreate(drmFd, objId, objType, name);
147 propId = mesonPropertyGetId(prop);
148 mesonPropertyDestroy(prop);
149 printf("\nmeson_drm_set_property name:%s propId:%d value:%llu\n", name, propId, value);
150 rc = drmModeAtomicAddProperty( req, objId, propId, value );
151 if (rc < 0)
152 printf("\n %s %d meson_drm_set_property fail\n",__FUNCTION__,__LINE__);
153 return rc;
154}
155
156int meson_drm_getModeInfo(int drmFd, MESON_CONNECTOR_TYPE connType, DisplayMode* modeInfo)
157{
158 int ret = -1;
159 struct mesonConnector* conn = NULL;
160 drmModeModeInfo* mode = NULL;
161 if (modeInfo == NULL || drmFd < 0) {
162 printf("\n %s %d modeInfo == NULL || drmFd < 0 return\n",__FUNCTION__,__LINE__);
163 return ret;
164 }
165 conn = get_current_connector(drmFd, connType);
166 if ( conn ) {
167 mode = mesonConnectorGetCurMode(drmFd, conn);
168 if (mode) {
169 modeInfo->w = mode->hdisplay;
170 modeInfo->h = mode->vdisplay;
171 modeInfo->vrefresh = mode->vrefresh;
172 modeInfo->interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
173 strcpy(modeInfo->name, mode->name);
174 free(mode);
175 mode = NULL;
176 ret = 0;
177 } else {
178 printf("\n %s %d mode get fail \n",__FUNCTION__,__LINE__);
179 }
180 } else {
181 printf("\n %s %d conn create fail \n",__FUNCTION__,__LINE__);
182 }
183 if (conn)
184 mesonConnectorDestroy(drmFd,conn);
185 return ret;
186}
187int meson_drm_changeMode(int drmFd, drmModeAtomicReq *req, DisplayMode* modeInfo, MESON_CONNECTOR_TYPE connType)
188{
189 int ret = -1;
190 struct mesonConnector* conn = NULL;
191 drmModeModeInfo drm_mode;
192 int i;
193 bool interlace = false;
194 bool found = false;
195 int rc = -1;
196 int rc1 = -1;
197 int rc2 = -1;
198 int rc3 = -1;
199 uint32_t connId;
200 uint32_t crtcId;
201
202 uint32_t blobId = 0;
203 drmModeModeInfo* modes = NULL;
204 int modesNumber = 0;
205
206 if (modeInfo == NULL || drmFd < 0 || req == NULL) {
207 printf("\n %s %d invalid parameter return\n",__FUNCTION__,__LINE__);
208 return ret;
209 }
210 conn = get_current_connector(drmFd, connType);
211 connId = mesonConnectorGetId(conn);
212 crtcId = mesonConnectorGetCRTCId(conn);
213 if ( conn ) {
214 mesonConnectorGetModes(conn, drmFd, &modes, &modesNumber);
215 for ( i = 0; i < modesNumber; i++ ) {
216 interlace = (modes[i].flags & DRM_MODE_FLAG_INTERLACE);
217 if ( (modeInfo->w == modes[i].hdisplay)
218 && (modeInfo->h == modes[i].vdisplay)
219 && (modeInfo->vrefresh == modes[i].vrefresh)
220 && (interlace == modeInfo->interlace)
221 ) {
222 drm_mode = modes[i];
223 found = true;
224 break;
225 }
226 }
227 } else {
228 printf("\n %s %d conn create fail \n",__FUNCTION__,__LINE__);
229 }
230
231 if (found) {
232 rc1 = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", crtcId);
233 rc = drmModeCreatePropertyBlob( drmFd, &drm_mode, sizeof(drm_mode), &blobId );
234 if (rc == 0) {
235 rc2 = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC, "MODE_ID", blobId);
236 rc3 = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC, "ACTIVE", 1);
237 printf("\n %s %d rc1:%d rc:%d rc2:%d, rc3:%d\n",__FUNCTION__,__LINE__, rc1, rc,rc2,rc3);
238 if (rc1 >= 0 && rc2 >= 0 && rc3 >= 0)
239 ret = 0;
240 }
241 }
242 if (conn)
243 mesonConnectorDestroy(drmFd,conn);
244 return ret;
245}
246
247ENUM_MESON_CONN_CONNECTION meson_drm_getConnectionStatus(int drmFd, MESON_CONNECTOR_TYPE connType)
248{
249 ENUM_MESON_CONN_CONNECTION ret = MESON_UNKNOWNCONNECTION;
250 struct mesonConnector* conn = NULL;
251 if ( drmFd < 0) {
252 printf("\n%s %d drmFd < 0\n",__FUNCTION__,__LINE__);
253 return ret;
254 }
255 conn = get_current_connector(drmFd, connType);
256 if (conn) {
257 int ConnectState = -1;
258 ConnectState = mesonConnectorGetConnectState(conn);
259 if (ConnectState == 1) {
260 ret = MESON_CONNECTED;
261 } else if (ConnectState == 2) {
262 ret = MESON_DISCONNECTED;
263 } else {
264 ret = MESON_UNKNOWNCONNECTION;
265 }
266 } else {
267 printf("\n drm open fail\n");
268 }
269 if (conn)
270 mesonConnectorDestroy(drmFd,conn);
271 return ret;
272}
273
274ENUM_MESON_COLOR_SPACE meson_drm_getColorSpace(int drmFd, MESON_CONNECTOR_TYPE connType )
275{
276 char propName[PROP_NAME_MAX_LEN] = {'\0'};
277 sprintf( propName, "%s", DRM_CONNECTOR_PROP_COLOR_SPACE);
278 uint32_t value = 0;
279 ENUM_MESON_COLOR_SPACE colorSpace = MESON_COLOR_SPACE_RESERVED;
280 if ( drmFd < 0) {
281 printf("\n%s %d drmFd < 0\n",__FUNCTION__,__LINE__);
282 return colorSpace;
283 }
284 if ( 0 == meson_drm_get_conn_prop_value(drmFd, connType, propName, &value )) {
285 switch (value)
286 {
287 case 0:
288 colorSpace = MESON_COLOR_SPACE_RGB;
289 break;
290 case 1:
291 colorSpace = MESON_COLOR_SPACE_YCBCR422;
292 break;
293 case 2:
294 colorSpace = MESON_COLOR_SPACE_YCBCR444;
295 break;
296 case 3:
297 colorSpace = MESON_COLOR_SPACE_YCBCR420;
298 break;
299 default:
300 colorSpace = MESON_COLOR_SPACE_RESERVED;
301 break;
302 }
303 } else {
304 printf("\n%s %d fail\n",__FUNCTION__,__LINE__);
305 }
306 return colorSpace;
307}
308int meson_drm_setColorSpace(int drmFd, drmModeAtomicReq *req,
309 ENUM_MESON_COLOR_SPACE colorSpace, MESON_CONNECTOR_TYPE connType)
310{
311 int ret = -1;
312 uint32_t connId = 0;
313 int rc = -1;
314 struct mesonConnector* conn = NULL;
315 if ( drmFd < 0 || req == NULL) {
316 printf("\n %s %d invalid parameter return\n",__FUNCTION__,__LINE__);
317 return ret;
318 }
319 conn = get_current_connector(drmFd, connType);
320 if (conn) {
321 connId = mesonConnectorGetId(conn);
322 rc = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR,
323 DRM_CONNECTOR_PROP_COLOR_SPACE, (uint64_t)colorSpace);
324 mesonConnectorDestroy(drmFd,conn);
325 }
326 if (rc >= 0)
327 ret = 0;
328 return ret;
329
330}
331
332uint32_t meson_drm_getColorDepth( int drmFd, MESON_CONNECTOR_TYPE connType )
333{
334 char propName[PROP_NAME_MAX_LEN] = {'\0'};
335 sprintf( propName, "%s", DRM_CONNECTOR_PROP_COLOR_DEPTH);
336 uint32_t value = 0;
337 if ( drmFd < 0) {
338 printf("\n%s %d drmFd < 0\n",__FUNCTION__,__LINE__);
339 return value;
340 }
341 if ( 0 != meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
342 printf("\n%s %d fail\n",__FUNCTION__,__LINE__);
343 }
344 return value;
345}
346int meson_drm_setColorDepth(int drmFd, drmModeAtomicReq *req,
347 uint32_t colorDepth, MESON_CONNECTOR_TYPE connType)
348{
349 int ret = -1;
350 int rc = -1;
351 struct mesonConnector* conn = NULL;
352 uint32_t connId = 0;
353 conn = get_current_connector(drmFd, connType);
354 if ( drmFd < 0 || req == NULL) {
355 printf("\n %s %d invalid parameter return\n",__FUNCTION__,__LINE__);
356 return ret;
357 }
358 if (conn) {
359 connId = mesonConnectorGetId(conn);
360 rc = meson_drm_set_property(drmFd, req, connId, DRM_MODE_OBJECT_CONNECTOR,
361 DRM_CONNECTOR_PROP_COLOR_DEPTH, (uint64_t)colorDepth);
362 mesonConnectorDestroy(drmFd,conn);
363 }
364 if (rc >= 0)
365 ret = 0;
366 return ret;
367}
368ENUM_MESON_HDR_POLICY meson_drm_getHDRPolicy( int drmFd, MESON_CONNECTOR_TYPE connType )
369{
370 char propName[PROP_NAME_MAX_LEN] = {'\0'};
371 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_POLICY);
372 uint32_t value = 0;
373 ENUM_MESON_HDR_POLICY hdrPolicy = MESON_HDR_POLICY_FOLLOW_SINK;
374 if ( drmFd < 0) {
375 printf("\n%s %d drmFd < 0\n",__FUNCTION__,__LINE__);
376 return hdrPolicy;
377 }
378 if ( 0 == meson_drm_get_crtc_prop_value( drmFd, connType, propName, &value )) {
379 if (value == 0)
380 hdrPolicy = MESON_HDR_POLICY_FOLLOW_SINK;
381 if (value == 1)
382 hdrPolicy = MESON_HDR_POLICY_FOLLOW_SOURCE;
383 }
384 return hdrPolicy;
385}
386
387int meson_drm_setHDRPolicy(int drmFd, drmModeAtomicReq *req,
388 ENUM_MESON_HDR_POLICY hdrPolicy, MESON_CONNECTOR_TYPE connType)
389{
390 int ret = -1;
391 int rc = -1;
392 struct mesonConnector* conn = NULL;
393 uint32_t crtcId = 0;
394 conn = get_current_connector(drmFd, connType);
395 if ( drmFd < 0 || req == NULL) {
396 printf("\n %s %d invalid parameter return\n",__FUNCTION__,__LINE__);
397 return ret;
398 }
399 if (conn) {
400 crtcId = mesonConnectorGetCRTCId(conn);
401 rc = meson_drm_set_property(drmFd, req, crtcId, DRM_MODE_OBJECT_CRTC,
402 DRM_CONNECTOR_PROP_TX_HDR_POLICY, (uint64_t)hdrPolicy);
403 mesonConnectorDestroy(drmFd,conn);
404 }
405 if (rc >= 0)
406 ret = 0;
407 return ret;
408}
409
410ENUM_MESON_HDCP_VERSION meson_drm_getHdcpVersion( int drmFd, MESON_CONNECTOR_TYPE connType )
411{
412 char propName[PROP_NAME_MAX_LEN] = {'\0'};
413 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDCP_AUTH_MODE);
414 uint32_t value = 0;
415 ENUM_MESON_HDCP_VERSION hdcpVersion = MESON_HDCP_RESERVED;
416 if ( drmFd < 0) {
417 printf("\n%s %d drmFd < 0\n",__FUNCTION__,__LINE__);
418 return hdcpVersion;
419 }
420 if ( 0 == meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
421 if (value & 0x1)
422 hdcpVersion = MESON_HDCP_14;
423 if (value & 0x2)
424 hdcpVersion = MESON_HDCP_22;
425 }
426 return hdcpVersion;
427}
428
429ENUM_MESON_HDR_MODE meson_drm_getHdrStatus(int drmFd, MESON_CONNECTOR_TYPE connType )
430{
431 char propName[PROP_NAME_MAX_LEN] = {'\0'};
432 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_MODE);
433 uint32_t value = 0;
434 ENUM_MESON_HDR_MODE hdrMode = MESON_SDR;
435 if ( drmFd < 0) {
436 printf("\n%s %d drmFd < 0\n",__FUNCTION__,__LINE__);
437 return hdrMode;
438 }
439 if ( 0 == meson_drm_get_conn_prop_value( drmFd, connType, propName, &value )) {
440 switch (value)
441 {
442 case 0:
443 hdrMode = MESON_HDR10PLUS;
444 break;
445 case 1:
446 hdrMode = MESON_DOLBYVISION_STD;
447 break;
448 case 2:
449 hdrMode = MESON_DOLBYVISION_LL;
450 break;
451 case 3:
452 hdrMode = MESON_HDR10_ST2084;
453 break;
454 case 4:
455 hdrMode = MESON_HDR10_TRADITIONAL;
456 break;
457 case 5:
458 hdrMode = MESON_HDR_HLG;
459 break;
460 case 6:
461 hdrMode = MESON_SDR;
462 break;
463 default:
464 hdrMode = MESON_SDR;
465 break;
466 }
467 } else {
468 printf("\n%s %d fail\n",__FUNCTION__,__LINE__);
469 }
470 return hdrMode;
471}
472