blob: a01653ad331102cc2e66408257f407b1f3906907 [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
leng.fang3c0ab6d2024-08-01 16:29:00 +0800287 if (!strcmp(conn->modes[i].name, mode))
288 miBest = i;
289
leng.fang91856072024-06-07 14:12:54 +0800290 if ( (conn->modes[i].hdisplay == width) &&
291 (conn->modes[i].vdisplay == height) ) {
292 bool modeIsInterlaced = (conn->modes[i].flags & DRM_MODE_FLAG_INTERLACE);
293 if ( modeIsInterlaced != interlaced )
294 continue;
295
296 if ( useBestRate ) {
297 if ( conn->modes[i].vrefresh > rateBest ) {
298 rateBest = conn->modes[i].vrefresh;
299 miBest = i;
300 }
301 } else if ( conn->modes[i].vrefresh == rate ) {
302 miBest = i;
303 break;
304 }
305 }
306 }
307
308 if ( miBest >= 0 ) {
309 *out_mode = conn->modes[miBest];
310
311 MESON_LOGI("%s: choosing output mode: %dx%dx%d (%s) flags 0x%x",
312 __func__,
313 out_mode->hdisplay,
314 out_mode->vdisplay,
315 out_mode->vrefresh,
316 out_mode->name,
317 out_mode->flags );
318
319 result= true;
320 } else {
321 MESON_LOGE("%s: failed to find a mode matching (%s)", __func__, mode);
322 }
323
324 drmModeFreeConnector( conn );
325 } else {
326 MESON_LOGE("%s: unable to get connector for card", __func__);
327 }
328 drmModeFreeResources(res);
329 } else {
330 MESON_LOGE("%s: unable to get card resources", __func__);
331 }
332 } else {
333 MESON_LOGE("%s: no open device", __func__);
334 }
335 } else {
336 MESON_LOGE("%s: unable to parse mode (%s)", __func__, mode);
337 }
338 }
339
340 return result;
341}
342
343static bool weston_set_mode(const char *mode)
344{
345 weston_ctx *ctx = weston_get_ctx();
346 drmModeModeInfo info = {0};
347
leng.fang3e8a4b52024-07-24 14:51:30 +0800348 if (!ctx)
349 return false;
350
leng.fang91856072024-06-07 14:12:54 +0800351 if (westonGetDrmModeInfoByName(ctx, mode, &info)) {
352 ctx->next_mode.width = info.hdisplay;
353 ctx->next_mode.height = info.vdisplay;
354 ctx->next_mode.refresh = info.vrefresh * 1000;
355 ctx->next_mode.flags = info.flags;
356 setBootConfig(info.name, WestonGetUbootIsBestmode());
357 ctx->mode_update = true;
358 ctx->mode_changed = true;
359 }
360 return 0;
361}
362
363static int weston_get_property(int id, const char *name, char *buf)
364{
365 weston_ctx *ctx = weston_get_ctx();
366 int value = 0;
367
leng.fang3e8a4b52024-07-24 14:51:30 +0800368 if (!ctx)
369 return 0;
370
leng.fang91856072024-06-07 14:12:54 +0800371 if (!ctx->crtc || !ctx->conn)
372 return 0;
373
374 if (ctx->crtc->crtc_id == id)
375 value = weston_get_crtc_property(name);
376
377 if (ctx->conn->connector_id == id)
378 value = weston_get_connector_property(name);
379
380 snprintf(buf, MAX_BUF_LEN, "%d", value);
381 return 0;
382}
383
384static int weston_set_property(int id, const char *name, int value)
385{
386 prop_info *info;
387 weston_ctx *ctx = weston_get_ctx();
388
leng.fang3e8a4b52024-07-24 14:51:30 +0800389 if (!ctx)
390 return 0;
391
leng.fang91856072024-06-07 14:12:54 +0800392 wl_list_for_each(info, &ctx->prop_list, link) {
393 if (!strcmp(name, info->name) && info->item_id == id) {
394 MESON_LOGD("name: %s, id: %d, prop: %d, value: %d\n",
395 name, id, info->prop_id, value);
396 info->value = value;
397 info->need_change = 1;
398 ctx->prop_changed = true;
399 break;
400 }
401 }
402
403 return 0;
404}
405
406static bool weston_set_colorattribute(const char *attr)
407{
408 weston_ctx *ctx = weston_get_ctx();
409 int depth = -1, value = -1; // default none
410
411 if ( attr && strlen(attr) > 3 ) {
412 if ( strstr (attr, "rgb") )
413 value = 0;
414 else if ( strstr (attr, "422") )
415 value = 1;
416 else if ( strstr (attr, "444") )
417 value = 2;
418 else if ( strstr (attr, "420") )
419 value = 3;
420 sscanf(attr + 4, "%dbit", &depth);
421 }
422 if (ctx && ctx->conn && ctx->conn->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
423 weston_set_property(ctx->conn->connector_id, "color_space", value);
424 weston_set_property(ctx->conn->connector_id, "color_depth", depth);
425 }
426 return 0;
427}
428
429void weston_set_scaling_position(int x, int y, int w, int h)
430{
431 weston_ctx *ctx = weston_get_ctx();
432 const char *value = bootenv_get("scaling");
leng.fang3e8a4b52024-07-24 14:51:30 +0800433 int scaling = -1;
leng.fang91856072024-06-07 14:12:54 +0800434
435 if (value)
436 scaling = atoi(value);
437
leng.fangb1081a32024-06-25 14:41:37 +0800438 if (ctx && ctx->scaling != scaling)
439 ctx->scaling = scaling;
leng.fang91856072024-06-07 14:12:54 +0800440}
441
442CompositorFunctionCallBack callback = {
443 .get_mode = weston_get_mode,
444 .set_mode = weston_set_mode,
445 .set_colorattribute = weston_set_colorattribute,
446 .get_property = weston_get_property,
447 .set_property = weston_set_property,
448 .set_scaling_position = weston_set_scaling_position,
449};
450
leng.fangb1081a32024-06-25 14:41:37 +0800451static char *get_color_space_by_value(int value)
452{
453 char *str;
454
455 switch ( value ) {
456 case 0:
457 str = "rgb";
458 break;
459 case 1:
460 str = "422";
461 break;
462 case 2:
463 str = "444";
464 break;
465 case 3:
466 default:
467 str = "420";
468 break;
469 }
470 return str;
471}
472
473static int get_property_value(char *name)
474{
475 prop_info *info;
476 weston_ctx *ctx = weston_get_ctx();
477
leng.fang3e8a4b52024-07-24 14:51:30 +0800478 if (!ctx)
479 return 0;
480
leng.fangb1081a32024-06-25 14:41:37 +0800481 wl_list_for_each(info, &ctx->prop_list, link) {
482 if (!strcmp(name, info->name)) {
483 if (info->need_change == 1)
484 return info->value;
485 }
486 }
487 return -1;
488}
489
490static int get_id_by_name(const char *name)
491{
492 prop_info *info;
493 weston_ctx *ctx = weston_get_ctx();
494
leng.fang3e8a4b52024-07-24 14:51:30 +0800495 if (!ctx)
496 return -1;
497
leng.fangb1081a32024-06-25 14:41:37 +0800498 wl_list_for_each(info, &ctx->prop_list, link) {
499 if (!strcmp(name, info->name))
500 return info->item_id;
501 }
502 return -1;
503}
504
leng.fang3e8a4b52024-07-24 14:51:30 +0800505static int mode_policy_parse_other(weston_ctx *ctx, const char *name, int value)
leng.fangb1081a32024-06-25 14:41:37 +0800506{
leng.fangb1081a32024-06-25 14:41:37 +0800507 char attrvalue[32] = { 0 };
508
509 if (STRCMPS(name, "scaling") == 0) {
510 if (ctx && ctx->scaling != value)
511 ctx->scaling = value;
512
513 sprintf(attrvalue, "%d", value);
514 bootenv_update("scaling", attrvalue);
515 return 0;
516 }
517 return -1;
518}
519
leng.fang13fd3982024-07-03 19:09:58 +0800520static void set_color_attribute(char *space, int depth)
521{
leng.fang13fd3982024-07-03 19:09:58 +0800522 char attrvalue[32] = { 0 };
523 char mode[] = { 0 };
524
525 sprintf(attrvalue, "%s,%dbit", space, depth);
526 setColorSpace(attrvalue);
527 weston_get_mode(mode);
528 setBootConfig(mode, false);
529}
530
leng.fangb1081a32024-06-25 14:41:37 +0800531int mode_policy_set_property(const char *name, int value)
532{
533 char attrvalue[32] = { 0 };
534 int color_space = 0;
535 int color_depth = 0;
536 int id = get_id_by_name(name);
leng.fang3e8a4b52024-07-24 14:51:30 +0800537 weston_ctx *ctx = weston_get_ctx();
leng.fangb1081a32024-06-25 14:41:37 +0800538 MESON_LOGI("id: %d, name: %s, value: %d", id, name, value);
539
leng.fang3e8a4b52024-07-24 14:51:30 +0800540 if (!ctx)
541 return 0;
542
leng.fang3c0ab6d2024-08-01 16:29:00 +0800543 if (!ctx->conn || ctx->conn->connector_type != DRM_MODE_CONNECTOR_HDMIA) {
544 MESON_LOGW("isn't hdmi, don't set property");
545 return 0;
546 }
547
leng.fang3e8a4b52024-07-24 14:51:30 +0800548 initModePolicyFun(ctx->crtc, ctx->conn, callback);
leng.fangb1081a32024-06-25 14:41:37 +0800549 if (value < 0 || id < 0)
leng.fang3e8a4b52024-07-24 14:51:30 +0800550 return mode_policy_parse_other(ctx, name, value);
leng.fangb1081a32024-06-25 14:41:37 +0800551
552 if (strncmp(name, "dv_mode", sizeof("dv_mode")) == 0) {
553 setDvMode(value == 0 ? 1 : (value == 1 ? 2 : 0));
554 return 0;
555 } else if (strncmp(name, "color_depth", sizeof("color_depth")) == 0) {
556 color_space = get_property_value("color_space");
557 if (color_space >= 0) {
leng.fang13fd3982024-07-03 19:09:58 +0800558 set_color_attribute(get_color_space_by_value(color_space), value);
leng.fangb1081a32024-06-25 14:41:37 +0800559 return 0;
560 }
561 } else if (strncmp(name, "color_space", sizeof("color_space")) == 0) {
562 color_depth = get_property_value("color_depth");
563 if (color_depth >= 0) {
leng.fang13fd3982024-07-03 19:09:58 +0800564 set_color_attribute(get_color_space_by_value(value), color_depth);
leng.fangb1081a32024-06-25 14:41:37 +0800565 return 0;
566 }
567 } else if (strncmp(name, "meson.crtc.hdr_policy", sizeof("meson.crtc.hdr_policy")) == 0) {
568 sprintf(attrvalue, "%d", value);
569 bootenv_update("hdr_policy", attrvalue);
570 }
571
572 return weston_set_property(id, name, value);
573}
574
575int mode_policy_get_scaling()
576{
577 weston_ctx *ctx = weston_get_ctx();
578
leng.fang3e8a4b52024-07-24 14:51:30 +0800579 if (!ctx)
580 return 100;
581
leng.fangb1081a32024-06-25 14:41:37 +0800582 if (ctx->scaling < 0)
583 return 100;
584
585 return ctx->scaling;
586}
587
leng.fang13fd3982024-07-03 19:09:58 +0800588static struct weston_mode
589drm_mode_to_weston_mode(drmModeModeInfoPtr info)
590{
591 struct weston_mode m;
592
593 m.width = info->hdisplay;
594 m.height = info->vdisplay;
595 //mhz:refresh * 1000
596 m.refresh = info->vrefresh * 1000;
597 //hack: use weston_mode's flags as drm_mode's flags.
598 m.flags = info->flags;
599 m.aspect_ratio = WESTON_MODE_PIC_AR_NONE;
600
601 return m;
602}
603
leng.fang5ec9b6c2024-07-29 14:25:00 +0800604drmModeCrtc *weston_get_crtc_for_conn(int drm_fd, drmModeConnector *conn)
leng.fang91856072024-06-07 14:12:54 +0800605{
606 drmModeEncoder *encoder;
607 drmModeCrtc *crtc = NULL;
chen.wang19f2f82b2024-07-16 11:43:59 +0000608 drmModeRes *res = 0;
609 int i, j, k;
leng.fang91856072024-06-07 14:12:54 +0800610 /* Get the current mode on the crtc that's currently driving
611 * this connector. */
chen.wang19f2f82b2024-07-16 11:43:59 +0000612 res = drmModeGetResources(drm_fd);
613 if ( res ) {
614 for (i= 0; i < res->count_encoders; ++i ) {
615 uint32_t crtcId= 0;
616 bool found= false;
617 encoder = drmModeGetEncoder(drm_fd, res->encoders[i]);
618 if (encoder && conn && (encoder->encoder_id == conn->encoder_id)) {
619 found = true;
620 break;
621 }
622 for (j = 0; j < res->count_crtcs; j++) {
623 if (encoder->possible_crtcs & (1 << j)) {
624 crtcId= res->crtcs[j];
625 for (k = 0; k < res->count_crtcs; k++) {
626 if (res->crtcs[k] == crtcId) {
627 drmModeFreeEncoder(encoder);
628 encoder= drmModeGetEncoder(drm_fd, res->encoders[k]);
629 encoder->crtc_id= crtcId;
630 MESON_LOGD("got enc %p crtc id %d", drm_fd, crtcId);
631 found = true;
632 break;
633 }
634 }
635 if (found) {
636 break;
637 }
638 }
639 }
640 if (!found) {
641 drmModeFreeEncoder(encoder);
642 encoder= 0;
643 }
644 if (found) {
645 break;
646 }
647 }
648 if (encoder != NULL) {
649 crtc = drmModeGetCrtc(drm_fd, encoder->crtc_id);
650 drmModeFreeEncoder(encoder);
651 }
652 drmModeFreeResources( res );
653 res = 0;
654 } else {
655 MESON_LOGD("unable to get card resources");
leng.fang91856072024-06-07 14:12:54 +0800656 }
657 return crtc;
658}
659
leng.fang3e8a4b52024-07-24 14:51:30 +0800660void mode_policy_set_head(struct weston_head *head)
leng.fang91856072024-06-07 14:12:54 +0800661{
leng.fang3e8a4b52024-07-24 14:51:30 +0800662 weston_ctx_list *ctx_list = weston_get_ctx_list();
663 ctx_list->head = head;
664}
leng.fang91856072024-06-07 14:12:54 +0800665
leng.fang3e8a4b52024-07-24 14:51:30 +0800666void mode_policy_set_output(struct weston_output *output)
667{
668 weston_ctx_list *ctx_list = weston_get_ctx_list();
669 weston_ctx *ctx, *tmp;
leng.fang91856072024-06-07 14:12:54 +0800670
leng.fang3e8a4b52024-07-24 14:51:30 +0800671 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
672 if (ctx->head && ctx->head->output == output) {
673 mode_policy_set_head(ctx->head);
674 break;
leng.fange9d800e2024-07-12 13:31:59 +0800675 }
leng.fang91856072024-06-07 14:12:54 +0800676 }
677}
678
leng.fang3e8a4b52024-07-24 14:51:30 +0800679static void mode_policy_update_ctx(weston_ctx *ctx,
680 struct weston_head *head, int fd, drmModeConnector *conn)
leng.fang91856072024-06-07 14:12:54 +0800681{
leng.fang3e8a4b52024-07-24 14:51:30 +0800682 drmModeCrtc *crtc = NULL;
683 bool changed = false;
684
685 if (!ctx)
686 return;
687
688 crtc = weston_get_crtc_for_conn(fd, conn);
689 if (!crtc)
690 return;
691
692 if ((ctx->crtc && ctx->crtc->crtc_id != crtc->crtc_id) || !ctx->crtc)
693 changed = true;
694
leng.fang91856072024-06-07 14:12:54 +0800695 if (ctx->crtc)
696 drmModeFreeCrtc(ctx->crtc);
697 ctx->drm_fd = fd;
698 ctx->crtc = crtc;
699 ctx->conn = conn;
leng.fang3e8a4b52024-07-24 14:51:30 +0800700 ctx->head = head;
701 if (changed) {
702 ctx->current_mode = drm_mode_to_weston_mode(&ctx->crtc->mode);
703 weston_prop_list_init(ctx);
704 weston_add_property(ctx, ctx->crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
705 weston_add_property(ctx, ctx->conn->connector_id, DRM_MODE_OBJECT_CONNECTOR);
706 }
707}
708
709void init_mode_policy_without_mode(struct weston_head *head, int fd, drmModeConnector *conn)
710{
711 weston_ctx_list *ctx_list = weston_get_ctx_list();
712 weston_ctx *ctx;
713
714 mode_policy_set_head(head);
715 ctx = weston_get_ctx();
716 if (!ctx) {
717 ctx = (weston_ctx *)calloc(1, sizeof(*ctx));
718 ctx->scaling = -1;
719 wl_list_init(&ctx->prop_list);
720 wl_list_insert(&ctx_list->ctx_list, &ctx->link);
721 }
722 mode_policy_update_ctx(ctx, head, fd, conn);
leng.fang91856072024-06-07 14:12:54 +0800723}
724
leng.fang13fd3982024-07-03 19:09:58 +0800725static bool need_mode_changed(char *name)
726{
727 int size = sizeof(prop_changed_and_mode) / sizeof(prop_changed_and_mode[0]);
728 int i;
729
730 for (i = 0; i < size; i++) {
731 if (STRCMPS(name, prop_changed_and_mode[i]) == 0)
732 return true;
733 }
734 return false;
735}
736
leng.fang3c0ab6d2024-08-01 16:29:00 +0800737static void mode_policy_add_mode(weston_ctx_list * ctx_list, bool mode_changed)
738{
739 weston_ctx *ctx, *tmp;
740
741 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
742 if (ctx->mode_changed && mode_changed)
743 ctx->need_update_hdmi_param = true;
744 }
745}
746
leng.fang13fd3982024-07-03 19:09:58 +0800747int mode_policy_add_prop(drmModeAtomicReq *req, bool mode_changed)
leng.fang91856072024-06-07 14:12:54 +0800748{
leng.fang91856072024-06-07 14:12:54 +0800749 prop_info *info;
750 int err = 0, ret = 0;
leng.fangb1081a32024-06-25 14:41:37 +0800751 int count = 0;
leng.fang3e8a4b52024-07-24 14:51:30 +0800752 weston_ctx_list * ctx_list = weston_get_ctx_list();
753 weston_ctx *ctx, *tmp;
leng.fang91856072024-06-07 14:12:54 +0800754
leng.fang3c0ab6d2024-08-01 16:29:00 +0800755 mode_policy_add_mode(ctx_list, mode_changed);
leng.fang3e8a4b52024-07-24 14:51:30 +0800756 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
757 wl_list_for_each(info, &ctx->prop_list, link) {
758 if (info->need_change) {
759 if (need_mode_changed(info->name) && !mode_changed)
760 continue;
leng.fang13fd3982024-07-03 19:09:58 +0800761
leng.fang3e8a4b52024-07-24 14:51:30 +0800762 err = drmModeAtomicAddProperty(req, info->item_id, info->prop_id, info->value);
763 if (!err)
764 MESON_LOGE("drmModeAtomicAddProperty %s fail: %d(%d)\n",
765 info->name, err, errno);
766 info->need_change = 0;
767 ret |= (err <= 0) ? -1 : 0;
768 if (!ret)
769 count++;
770 ctx->need_update_hdmi_param = true;
771 }
leng.fang91856072024-06-07 14:12:54 +0800772 }
773 }
leng.fangb1081a32024-06-25 14:41:37 +0800774 return ret >= 0 ? count : ret;
leng.fang91856072024-06-07 14:12:54 +0800775}
776
leng.fang13fd3982024-07-03 19:09:58 +0800777void mode_policy_set_hotplug(int plug, bool force)
leng.fang91856072024-06-07 14:12:54 +0800778{
leng.fang3e8a4b52024-07-24 14:51:30 +0800779 weston_ctx_list *ctx_list = weston_get_ctx_list();
leng.fang13fd3982024-07-03 19:09:58 +0800780
781 if (force) {
leng.fang3e8a4b52024-07-24 14:51:30 +0800782 ctx_list->hotplug = plug;
leng.fang13fd3982024-07-03 19:09:58 +0800783 } else {
leng.fang3e8a4b52024-07-24 14:51:30 +0800784 if (ctx_list->hotplug & plug)
785 ctx_list->hotplug = plug;
leng.fang13fd3982024-07-03 19:09:58 +0800786 }
leng.fang91856072024-06-07 14:12:54 +0800787}
788
789void mode_policy_update_mode(struct weston_mode *mode)
790{
791 weston_ctx *ctx = weston_get_ctx();
leng.fang3e8a4b52024-07-24 14:51:30 +0800792
793 if (!ctx)
794 return;
795
leng.fang91856072024-06-07 14:12:54 +0800796 if (mode)
797 ctx->current_mode = *mode;
leng.fang13fd3982024-07-03 19:09:58 +0800798 else if (ctx->mode_changed)
leng.fang91856072024-06-07 14:12:54 +0800799 ctx->current_mode = ctx->next_mode;
800 MESON_LOGD("curr: %dx%d@%d",
801 ctx->current_mode.width,
802 ctx->current_mode.height,
803 ctx->current_mode.refresh);
804}
805
806struct weston_mode *mode_policy_choose_mode(struct weston_mode *mode)
807{
leng.fang3e8a4b52024-07-24 14:51:30 +0800808 weston_ctx_list * ctx_list = weston_get_ctx_list();
leng.fang91856072024-06-07 14:12:54 +0800809 weston_ctx *ctx = weston_get_ctx();
810 char name[32] = { 0 };
leng.fang91856072024-06-07 14:12:54 +0800811
leng.fang3e8a4b52024-07-24 14:51:30 +0800812 if (!ctx)
813 return NULL;
814
815 initModePolicyFun(ctx->crtc, ctx->conn, callback);
leng.fang91856072024-06-07 14:12:54 +0800816 if (mode) {
817 if (get_mode_name_for_weston_mode(ctx, mode, name))
818 setActiveConfig(name);
819 } else {
leng.fang3e8a4b52024-07-24 14:51:30 +0800820 if (ctx_list->hotplug & (AML_WESTON_HOTPLUG_PLUG | AML_WESTON_HOTPLUG_UNPLUG))
821 onHotplug(ctx_list->hotplug & AML_WESTON_HOTPLUG_PLUG);
822 else if (ctx_list->hotplug & (AML_WESTON_HOTPLUG_BOOT | AML_WESTON_HOTPLUG_SET))
leng.fang91856072024-06-07 14:12:54 +0800823 initModePolicy(NULL, NULL, callback);
leng.fang3e8a4b52024-07-24 14:51:30 +0800824 ctx_list->hotplug = AML_WESTON_HOTPLUG_INIT;
leng.fang91856072024-06-07 14:12:54 +0800825 }
826 if (ctx->mode_update)
827 return &ctx->next_mode;
leng.fang13fd3982024-07-03 19:09:58 +0800828 return &ctx->current_mode;
leng.fang91856072024-06-07 14:12:54 +0800829}
830
leng.fangb1081a32024-06-25 14:41:37 +0800831void mode_policy_update_bestmode(bool bestmode)
832{
833 bootenv_update("is.bestmode", bestmode ? "true" : "false");
834}
835
leng.fang13fd3982024-07-03 19:09:58 +0800836void mode_policy_update_modeset(bool *state, bool *modeset)
837{
leng.fang3e8a4b52024-07-24 14:51:30 +0800838 weston_ctx_list * ctx_list = weston_get_ctx_list();
839 weston_ctx *ctx, *tmp;
840 bool mode_changed = false;
leng.fang13fd3982024-07-03 19:09:58 +0800841
leng.fang3e8a4b52024-07-24 14:51:30 +0800842
843 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
844 if (ctx->mode_changed)
845 mode_changed = true;
846 }
847
848 MESON_LOGV("state: %d, modeset: %d, mode_changed: %d", *state, *modeset, mode_changed);
849 if (mode_changed) {
leng.fang13fd3982024-07-03 19:09:58 +0800850 if (!*state)
851 *state = true;
852 if (!*modeset)
853 *modeset = true;
854 }
855}
856
leng.fange9d800e2024-07-12 13:31:59 +0800857void mode_policy_resume()
858{
859 weston_ctx *ctx = weston_get_ctx();
860 int flag;
861
leng.fang3e8a4b52024-07-24 14:51:30 +0800862 if (!ctx)
863 return;
864
leng.fange9d800e2024-07-12 13:31:59 +0800865 flag = (ctx->conn &&
leng.fang5ec9b6c2024-07-29 14:25:00 +0800866 ctx->conn->connector_type == DRM_MODE_CONNECTOR_HDMIA) ?
leng.fange9d800e2024-07-12 13:31:59 +0800867 AML_WESTON_HOTPLUG_PLUG : AML_WESTON_HOTPLUG_SET;
868
869 mode_policy_set_hotplug(flag, true);
870}
871
leng.fang91856072024-06-07 14:12:54 +0800872static void * wstUpdatenvThread(void *arg )
873{
874 long long delay = 16667LL;
leng.fang3e8a4b52024-07-24 14:51:30 +0800875 weston_ctx_list *ctx_list = (weston_ctx_list *)arg;
876 weston_ctx *ctx, *tmp;
leng.fang13fd3982024-07-03 19:09:58 +0800877
leng.fang3e8a4b52024-07-24 14:51:30 +0800878 while (!ctx_list->update_env_thread_stop_requested)
leng.fang91856072024-06-07 14:12:54 +0800879 {
leng.fang3e8a4b52024-07-24 14:51:30 +0800880 wl_list_for_each_safe(ctx, tmp, &ctx_list->ctx_list, link) {
leng.fang3c0ab6d2024-08-01 16:29:00 +0800881 if ((ctx->mode_changed && !ctx->prop_changed && ctx->need_update_hdmi_param) ||
leng.fang3e8a4b52024-07-24 14:51:30 +0800882 (ctx->prop_changed && ctx->need_update_hdmi_param))
883 {
884 weston_log("%s[%d]\n", __func__, __LINE__);
885 initModePolicyFun(ctx->crtc, ctx->conn, callback);
886 updateEnv();
887 ctx->need_update_hdmi_param = false;
888 ctx->mode_changed = false;
889 ctx->prop_changed = false;
890 }
leng.fang91856072024-06-07 14:12:54 +0800891 }
892 usleep( delay );
893 }
894 MESON_LOGD("update env thread exit");
895 return NULL;
896}
897
898void weston_start_update_env_thread()
899{
900 int rc;
leng.fang3e8a4b52024-07-24 14:51:30 +0800901 weston_ctx_list *ctx_list = weston_get_ctx_list();
leng.fang91856072024-06-07 14:12:54 +0800902
leng.fang3e8a4b52024-07-24 14:51:30 +0800903 ctx_list->update_env_thread_stop_requested = false;
904 rc = pthread_create(&ctx_list->update_env_thread_id, NULL, wstUpdatenvThread, ctx_list);
leng.fang91856072024-06-07 14:12:54 +0800905 if ( rc )
906 MESON_LOGE("unable to start updatenv thread: rc %d errno %d", rc, errno);
907}