blob: d766e802daa948af5ba7eb598b543e3409b15ea8 [file] [log] [blame]
limin.tian79bf2b12023-02-24 10:28:26 +00001 /*
limin.tian75338482022-06-20 09:27:34 +08002 * 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 */
limin.tian79bf2b12023-02-24 10:28:26 +00009
limin.tian75338482022-06-20 09:27:34 +080010#include <stdio.h>
11#include <stdlib.h>
12#include <fcntl.h>
13#include <unistd.h>
limin.tianb3c16ad2022-06-22 14:28:27 +080014#include <errno.h>
15#include <xf86drm.h>
16#include <xf86drmMode.h>
limin.tian75338482022-06-20 09:27:34 +080017#include <linux/string.h>
18#include "libdrm_meson_connector.h"
19#include "libdrm_meson_property.h"
20#include "meson_drm_display.h"
21
22
23#define DEFAULT_CARD "/dev/dri/card0"
24#ifndef XDG_RUNTIME_DIR
25#define XDG_RUNTIME_DIR "/run"
26#endif
limin.tian75338482022-06-20 09:27:34 +080027
28static int meson_drm_setprop(int obj_id, char* prop_name, int prop_value );
limin.tian75338482022-06-20 09:27:34 +080029static uint32_t _getHDRSupportedList(uint64_t hdrlist, uint64_t dvlist);
limin.tianb3c16ad2022-06-22 14:28:27 +080030struct mesonConnector* get_current_connector(int drmFd);
limin.tianfe3eca92022-09-01 10:50:52 +080031#define FRAC_RATE_POLICY "/sys/class/amhdmitx/amhdmitx0/frac_rate_policy"
32static int _amsysfs_get_sysfs_str(const char *path, char *valstr, int size);
33static int _get_frac_rate_policy();
34
limin.tian75338482022-06-20 09:27:34 +080035
36static int meson_drm_setprop(int obj_id, char* prop_name, int prop_value )
37{
38 int ret = -1;
39 printf(" meson_drm_setprop: obj_id %d, prop_name: %s, prop_value:%d\n",obj_id, prop_name,prop_value);
40 char* xdgRunDir = getenv("XDG_RUNTIME_DIR");
41 if (!xdgRunDir)
42 xdgRunDir = XDG_RUNTIME_DIR;
43 if (prop_name) {
44 do {
45 char cmdBuf[512] = {'\0'};
46 snprintf(cmdBuf, sizeof(cmdBuf)-1, "export XDG_RUNTIME_DIR=%s;westeros-gl-console set property -s %d:%s:%d | grep \"Response\"",
47 xdgRunDir, obj_id, prop_name, prop_value);
48 printf("Executing '%s'\n", cmdBuf);
49 FILE* fp = popen(cmdBuf, "r");
50 if (NULL != fp) {
51 char output[64] = {'\0'};
52 while (fgets(output, sizeof(output)-1, fp)) {
53 if (strlen(output) && strstr(output, "[0:")) {
54 ret = 0;
55 printf("\n meson_drm_setprop:%s\n",output);
56 }
57 }
58 pclose(fp);
59 } else {
60 printf("meson_drm_setprop: popen failed\n");
61 }
62 if (ret != 0 ) {
63 if (strcmp(xdgRunDir, XDG_RUNTIME_DIR) == 0) {
limin.tian75338482022-06-20 09:27:34 +080064 break;
65 }
66 xdgRunDir = XDG_RUNTIME_DIR;
67 }
68 } while (ret != 0);
69 }
70 return ret;
71}
72
limin.tian75338482022-06-20 09:27:34 +080073static uint32_t _getHDRSupportedList(uint64_t hdrlist, uint64_t dvlist)
74{
75 uint32_t ret = 0;
76 printf("\n _getHDRSupportedList hdrlist:%llu, dvlist:%llu\n", hdrlist, dvlist);
77 if (!!(hdrlist & 0x1))
78 ret = ret | (0x1 << (int)MESON_DRM_HDR10PLUS);
79
80 if (!!(dvlist & 0x1A))
81 ret = ret | (0x1 << (int)MESON_DRM_DOLBYVISION_STD);
82
83 if (!!(dvlist & 0xE0))
84 ret = ret | (0x1 << (int)MESON_DRM_DOLBYVISION_LL);
85
86 if (!!(hdrlist & 0x8))
87 ret = ret | (0x1 << (int)MESON_DRM_HDR10_ST2084);
88
89 if (!!(hdrlist & 0x4))
90 ret = ret | (0x1 << (int)MESON_DRM_HDR10_TRADITIONAL);
91
92 if (!!(hdrlist & 0x10))
93 ret = ret | (0x1 << (int)MESON_DRM_HDR_HLG);
94
95 if (!!(hdrlist & 0x2))
96 ret = ret | (0x1 << (int)MESON_DRM_SDR);
97
98 return ret;
99}
100
limin.tianb3c16ad2022-06-22 14:28:27 +0800101int meson_drm_setMode(DisplayMode* mode)
limin.tian75338482022-06-20 09:27:34 +0800102{
103 int ret = -1;
limin.tianb3c16ad2022-06-22 14:28:27 +0800104 char cmdBuf[512] = {'\0'};
105 char output[64] = {'\0'};
106 char modeSet[20] = {'\0'};
limin.tian75338482022-06-20 09:27:34 +0800107 char* xdgRunDir = getenv("XDG_RUNTIME_DIR");
108 if (!xdgRunDir)
109 xdgRunDir = XDG_RUNTIME_DIR;
110 if (!mode) {
111 ret = -1;
112 } else {
limin.tiane709cad2022-07-07 17:07:21 +0800113 sprintf(modeSet, "%dx%d%c%d", mode->w, mode->h, mode->interlace ? 'i':'p',mode->vrefresh);
limin.tian75338482022-06-20 09:27:34 +0800114 do {
115 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 +0800116 xdgRunDir, modeSet);
limin.tian75338482022-06-20 09:27:34 +0800117 printf("Executing '%s'\n", cmdBuf);
118 /* FIXME: popen in use */
119 FILE* fp = popen(cmdBuf, "r");
120 if (NULL != fp) {
121 while (fgets(output, sizeof(output)-1, fp)) {
122 if (strlen(output) && strstr(output, "[0:")) {
123 ret = 0;
124 } else {
125 ret = -1;
126 }
127 }
128 pclose(fp);
129 } else {
130 printf(" popen failed\n");
131 ret = -1;
132 }
133 if (ret != 0 ) {
134 if (strcmp(xdgRunDir, XDG_RUNTIME_DIR) == 0) {
limin.tiane709cad2022-07-07 17:07:21 +0800135 printf("meson_drm_setMode: failed !!\n");
limin.tian75338482022-06-20 09:27:34 +0800136 break;
137 }
138 xdgRunDir = XDG_RUNTIME_DIR;
139 }
140 } while (ret != 0);
141 }
142 return ret;
143}
limin.tianb3c16ad2022-06-22 14:28:27 +0800144int meson_drm_getMode(DisplayMode* modeInfo)
limin.tian75338482022-06-20 09:27:34 +0800145{
limin.tianb3c16ad2022-06-22 14:28:27 +0800146 int ret = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800147 struct mesonConnector* conn = NULL;
148 drmModeModeInfo* mode = NULL;
149 int drmFd = -1;
150 if (modeInfo == NULL) {
151 printf("\n %s %d modeInfo == NULL return\n",__FUNCTION__,__LINE__);
limin.tianb3c16ad2022-06-22 14:28:27 +0800152 return ret;
limin.tiane709cad2022-07-07 17:07:21 +0800153 }
154 drmFd = meson_drm_open();
155 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
156 if ( conn ) {
157 mode = mesonConnectorGetCurMode(drmFd, conn);
158 if (mode) {
159 modeInfo->w = mode->hdisplay;
160 modeInfo->h = mode->vdisplay;
161 modeInfo->vrefresh = mode->vrefresh;
162 modeInfo->interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
163 strcpy(modeInfo->name, mode->name);
164 free(mode);
165 mode = NULL;
166 ret = 0;
limin.tian75338482022-06-20 09:27:34 +0800167 } else {
limin.tiane709cad2022-07-07 17:07:21 +0800168 printf("\n %s %d mode get fail \n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800169 }
limin.tiane709cad2022-07-07 17:07:21 +0800170 } else {
171 printf("\n %s %d conn create fail \n",__FUNCTION__,__LINE__);
172 }
173 if (conn)
174 mesonConnectorDestroy(drmFd,conn);
175 if (drmFd >= 0 )
176 close(drmFd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800177 return ret;
limin.tian75338482022-06-20 09:27:34 +0800178}
179
limin.tianb3c16ad2022-06-22 14:28:27 +0800180int meson_drm_getRxSurportedModes( DisplayMode** modes, int* modeCount )
limin.tian75338482022-06-20 09:27:34 +0800181{
182 int ret = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800183 int drmFd = -1;
184 struct mesonConnector* conn = NULL;
185 drmFd = meson_drm_open();
186 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
187 if (conn == NULL || drmFd < 0)
188 {
189 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800190 }
191 drmModeModeInfo* modeall = NULL;
192 int count = 0;
193 int i = 0;
limin.tiane709cad2022-07-07 17:07:21 +0800194 if (0 != mesonConnectorGetModes(conn, drmFd, &modeall, &count))
limin.tian75338482022-06-20 09:27:34 +0800195 goto out;
limin.tianb3c16ad2022-06-22 14:28:27 +0800196 DisplayMode* modestemp = (DisplayMode*)calloc(count, sizeof(DisplayMode));
limin.tian75338482022-06-20 09:27:34 +0800197 for (i = 0; i < count; i++)
198 {
199 modestemp[i].w = modeall[i].hdisplay;
200 modestemp[i].h = modeall[i].vdisplay;
201 modestemp[i].vrefresh = modeall[i].vrefresh;
202 modestemp[i].interlace = (modeall[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false;
203 strcpy(modestemp[i].name, modeall[i].name );
204 }
205 *modeCount = count;
206 *modes = modestemp;
207 ret = 0;
208out:
limin.tiane709cad2022-07-07 17:07:21 +0800209 if (conn)
210 mesonConnectorDestroy(drmFd,conn);
211 if (drmFd >= 0 )
212 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800213 return ret;
214}
limin.tianb3c16ad2022-06-22 14:28:27 +0800215int meson_drm_getRxPreferredMode( DisplayMode* mode)
limin.tian75338482022-06-20 09:27:34 +0800216{
217 int ret = -1;
218 int i = 0;
219 int count = 0;
220 drmModeModeInfo* modes = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800221 int drmFd = -1;
222 struct mesonConnector* conn = NULL;
223 drmFd = meson_drm_open();
224 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
225 if (conn == NULL || drmFd < 0)
226 {
227 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800228 }
limin.tiane709cad2022-07-07 17:07:21 +0800229
230 if (0 != mesonConnectorGetModes(conn, drmFd, &modes, &count))
limin.tian75338482022-06-20 09:27:34 +0800231 goto out;
232 for (i = 0; i < count; i++)
233 {
234 if (modes[i].type & DRM_MODE_TYPE_PREFERRED)
235 {
236 mode->w = modes[i].hdisplay;
237 mode->h = modes[i].vdisplay;
238 mode->interlace = (modes[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false;
239 strcpy(mode->name, modes[i].name );
240 break;
241 }
242 }
243 ret = 0;
244out:
limin.tiane709cad2022-07-07 17:07:21 +0800245 if (conn)
246 mesonConnectorDestroy(drmFd,conn);
247 if (drmFd >= 0 )
248 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800249 return ret;
250}
251
252int meson_drm_getEDID( int * data_Len, char **data)
253{
254 int ret = -1;
255 int i = 0;
256 int count = 0;
limin.tian75338482022-06-20 09:27:34 +0800257 char* edid_data = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800258 int drmFd = -1;
259 struct mesonConnector* conn = NULL;
260 drmFd = meson_drm_open();
261 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
262 if (conn == NULL || drmFd < 0)
263 {
264 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800265 }
limin.tiane709cad2022-07-07 17:07:21 +0800266 if (0 != mesonConnectorGetEdidBlob(conn, &count, &edid_data))
limin.tian75338482022-06-20 09:27:34 +0800267 goto out;
268 char* edid = (char*)calloc(count, sizeof(char));
269 for (i = 0; i < count; i++)
270 {
271 edid[i] = edid_data[i];
272 }
273 *data_Len = count;
274 *data = edid;
275 ret = 0;
276out:
limin.tiane709cad2022-07-07 17:07:21 +0800277 if (conn)
278 mesonConnectorDestroy(drmFd,conn);
279 if (drmFd >= 0 )
280 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800281 return ret;
282}
283
284int meson_drm_getRxSurportedEOTF(ENUM_DRM_HDMITX_PROP_EOTF* EOTFs)
285{
286 //get from EDID
287 return 0;
288}
289
290ENUM_MESON_DRM_CONNECTION meson_drm_getConnection()
291{
292 ENUM_MESON_DRM_CONNECTION ret = MESON_DRM_UNKNOWNCONNECTION;
limin.tiane709cad2022-07-07 17:07:21 +0800293 int drmFd = -1;
294 struct mesonConnector* conn = NULL;
295 drmFd = meson_drm_open();
296 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
297 if (conn == NULL || drmFd < 0)
298 {
299 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
300 }
301 if (conn) {
limin.tian75338482022-06-20 09:27:34 +0800302 int ConnectState = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800303 ConnectState = mesonConnectorGetConnectState(conn);
limin.tian75338482022-06-20 09:27:34 +0800304 if (ConnectState == 1) {
305 ret = MESON_DRM_CONNECTED;
306 } else if (ConnectState == 2) {
307 ret = MESON_DRM_DISCONNECTED;
308 } else {
309 ret = MESON_DRM_UNKNOWNCONNECTION;
limin.tian75338482022-06-20 09:27:34 +0800310 }
311 } else {
312 printf("\n drm open fail\n");
313 }
limin.tiane709cad2022-07-07 17:07:21 +0800314 if (conn)
315 mesonConnectorDestroy(drmFd,conn);
316 if (drmFd >= 0 )
317 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800318 return ret;
319}
320
321int meson_drm_set_prop( ENUM_MESON_DRM_PROP enProp, int prop_value )
322{
323 int ret = -1;
324 int objID = -1;
325 char propName[50] = {'\0'};
326 bool force1_4 = false;
327 if (enProp >= ENUM_DRM_PROP_MAX) {
328 printf("\n%s %d invalid para\n",__FUNCTION__,__LINE__);
329 goto out;
330 }
limin.tiane709cad2022-07-07 17:07:21 +0800331 int drmFd = -1;
332 struct mesonConnector* conn = NULL;
333 drmFd = meson_drm_open();
334 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
335 if (conn == NULL || drmFd < 0)
336 {
337 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800338 goto out;
339 }
340 switch (enProp)
341 {
342 case ENUM_DRM_PROP_HDMI_ENABLE:
343 {
limin.tiane709cad2022-07-07 17:07:21 +0800344 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800345 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_AVMUTE);
346 prop_value = prop_value ? 0:1;
347 break;
348 }
349 case ENUM_DRM_PROP_HDMITX_EOTF:
350 {
limin.tiane709cad2022-07-07 17:07:21 +0800351 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800352 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_EOTF);
353 break;
354 }
355 case ENUM_DRM_PROP_CONTENT_PROTECTION:
356 {
limin.tiane709cad2022-07-07 17:07:21 +0800357 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800358 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_PROTECTION);
359 break;
360 }
361 case ENUM_DRM_PROP_HDCP_VERSION:
362 {
limin.tiane709cad2022-07-07 17:07:21 +0800363 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800364 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_TYPE);
365 if (ENUM_HDCP_VERSION_FORCE_1_4 == prop_value)
366 {
367 prop_value = 0;
368 force1_4 = true;
369 }
370 break;
371 }
372 case ENUM_DRM_PROP_HDR_POLICY:
373 {
limin.tiane709cad2022-07-07 17:07:21 +0800374 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800375 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_POLICY);
376 break;
377 }
378 case ENUM_DRM_PROP_HDMI_ASPECT_RATIO:
379 {
limin.tiane709cad2022-07-07 17:07:21 +0800380 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800381 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_ASPECT_RATIO);
382 break;
383 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800384 case ENUM_DRM_PROP_HDMI_DV_ENABLE:
385 {
limin.tiane709cad2022-07-07 17:07:21 +0800386 objID = mesonConnectorGetCRTCId(conn);
limin.tianb3c16ad2022-06-22 14:28:27 +0800387 sprintf( propName, "%s", DRM_CONNECTOR_PROP_DV_ENABLE);
388 }
limin.tian75338482022-06-20 09:27:34 +0800389 default:
390 break;
391 }
392 meson_drm_setprop(objID, propName, prop_value);
393 if (enProp == ENUM_DRM_PROP_HDCP_VERSION)
394 {
limin.tiane709cad2022-07-07 17:07:21 +0800395 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800396 sprintf( propName, "%s", DRM_CONNECTOR_PROP_HDCP_PRIORITY);
397 int priority = 0;
398 if (force1_4)
399 {
400 priority = 1;
401 }
402 meson_drm_setprop(objID, propName, priority);
403 }
limin.tian75338482022-06-20 09:27:34 +0800404 ret = 0;
405out:
limin.tiane709cad2022-07-07 17:07:21 +0800406 if (conn)
407 mesonConnectorDestroy(drmFd,conn);
408 if (drmFd >= 0 )
409 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800410 return ret;
411}
412
413int meson_drm_get_prop( ENUM_MESON_DRM_PROP enProp, uint32_t* prop_value )
414{
415 int ret = -1;
416 int objID = -1;
417 int objtype = -1;
418 char propName[50] = {'\0'};
419 if (!prop_value || enProp >= ENUM_DRM_PROP_MAX) {
420 printf("\n%s %d invalid para\n",__FUNCTION__,__LINE__);
421 goto out;
422 }
limin.tiane709cad2022-07-07 17:07:21 +0800423 int drmFd = -1;
424 struct mesonConnector* conn = NULL;
425 drmFd = meson_drm_open();
426 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
427 if (conn == NULL || drmFd < 0)
428 {
429 printf("\n%s %d connector create fail\n",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800430 goto out;
431 }
432 switch (enProp)
433 {
434 case ENUM_DRM_PROP_HDMI_ENABLE:
435 {
limin.tiane709cad2022-07-07 17:07:21 +0800436 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800437 objtype = DRM_MODE_OBJECT_CONNECTOR;
438 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_AVMUTE);
439 break;
440 }
441 case ENUM_DRM_PROP_HDMITX_EOTF:
442 {
limin.tiane709cad2022-07-07 17:07:21 +0800443 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800444 objtype = DRM_MODE_OBJECT_CRTC;
445 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_EOTF);
446 break;
447 }
448 case ENUM_DRM_PROP_CONTENT_PROTECTION:
449 {
limin.tiane709cad2022-07-07 17:07:21 +0800450 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800451 objtype = DRM_MODE_OBJECT_CONNECTOR;
452 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_PROTECTION);
453 break;
454 }
455 case ENUM_DRM_PROP_HDCP_VERSION:
456 {
limin.tiane709cad2022-07-07 17:07:21 +0800457 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800458 objtype = DRM_MODE_OBJECT_CONNECTOR;
459 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_TYPE);
460 break;
461 }
462 case ENUM_DRM_PROP_HDR_POLICY:
463 {
limin.tiane709cad2022-07-07 17:07:21 +0800464 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800465 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_POLICY);
466 objtype = DRM_MODE_OBJECT_CRTC;
467 break;
468 }
469 case ENUM_DRM_PROP_GETRX_HDCP_SUPPORTED_VERS:
470 {
limin.tiane709cad2022-07-07 17:07:21 +0800471 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800472 objtype = DRM_MODE_OBJECT_CONNECTOR;
473 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_HDCP_SUPPORTED_VER);
474 break;
475 }
476 case ENUM_DRM_PROP_GETRX_HDR_CAP:
477 {
limin.tiane709cad2022-07-07 17:07:21 +0800478 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800479 objtype = DRM_MODE_OBJECT_CONNECTOR;
480 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_HDR_CAP);
481 break;
482 }
483 case ENUM_DRM_PROP_GETTX_HDR_MODE:
484 {
limin.tiane709cad2022-07-07 17:07:21 +0800485 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800486 objtype = DRM_MODE_OBJECT_CONNECTOR;
487 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_MODE);
488 break;
489 }
490 case ENUM_DRM_PROP_HDMI_ASPECT_RATIO:
491 {
limin.tiane709cad2022-07-07 17:07:21 +0800492 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800493 objtype = DRM_MODE_OBJECT_CONNECTOR;
494 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_ASPECT_RATIO);
495 break;
496 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800497 case ENUM_DRM_PROP_HDMI_DV_ENABLE:
498 {
limin.tiane709cad2022-07-07 17:07:21 +0800499 objID = mesonConnectorGetCRTCId(conn);
limin.tianb3c16ad2022-06-22 14:28:27 +0800500 objtype = DRM_MODE_OBJECT_CRTC;
501 sprintf( propName, "%s", DRM_CONNECTOR_PROP_DV_ENABLE);
limin.tiane709cad2022-07-07 17:07:21 +0800502 break;
503 }
504 case ENUM_DRM_PROP_GETRX_HDCP_AUTHMODE:
505 {
506 objID = mesonConnectorGetId(conn);
507 objtype = DRM_MODE_OBJECT_CONNECTOR;
508 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDCP_AUTH_MODE);
509 break;
limin.tianb3c16ad2022-06-22 14:28:27 +0800510 }
limin.tian75338482022-06-20 09:27:34 +0800511 default:
512 break;
513 }
514 struct mesonProperty* meson_prop = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800515 meson_prop = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800516 if (!meson_prop) {
517 printf("\n meson_prop create fail\n");
518 goto out;
519 }
520 uint64_t value = mesonPropertyGetValue(meson_prop);
521 printf("\n prop value:%llu objID:%d,name:%s\n",value, objID,propName);
522 if (enProp == ENUM_DRM_PROP_HDMI_ENABLE)
523 value = value ? 0:1;
524 *prop_value = (uint32_t)value;
525
526 if (enProp == ENUM_DRM_PROP_GETRX_HDR_CAP)
527 {
limin.tiane709cad2022-07-07 17:07:21 +0800528 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800529 objtype = DRM_MODE_OBJECT_CONNECTOR;
530 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_DV_CAP);
531 struct mesonProperty* meson_prop_dv = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800532 meson_prop_dv = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800533 uint64_t value_2 = mesonPropertyGetValue(meson_prop_dv);
534 mesonPropertyDestroy(meson_prop_dv);
535 *prop_value = _getHDRSupportedList(value, value_2);
536 }
537 if (enProp == ENUM_DRM_PROP_GETRX_HDCP_SUPPORTED_VERS)
538 {
539 *prop_value = 0;
540 if (value == 14)
541 *prop_value = 0x1 << 0;
542 if (value == 22)
543 *prop_value = 0x1 << 1;
544 if (value == 36)
545 *prop_value = 0x1 | (0x1 << 1);
546 }
547 if (enProp == ENUM_DRM_PROP_HDCP_VERSION)
548 {
549 if (*prop_value == 0)
550 {
limin.tiane709cad2022-07-07 17:07:21 +0800551 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800552 objtype = DRM_MODE_OBJECT_CONNECTOR;
553 sprintf( propName, "%s", DRM_CONNECTOR_PROP_HDCP_PRIORITY);
554 struct mesonProperty* meson_prop_HDCP = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800555 meson_prop_HDCP = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800556 uint64_t value_3 = mesonPropertyGetValue(meson_prop_HDCP);
557 mesonPropertyDestroy(meson_prop_HDCP);
558 printf("\n prop value:%llu objID:%d,name:%s\n",value_3, objID,propName);
559 if (value_3 == 1)
560 *prop_value = 2;
561 }
562 }
563 mesonPropertyDestroy(meson_prop);
limin.tian75338482022-06-20 09:27:34 +0800564 ret = 0;
565out:
limin.tiane709cad2022-07-07 17:07:21 +0800566 if (conn)
567 mesonConnectorDestroy(drmFd,conn);
568 if (drmFd >= 0 )
569 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800570 return ret;
571}
572
limin.tianb3c16ad2022-06-22 14:28:27 +0800573int meson_drm_open()
574{
575 int ret_fd = -1;
576 const char *card;
577 card= getenv("WESTEROS_DRM_CARD");
578 if ( !card ) {
579 card = DEFAULT_CARD;
580 }
581 ret_fd = open(card, O_RDONLY|O_CLOEXEC);
582 if ( ret_fd < 0 )
583 printf("\n drm card:%s open fail\n",card);
jingxia.zhange9be5182022-10-09 10:56:04 +0800584 else
585 drmDropMaster(ret_fd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800586 return ret_fd;
587}
588struct mesonConnector* get_current_connector(int drmFd)
589{
590 struct mesonConnector* connectorHDMI = NULL;
limin.tian66bdb152022-11-08 13:38:55 +0800591 struct mesonConnector* connectorLVDS = NULL;
592 struct mesonConnector* connectorCVBS = NULL;
limin.tianb3c16ad2022-06-22 14:28:27 +0800593 int HDMIconnected = 0;
limin.tian66bdb152022-11-08 13:38:55 +0800594 int TVConnected = 0;
limin.tianb3c16ad2022-06-22 14:28:27 +0800595 connectorHDMI = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
limin.tian12bbe0e2022-10-09 19:28:06 +0800596 if (connectorHDMI)
597 HDMIconnected = mesonConnectorGetConnectState(connectorHDMI);
limin.tianb3c16ad2022-06-22 14:28:27 +0800598 if (HDMIconnected == 1) {
599 return connectorHDMI;
600 } else {
limin.tian66bdb152022-11-08 13:38:55 +0800601 connectorLVDS = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_LVDS);
602 if (connectorLVDS)
603 TVConnected = mesonConnectorGetConnectState(connectorLVDS);
604 if (TVConnected == 1) {
605 return connectorLVDS;
606 } else {
607 connectorCVBS = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_TV);
608 return connectorCVBS;
609 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800610 }
611}
limin.tian75338482022-06-20 09:27:34 +0800612
limin.tianb3c16ad2022-06-22 14:28:27 +0800613void meson_drm_close_fd(int drmFd)
614{
615 if (drmFd >= 0)
limin.tiane709cad2022-07-07 17:07:21 +0800616 close(drmFd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800617}
618
limin.tianfe3eca92022-09-01 10:50:52 +0800619static int _amsysfs_get_sysfs_str(const char *path, char *valstr, int size)
620{
621 int fd;
622 fd = open(path, O_RDONLY);
623 if (fd >= 0) {
624 memset(valstr,0,size);
625 read(fd, valstr, size - 1);
626 valstr[strlen(valstr)] = '\0';
627 close(fd);
628 } else {
629 sprintf(valstr, "%s", "fail");
630 return -1;
631 };
632 return 0;
633}
634
635static int _get_frac_rate_policy()
636{
637 int ret = 0;
638 char buffer[10] = {'\0'};
639 if (0 == _amsysfs_get_sysfs_str(FRAC_RATE_POLICY, buffer, sizeof(buffer)-1) ) {
640 if (strstr(buffer, "1"))
641 ret = 1;
642 }
643 return ret;
644}
645
limin.tianb3c16ad2022-06-22 14:28:27 +0800646int meson_drm_get_vblank_time(int drmFd, int nextVsync,uint64_t *vblankTime, uint64_t *refreshInterval)
647{
648 int ret = -1;
649 int rc = -1;
650 struct mesonConnector* connector = NULL;
651 drmModeModeInfo* mode = NULL;
652 if (drmFd < 0) {
653 printf("\n drmFd error\n");
654 goto out;
655 }
656 if (nextVsync < 0)
657 nextVsync = 0;
658 connector = get_current_connector(drmFd);
659 if (connector != NULL ) {
660 mode = mesonConnectorGetCurMode(drmFd, connector);
661 if (mode) {
limin.tianfe3eca92022-09-01 10:50:52 +0800662 *refreshInterval = (1000000LL+(mode->vrefresh/2)) / mode->vrefresh;
663 if ( ( mode->vrefresh == 60 || mode->vrefresh == 30 || mode->vrefresh == 24
664 || mode->vrefresh == 120 || mode->vrefresh == 240 )
665 && _get_frac_rate_policy() == 1 ) {
666 *refreshInterval = (1000000LL+(mode->vrefresh/2)) * 1001 / mode->vrefresh / 1000;
667 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800668 free(mode);
limin.tianb3c16ad2022-06-22 14:28:27 +0800669 }
670 }
671 drmVBlank vbl;
672 vbl.request.type= DRM_VBLANK_RELATIVE;
673 vbl.request.sequence= nextVsync;
674 vbl.request.signal= 0;
675 rc = drmWaitVBlank(drmFd, &vbl );
676 if (rc != 0 ) {
677 printf("drmWaitVBlank failed: rc %d errno %d",rc, errno);
limin.tianfe3eca92022-09-01 10:50:52 +0800678 ret = -1;
limin.tianb3c16ad2022-06-22 14:28:27 +0800679 goto out;
680 }
681 if ((rc == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
682 *vblankTime = vbl.reply.tval_sec * 1000000LL + vbl.reply.tval_usec;
683 }
limin.tianfe3eca92022-09-01 10:50:52 +0800684 ret = 0;
limin.tianb3c16ad2022-06-22 14:28:27 +0800685out:
686 mesonConnectorDestroy(drmFd, connector);
687 return ret;
688}
limin.tian75338482022-06-20 09:27:34 +0800689
limin.tianfe3eca92022-09-01 10:50:52 +0800690