blob: 36036ea4926cbfe4ccc0cfeb1bae472fc8d02b15 [file] [log] [blame]
limin.tian75338482022-06-20 09:27:34 +08001/*
2 * Copyright (c) 2021 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>
limin.tianb3c16ad2022-06-22 14:28:27 +080013#include <errno.h>
14#include <xf86drm.h>
15#include <xf86drmMode.h>
limin.tian75338482022-06-20 09:27:34 +080016#include <linux/string.h>
17#include "libdrm_meson_connector.h"
18#include "libdrm_meson_property.h"
19#include "meson_drm_display.h"
20
21
22#define DEFAULT_CARD "/dev/dri/card0"
23#ifndef XDG_RUNTIME_DIR
24#define XDG_RUNTIME_DIR "/run"
25#endif
limin.tian75338482022-06-20 09:27:34 +080026
27static int meson_drm_setprop(int obj_id, char* prop_name, int prop_value );
limin.tian75338482022-06-20 09:27:34 +080028static uint32_t _getHDRSupportedList(uint64_t hdrlist, uint64_t dvlist);
limin.tianb3c16ad2022-06-22 14:28:27 +080029struct mesonConnector* get_current_connector(int drmFd);
limin.tianfe3eca92022-09-01 10:50:52 +080030#define FRAC_RATE_POLICY "/sys/class/amhdmitx/amhdmitx0/frac_rate_policy"
31static int _amsysfs_get_sysfs_str(const char *path, char *valstr, int size);
32static int _get_frac_rate_policy();
33
limin.tian75338482022-06-20 09:27:34 +080034
35static int meson_drm_setprop(int obj_id, char* prop_name, int prop_value )
36{
37 int ret = -1;
38 printf(" meson_drm_setprop: obj_id %d, prop_name: %s, prop_value:%d\n",obj_id, prop_name,prop_value);
39 char* xdgRunDir = getenv("XDG_RUNTIME_DIR");
40 if (!xdgRunDir)
41 xdgRunDir = XDG_RUNTIME_DIR;
42 if (prop_name) {
43 do {
44 char cmdBuf[512] = {'\0'};
45 snprintf(cmdBuf, sizeof(cmdBuf)-1, "export XDG_RUNTIME_DIR=%s;westeros-gl-console set property -s %d:%s:%d | grep \"Response\"",
46 xdgRunDir, obj_id, prop_name, prop_value);
47 printf("Executing '%s'\n", cmdBuf);
48 FILE* fp = popen(cmdBuf, "r");
49 if (NULL != fp) {
50 char output[64] = {'\0'};
51 while (fgets(output, sizeof(output)-1, fp)) {
52 if (strlen(output) && strstr(output, "[0:")) {
53 ret = 0;
54 printf("\n meson_drm_setprop:%s\n",output);
55 }
56 }
57 pclose(fp);
58 } else {
59 printf("meson_drm_setprop: popen failed\n");
60 }
61 if (ret != 0 ) {
62 if (strcmp(xdgRunDir, XDG_RUNTIME_DIR) == 0) {
limin.tian75338482022-06-20 09:27:34 +080063 break;
64 }
65 xdgRunDir = XDG_RUNTIME_DIR;
66 }
67 } while (ret != 0);
68 }
69 return ret;
70}
71
limin.tian75338482022-06-20 09:27:34 +080072static uint32_t _getHDRSupportedList(uint64_t hdrlist, uint64_t dvlist)
73{
74 uint32_t ret = 0;
75 printf("\n _getHDRSupportedList hdrlist:%llu, dvlist:%llu\n", hdrlist, dvlist);
76 if (!!(hdrlist & 0x1))
77 ret = ret | (0x1 << (int)MESON_DRM_HDR10PLUS);
78
79 if (!!(dvlist & 0x1A))
80 ret = ret | (0x1 << (int)MESON_DRM_DOLBYVISION_STD);
81
82 if (!!(dvlist & 0xE0))
83 ret = ret | (0x1 << (int)MESON_DRM_DOLBYVISION_LL);
84
85 if (!!(hdrlist & 0x8))
86 ret = ret | (0x1 << (int)MESON_DRM_HDR10_ST2084);
87
88 if (!!(hdrlist & 0x4))
89 ret = ret | (0x1 << (int)MESON_DRM_HDR10_TRADITIONAL);
90
91 if (!!(hdrlist & 0x10))
92 ret = ret | (0x1 << (int)MESON_DRM_HDR_HLG);
93
94 if (!!(hdrlist & 0x2))
95 ret = ret | (0x1 << (int)MESON_DRM_SDR);
96
97 return ret;
98}
99
limin.tianb3c16ad2022-06-22 14:28:27 +0800100int meson_drm_setMode(DisplayMode* mode)
limin.tian75338482022-06-20 09:27:34 +0800101{
102 int ret = -1;
limin.tianb3c16ad2022-06-22 14:28:27 +0800103 char cmdBuf[512] = {'\0'};
104 char output[64] = {'\0'};
105 char modeSet[20] = {'\0'};
limin.tian75338482022-06-20 09:27:34 +0800106 char* xdgRunDir = getenv("XDG_RUNTIME_DIR");
107 if (!xdgRunDir)
108 xdgRunDir = XDG_RUNTIME_DIR;
109 if (!mode) {
110 ret = -1;
111 } else {
limin.tiane709cad2022-07-07 17:07:21 +0800112 sprintf(modeSet, "%dx%d%c%d", mode->w, mode->h, mode->interlace ? 'i':'p',mode->vrefresh);
limin.tian75338482022-06-20 09:27:34 +0800113 do {
114 snprintf(cmdBuf, sizeof(cmdBuf)-1, "export XDG_RUNTIME_DIR=%s;westeros-gl-console set mode %s | grep \"Response\"",
limin.tianb3c16ad2022-06-22 14:28:27 +0800115 xdgRunDir, modeSet);
limin.tian75338482022-06-20 09:27:34 +0800116 printf("Executing '%s'\n", cmdBuf);
117 /* FIXME: popen in use */
118 FILE* fp = popen(cmdBuf, "r");
119 if (NULL != fp) {
120 while (fgets(output, sizeof(output)-1, fp)) {
121 if (strlen(output) && strstr(output, "[0:")) {
122 ret = 0;
123 } else {
124 ret = -1;
125 }
126 }
127 pclose(fp);
128 } else {
129 printf(" popen failed\n");
130 ret = -1;
131 }
132 if (ret != 0 ) {
133 if (strcmp(xdgRunDir, XDG_RUNTIME_DIR) == 0) {
limin.tiane709cad2022-07-07 17:07:21 +0800134 printf("meson_drm_setMode: failed !!\n");
limin.tian75338482022-06-20 09:27:34 +0800135 break;
136 }
137 xdgRunDir = XDG_RUNTIME_DIR;
138 }
139 } while (ret != 0);
140 }
141 return ret;
142}
limin.tianb3c16ad2022-06-22 14:28:27 +0800143int meson_drm_getMode(DisplayMode* modeInfo)
limin.tian75338482022-06-20 09:27:34 +0800144{
limin.tianb3c16ad2022-06-22 14:28:27 +0800145 int ret = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800146 struct mesonConnector* conn = NULL;
147 drmModeModeInfo* mode = NULL;
148 int drmFd = -1;
149 if (modeInfo == NULL) {
150 printf("\n %s %d modeInfo == NULL return\n",__FUNCTION__,__LINE__);
limin.tianb3c16ad2022-06-22 14:28:27 +0800151 return ret;
limin.tiane709cad2022-07-07 17:07:21 +0800152 }
153 drmFd = meson_drm_open();
154 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
155 if ( conn ) {
156 mode = mesonConnectorGetCurMode(drmFd, conn);
157 if (mode) {
158 modeInfo->w = mode->hdisplay;
159 modeInfo->h = mode->vdisplay;
160 modeInfo->vrefresh = mode->vrefresh;
161 modeInfo->interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
162 strcpy(modeInfo->name, mode->name);
163 free(mode);
164 mode = NULL;
165 ret = 0;
limin.tian75338482022-06-20 09:27:34 +0800166 } else {
limin.tiane709cad2022-07-07 17:07:21 +0800167 printf("\n %s %d mode get fail \n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800168 }
limin.tiane709cad2022-07-07 17:07:21 +0800169 } else {
170 printf("\n %s %d conn create fail \n",__FUNCTION__,__LINE__);
171 }
172 if (conn)
173 mesonConnectorDestroy(drmFd,conn);
174 if (drmFd >= 0 )
175 close(drmFd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800176 return ret;
limin.tian75338482022-06-20 09:27:34 +0800177}
178
limin.tianb3c16ad2022-06-22 14:28:27 +0800179int meson_drm_getRxSurportedModes( DisplayMode** modes, int* modeCount )
limin.tian75338482022-06-20 09:27:34 +0800180{
181 int ret = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800182 int drmFd = -1;
183 struct mesonConnector* conn = NULL;
184 drmFd = meson_drm_open();
185 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
186 if (conn == NULL || drmFd < 0)
187 {
188 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800189 }
190 drmModeModeInfo* modeall = NULL;
191 int count = 0;
192 int i = 0;
limin.tiane709cad2022-07-07 17:07:21 +0800193 if (0 != mesonConnectorGetModes(conn, drmFd, &modeall, &count))
limin.tian75338482022-06-20 09:27:34 +0800194 goto out;
limin.tianb3c16ad2022-06-22 14:28:27 +0800195 DisplayMode* modestemp = (DisplayMode*)calloc(count, sizeof(DisplayMode));
limin.tian75338482022-06-20 09:27:34 +0800196 for (i = 0; i < count; i++)
197 {
198 modestemp[i].w = modeall[i].hdisplay;
199 modestemp[i].h = modeall[i].vdisplay;
200 modestemp[i].vrefresh = modeall[i].vrefresh;
201 modestemp[i].interlace = (modeall[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false;
202 strcpy(modestemp[i].name, modeall[i].name );
203 }
204 *modeCount = count;
205 *modes = modestemp;
206 ret = 0;
207out:
limin.tiane709cad2022-07-07 17:07:21 +0800208 if (conn)
209 mesonConnectorDestroy(drmFd,conn);
210 if (drmFd >= 0 )
211 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800212 return ret;
213}
limin.tianb3c16ad2022-06-22 14:28:27 +0800214int meson_drm_getRxPreferredMode( DisplayMode* mode)
limin.tian75338482022-06-20 09:27:34 +0800215{
216 int ret = -1;
217 int i = 0;
218 int count = 0;
219 drmModeModeInfo* modes = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800220 int drmFd = -1;
221 struct mesonConnector* conn = NULL;
222 drmFd = meson_drm_open();
223 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
224 if (conn == NULL || drmFd < 0)
225 {
226 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800227 }
limin.tiane709cad2022-07-07 17:07:21 +0800228
229 if (0 != mesonConnectorGetModes(conn, drmFd, &modes, &count))
limin.tian75338482022-06-20 09:27:34 +0800230 goto out;
231 for (i = 0; i < count; i++)
232 {
233 if (modes[i].type & DRM_MODE_TYPE_PREFERRED)
234 {
235 mode->w = modes[i].hdisplay;
236 mode->h = modes[i].vdisplay;
237 mode->interlace = (modes[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false;
238 strcpy(mode->name, modes[i].name );
239 break;
240 }
241 }
242 ret = 0;
243out:
limin.tiane709cad2022-07-07 17:07:21 +0800244 if (conn)
245 mesonConnectorDestroy(drmFd,conn);
246 if (drmFd >= 0 )
247 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800248 return ret;
249}
250
251int meson_drm_getEDID( int * data_Len, char **data)
252{
253 int ret = -1;
254 int i = 0;
255 int count = 0;
limin.tian75338482022-06-20 09:27:34 +0800256 char* edid_data = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800257 int drmFd = -1;
258 struct mesonConnector* conn = NULL;
259 drmFd = meson_drm_open();
260 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
261 if (conn == NULL || drmFd < 0)
262 {
263 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800264 }
limin.tiane709cad2022-07-07 17:07:21 +0800265 if (0 != mesonConnectorGetEdidBlob(conn, &count, &edid_data))
limin.tian75338482022-06-20 09:27:34 +0800266 goto out;
267 char* edid = (char*)calloc(count, sizeof(char));
268 for (i = 0; i < count; i++)
269 {
270 edid[i] = edid_data[i];
271 }
272 *data_Len = count;
273 *data = edid;
274 ret = 0;
275out:
limin.tiane709cad2022-07-07 17:07:21 +0800276 if (conn)
277 mesonConnectorDestroy(drmFd,conn);
278 if (drmFd >= 0 )
279 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800280 return ret;
281}
282
283int meson_drm_getRxSurportedEOTF(ENUM_DRM_HDMITX_PROP_EOTF* EOTFs)
284{
285 //get from EDID
286 return 0;
287}
288
289ENUM_MESON_DRM_CONNECTION meson_drm_getConnection()
290{
291 ENUM_MESON_DRM_CONNECTION ret = MESON_DRM_UNKNOWNCONNECTION;
limin.tiane709cad2022-07-07 17:07:21 +0800292 int drmFd = -1;
293 struct mesonConnector* conn = NULL;
294 drmFd = meson_drm_open();
295 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
296 if (conn == NULL || drmFd < 0)
297 {
298 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
299 }
300 if (conn) {
limin.tian75338482022-06-20 09:27:34 +0800301 int ConnectState = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800302 ConnectState = mesonConnectorGetConnectState(conn);
limin.tian75338482022-06-20 09:27:34 +0800303 if (ConnectState == 1) {
304 ret = MESON_DRM_CONNECTED;
305 } else if (ConnectState == 2) {
306 ret = MESON_DRM_DISCONNECTED;
307 } else {
308 ret = MESON_DRM_UNKNOWNCONNECTION;
limin.tian75338482022-06-20 09:27:34 +0800309 }
310 } else {
311 printf("\n drm open fail\n");
312 }
limin.tiane709cad2022-07-07 17:07:21 +0800313 if (conn)
314 mesonConnectorDestroy(drmFd,conn);
315 if (drmFd >= 0 )
316 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800317 return ret;
318}
319
320int meson_drm_set_prop( ENUM_MESON_DRM_PROP enProp, int prop_value )
321{
322 int ret = -1;
323 int objID = -1;
324 char propName[50] = {'\0'};
325 bool force1_4 = false;
326 if (enProp >= ENUM_DRM_PROP_MAX) {
327 printf("\n%s %d invalid para\n",__FUNCTION__,__LINE__);
328 goto out;
329 }
limin.tiane709cad2022-07-07 17:07:21 +0800330 int drmFd = -1;
331 struct mesonConnector* conn = NULL;
332 drmFd = meson_drm_open();
333 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
334 if (conn == NULL || drmFd < 0)
335 {
336 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800337 goto out;
338 }
339 switch (enProp)
340 {
341 case ENUM_DRM_PROP_HDMI_ENABLE:
342 {
limin.tiane709cad2022-07-07 17:07:21 +0800343 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800344 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_AVMUTE);
345 prop_value = prop_value ? 0:1;
346 break;
347 }
348 case ENUM_DRM_PROP_HDMITX_EOTF:
349 {
limin.tiane709cad2022-07-07 17:07:21 +0800350 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800351 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_EOTF);
352 break;
353 }
354 case ENUM_DRM_PROP_CONTENT_PROTECTION:
355 {
limin.tiane709cad2022-07-07 17:07:21 +0800356 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800357 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_PROTECTION);
358 break;
359 }
360 case ENUM_DRM_PROP_HDCP_VERSION:
361 {
limin.tiane709cad2022-07-07 17:07:21 +0800362 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800363 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_TYPE);
364 if (ENUM_HDCP_VERSION_FORCE_1_4 == prop_value)
365 {
366 prop_value = 0;
367 force1_4 = true;
368 }
369 break;
370 }
371 case ENUM_DRM_PROP_HDR_POLICY:
372 {
limin.tiane709cad2022-07-07 17:07:21 +0800373 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800374 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_POLICY);
375 break;
376 }
377 case ENUM_DRM_PROP_HDMI_ASPECT_RATIO:
378 {
limin.tiane709cad2022-07-07 17:07:21 +0800379 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800380 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_ASPECT_RATIO);
381 break;
382 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800383 case ENUM_DRM_PROP_HDMI_DV_ENABLE:
384 {
limin.tiane709cad2022-07-07 17:07:21 +0800385 objID = mesonConnectorGetCRTCId(conn);
limin.tianb3c16ad2022-06-22 14:28:27 +0800386 sprintf( propName, "%s", DRM_CONNECTOR_PROP_DV_ENABLE);
387 }
limin.tian75338482022-06-20 09:27:34 +0800388 default:
389 break;
390 }
391 meson_drm_setprop(objID, propName, prop_value);
392 if (enProp == ENUM_DRM_PROP_HDCP_VERSION)
393 {
limin.tiane709cad2022-07-07 17:07:21 +0800394 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800395 sprintf( propName, "%s", DRM_CONNECTOR_PROP_HDCP_PRIORITY);
396 int priority = 0;
397 if (force1_4)
398 {
399 priority = 1;
400 }
401 meson_drm_setprop(objID, propName, priority);
402 }
limin.tian75338482022-06-20 09:27:34 +0800403 ret = 0;
404out:
limin.tiane709cad2022-07-07 17:07:21 +0800405 if (conn)
406 mesonConnectorDestroy(drmFd,conn);
407 if (drmFd >= 0 )
408 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800409 return ret;
410}
411
412int meson_drm_get_prop( ENUM_MESON_DRM_PROP enProp, uint32_t* prop_value )
413{
414 int ret = -1;
415 int objID = -1;
416 int objtype = -1;
417 char propName[50] = {'\0'};
418 if (!prop_value || enProp >= ENUM_DRM_PROP_MAX) {
419 printf("\n%s %d invalid para\n",__FUNCTION__,__LINE__);
420 goto out;
421 }
limin.tiane709cad2022-07-07 17:07:21 +0800422 int drmFd = -1;
423 struct mesonConnector* conn = NULL;
424 drmFd = meson_drm_open();
425 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
426 if (conn == NULL || drmFd < 0)
427 {
428 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800429 goto out;
430 }
431 switch (enProp)
432 {
433 case ENUM_DRM_PROP_HDMI_ENABLE:
434 {
limin.tiane709cad2022-07-07 17:07:21 +0800435 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800436 objtype = DRM_MODE_OBJECT_CONNECTOR;
437 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_AVMUTE);
438 break;
439 }
440 case ENUM_DRM_PROP_HDMITX_EOTF:
441 {
limin.tiane709cad2022-07-07 17:07:21 +0800442 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800443 objtype = DRM_MODE_OBJECT_CRTC;
444 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_EOTF);
445 break;
446 }
447 case ENUM_DRM_PROP_CONTENT_PROTECTION:
448 {
limin.tiane709cad2022-07-07 17:07:21 +0800449 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800450 objtype = DRM_MODE_OBJECT_CONNECTOR;
451 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_PROTECTION);
452 break;
453 }
454 case ENUM_DRM_PROP_HDCP_VERSION:
455 {
limin.tiane709cad2022-07-07 17:07:21 +0800456 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800457 objtype = DRM_MODE_OBJECT_CONNECTOR;
458 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_TYPE);
459 break;
460 }
461 case ENUM_DRM_PROP_HDR_POLICY:
462 {
limin.tiane709cad2022-07-07 17:07:21 +0800463 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800464 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_POLICY);
465 objtype = DRM_MODE_OBJECT_CRTC;
466 break;
467 }
468 case ENUM_DRM_PROP_GETRX_HDCP_SUPPORTED_VERS:
469 {
limin.tiane709cad2022-07-07 17:07:21 +0800470 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800471 objtype = DRM_MODE_OBJECT_CONNECTOR;
472 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_HDCP_SUPPORTED_VER);
473 break;
474 }
475 case ENUM_DRM_PROP_GETRX_HDR_CAP:
476 {
limin.tiane709cad2022-07-07 17:07:21 +0800477 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800478 objtype = DRM_MODE_OBJECT_CONNECTOR;
479 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_HDR_CAP);
480 break;
481 }
482 case ENUM_DRM_PROP_GETTX_HDR_MODE:
483 {
limin.tiane709cad2022-07-07 17:07:21 +0800484 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800485 objtype = DRM_MODE_OBJECT_CONNECTOR;
486 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_MODE);
487 break;
488 }
489 case ENUM_DRM_PROP_HDMI_ASPECT_RATIO:
490 {
limin.tiane709cad2022-07-07 17:07:21 +0800491 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800492 objtype = DRM_MODE_OBJECT_CONNECTOR;
493 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_ASPECT_RATIO);
494 break;
495 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800496 case ENUM_DRM_PROP_HDMI_DV_ENABLE:
497 {
limin.tiane709cad2022-07-07 17:07:21 +0800498 objID = mesonConnectorGetCRTCId(conn);
limin.tianb3c16ad2022-06-22 14:28:27 +0800499 objtype = DRM_MODE_OBJECT_CRTC;
500 sprintf( propName, "%s", DRM_CONNECTOR_PROP_DV_ENABLE);
limin.tiane709cad2022-07-07 17:07:21 +0800501 break;
502 }
503 case ENUM_DRM_PROP_GETRX_HDCP_AUTHMODE:
504 {
505 objID = mesonConnectorGetId(conn);
506 objtype = DRM_MODE_OBJECT_CONNECTOR;
507 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDCP_AUTH_MODE);
508 break;
limin.tianb3c16ad2022-06-22 14:28:27 +0800509 }
limin.tian75338482022-06-20 09:27:34 +0800510 default:
511 break;
512 }
513 struct mesonProperty* meson_prop = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800514 meson_prop = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800515 if (!meson_prop) {
516 printf("\n meson_prop create fail\n");
517 goto out;
518 }
519 uint64_t value = mesonPropertyGetValue(meson_prop);
520 printf("\n prop value:%llu objID:%d,name:%s\n",value, objID,propName);
521 if (enProp == ENUM_DRM_PROP_HDMI_ENABLE)
522 value = value ? 0:1;
523 *prop_value = (uint32_t)value;
524
525 if (enProp == ENUM_DRM_PROP_GETRX_HDR_CAP)
526 {
limin.tiane709cad2022-07-07 17:07:21 +0800527 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800528 objtype = DRM_MODE_OBJECT_CONNECTOR;
529 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_DV_CAP);
530 struct mesonProperty* meson_prop_dv = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800531 meson_prop_dv = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800532 uint64_t value_2 = mesonPropertyGetValue(meson_prop_dv);
533 mesonPropertyDestroy(meson_prop_dv);
534 *prop_value = _getHDRSupportedList(value, value_2);
535 }
536 if (enProp == ENUM_DRM_PROP_GETRX_HDCP_SUPPORTED_VERS)
537 {
538 *prop_value = 0;
539 if (value == 14)
540 *prop_value = 0x1 << 0;
541 if (value == 22)
542 *prop_value = 0x1 << 1;
543 if (value == 36)
544 *prop_value = 0x1 | (0x1 << 1);
545 }
546 if (enProp == ENUM_DRM_PROP_HDCP_VERSION)
547 {
548 if (*prop_value == 0)
549 {
limin.tiane709cad2022-07-07 17:07:21 +0800550 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800551 objtype = DRM_MODE_OBJECT_CONNECTOR;
552 sprintf( propName, "%s", DRM_CONNECTOR_PROP_HDCP_PRIORITY);
553 struct mesonProperty* meson_prop_HDCP = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800554 meson_prop_HDCP = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800555 uint64_t value_3 = mesonPropertyGetValue(meson_prop_HDCP);
556 mesonPropertyDestroy(meson_prop_HDCP);
557 printf("\n prop value:%llu objID:%d,name:%s\n",value_3, objID,propName);
558 if (value_3 == 1)
559 *prop_value = 2;
560 }
561 }
562 mesonPropertyDestroy(meson_prop);
limin.tian75338482022-06-20 09:27:34 +0800563 ret = 0;
564out:
limin.tiane709cad2022-07-07 17:07:21 +0800565 if (conn)
566 mesonConnectorDestroy(drmFd,conn);
567 if (drmFd >= 0 )
568 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800569 return ret;
570}
571
limin.tianb3c16ad2022-06-22 14:28:27 +0800572int meson_drm_open()
573{
574 int ret_fd = -1;
575 const char *card;
576 card= getenv("WESTEROS_DRM_CARD");
577 if ( !card ) {
578 card = DEFAULT_CARD;
579 }
580 ret_fd = open(card, O_RDONLY|O_CLOEXEC);
581 if ( ret_fd < 0 )
582 printf("\n drm card:%s open fail\n",card);
jingxia.zhange9be5182022-10-09 10:56:04 +0800583 else
584 drmDropMaster(ret_fd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800585 return ret_fd;
586}
587struct mesonConnector* get_current_connector(int drmFd)
588{
589 struct mesonConnector* connectorHDMI = NULL;
590 struct mesonConnector* connectorTV = NULL;
591 int HDMIconnected = 0;
592 connectorHDMI = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
limin.tian12bbe0e2022-10-09 19:28:06 +0800593 if (connectorHDMI)
594 HDMIconnected = mesonConnectorGetConnectState(connectorHDMI);
limin.tianb3c16ad2022-06-22 14:28:27 +0800595 if (HDMIconnected == 1) {
596 return connectorHDMI;
597 } else {
598 connectorTV = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_LVDS);
599 return connectorTV;
600 }
601}
limin.tian75338482022-06-20 09:27:34 +0800602
limin.tianb3c16ad2022-06-22 14:28:27 +0800603void meson_drm_close_fd(int drmFd)
604{
605 if (drmFd >= 0)
limin.tiane709cad2022-07-07 17:07:21 +0800606 close(drmFd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800607}
608
limin.tianfe3eca92022-09-01 10:50:52 +0800609static int _amsysfs_get_sysfs_str(const char *path, char *valstr, int size)
610{
611 int fd;
612 fd = open(path, O_RDONLY);
613 if (fd >= 0) {
614 memset(valstr,0,size);
615 read(fd, valstr, size - 1);
616 valstr[strlen(valstr)] = '\0';
617 close(fd);
618 } else {
619 sprintf(valstr, "%s", "fail");
620 return -1;
621 };
622 return 0;
623}
624
625static int _get_frac_rate_policy()
626{
627 int ret = 0;
628 char buffer[10] = {'\0'};
629 if (0 == _amsysfs_get_sysfs_str(FRAC_RATE_POLICY, buffer, sizeof(buffer)-1) ) {
630 if (strstr(buffer, "1"))
631 ret = 1;
632 }
633 return ret;
634}
635
limin.tianb3c16ad2022-06-22 14:28:27 +0800636int meson_drm_get_vblank_time(int drmFd, int nextVsync,uint64_t *vblankTime, uint64_t *refreshInterval)
637{
638 int ret = -1;
639 int rc = -1;
640 struct mesonConnector* connector = NULL;
641 drmModeModeInfo* mode = NULL;
642 if (drmFd < 0) {
643 printf("\n drmFd error\n");
644 goto out;
645 }
646 if (nextVsync < 0)
647 nextVsync = 0;
648 connector = get_current_connector(drmFd);
649 if (connector != NULL ) {
650 mode = mesonConnectorGetCurMode(drmFd, connector);
651 if (mode) {
limin.tianfe3eca92022-09-01 10:50:52 +0800652 *refreshInterval = (1000000LL+(mode->vrefresh/2)) / mode->vrefresh;
653 if ( ( mode->vrefresh == 60 || mode->vrefresh == 30 || mode->vrefresh == 24
654 || mode->vrefresh == 120 || mode->vrefresh == 240 )
655 && _get_frac_rate_policy() == 1 ) {
656 *refreshInterval = (1000000LL+(mode->vrefresh/2)) * 1001 / mode->vrefresh / 1000;
657 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800658 free(mode);
limin.tianb3c16ad2022-06-22 14:28:27 +0800659 }
660 }
661 drmVBlank vbl;
662 vbl.request.type= DRM_VBLANK_RELATIVE;
663 vbl.request.sequence= nextVsync;
664 vbl.request.signal= 0;
665 rc = drmWaitVBlank(drmFd, &vbl );
666 if (rc != 0 ) {
667 printf("drmWaitVBlank failed: rc %d errno %d",rc, errno);
limin.tianfe3eca92022-09-01 10:50:52 +0800668 ret = -1;
limin.tianb3c16ad2022-06-22 14:28:27 +0800669 goto out;
670 }
671 if ((rc == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
672 *vblankTime = vbl.reply.tval_sec * 1000000LL + vbl.reply.tval_usec;
673 }
limin.tianfe3eca92022-09-01 10:50:52 +0800674 ret = 0;
limin.tianb3c16ad2022-06-22 14:28:27 +0800675out:
676 mesonConnectorDestroy(drmFd, connector);
677 return ret;
678}
limin.tian75338482022-06-20 09:27:34 +0800679
limin.tianfe3eca92022-09-01 10:50:52 +0800680