blob: 5d53c44106cef3b27d68524f09d7dfa3e594d4d4 [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 */
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"
chen.wang19fec1842023-06-15 06:52:30 +000020#include "meson_drm_log.h"
limin.tian75338482022-06-20 09:27:34 +080021
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 +080034static int meson_drm_setprop(int obj_id, char* prop_name, int prop_value )
35{
36 int ret = -1;
chen.wang1e6ac8df2023-09-12 06:07:18 +000037 DEBUG("%s %d obj_id %d, prop_name: %s, prop_value:%d",__FUNCTION__,__LINE__,obj_id, prop_name,prop_value);
limin.tian75338482022-06-20 09:27:34 +080038 char* xdgRunDir = getenv("XDG_RUNTIME_DIR");
39 if (!xdgRunDir)
40 xdgRunDir = XDG_RUNTIME_DIR;
41 if (prop_name) {
42 do {
43 char cmdBuf[512] = {'\0'};
44 snprintf(cmdBuf, sizeof(cmdBuf)-1, "export XDG_RUNTIME_DIR=%s;westeros-gl-console set property -s %d:%s:%d | grep \"Response\"",
45 xdgRunDir, obj_id, prop_name, prop_value);
chen.wang1e6ac8df2023-09-12 06:07:18 +000046 DEBUG("%s %d Executing '%s'\n", __FUNCTION__,__LINE__,cmdBuf);
limin.tian75338482022-06-20 09:27:34 +080047 FILE* fp = popen(cmdBuf, "r");
48 if (NULL != fp) {
49 char output[64] = {'\0'};
50 while (fgets(output, sizeof(output)-1, fp)) {
51 if (strlen(output) && strstr(output, "[0:")) {
52 ret = 0;
chen.wang1e6ac8df2023-09-12 06:07:18 +000053 DEBUG("%s %d output:%s",__FUNCTION__,__LINE__,output);
limin.tian75338482022-06-20 09:27:34 +080054 }
55 }
56 pclose(fp);
57 } else {
chen.wang1e6ac8df2023-09-12 06:07:18 +000058 ERROR("%s %d open failed",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +080059 }
60 if (ret != 0 ) {
61 if (strcmp(xdgRunDir, XDG_RUNTIME_DIR) == 0) {
limin.tian75338482022-06-20 09:27:34 +080062 break;
63 }
64 xdgRunDir = XDG_RUNTIME_DIR;
65 }
66 } while (ret != 0);
67 }
68 return ret;
69}
70
limin.tian75338482022-06-20 09:27:34 +080071static uint32_t _getHDRSupportedList(uint64_t hdrlist, uint64_t dvlist)
72{
73 uint32_t ret = 0;
chen.wang1e6ac8df2023-09-12 06:07:18 +000074 DEBUG("%s %d hdrlist:%llu, dvlist:%llu",__FUNCTION__,__LINE__, hdrlist, dvlist);
limin.tian75338482022-06-20 09:27:34 +080075 if (!!(hdrlist & 0x1))
76 ret = ret | (0x1 << (int)MESON_DRM_HDR10PLUS);
77
78 if (!!(dvlist & 0x1A))
79 ret = ret | (0x1 << (int)MESON_DRM_DOLBYVISION_STD);
80
81 if (!!(dvlist & 0xE0))
82 ret = ret | (0x1 << (int)MESON_DRM_DOLBYVISION_LL);
83
84 if (!!(hdrlist & 0x8))
85 ret = ret | (0x1 << (int)MESON_DRM_HDR10_ST2084);
86
87 if (!!(hdrlist & 0x4))
88 ret = ret | (0x1 << (int)MESON_DRM_HDR10_TRADITIONAL);
89
90 if (!!(hdrlist & 0x10))
91 ret = ret | (0x1 << (int)MESON_DRM_HDR_HLG);
92
93 if (!!(hdrlist & 0x2))
94 ret = ret | (0x1 << (int)MESON_DRM_SDR);
95
96 return ret;
97}
98
limin.tianb3c16ad2022-06-22 14:28:27 +080099int meson_drm_setMode(DisplayMode* mode)
limin.tian75338482022-06-20 09:27:34 +0800100{
101 int ret = -1;
limin.tianb3c16ad2022-06-22 14:28:27 +0800102 char cmdBuf[512] = {'\0'};
103 char output[64] = {'\0'};
104 char modeSet[20] = {'\0'};
limin.tian75338482022-06-20 09:27:34 +0800105 char* xdgRunDir = getenv("XDG_RUNTIME_DIR");
106 if (!xdgRunDir)
107 xdgRunDir = XDG_RUNTIME_DIR;
108 if (!mode) {
109 ret = -1;
110 } else {
limin.tiane709cad2022-07-07 17:07:21 +0800111 sprintf(modeSet, "%dx%d%c%d", mode->w, mode->h, mode->interlace ? 'i':'p',mode->vrefresh);
limin.tian75338482022-06-20 09:27:34 +0800112 do {
113 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 +0800114 xdgRunDir, modeSet);
chen.wang1e6ac8df2023-09-12 06:07:18 +0000115 DEBUG("%s %d Executing '%s'",__FUNCTION__,__LINE__, cmdBuf);
limin.tian75338482022-06-20 09:27:34 +0800116 /* FIXME: popen in use */
117 FILE* fp = popen(cmdBuf, "r");
118 if (NULL != fp) {
119 while (fgets(output, sizeof(output)-1, fp)) {
120 if (strlen(output) && strstr(output, "[0:")) {
121 ret = 0;
122 } else {
123 ret = -1;
124 }
125 }
126 pclose(fp);
127 } else {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000128 ERROR("%s %d popen failed",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800129 ret = -1;
130 }
131 if (ret != 0 ) {
132 if (strcmp(xdgRunDir, XDG_RUNTIME_DIR) == 0) {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000133 ERROR("%s %d failed !!",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800134 break;
135 }
136 xdgRunDir = XDG_RUNTIME_DIR;
137 }
138 } while (ret != 0);
139 }
140 return ret;
141}
limin.tianb3c16ad2022-06-22 14:28:27 +0800142int meson_drm_getMode(DisplayMode* modeInfo)
limin.tian75338482022-06-20 09:27:34 +0800143{
limin.tianb3c16ad2022-06-22 14:28:27 +0800144 int ret = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800145 struct mesonConnector* conn = NULL;
146 drmModeModeInfo* mode = NULL;
147 int drmFd = -1;
148 if (modeInfo == NULL) {
chen.wang19fec1842023-06-15 06:52:30 +0000149 ERROR("%s %d modeInfo == NULL return",__FUNCTION__,__LINE__);
limin.tianb3c16ad2022-06-22 14:28:27 +0800150 return ret;
limin.tiane709cad2022-07-07 17:07:21 +0800151 }
152 drmFd = meson_drm_open();
153 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
154 if ( conn ) {
155 mode = mesonConnectorGetCurMode(drmFd, conn);
156 if (mode) {
157 modeInfo->w = mode->hdisplay;
158 modeInfo->h = mode->vdisplay;
159 modeInfo->vrefresh = mode->vrefresh;
160 modeInfo->interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
161 strcpy(modeInfo->name, mode->name);
162 free(mode);
163 mode = NULL;
164 ret = 0;
limin.tian75338482022-06-20 09:27:34 +0800165 } else {
chen.wang19fec1842023-06-15 06:52:30 +0000166 ERROR("%s %d mode get fail ",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800167 }
limin.tiane709cad2022-07-07 17:07:21 +0800168 } else {
chen.wang19fec1842023-06-15 06:52:30 +0000169 ERROR("%s %d conn create fail ",__FUNCTION__,__LINE__);
limin.tiane709cad2022-07-07 17:07:21 +0800170 }
171 if (conn)
172 mesonConnectorDestroy(drmFd,conn);
173 if (drmFd >= 0 )
174 close(drmFd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800175 return ret;
limin.tian75338482022-06-20 09:27:34 +0800176}
177
limin.tianb3c16ad2022-06-22 14:28:27 +0800178int meson_drm_getRxSurportedModes( DisplayMode** modes, int* modeCount )
limin.tian75338482022-06-20 09:27:34 +0800179{
180 int ret = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800181 int drmFd = -1;
182 struct mesonConnector* conn = NULL;
183 drmFd = meson_drm_open();
184 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
185 if (conn == NULL || drmFd < 0)
186 {
chen.wang19fec1842023-06-15 06:52:30 +0000187 ERROR("%s %d connector create fail",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800188 }
189 drmModeModeInfo* modeall = NULL;
190 int count = 0;
191 int i = 0;
limin.tiane709cad2022-07-07 17:07:21 +0800192 if (0 != mesonConnectorGetModes(conn, drmFd, &modeall, &count))
limin.tian75338482022-06-20 09:27:34 +0800193 goto out;
limin.tianb3c16ad2022-06-22 14:28:27 +0800194 DisplayMode* modestemp = (DisplayMode*)calloc(count, sizeof(DisplayMode));
limin.tian75338482022-06-20 09:27:34 +0800195 for (i = 0; i < count; i++)
196 {
197 modestemp[i].w = modeall[i].hdisplay;
198 modestemp[i].h = modeall[i].vdisplay;
199 modestemp[i].vrefresh = modeall[i].vrefresh;
200 modestemp[i].interlace = (modeall[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false;
201 strcpy(modestemp[i].name, modeall[i].name );
202 }
203 *modeCount = count;
204 *modes = modestemp;
205 ret = 0;
206out:
limin.tiane709cad2022-07-07 17:07:21 +0800207 if (conn)
208 mesonConnectorDestroy(drmFd,conn);
209 if (drmFd >= 0 )
210 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800211 return ret;
212}
limin.tianb3c16ad2022-06-22 14:28:27 +0800213int meson_drm_getRxPreferredMode( DisplayMode* mode)
limin.tian75338482022-06-20 09:27:34 +0800214{
215 int ret = -1;
216 int i = 0;
217 int count = 0;
218 drmModeModeInfo* modes = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800219 int drmFd = -1;
220 struct mesonConnector* conn = NULL;
221 drmFd = meson_drm_open();
222 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
223 if (conn == NULL || drmFd < 0)
224 {
chen.wang19fec1842023-06-15 06:52:30 +0000225 ERROR("%s %d connector create fail",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800226 }
limin.tiane709cad2022-07-07 17:07:21 +0800227
228 if (0 != mesonConnectorGetModes(conn, drmFd, &modes, &count))
limin.tian75338482022-06-20 09:27:34 +0800229 goto out;
230 for (i = 0; i < count; i++)
231 {
232 if (modes[i].type & DRM_MODE_TYPE_PREFERRED)
233 {
234 mode->w = modes[i].hdisplay;
235 mode->h = modes[i].vdisplay;
236 mode->interlace = (modes[i].flags & DRM_MODE_FLAG_INTERLACE) ? true : false;
237 strcpy(mode->name, modes[i].name );
238 break;
239 }
240 }
241 ret = 0;
242out:
limin.tiane709cad2022-07-07 17:07:21 +0800243 if (conn)
244 mesonConnectorDestroy(drmFd,conn);
245 if (drmFd >= 0 )
246 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800247 return ret;
248}
249
250int meson_drm_getEDID( int * data_Len, char **data)
251{
252 int ret = -1;
253 int i = 0;
254 int count = 0;
limin.tian75338482022-06-20 09:27:34 +0800255 char* edid_data = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800256 int drmFd = -1;
257 struct mesonConnector* conn = NULL;
258 drmFd = meson_drm_open();
259 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
260 if (conn == NULL || drmFd < 0)
261 {
chen.wang19fec1842023-06-15 06:52:30 +0000262 ERROR("%s %d connector create fail",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800263 }
limin.tiane709cad2022-07-07 17:07:21 +0800264 if (0 != mesonConnectorGetEdidBlob(conn, &count, &edid_data))
limin.tian75338482022-06-20 09:27:34 +0800265 goto out;
266 char* edid = (char*)calloc(count, sizeof(char));
267 for (i = 0; i < count; i++)
268 {
269 edid[i] = edid_data[i];
270 }
271 *data_Len = count;
272 *data = edid;
273 ret = 0;
274out:
limin.tiane709cad2022-07-07 17:07:21 +0800275 if (conn)
276 mesonConnectorDestroy(drmFd,conn);
277 if (drmFd >= 0 )
278 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800279 return ret;
280}
281
282int meson_drm_getRxSurportedEOTF(ENUM_DRM_HDMITX_PROP_EOTF* EOTFs)
283{
284 //get from EDID
285 return 0;
286}
287
288ENUM_MESON_DRM_CONNECTION meson_drm_getConnection()
289{
290 ENUM_MESON_DRM_CONNECTION ret = MESON_DRM_UNKNOWNCONNECTION;
limin.tiane709cad2022-07-07 17:07:21 +0800291 int drmFd = -1;
292 struct mesonConnector* conn = NULL;
293 drmFd = meson_drm_open();
294 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
295 if (conn == NULL || drmFd < 0)
296 {
chen.wang19fec1842023-06-15 06:52:30 +0000297 ERROR("%s %d connector create fail",__FUNCTION__,__LINE__);
limin.tiane709cad2022-07-07 17:07:21 +0800298 }
299 if (conn) {
limin.tian75338482022-06-20 09:27:34 +0800300 int ConnectState = -1;
limin.tiane709cad2022-07-07 17:07:21 +0800301 ConnectState = mesonConnectorGetConnectState(conn);
limin.tian75338482022-06-20 09:27:34 +0800302 if (ConnectState == 1) {
303 ret = MESON_DRM_CONNECTED;
304 } else if (ConnectState == 2) {
305 ret = MESON_DRM_DISCONNECTED;
306 } else {
307 ret = MESON_DRM_UNKNOWNCONNECTION;
limin.tian75338482022-06-20 09:27:34 +0800308 }
309 } else {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000310 ERROR("%s %d drm open fail",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800311 }
limin.tiane709cad2022-07-07 17:07:21 +0800312 if (conn)
313 mesonConnectorDestroy(drmFd,conn);
314 if (drmFd >= 0 )
315 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800316 return ret;
317}
318
319int meson_drm_set_prop( ENUM_MESON_DRM_PROP enProp, int prop_value )
320{
321 int ret = -1;
322 int objID = -1;
323 char propName[50] = {'\0'};
324 bool force1_4 = false;
325 if (enProp >= ENUM_DRM_PROP_MAX) {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000326 ERROR("%s %d invalid para",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800327 goto out;
328 }
limin.tiane709cad2022-07-07 17:07:21 +0800329 int drmFd = -1;
330 struct mesonConnector* conn = NULL;
331 drmFd = meson_drm_open();
332 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
333 if (conn == NULL || drmFd < 0)
334 {
chen.wang19fec1842023-06-15 06:52:30 +0000335 ERROR("%s %d connector create fail",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800336 goto out;
337 }
338 switch (enProp)
339 {
340 case ENUM_DRM_PROP_HDMI_ENABLE:
341 {
limin.tiane709cad2022-07-07 17:07:21 +0800342 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800343 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_AVMUTE);
344 prop_value = prop_value ? 0:1;
345 break;
346 }
347 case ENUM_DRM_PROP_HDMITX_EOTF:
348 {
limin.tiane709cad2022-07-07 17:07:21 +0800349 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800350 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_EOTF);
351 break;
352 }
353 case ENUM_DRM_PROP_CONTENT_PROTECTION:
354 {
limin.tiane709cad2022-07-07 17:07:21 +0800355 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800356 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_PROTECTION);
357 break;
358 }
359 case ENUM_DRM_PROP_HDCP_VERSION:
360 {
limin.tiane709cad2022-07-07 17:07:21 +0800361 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800362 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_TYPE);
363 if (ENUM_HDCP_VERSION_FORCE_1_4 == prop_value)
364 {
365 prop_value = 0;
366 force1_4 = true;
367 }
368 break;
369 }
370 case ENUM_DRM_PROP_HDR_POLICY:
371 {
limin.tiane709cad2022-07-07 17:07:21 +0800372 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800373 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_POLICY);
374 break;
375 }
376 case ENUM_DRM_PROP_HDMI_ASPECT_RATIO:
377 {
limin.tiane709cad2022-07-07 17:07:21 +0800378 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800379 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_ASPECT_RATIO);
380 break;
381 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800382 case ENUM_DRM_PROP_HDMI_DV_ENABLE:
383 {
limin.tiane709cad2022-07-07 17:07:21 +0800384 objID = mesonConnectorGetCRTCId(conn);
limin.tianb3c16ad2022-06-22 14:28:27 +0800385 sprintf( propName, "%s", DRM_CONNECTOR_PROP_DV_ENABLE);
386 }
limin.tian75338482022-06-20 09:27:34 +0800387 default:
388 break;
389 }
390 meson_drm_setprop(objID, propName, prop_value);
391 if (enProp == ENUM_DRM_PROP_HDCP_VERSION)
392 {
limin.tiane709cad2022-07-07 17:07:21 +0800393 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800394 sprintf( propName, "%s", DRM_CONNECTOR_PROP_HDCP_PRIORITY);
395 int priority = 0;
396 if (force1_4)
397 {
398 priority = 1;
399 }
400 meson_drm_setprop(objID, propName, priority);
401 }
limin.tian75338482022-06-20 09:27:34 +0800402 ret = 0;
403out:
limin.tiane709cad2022-07-07 17:07:21 +0800404 if (conn)
405 mesonConnectorDestroy(drmFd,conn);
406 if (drmFd >= 0 )
407 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800408 return ret;
409}
410
411int meson_drm_get_prop( ENUM_MESON_DRM_PROP enProp, uint32_t* prop_value )
412{
413 int ret = -1;
414 int objID = -1;
415 int objtype = -1;
416 char propName[50] = {'\0'};
417 if (!prop_value || enProp >= ENUM_DRM_PROP_MAX) {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000418 ERROR("%s %d invalid para",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800419 goto out;
420 }
limin.tiane709cad2022-07-07 17:07:21 +0800421 int drmFd = -1;
422 struct mesonConnector* conn = NULL;
423 drmFd = meson_drm_open();
424 conn = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
425 if (conn == NULL || drmFd < 0)
426 {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000427 ERROR("%s %d connector create fail",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800428 goto out;
429 }
430 switch (enProp)
431 {
432 case ENUM_DRM_PROP_HDMI_ENABLE:
433 {
limin.tiane709cad2022-07-07 17:07:21 +0800434 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800435 objtype = DRM_MODE_OBJECT_CONNECTOR;
436 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_AVMUTE);
437 break;
438 }
439 case ENUM_DRM_PROP_HDMITX_EOTF:
440 {
limin.tiane709cad2022-07-07 17:07:21 +0800441 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800442 objtype = DRM_MODE_OBJECT_CRTC;
443 sprintf( propName, "%s", MESON_DRM_HDMITX_PROP_EOTF);
444 break;
445 }
446 case ENUM_DRM_PROP_CONTENT_PROTECTION:
447 {
limin.tiane709cad2022-07-07 17:07:21 +0800448 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800449 objtype = DRM_MODE_OBJECT_CONNECTOR;
450 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_PROTECTION);
451 break;
452 }
453 case ENUM_DRM_PROP_HDCP_VERSION:
454 {
limin.tiane709cad2022-07-07 17:07:21 +0800455 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800456 objtype = DRM_MODE_OBJECT_CONNECTOR;
457 sprintf( propName, "%s", DRM_CONNECTOR_PROP_CONTENT_TYPE);
458 break;
459 }
460 case ENUM_DRM_PROP_HDR_POLICY:
461 {
limin.tiane709cad2022-07-07 17:07:21 +0800462 objID = mesonConnectorGetCRTCId(conn);
limin.tian75338482022-06-20 09:27:34 +0800463 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_POLICY);
464 objtype = DRM_MODE_OBJECT_CRTC;
465 break;
466 }
467 case ENUM_DRM_PROP_GETRX_HDCP_SUPPORTED_VERS:
468 {
limin.tiane709cad2022-07-07 17:07:21 +0800469 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800470 objtype = DRM_MODE_OBJECT_CONNECTOR;
471 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_HDCP_SUPPORTED_VER);
472 break;
473 }
474 case ENUM_DRM_PROP_GETRX_HDR_CAP:
475 {
limin.tiane709cad2022-07-07 17:07:21 +0800476 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800477 objtype = DRM_MODE_OBJECT_CONNECTOR;
478 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_HDR_CAP);
479 break;
480 }
481 case ENUM_DRM_PROP_GETTX_HDR_MODE:
482 {
limin.tiane709cad2022-07-07 17:07:21 +0800483 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800484 objtype = DRM_MODE_OBJECT_CONNECTOR;
485 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDR_MODE);
486 break;
487 }
488 case ENUM_DRM_PROP_HDMI_ASPECT_RATIO:
489 {
limin.tiane709cad2022-07-07 17:07:21 +0800490 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800491 objtype = DRM_MODE_OBJECT_CONNECTOR;
492 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_ASPECT_RATIO);
493 break;
494 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800495 case ENUM_DRM_PROP_HDMI_DV_ENABLE:
496 {
limin.tiane709cad2022-07-07 17:07:21 +0800497 objID = mesonConnectorGetCRTCId(conn);
limin.tianb3c16ad2022-06-22 14:28:27 +0800498 objtype = DRM_MODE_OBJECT_CRTC;
499 sprintf( propName, "%s", DRM_CONNECTOR_PROP_DV_ENABLE);
limin.tiane709cad2022-07-07 17:07:21 +0800500 break;
501 }
502 case ENUM_DRM_PROP_GETRX_HDCP_AUTHMODE:
503 {
504 objID = mesonConnectorGetId(conn);
505 objtype = DRM_MODE_OBJECT_CONNECTOR;
506 sprintf( propName, "%s", DRM_CONNECTOR_PROP_TX_HDCP_AUTH_MODE);
507 break;
limin.tianb3c16ad2022-06-22 14:28:27 +0800508 }
limin.tian75338482022-06-20 09:27:34 +0800509 default:
510 break;
511 }
512 struct mesonProperty* meson_prop = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800513 meson_prop = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800514 if (!meson_prop) {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000515 ERROR("%s %d meson_prop create fail",__FUNCTION__,__LINE__);
limin.tian75338482022-06-20 09:27:34 +0800516 goto out;
517 }
518 uint64_t value = mesonPropertyGetValue(meson_prop);
chen.wang1e6ac8df2023-09-12 06:07:18 +0000519 DEBUG("%s %d prop value:%llu objID:%d,name:%s",__FUNCTION__,__LINE__,value, objID,propName);
limin.tian75338482022-06-20 09:27:34 +0800520 if (enProp == ENUM_DRM_PROP_HDMI_ENABLE)
521 value = value ? 0:1;
522 *prop_value = (uint32_t)value;
523
524 if (enProp == ENUM_DRM_PROP_GETRX_HDR_CAP)
525 {
limin.tiane709cad2022-07-07 17:07:21 +0800526 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800527 objtype = DRM_MODE_OBJECT_CONNECTOR;
528 sprintf( propName, "%s", DRM_CONNECTOR_PROP_RX_DV_CAP);
529 struct mesonProperty* meson_prop_dv = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800530 meson_prop_dv = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800531 uint64_t value_2 = mesonPropertyGetValue(meson_prop_dv);
532 mesonPropertyDestroy(meson_prop_dv);
533 *prop_value = _getHDRSupportedList(value, value_2);
534 }
535 if (enProp == ENUM_DRM_PROP_GETRX_HDCP_SUPPORTED_VERS)
536 {
537 *prop_value = 0;
538 if (value == 14)
539 *prop_value = 0x1 << 0;
540 if (value == 22)
541 *prop_value = 0x1 << 1;
542 if (value == 36)
543 *prop_value = 0x1 | (0x1 << 1);
544 }
545 if (enProp == ENUM_DRM_PROP_HDCP_VERSION)
546 {
547 if (*prop_value == 0)
548 {
limin.tiane709cad2022-07-07 17:07:21 +0800549 objID = mesonConnectorGetId(conn);
limin.tian75338482022-06-20 09:27:34 +0800550 objtype = DRM_MODE_OBJECT_CONNECTOR;
551 sprintf( propName, "%s", DRM_CONNECTOR_PROP_HDCP_PRIORITY);
552 struct mesonProperty* meson_prop_HDCP = NULL;
limin.tiane709cad2022-07-07 17:07:21 +0800553 meson_prop_HDCP = mesonPropertyCreate(drmFd, objID, objtype, propName);
limin.tian75338482022-06-20 09:27:34 +0800554 uint64_t value_3 = mesonPropertyGetValue(meson_prop_HDCP);
555 mesonPropertyDestroy(meson_prop_HDCP);
chen.wang1e6ac8df2023-09-12 06:07:18 +0000556 DEBUG("%s %d prop value:%llu objID:%d,name:%s",__FUNCTION__,__LINE__,value_3, objID,propName);
limin.tian75338482022-06-20 09:27:34 +0800557 if (value_3 == 1)
558 *prop_value = 2;
559 }
560 }
561 mesonPropertyDestroy(meson_prop);
limin.tian75338482022-06-20 09:27:34 +0800562 ret = 0;
563out:
limin.tiane709cad2022-07-07 17:07:21 +0800564 if (conn)
565 mesonConnectorDestroy(drmFd,conn);
566 if (drmFd >= 0 )
567 close(drmFd);
limin.tian75338482022-06-20 09:27:34 +0800568 return ret;
569}
570
limin.tianb3c16ad2022-06-22 14:28:27 +0800571int meson_drm_open()
572{
573 int ret_fd = -1;
574 const char *card;
575 card= getenv("WESTEROS_DRM_CARD");
576 if ( !card ) {
577 card = DEFAULT_CARD;
578 }
579 ret_fd = open(card, O_RDONLY|O_CLOEXEC);
580 if ( ret_fd < 0 )
chen.wang1e6ac8df2023-09-12 06:07:18 +0000581 ERROR("%s %d drm card:%s open fail",__FUNCTION__,__LINE__,card);
jingxia.zhange9be5182022-10-09 10:56:04 +0800582 else
583 drmDropMaster(ret_fd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800584 return ret_fd;
585}
586struct mesonConnector* get_current_connector(int drmFd)
587{
588 struct mesonConnector* connectorHDMI = NULL;
limin.tian66bdb152022-11-08 13:38:55 +0800589 struct mesonConnector* connectorLVDS = NULL;
590 struct mesonConnector* connectorCVBS = NULL;
limin.tianb3c16ad2022-06-22 14:28:27 +0800591 int HDMIconnected = 0;
limin.tian66bdb152022-11-08 13:38:55 +0800592 int TVConnected = 0;
limin.tianb3c16ad2022-06-22 14:28:27 +0800593 connectorHDMI = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_HDMIA);
limin.tian12bbe0e2022-10-09 19:28:06 +0800594 if (connectorHDMI)
595 HDMIconnected = mesonConnectorGetConnectState(connectorHDMI);
limin.tianb3c16ad2022-06-22 14:28:27 +0800596 if (HDMIconnected == 1) {
597 return connectorHDMI;
598 } else {
limin.tian66bdb152022-11-08 13:38:55 +0800599 connectorLVDS = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_LVDS);
600 if (connectorLVDS)
601 TVConnected = mesonConnectorGetConnectState(connectorLVDS);
602 if (TVConnected == 1) {
603 return connectorLVDS;
604 } else {
605 connectorCVBS = mesonConnectorCreate(drmFd, DRM_MODE_CONNECTOR_TV);
606 return connectorCVBS;
607 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800608 }
609}
limin.tian75338482022-06-20 09:27:34 +0800610
limin.tianb3c16ad2022-06-22 14:28:27 +0800611void meson_drm_close_fd(int drmFd)
612{
613 if (drmFd >= 0)
limin.tiane709cad2022-07-07 17:07:21 +0800614 close(drmFd);
limin.tianb3c16ad2022-06-22 14:28:27 +0800615}
616
limin.tianfe3eca92022-09-01 10:50:52 +0800617static int _amsysfs_get_sysfs_str(const char *path, char *valstr, int size)
618{
619 int fd;
620 fd = open(path, O_RDONLY);
621 if (fd >= 0) {
622 memset(valstr,0,size);
623 read(fd, valstr, size - 1);
624 valstr[strlen(valstr)] = '\0';
625 close(fd);
626 } else {
627 sprintf(valstr, "%s", "fail");
628 return -1;
629 };
630 return 0;
631}
632
633static int _get_frac_rate_policy()
634{
635 int ret = 0;
636 char buffer[10] = {'\0'};
637 if (0 == _amsysfs_get_sysfs_str(FRAC_RATE_POLICY, buffer, sizeof(buffer)-1) ) {
638 if (strstr(buffer, "1"))
639 ret = 1;
640 }
641 return ret;
642}
643
limin.tianb3c16ad2022-06-22 14:28:27 +0800644int meson_drm_get_vblank_time(int drmFd, int nextVsync,uint64_t *vblankTime, uint64_t *refreshInterval)
645{
646 int ret = -1;
647 int rc = -1;
648 struct mesonConnector* connector = NULL;
649 drmModeModeInfo* mode = NULL;
650 if (drmFd < 0) {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000651 ERROR("%s %d drmFd < 0",__FUNCTION__,__LINE__);
limin.tianb3c16ad2022-06-22 14:28:27 +0800652 goto out;
653 }
654 if (nextVsync < 0)
655 nextVsync = 0;
656 connector = get_current_connector(drmFd);
657 if (connector != NULL ) {
658 mode = mesonConnectorGetCurMode(drmFd, connector);
659 if (mode) {
limin.tianfe3eca92022-09-01 10:50:52 +0800660 *refreshInterval = (1000000LL+(mode->vrefresh/2)) / mode->vrefresh;
661 if ( ( mode->vrefresh == 60 || mode->vrefresh == 30 || mode->vrefresh == 24
662 || mode->vrefresh == 120 || mode->vrefresh == 240 )
663 && _get_frac_rate_policy() == 1 ) {
664 *refreshInterval = (1000000LL+(mode->vrefresh/2)) * 1001 / mode->vrefresh / 1000;
665 }
limin.tianb3c16ad2022-06-22 14:28:27 +0800666 free(mode);
limin.tianb3c16ad2022-06-22 14:28:27 +0800667 }
668 }
669 drmVBlank vbl;
670 vbl.request.type= DRM_VBLANK_RELATIVE;
671 vbl.request.sequence= nextVsync;
672 vbl.request.signal= 0;
673 rc = drmWaitVBlank(drmFd, &vbl );
674 if (rc != 0 ) {
chen.wang1e6ac8df2023-09-12 06:07:18 +0000675 ERROR("%s %d drmWaitVBlank failed: rc %d errno %d",__FUNCTION__,__LINE__,rc, errno);
limin.tianfe3eca92022-09-01 10:50:52 +0800676 ret = -1;
limin.tianb3c16ad2022-06-22 14:28:27 +0800677 goto out;
678 }
679 if ((rc == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
680 *vblankTime = vbl.reply.tval_sec * 1000000LL + vbl.reply.tval_usec;
681 }
limin.tianfe3eca92022-09-01 10:50:52 +0800682 ret = 0;
limin.tianb3c16ad2022-06-22 14:28:27 +0800683out:
684 mesonConnectorDestroy(drmFd, connector);
685 return ret;
686}
limin.tian75338482022-06-20 09:27:34 +0800687