blob: 5334395b1df26e72b79af248c46f6c8e149eb294 [file] [log] [blame]
leng.fang91856072024-06-07 14:12:54 +08001#include <pthread.h>
2
3#include "modepolicyfunc.h"
4#include "DisplayAdapter.h"
5#include "modepolicy_aml.h"
6
leng.fang3e8a4b52024-07-24 14:51:30 +08007weston_ctx_list *gCtx_list = NULL;
leng.fang91856072024-06-07 14:12:54 +08008static int g_activeLevel = 3;
9
leng.fang3e8a4b52024-07-24 14:51:30 +080010/* if prop set need change mode, add it to this */
leng.fang13fd3982024-07-03 19:09:58 +080011static char *prop_changed_and_mode[] = {
12 "color_space",
13 "color_depth"
14};
15
leng.fang3e8a4b52024-07-24 14:51:30 +080016static weston_ctx_list *weston_get_ctx_list()
17{
18 if (!gCtx_list) {
19 gCtx_list = (weston_ctx_list *)calloc(1, sizeof(*gCtx_list));
20 wl_list_init(&gCtx_list->ctx_list);
21 }
22 return gCtx_list;
23}
24
leng.fang91856072024-06-07 14:12:54 +080025weston_ctx *weston_get_ctx()
26{
leng.fang3e8a4b52024-07-24 14:51:30 +080027 weston_ctx_list *ctx_list = weston_get_ctx_list();
28 weston_ctx *ctx, *tmp;
29
30 wl_list_for_each(ctx, &ctx_list->ctx_list, link) {
31 if (ctx->head == ctx_list->head)
32 return ctx;
leng.fang91856072024-06-07 14:12:54 +080033 }
leng.fang3e8a4b52024-07-24 14:51:30 +080034 return NULL;
leng.fang91856072024-06-07 14:12:54 +080035}
36
37static void weston_prop_list_init(weston_ctx *ctx)
38{
39 prop_info *info, *tmp;
40 if (!wl_list_empty(&ctx->prop_list)) {
41 wl_list_for_each_safe(info, tmp, &ctx->prop_list, link) {
42 wl_list_remove(&info->link);
43 free(info);
44 }
45 }
46 wl_list_init(&ctx->prop_list);
47}
48
49static int weston_add_property_item(weston_ctx *ctx,
50 const char *name, int id, int prop_id)
51{
52 prop_info *info;
53
54 wl_list_for_each(info, &ctx->prop_list, link) {
55 if (!strcmp(name, info->name) && info->item_id == id)
56 return 0;
57 }
58
59 info = (prop_info *)calloc(1, sizeof(*info));
60 memcpy(info->name, name, sizeof(info->name));
61 info->item_id = id;
62 info->prop_id = prop_id;
63 info->need_change = 0;
64 MESON_LOGD("ctx: %p, name: %s, id: %d, prop_id: %d\n", ctx, name, id, prop_id);
65 wl_list_insert(&ctx->prop_list, &info->link);
66 return 0;
67}
68
69static int weston_add_property(weston_ctx *ctx, int id, int type)
70{
71 int i, len;
72 int value = 0;
73 drmModePropertyRes *propRes;
74 drmModeObjectProperties *props;
75
76 props = drmModeObjectGetProperties( ctx->drm_fd, id, type );
77 if ( props ) {
78 for ( i= 0; i < props->count_props; ++i ) {
79 propRes = drmModeGetProperty( ctx->drm_fd, props->props[i] );
80 if ( propRes ) {
81 weston_add_property_item(ctx, propRes->name, id, props->props[i]);
82 drmModeFreeProperty( propRes );
83 propRes = 0;
84 }
85 }
86 drmModeFreeObjectProperties( props );
87 props = 0;
88 }
89 return value;
90}
91
92static int weston_get_property_value(weston_ctx *ctx, const char * key, int id, int type)
93{
94 int i, len;
95 int value = 0;
96 drmModePropertyRes *propRes;
97 drmModeObjectProperties *props;
98
99 props = drmModeObjectGetProperties( ctx->drm_fd, id, type );
100 if ( props ) {
101 for ( i= 0; i < props->count_props; ++i ) {
102 propRes = drmModeGetProperty( ctx->drm_fd, props->props[i] );
103 if ( propRes ) {
104 len = strlen(propRes->name);
105 if ( !strncmp( propRes->name, key, len) ) {
106 MESON_LOGD("property %d name (%s) value (%lld)",
107 props->props[i], propRes->name, props->prop_values[i] );
108 value = props->prop_values[i];
109 drmModeFreeProperty( propRes );
110 propRes = 0;
111 break;
112 }
113 drmModeFreeProperty( propRes );
114 propRes = 0;
115 }
116 }
117 drmModeFreeObjectProperties( props );
118 props = 0;
119 }
120 return value;
121}
122
123static int weston_get_connector_property(const char * key)
124{
125 weston_ctx *ctx = weston_get_ctx();
126
leng.fang3e8a4b52024-07-24 14:51:30 +0800127 if (!ctx)
128 return 0;
129
leng.fang91856072024-06-07 14:12:54 +0800130 return weston_get_property_value(ctx, key, ctx->conn->connector_id, DRM_MODE_OBJECT_CONNECTOR);
131}
132
133static int weston_get_crtc_property(const char * key)
134{
135 weston_ctx *ctx = weston_get_ctx();
136
leng.fang3e8a4b52024-07-24 14:51:30 +0800137 if (!ctx)
138 return 0;
139
leng.fang91856072024-06-07 14:12:54 +0800140 return weston_get_property_value(ctx, key, ctx->crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
141}
142
143static bool get_mode_name_for_weston_mode(
144 weston_ctx *ctx,
145 struct weston_mode *mode,
146 char *out)
147{
148 int i;
149 int current_interlaced;
150 const char *value;
151
152 if (mode && getModeNameForPix(out, mode->width, mode->height, mode->refresh, mode->flags))
153 return true;
154
155 value = bootenv_get("hdmimode");
156 if (value)
157 strcpy(out, value);
158 else
159 strcpy(out, "none");
160 MESON_LOGD("out: %s", out);
161 return false;
162}
163
164static bool weston_get_mode(char *mode)
165{
166 weston_ctx *ctx = weston_get_ctx();
167 struct weston_mode *wmode = NULL;
168
leng.fang3e8a4b52024-07-24 14:51:30 +0800169 if (!wmode && ctx && ctx->current_mode.width != 0)
leng.fang91856072024-06-07 14:12:54 +0800170 wmode = &ctx->current_mode;
171
172 return get_mode_name_for_weston_mode(ctx, wmode, mode);
173}
174
leng.fang9cf09e22024-07-17 20:01:11 +0800175bool WestonGetUbootIsBestmode()
leng.fang91856072024-06-07 14:12:54 +0800176{
177 const char *isbestmode = bootenv_get("is.bestmode");
178 if ( isbestmode != NULL ) {
179 if (strcmp("false", isbestmode) == 0)
180 return false;
181 else
182 return true;
183 } else
184 return true;
185}
186
187bool westonGetDrmModeInfoByName( weston_ctx *ctx, const char *mode, drmModeModeInfo *out_mode )
188{
189 bool result= false;
190
191 if ( ctx && mode && out_mode ) {
192 int width = -1, height = -1, rate = -1;
193 bool interlaced = false;
194 bool haveTarget = false;
195 bool useBestRate = true;
196
197 MESON_LOGD("%s: mode (%s)", __func__, mode);
198
199 if ( sscanf( mode, "%dx%dp%d", &width, &height, &rate ) == 3 ) {
200 interlaced = false;
201 } else if ( sscanf( mode, "%dx%di%d", &width, &height, &rate ) == 3 ) {
202 interlaced = true;
203 } else if ( sscanf( mode, "%dx%dx%d", &width, &height, &rate ) == 3 ) {
204 interlaced = false;
205 } else if ( sscanf( mode, "%dx%d", &width, &height ) == 2 ) {
206 int len = strlen(mode);
207 interlaced = (mode[len - 1] == 'i');
208 } else if (sscanf( mode, "%dp%dhz", &height,&rate ) == 2) {
209 interlaced = false;
210 width = -1;
211 } else if (sscanf( mode, "%di%dhz", &height,&rate ) == 2) {
212 interlaced = true;
213 width = -1;
214 } else if ( sscanf( mode, "%dp", &height ) == 1 ) {
215 int len = strlen(mode);
216 interlaced = (mode[len - 1] == 'i');
217 width = -1;
218 } else if (sscanf( mode, "smpte%dhz", &rate ) == 1) {
219 interlaced = false;
220 height = 2160;
221 width = 4096;
222 }
223
224 if ( height > 0 ) {
225 if ( width < 0 ) {
226 switch ( height ) {
227 case 480:
228 case 576:
229 width = 720;
230 break;
231 case 720:
232 width = 1280;
233 break;
234 case 1080:
235 width = 1920;
236 break;
237 case 1440:
238 width = 2560;
239 break;
240 case 2160:
241 width = 3840;
242 break;
243 case 2880:
244 width = 5120;
245 break;
246 case 4320:
247 width = 7680;
248 break;
249 default:
250 break;
251 }
252 }
253 }
254 MESON_LOGD("%s w %d h %d rate %d", __func__, width, height, rate);
255 if ( rate >= 0 )
256 useBestRate = false;
257
258 if ( (width > 0) && (height > 0) ) {
259 if ( ctx->drm_fd >= 0 ) {
260 drmModeRes *res = 0;
261 drmModeConnector *conn = 0;
262
263 res = drmModeGetResources( ctx->drm_fd );
264 if ( res ) {
265 int i;
266 for ( i = 0; i < res->count_connectors; ++i ) {
267 conn = drmModeGetConnector( ctx->drm_fd, res->connectors[i] );
268 if ( conn ) {
269 if ( conn->count_modes && (conn->connection == DRM_MODE_CONNECTED) )
270 break;
271 drmModeFreeConnector(conn);
272 conn = 0;
273 }
274 }
275 if ( conn ) {
276 uint32_t rateBest = 0;
277 int miBest = -1;
278
279 MESON_LOGD("%s: want %dx%dx%d interlaced %d use best rate %d",
280 __func__, width, height, rate, interlaced, useBestRate);
281 for ( i = 0; i < conn->count_modes; ++i ) {
282 MESON_LOGD("%s: consider mode %d: %dx%dx%d (%s) type 0x%x flags 0x%x",
283 __func__, i, conn->modes[i].hdisplay, conn->modes[i].vdisplay,
284 conn->modes[i].vrefresh, conn->modes[i].name,
285 conn->modes[i].type, conn->modes[i].flags );
286
287 if ( (conn->modes[i].hdisplay == width) &&
288 (conn->modes[i].vdisplay == height) ) {
289 bool modeIsInterlaced = (conn->modes[i].flags & DRM_MODE_FLAG_INTERLACE);
290 if ( modeIsInterlaced != interlaced )
291 continue;
292
293 if ( useBestRate ) {
294 if ( conn->modes[i].vrefresh > rateBest ) {
295 rateBest = conn->modes[i].vrefresh;
296 miBest = i;
297 }
298 } else if ( conn->modes[i].vrefresh == rate ) {
299 miBest = i;
300 break;
301 }
302 }
303 }
304
305 if ( miBest >= 0 ) {
306 *out_mode = conn->modes[miBest];
307
308 MESON_LOGI("%s: choosing output mode: %dx%dx%d (%s) flags 0x%x",
309 __func__,
310 out_mode->hdisplay,
311 out_mode->vdisplay,
312 out_mode->vrefresh,
313 out_mode->name,
314 out_mode->flags );
315
316 result= true;
317 } else {
318 MESON_LOGE("%s: failed to find a mode matching (%s)", __func__, mode);
319 }
320
321 drmModeFreeConnector( conn );
322 } else {
323 MESON_LOGE("%s: unable to get connector for card", __func__);
324 }
325 drmModeFreeResources(res);
326 } else {
327 MESON_LOGE("%s: unable to get card resources", __func__);
328 }
329 } else {
330 MESON_LOGE("%s: no open device", __func__);
331 }
332 } else {
333 MESON_LOGE("%s: unable to parse mode (%s)", __func__, mode);
334 }
335 }
336
337 return result;
338}
339
340static bool weston_set_mode(const char *mode)
341{
342 weston_ctx *ctx = weston_get_ctx();
343 drmModeModeInfo info = {0};
344
leng.fang3e8a4b52024-07-24 14:51:30 +0800345 if (!ctx)
346 return false;
347
leng.fang91856072024-06-07 14:12:54 +0800348 if (westonGetDrmModeInfoByName(ctx, mode, &info)) {
349 ctx->next_mode.width = info.hdisplay;
350 ctx->next_mode.height = info.vdisplay;
351 ctx->next_mode.refresh = info.vrefresh * 1000;
352 ctx->next_mode.flags = info.flags;
353 setBootConfig(info.name, WestonGetUbootIsBestmode());
354 ctx->mode_update = true;
355 ctx->mode_changed = true;
356 }
357 return 0;
358}
359
360static int weston_get_property(int id, const char *name, char *buf)
361{
362 weston_ctx *ctx = weston_get_ctx();
363 int value = 0;
364
leng.fang3e8a4b52024-07-24 14:51:30 +0800365 if (!ctx)
366 return 0;
367
leng.fang91856072024-06-07 14:12:54 +0800368 if (!ctx->crtc || !ctx->conn)
369 return 0;
370
371 if (ctx->crtc->crtc_id == id)
372 value = weston_get_crtc_property(name);
373
374 if (ctx->conn->connector_id == id)
375 value = weston_get_connector_property(name);
376
377 snprintf(buf, MAX_BUF_LEN, "%d", value);
378 return 0;
379}
380
381static int weston_set_property(int id, const char *name, int value)
382{
383 prop_info *info;
384 weston_ctx *ctx = weston_get_ctx();
385
leng.fang3e8a4b52024-07-24 14:51:30 +0800386 if (!ctx)
387 return 0;
388
leng.fang91856072024-06-07 14:12:54 +0800389 wl_list_for_each(info, &ctx->prop_list, link) {
390 if (!strcmp(name, info->name) && info->item_id == id) {
391 MESON_LOGD("name: %s, id: %d, prop: %d, value: %d\n",
392 name, id, info->prop_id, value);
393 info->value = value;
394 info->need_change = 1;
395 ctx->prop_changed = true;
396 break;
397 }
398 }
399
400 return 0;
401}
402
403static bool weston_set_colorattribute(const char *attr)
404{
405 weston_ctx *ctx = weston_get_ctx();
406 int depth = -1, value = -1; // default none
407
408 if ( attr && strlen(attr) > 3 ) {
409 if ( strstr (attr, "rgb") )
410 value = 0;
411 else if ( strstr (attr, "422") )
412 value = 1;
413 else if ( strstr (attr, "444") )
414 value = 2;
415 else if ( strstr (attr, "420") )
416 value = 3;
417 sscanf(attr + 4, "%dbit", &depth);
418 }
419 if (ctx && ctx->conn && ctx->conn->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
420 weston_set_property(ctx->conn->connector_id, "color_space", value);
421 weston_set_property(ctx->conn->connector_id, "color_depth", depth);
422 }
423 return 0;
424}
425
426void weston_set_scaling_position(int x, int y, int w, int h)
427{
428 weston_ctx *ctx = weston_get_ctx();
429 const char *value = bootenv_get("scaling");
leng.fang3e8a4b52024-07-24 14:51:30 +0800430 int scaling = -1;
leng.fang91856072024-06-07 14:12:54 +0800431
432 if (value)
433 scaling = atoi(value);
434
leng.fangb1081a32024-06-25 14:41:37 +0800435 if (ctx && ctx->scaling != scaling)
436 ctx->scaling = scaling;
leng.fang91856072024-06-07 14:12:54 +0800437}
438
439CompositorFunctionCallBack callback = {
440 .get_mode = weston_get_mode,
441 .set_mode = weston_set_mode,
442 .set_colorattribute = weston_set_colorattribute,
443 .get_property = weston_get_property,
444 .set_property = weston_set_property,
445 .set_scaling_position = weston_set_scaling_position,
446};
447
leng.fangb1081a32024-06-25 14:41:37 +0800448static char *get_color_space_by_value(int value)
449{
450 char *str;
451
452 switch ( value ) {
453 case 0:
454 str = "rgb";
455 break;
456 case 1:
457 str = "422";
458 break;
459 case 2:
460 str = "444";
461 break;
462 case 3:
463 default:
464 str = "420";
465 break;
466 }
467 return str;
468}
469
470static int get_property_value(char *name)
471{
472 prop_info *info;
473 weston_ctx *ctx = weston_get_ctx();
474
leng.fang3e8a4b52024-07-24 14:51:30 +0800475 if (!ctx)
476 return 0;
477
leng.fangb1081a32024-06-25 14:41:37 +0800478 wl_list_for_each(info, &ctx->prop_list, link) {
479 if (!strcmp(name, info->name)) {
480 if (info->need_change == 1)
481 return info->value;
482 }
483 }
484 return -1;
485}
486
487static int get_id_by_name(const char *name)
488{
489 prop_info *info;
490 weston_ctx *ctx = weston_get_ctx();
491
leng.fang3e8a4b52024-07-24 14:51:30 +0800492 if (!ctx)
493 return -1;
494
leng.fangb1081a32024-06-25 14:41:37 +0800495 wl_list_for_each(info, &ctx->prop_list, link) {
496 if (!strcmp(name, info->name))
497 return info->item_id;
498 }
499 return -1;
500}
501
leng.fang3e8a4b52024-07-24 14:51:30 +0800502static int mode_policy_parse_other(weston_ctx *ctx, const char *name, int value)
leng.fangb1081a32024-06-25 14:41:37 +0800503{
leng.fangb1081a32024-06-25 14:41:37 +0800504 char attrvalue[32] = { 0 };
505
506 if (STRCMPS(name, "scaling") == 0) {
507 if (ctx && ctx->scaling != value)
508 ctx->scaling = value;
509
510 sprintf(attrvalue, "%d", value);
511 bootenv_update("scaling", attrvalue);
512 return 0;
513 }
514 return -1;
515}
516
leng.fang13fd3982024-07-03 19:09:58 +0800517static void set_color_attribute(char *space, int depth)
518{
leng.fang13fd3982024-07-03 19:09:58 +0800519 char attrvalue[32] = { 0 };
520 char mode[] = { 0 };
521
522 sprintf(attrvalue, "%s,%dbit", space, depth);
523 setColorSpace(attrvalue);
524 weston_get_mode(mode);
525 setBootConfig(mode, false);
526}
527
leng.fangb1081a32024-06-25 14:41:37 +0800528int mode_policy_set_property(const char *name, int value)
529{
530 char attrvalue[32] = { 0 };
531 int color_space = 0;
532 int color_depth = 0;
533 int id = get_id_by_name(name);
leng.fang3e8a4b52024-07-24 14:51:30 +0800534 weston_ctx *ctx = weston_get_ctx();
leng.fangb1081a32024-06-25 14:41:37 +0800535 MESON_LOGI("id: %d, name: %s, value: %d", id, name, value);
536
leng.fang3e8a4b52024-07-24 14:51:30 +0800537 if (!ctx)
538 return 0;
539
540 initModePolicyFun(ctx->crtc, ctx->conn, callback);
leng.fangb1081a32024-06-25 14:41:37 +0800541 if (value < 0 || id < 0)
leng.fang3e8a4b52024-07-24 14:51:30 +0800542 return mode_policy_parse_other(ctx, name, value);
leng.fangb1081a32024-06-25 14:41:37 +0800543
544 if (strncmp(name, "dv_mode", sizeof("dv_mode")) == 0) {
545 setDvMode(value == 0 ? 1 : (value == 1 ? 2 : 0));
546 return 0;
547 } else if (strncmp(name, "color_depth", sizeof("color_depth")) == 0) {
548 color_space = get_property_value("color_space");
549 if (color_space >= 0) {
leng.fang13fd3982024-07-03 19:09:58 +0800550 set_color_attribute(get_color_space_by_value(color_space), value);
leng.fangb1081a32024-06-25 14:41:37 +0800551 return 0;
552 }
553 } else if (strncmp(name, "color_space", sizeof("color_space")) == 0) {
554 color_depth = get_property_value("color_depth");
555 if (color_depth >= 0) {
leng.fang13fd3982024-07-03 19:09:58 +0800556 set_color_attribute(get_color_space_by_value(value), color_depth);
leng.fangb1081a32024-06-25 14:41:37 +0800557 return 0;
558 }
559 } else if (strncmp(name, "meson.crtc.hdr_policy", sizeof("meson.crtc.hdr_policy")) == 0) {
560 sprintf(attrvalue, "%d", value);
561 bootenv_update("hdr_policy", attrvalue);
562 }
563
564 return weston_set_property(id, name, value);
565}
566
567int mode_policy_get_scaling()
568{
569 weston_ctx *ctx = weston_get_ctx();
570
leng.fang3e8a4b52024-07-24 14:51:30 +0800571 if (!ctx)
572 return 100;
573
leng.fangb1081a32024-06-25 14:41:37 +0800574 if (ctx->scaling < 0)
575 return 100;
576
577 return ctx->scaling;
578}
579
leng.fang13fd3982024-07-03 19:09:58 +0800580static struct weston_mode
581drm_mode_to_weston_mode(drmModeModeInfoPtr info)
582{
583 struct weston_mode m;
584
585 m.width = info->hdisplay;
586 m.height = info->vdisplay;
587 //mhz:refresh * 1000
588 m.refresh = info->vrefresh * 1000;
589 //hack: use weston_mode's flags as drm_mode's flags.
590 m.flags = info->flags;
591 m.aspect_ratio = WESTON_MODE_PIC_AR_NONE;
592
593 return m;
594}
595
leng.fang91856072024-06-07 14:12:54 +0800596static drmModeCrtc *weston_get_crtc_for_conn(int drm_fd, drmModeConnector *conn)
597{
598 drmModeEncoder *encoder;
599 drmModeCrtc *crtc = NULL;
chen.wang19f2f82b2024-07-16 11:43:59 +0000600 drmModeRes *res = 0;
601 int i, j, k;
leng.fang91856072024-06-07 14:12:54 +0800602 /* Get the current mode on the crtc that's currently driving
603 * this connector. */
chen.wang19f2f82b2024-07-16 11:43:59 +0000604 res = drmModeGetResources(drm_fd);
605 if ( res ) {
606 for (i= 0; i < res->count_encoders; ++i ) {
607 uint32_t crtcId= 0;
608 bool found= false;
609 encoder = drmModeGetEncoder(drm_fd, res->encoders[i]);
610 if (encoder && conn && (encoder->encoder_id == conn->encoder_id)) {
611 found = true;
612 break;
613 }
614 for (j = 0; j < res->count_crtcs; j++) {
615 if (encoder->possible_crtcs & (1 << j)) {
616 crtcId= res->crtcs[j];
617 for (k = 0; k < res->count_crtcs; k++) {
618 if (res->crtcs[k] == crtcId) {
619 drmModeFreeEncoder(encoder);
620 encoder= drmModeGetEncoder(drm_fd, res->encoders[k]);
621 encoder->crtc_id= crtcId;
622 MESON_LOGD("got enc %p crtc id %d", drm_fd, crtcId);
623 found = true;
624 break;
625 }
626 }
627 if (found) {
628 break;
629 }
630 }
631 }
632 if (!found) {
633 drmModeFreeEncoder(encoder);
634 encoder= 0;
635 }
636 if (found) {
637 break;
638 }
639 }
640 if (encoder != NULL) {
641 crtc = drmModeGetCrtc(drm_fd, encoder->crtc_id);
642 drmModeFreeEncoder(encoder);
643 }
644 drmModeFreeResources( res );
645 res = 0;
646 } else {
647 MESON_LOGD("unable to get card resources");
leng.fang91856072024-06-07 14:12:54 +0800648 }
649 return crtc;
650}
651
leng.fang3e8a4b52024-07-24 14:51:30 +0800652void mode_policy_set_head(struct weston_head *head)
leng.fang91856072024-06-07 14:12:54 +0800653{
leng.fang3e8a4b52024-07-24 14:51:30 +0800654 weston_ctx_list *ctx_list = weston_get_ctx_list();
655 ctx_list->head = head;
656}
leng.fang91856072024-06-07 14:12:54 +0800657
leng.fang3e8a4b52024-07-24 14:51:30 +0800658void mode_policy_set_output(struct weston_output *output)
659{
660 weston_ctx_list *ctx_list = weston_get_ctx_list();
661 weston_ctx *ctx, *tmp;
leng.fang91856072024-06-07 14:12:54 +0800662
leng.fang3e8a4b52024-07-24 14:51:30 +0800663 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
664 if (ctx->head && ctx->head->output == output) {
665 mode_policy_set_head(ctx->head);
666 break;
leng.fange9d800e2024-07-12 13:31:59 +0800667 }
leng.fang91856072024-06-07 14:12:54 +0800668 }
669}
670
leng.fang3e8a4b52024-07-24 14:51:30 +0800671static void mode_policy_update_ctx(weston_ctx *ctx,
672 struct weston_head *head, int fd, drmModeConnector *conn)
leng.fang91856072024-06-07 14:12:54 +0800673{
leng.fang3e8a4b52024-07-24 14:51:30 +0800674 drmModeCrtc *crtc = NULL;
675 bool changed = false;
676
677 if (!ctx)
678 return;
679
680 crtc = weston_get_crtc_for_conn(fd, conn);
681 if (!crtc)
682 return;
683
684 if ((ctx->crtc && ctx->crtc->crtc_id != crtc->crtc_id) || !ctx->crtc)
685 changed = true;
686
leng.fang91856072024-06-07 14:12:54 +0800687 if (ctx->crtc)
688 drmModeFreeCrtc(ctx->crtc);
689 ctx->drm_fd = fd;
690 ctx->crtc = crtc;
691 ctx->conn = conn;
leng.fang3e8a4b52024-07-24 14:51:30 +0800692 ctx->head = head;
693 if (changed) {
694 ctx->current_mode = drm_mode_to_weston_mode(&ctx->crtc->mode);
695 weston_prop_list_init(ctx);
696 weston_add_property(ctx, ctx->crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
697 weston_add_property(ctx, ctx->conn->connector_id, DRM_MODE_OBJECT_CONNECTOR);
698 }
699}
700
701void init_mode_policy_without_mode(struct weston_head *head, int fd, drmModeConnector *conn)
702{
703 weston_ctx_list *ctx_list = weston_get_ctx_list();
704 weston_ctx *ctx;
705
706 mode_policy_set_head(head);
707 ctx = weston_get_ctx();
708 if (!ctx) {
709 ctx = (weston_ctx *)calloc(1, sizeof(*ctx));
710 ctx->scaling = -1;
711 wl_list_init(&ctx->prop_list);
712 wl_list_insert(&ctx_list->ctx_list, &ctx->link);
713 }
714 mode_policy_update_ctx(ctx, head, fd, conn);
leng.fang91856072024-06-07 14:12:54 +0800715}
716
leng.fang13fd3982024-07-03 19:09:58 +0800717static bool need_mode_changed(char *name)
718{
719 int size = sizeof(prop_changed_and_mode) / sizeof(prop_changed_and_mode[0]);
720 int i;
721
722 for (i = 0; i < size; i++) {
723 if (STRCMPS(name, prop_changed_and_mode[i]) == 0)
724 return true;
725 }
726 return false;
727}
728
729int mode_policy_add_prop(drmModeAtomicReq *req, bool mode_changed)
leng.fang91856072024-06-07 14:12:54 +0800730{
leng.fang91856072024-06-07 14:12:54 +0800731 prop_info *info;
732 int err = 0, ret = 0;
leng.fangb1081a32024-06-25 14:41:37 +0800733 int count = 0;
leng.fang3e8a4b52024-07-24 14:51:30 +0800734 weston_ctx_list * ctx_list = weston_get_ctx_list();
735 weston_ctx *ctx, *tmp;
leng.fang91856072024-06-07 14:12:54 +0800736
leng.fang3e8a4b52024-07-24 14:51:30 +0800737 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
738 wl_list_for_each(info, &ctx->prop_list, link) {
739 if (info->need_change) {
740 if (need_mode_changed(info->name) && !mode_changed)
741 continue;
leng.fang13fd3982024-07-03 19:09:58 +0800742
leng.fang3e8a4b52024-07-24 14:51:30 +0800743 err = drmModeAtomicAddProperty(req, info->item_id, info->prop_id, info->value);
744 if (!err)
745 MESON_LOGE("drmModeAtomicAddProperty %s fail: %d(%d)\n",
746 info->name, err, errno);
747 info->need_change = 0;
748 ret |= (err <= 0) ? -1 : 0;
749 if (!ret)
750 count++;
751 ctx->need_update_hdmi_param = true;
752 }
leng.fang91856072024-06-07 14:12:54 +0800753 }
754 }
leng.fangb1081a32024-06-25 14:41:37 +0800755 return ret >= 0 ? count : ret;
leng.fang91856072024-06-07 14:12:54 +0800756}
757
leng.fang13fd3982024-07-03 19:09:58 +0800758void mode_policy_set_hotplug(int plug, bool force)
leng.fang91856072024-06-07 14:12:54 +0800759{
leng.fang3e8a4b52024-07-24 14:51:30 +0800760 weston_ctx_list *ctx_list = weston_get_ctx_list();
leng.fang13fd3982024-07-03 19:09:58 +0800761
762 if (force) {
leng.fang3e8a4b52024-07-24 14:51:30 +0800763 ctx_list->hotplug = plug;
leng.fang13fd3982024-07-03 19:09:58 +0800764 } else {
leng.fang3e8a4b52024-07-24 14:51:30 +0800765 if (ctx_list->hotplug & plug)
766 ctx_list->hotplug = plug;
leng.fang13fd3982024-07-03 19:09:58 +0800767 }
leng.fang91856072024-06-07 14:12:54 +0800768}
769
770void mode_policy_update_mode(struct weston_mode *mode)
771{
772 weston_ctx *ctx = weston_get_ctx();
leng.fang3e8a4b52024-07-24 14:51:30 +0800773
774 if (!ctx)
775 return;
776
leng.fang91856072024-06-07 14:12:54 +0800777 if (mode)
778 ctx->current_mode = *mode;
leng.fang13fd3982024-07-03 19:09:58 +0800779 else if (ctx->mode_changed)
leng.fang91856072024-06-07 14:12:54 +0800780 ctx->current_mode = ctx->next_mode;
781 MESON_LOGD("curr: %dx%d@%d",
782 ctx->current_mode.width,
783 ctx->current_mode.height,
784 ctx->current_mode.refresh);
785}
786
787struct weston_mode *mode_policy_choose_mode(struct weston_mode *mode)
788{
leng.fang3e8a4b52024-07-24 14:51:30 +0800789 weston_ctx_list * ctx_list = weston_get_ctx_list();
leng.fang91856072024-06-07 14:12:54 +0800790 weston_ctx *ctx = weston_get_ctx();
791 char name[32] = { 0 };
leng.fang91856072024-06-07 14:12:54 +0800792
leng.fang3e8a4b52024-07-24 14:51:30 +0800793 if (!ctx)
794 return NULL;
795
796 initModePolicyFun(ctx->crtc, ctx->conn, callback);
leng.fang91856072024-06-07 14:12:54 +0800797 if (mode) {
798 if (get_mode_name_for_weston_mode(ctx, mode, name))
799 setActiveConfig(name);
800 } else {
leng.fang3e8a4b52024-07-24 14:51:30 +0800801 if (ctx_list->hotplug & (AML_WESTON_HOTPLUG_PLUG | AML_WESTON_HOTPLUG_UNPLUG))
802 onHotplug(ctx_list->hotplug & AML_WESTON_HOTPLUG_PLUG);
803 else if (ctx_list->hotplug & (AML_WESTON_HOTPLUG_BOOT | AML_WESTON_HOTPLUG_SET))
leng.fang91856072024-06-07 14:12:54 +0800804 initModePolicy(NULL, NULL, callback);
leng.fang3e8a4b52024-07-24 14:51:30 +0800805 ctx_list->hotplug = AML_WESTON_HOTPLUG_INIT;
leng.fang91856072024-06-07 14:12:54 +0800806 }
807 if (ctx->mode_update)
808 return &ctx->next_mode;
leng.fang13fd3982024-07-03 19:09:58 +0800809 return &ctx->current_mode;
leng.fang91856072024-06-07 14:12:54 +0800810}
811
leng.fangb1081a32024-06-25 14:41:37 +0800812void mode_policy_update_bestmode(bool bestmode)
813{
814 bootenv_update("is.bestmode", bestmode ? "true" : "false");
815}
816
leng.fang13fd3982024-07-03 19:09:58 +0800817void mode_policy_update_modeset(bool *state, bool *modeset)
818{
leng.fang3e8a4b52024-07-24 14:51:30 +0800819 weston_ctx_list * ctx_list = weston_get_ctx_list();
820 weston_ctx *ctx, *tmp;
821 bool mode_changed = false;
leng.fang13fd3982024-07-03 19:09:58 +0800822
leng.fang3e8a4b52024-07-24 14:51:30 +0800823
824 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
825 if (ctx->mode_changed)
826 mode_changed = true;
827 }
828
829 MESON_LOGV("state: %d, modeset: %d, mode_changed: %d", *state, *modeset, mode_changed);
830 if (mode_changed) {
leng.fang13fd3982024-07-03 19:09:58 +0800831 if (!*state)
832 *state = true;
833 if (!*modeset)
834 *modeset = true;
835 }
836}
837
leng.fange9d800e2024-07-12 13:31:59 +0800838void mode_policy_resume()
839{
840 weston_ctx *ctx = weston_get_ctx();
841 int flag;
842
leng.fang3e8a4b52024-07-24 14:51:30 +0800843 if (!ctx)
844 return;
845
leng.fange9d800e2024-07-12 13:31:59 +0800846 flag = (ctx->conn &&
847 (ctx->conn->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
848 ctx->conn->connector_type == DRM_MODE_CONNECTOR_TV)) ?
849 AML_WESTON_HOTPLUG_PLUG : AML_WESTON_HOTPLUG_SET;
850
851 mode_policy_set_hotplug(flag, true);
852}
853
leng.fang91856072024-06-07 14:12:54 +0800854static void * wstUpdatenvThread(void *arg )
855{
856 long long delay = 16667LL;
leng.fang3e8a4b52024-07-24 14:51:30 +0800857 weston_ctx_list *ctx_list = (weston_ctx_list *)arg;
858 weston_ctx *ctx, *tmp;
leng.fang13fd3982024-07-03 19:09:58 +0800859
leng.fang3e8a4b52024-07-24 14:51:30 +0800860 while (!ctx_list->update_env_thread_stop_requested)
leng.fang91856072024-06-07 14:12:54 +0800861 {
leng.fang3e8a4b52024-07-24 14:51:30 +0800862 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
863 if ((ctx->mode_changed && !ctx->prop_changed) ||
864 (ctx->prop_changed && ctx->need_update_hdmi_param))
865 {
866 weston_log("%s[%d]\n", __func__, __LINE__);
867 initModePolicyFun(ctx->crtc, ctx->conn, callback);
868 updateEnv();
869 ctx->need_update_hdmi_param = false;
870 ctx->mode_changed = false;
871 ctx->prop_changed = false;
872 }
leng.fang91856072024-06-07 14:12:54 +0800873 }
874 usleep( delay );
875 }
876 MESON_LOGD("update env thread exit");
877 return NULL;
878}
879
880void weston_start_update_env_thread()
881{
882 int rc;
leng.fang3e8a4b52024-07-24 14:51:30 +0800883 weston_ctx_list *ctx_list = weston_get_ctx_list();
leng.fang91856072024-06-07 14:12:54 +0800884
leng.fang3e8a4b52024-07-24 14:51:30 +0800885 ctx_list->update_env_thread_stop_requested = false;
886 rc = pthread_create(&ctx_list->update_env_thread_id, NULL, wstUpdatenvThread, ctx_list);
leng.fang91856072024-06-07 14:12:54 +0800887 if ( rc )
888 MESON_LOGE("unable to start updatenv thread: rc %d errno %d", rc, errno);
889}