Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/display: hdmi_state_helper: split InfoFrame functions per type

Havign a single set of InfoFrame callbacks doesn't provide enough
information to the DRM framework about the InfoFrame types that are
actually supported. Also it's not really future-proof: it provides a way
to program only a single Vendor-Specific frame, however we might need to
support multiple VSIs at the same time (e.g. HDMI vs HDMI Forum
VSIs).

Provide separate sets of callbacks, one per the InfoFrame type.

Acked-by: Maxime Ripard <mripard@kernel.org>
Link: https://patch.msgid.link/20260107-limit-infoframes-2-v4-6-213d0d3bd490@oss.qualcomm.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>

+471 -201
+157 -49
drivers/gpu/drm/display/drm_bridge_connector.c
··· 401 401 return MODE_OK; 402 402 } 403 403 404 - static int drm_bridge_connector_clear_infoframe(struct drm_connector *connector, 405 - enum hdmi_infoframe_type type) 404 + static int drm_bridge_connector_clear_avi_infoframe(struct drm_connector *connector) 406 405 { 407 406 struct drm_bridge_connector *bridge_connector = 408 407 to_drm_bridge_connector(connector); ··· 411 412 if (!bridge) 412 413 return -EINVAL; 413 414 414 - switch (type) { 415 - case HDMI_INFOFRAME_TYPE_AVI: 416 - /* required */ 417 - return bridge->funcs->hdmi_clear_avi_infoframe(bridge); 418 - case HDMI_INFOFRAME_TYPE_VENDOR: 419 - /* required */ 420 - return bridge->funcs->hdmi_clear_hdmi_infoframe(bridge); 421 - case HDMI_INFOFRAME_TYPE_AUDIO: 422 - if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO) 423 - return bridge->funcs->hdmi_clear_audio_infoframe(bridge); 424 - break; 425 - case HDMI_INFOFRAME_TYPE_DRM: 426 - if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME) 427 - return bridge->funcs->hdmi_clear_hdr_drm_infoframe(bridge); 428 - break; 429 - case HDMI_INFOFRAME_TYPE_SPD: 430 - if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME) 431 - return bridge->funcs->hdmi_clear_spd_infoframe(bridge); 432 - break; 433 - } 415 + return bridge->funcs->hdmi_clear_avi_infoframe(bridge); 416 + } 434 417 435 - drm_dbg_driver(connector->dev, "Unsupported HDMI InfoFrame %x\n", type); 418 + static int drm_bridge_connector_write_avi_infoframe(struct drm_connector *connector, 419 + const u8 *buffer, size_t len) 420 + { 421 + struct drm_bridge_connector *bridge_connector = 422 + to_drm_bridge_connector(connector); 423 + struct drm_bridge *bridge; 424 + 425 + bridge = bridge_connector->bridge_hdmi; 426 + if (!bridge) 427 + return -EINVAL; 428 + 429 + return bridge->funcs->hdmi_write_avi_infoframe(bridge, buffer, len); 430 + } 431 + 432 + static int drm_bridge_connector_clear_hdmi_infoframe(struct drm_connector *connector) 433 + { 434 + struct drm_bridge_connector *bridge_connector = 435 + to_drm_bridge_connector(connector); 436 + struct drm_bridge *bridge; 437 + 438 + bridge = bridge_connector->bridge_hdmi; 439 + if (!bridge) 440 + return -EINVAL; 441 + 442 + return bridge->funcs->hdmi_clear_hdmi_infoframe(bridge); 443 + } 444 + 445 + static int drm_bridge_connector_write_hdmi_infoframe(struct drm_connector *connector, 446 + const u8 *buffer, size_t len) 447 + { 448 + struct drm_bridge_connector *bridge_connector = 449 + to_drm_bridge_connector(connector); 450 + struct drm_bridge *bridge; 451 + 452 + bridge = bridge_connector->bridge_hdmi; 453 + if (!bridge) 454 + return -EINVAL; 455 + 456 + return bridge->funcs->hdmi_write_hdmi_infoframe(bridge, buffer, len); 457 + } 458 + 459 + static int drm_bridge_connector_clear_audio_infoframe(struct drm_connector *connector) 460 + { 461 + struct drm_bridge_connector *bridge_connector = 462 + to_drm_bridge_connector(connector); 463 + struct drm_bridge *bridge; 464 + 465 + bridge = bridge_connector->bridge_hdmi; 466 + if (!bridge) 467 + return -EINVAL; 468 + 469 + if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO) 470 + return bridge->funcs->hdmi_clear_audio_infoframe(bridge); 471 + 472 + drm_dbg_driver(connector->dev, "Unsupported HDMI Audio InfoFrame\n"); 436 473 437 474 return 0; 438 475 } 439 476 440 - static int drm_bridge_connector_write_infoframe(struct drm_connector *connector, 441 - enum hdmi_infoframe_type type, 442 - const u8 *buffer, size_t len) 477 + static int drm_bridge_connector_write_audio_infoframe(struct drm_connector *connector, 478 + const u8 *buffer, size_t len) 443 479 { 444 480 struct drm_bridge_connector *bridge_connector = 445 481 to_drm_bridge_connector(connector); ··· 484 450 if (!bridge) 485 451 return -EINVAL; 486 452 487 - switch (type) { 488 - case HDMI_INFOFRAME_TYPE_AVI: 489 - /* required */ 490 - return bridge->funcs->hdmi_write_avi_infoframe(bridge, buffer, len); 491 - case HDMI_INFOFRAME_TYPE_VENDOR: 492 - /* required */ 493 - return bridge->funcs->hdmi_write_hdmi_infoframe(bridge, buffer, len); 494 - case HDMI_INFOFRAME_TYPE_AUDIO: 495 - if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO) 496 - return bridge->funcs->hdmi_write_audio_infoframe(bridge, buffer, len); 497 - break; 498 - case HDMI_INFOFRAME_TYPE_DRM: 499 - if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME) 500 - return bridge->funcs->hdmi_write_hdr_drm_infoframe(bridge, buffer, len); 501 - break; 502 - case HDMI_INFOFRAME_TYPE_SPD: 503 - if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME) 504 - return bridge->funcs->hdmi_write_spd_infoframe(bridge, buffer, len); 505 - break; 506 - } 453 + if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO) 454 + return bridge->funcs->hdmi_write_audio_infoframe(bridge, buffer, len); 507 455 508 - drm_dbg_driver(connector->dev, "Unsupported HDMI InfoFrame %x\n", type); 456 + drm_dbg_driver(connector->dev, "Unsupported HDMI Audio InfoFrame\n"); 457 + 458 + return 0; 459 + } 460 + 461 + static int drm_bridge_connector_clear_hdr_drm_infoframe(struct drm_connector *connector) 462 + { 463 + struct drm_bridge_connector *bridge_connector = 464 + to_drm_bridge_connector(connector); 465 + struct drm_bridge *bridge; 466 + 467 + bridge = bridge_connector->bridge_hdmi; 468 + if (!bridge) 469 + return -EINVAL; 470 + 471 + if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME) 472 + return bridge->funcs->hdmi_clear_hdr_drm_infoframe(bridge); 473 + 474 + drm_dbg_driver(connector->dev, "Unsupported HDMI HDR DRM InfoFrame\n"); 475 + 476 + return 0; 477 + } 478 + 479 + static int drm_bridge_connector_write_hdr_drm_infoframe(struct drm_connector *connector, 480 + const u8 *buffer, size_t len) 481 + { 482 + struct drm_bridge_connector *bridge_connector = 483 + to_drm_bridge_connector(connector); 484 + struct drm_bridge *bridge; 485 + 486 + bridge = bridge_connector->bridge_hdmi; 487 + if (!bridge) 488 + return -EINVAL; 489 + 490 + if (bridge->ops & DRM_BRIDGE_OP_HDMI_HDR_DRM_INFOFRAME) 491 + return bridge->funcs->hdmi_write_hdr_drm_infoframe(bridge, buffer, len); 492 + 493 + drm_dbg_driver(connector->dev, "Unsupported HDMI HDR DRM InfoFrame\n"); 494 + 495 + return 0; 496 + } 497 + 498 + static int drm_bridge_connector_clear_spd_infoframe(struct drm_connector *connector) 499 + { 500 + struct drm_bridge_connector *bridge_connector = 501 + to_drm_bridge_connector(connector); 502 + struct drm_bridge *bridge; 503 + 504 + bridge = bridge_connector->bridge_hdmi; 505 + if (!bridge) 506 + return -EINVAL; 507 + 508 + if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME) 509 + return bridge->funcs->hdmi_clear_spd_infoframe(bridge); 510 + 511 + drm_dbg_driver(connector->dev, "Unsupported HDMI SPD InfoFrame\n"); 512 + 513 + return 0; 514 + } 515 + 516 + static int drm_bridge_connector_write_spd_infoframe(struct drm_connector *connector, 517 + const u8 *buffer, size_t len) 518 + { 519 + struct drm_bridge_connector *bridge_connector = 520 + to_drm_bridge_connector(connector); 521 + struct drm_bridge *bridge; 522 + 523 + bridge = bridge_connector->bridge_hdmi; 524 + if (!bridge) 525 + return -EINVAL; 526 + 527 + if (bridge->ops & DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME) 528 + return bridge->funcs->hdmi_write_spd_infoframe(bridge, buffer, len); 529 + 530 + drm_dbg_driver(connector->dev, "Unsupported HDMI SPD InfoFrame\n"); 509 531 510 532 return 0; 511 533 } ··· 582 492 583 493 static const struct drm_connector_hdmi_funcs drm_bridge_connector_hdmi_funcs = { 584 494 .tmds_char_rate_valid = drm_bridge_connector_tmds_char_rate_valid, 585 - .clear_infoframe = drm_bridge_connector_clear_infoframe, 586 - .write_infoframe = drm_bridge_connector_write_infoframe, 587 495 .read_edid = drm_bridge_connector_read_edid, 496 + .avi = { 497 + .clear_infoframe = drm_bridge_connector_clear_avi_infoframe, 498 + .write_infoframe = drm_bridge_connector_write_avi_infoframe, 499 + }, 500 + .hdmi = { 501 + .clear_infoframe = drm_bridge_connector_clear_hdmi_infoframe, 502 + .write_infoframe = drm_bridge_connector_write_hdmi_infoframe, 503 + }, 504 + .audio = { 505 + .clear_infoframe = drm_bridge_connector_clear_audio_infoframe, 506 + .write_infoframe = drm_bridge_connector_write_audio_infoframe, 507 + }, 508 + .hdr_drm = { 509 + .clear_infoframe = drm_bridge_connector_clear_hdr_drm_infoframe, 510 + .write_infoframe = drm_bridge_connector_write_hdr_drm_infoframe, 511 + }, 512 + .spd = { 513 + .clear_infoframe = drm_bridge_connector_clear_spd_infoframe, 514 + .write_infoframe = drm_bridge_connector_write_spd_infoframe, 515 + }, 588 516 }; 589 517 590 518 static int drm_bridge_connector_audio_startup(struct drm_connector *connector)
+55 -53
drivers/gpu/drm/display/drm_hdmi_state_helper.c
··· 891 891 } 892 892 EXPORT_SYMBOL(drm_hdmi_connector_mode_valid); 893 893 894 - static int clear_device_infoframe(struct drm_connector *connector, 895 - enum hdmi_infoframe_type type) 894 + static int clear_infoframe(struct drm_connector *connector, 895 + const struct drm_connector_infoframe_funcs *funcs, 896 + const char *type) 896 897 { 897 - const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 898 898 struct drm_device *dev = connector->dev; 899 899 int ret; 900 900 901 - drm_dbg_kms(dev, "Clearing infoframe type 0x%x\n", type); 901 + drm_dbg_kms(dev, "Clearing %s InfoFrame\n", type); 902 902 903 - if (!funcs || !funcs->clear_infoframe) { 903 + if (!funcs->clear_infoframe) { 904 904 drm_dbg_kms(dev, "Function not implemented, bailing.\n"); 905 905 return 0; 906 906 } 907 907 908 - ret = funcs->clear_infoframe(connector, type); 909 - if (ret) { 910 - drm_dbg_kms(dev, "Call failed: %d\n", ret); 911 - return ret; 912 - } 913 - 914 - return 0; 915 - } 916 - 917 - static int clear_infoframe(struct drm_connector *connector, 918 - struct drm_connector_hdmi_infoframe *old_frame) 919 - { 920 - int ret; 921 - 922 - ret = clear_device_infoframe(connector, old_frame->data.any.type); 923 - if (ret) 924 - return ret; 925 - 926 - return 0; 927 - } 928 - 929 - static int write_device_infoframe(struct drm_connector *connector, 930 - union hdmi_infoframe *frame) 931 - { 932 - const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 933 - struct drm_device *dev = connector->dev; 934 - u8 buffer[HDMI_INFOFRAME_SIZE(MAX)]; 935 - int ret; 936 - int len; 937 - 938 - drm_dbg_kms(dev, "Writing infoframe type %x\n", frame->any.type); 939 - 940 - if (!funcs || !funcs->write_infoframe) { 941 - drm_dbg_kms(dev, "Function not implemented, bailing.\n"); 942 - return -EINVAL; 943 - } 944 - 945 - len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); 946 - if (len < 0) 947 - return len; 948 - 949 - ret = funcs->write_infoframe(connector, frame->any.type, buffer, len); 908 + ret = funcs->clear_infoframe(connector); 950 909 if (ret) { 951 910 drm_dbg_kms(dev, "Call failed: %d\n", ret); 952 911 return ret; ··· 915 956 } 916 957 917 958 static int write_infoframe(struct drm_connector *connector, 959 + const struct drm_connector_infoframe_funcs *funcs, 960 + const char *type, 918 961 struct drm_connector_hdmi_infoframe *new_frame) 919 962 { 963 + struct drm_device *dev = connector->dev; 964 + u8 buffer[HDMI_INFOFRAME_SIZE(MAX)]; 920 965 int ret; 966 + int len; 921 967 922 - ret = write_device_infoframe(connector, &new_frame->data); 923 - if (ret) 968 + drm_dbg_kms(dev, "Writing %s InfoFrame\n", type); 969 + 970 + if (!funcs->write_infoframe) { 971 + drm_dbg_kms(dev, "Function not implemented, bailing.\n"); 972 + return 0; /* XXX: temporal until we stop generating unsupported frames */ 973 + } 974 + 975 + len = hdmi_infoframe_pack(&new_frame->data, buffer, sizeof(buffer)); 976 + if (len < 0) 977 + return len; 978 + 979 + ret = funcs->write_infoframe(connector, buffer, len); 980 + if (ret) { 981 + drm_dbg_kms(dev, "Call failed: %d\n", ret); 924 982 return ret; 983 + } 925 984 926 985 return 0; 927 986 } 928 987 929 988 static int write_or_clear_infoframe(struct drm_connector *connector, 989 + const struct drm_connector_infoframe_funcs *funcs, 990 + const char *type, 930 991 struct drm_connector_hdmi_infoframe *old_frame, 931 992 struct drm_connector_hdmi_infoframe *new_frame) 932 993 { 933 994 if (new_frame->set) 934 - return write_infoframe(connector, new_frame); 995 + return write_infoframe(connector, funcs, type, new_frame); 935 996 936 997 if (old_frame->set && !new_frame->set) 937 - return clear_infoframe(connector, old_frame); 998 + return clear_infoframe(connector, funcs, type); 938 999 939 1000 return 0; 940 1001 } ··· 974 995 int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector, 975 996 struct drm_atomic_state *state) 976 997 { 998 + const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 977 999 struct drm_connector_state *old_conn_state = 978 1000 drm_atomic_get_old_connector_state(state, connector); 979 1001 struct drm_connector_state *new_conn_state = ··· 985 1005 if (!info->is_hdmi) 986 1006 return 0; 987 1007 1008 + if (!funcs) { 1009 + drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n"); 1010 + return -EINVAL; 1011 + } 1012 + 988 1013 mutex_lock(&connector->hdmi.infoframes.lock); 989 1014 990 1015 ret = write_or_clear_infoframe(connector, 1016 + &funcs->avi, "AVI", 991 1017 &old_conn_state->hdmi.infoframes.avi, 992 1018 &new_conn_state->hdmi.infoframes.avi); 993 1019 if (ret) ··· 1001 1015 1002 1016 if (connector->hdmi.infoframes.audio.set) { 1003 1017 ret = write_infoframe(connector, 1018 + &funcs->audio, "Audio", 1004 1019 &connector->hdmi.infoframes.audio); 1005 1020 if (ret) 1006 1021 goto out; 1007 1022 } 1008 1023 1009 1024 ret = write_or_clear_infoframe(connector, 1025 + &funcs->hdr_drm, "HDR DRM", 1010 1026 &old_conn_state->hdmi.infoframes.hdr_drm, 1011 1027 &new_conn_state->hdmi.infoframes.hdr_drm); 1012 1028 if (ret) 1013 1029 goto out; 1014 1030 1015 1031 ret = write_or_clear_infoframe(connector, 1032 + &funcs->spd, "SPD", 1016 1033 &old_conn_state->hdmi.infoframes.spd, 1017 1034 &new_conn_state->hdmi.infoframes.spd); 1018 1035 if (ret) ··· 1023 1034 1024 1035 if (info->has_hdmi_infoframe) { 1025 1036 ret = write_or_clear_infoframe(connector, 1037 + &funcs->hdmi, "HDMI-VS", 1026 1038 &old_conn_state->hdmi.infoframes.hdmi, 1027 1039 &new_conn_state->hdmi.infoframes.hdmi); 1028 1040 if (ret) ··· 1052 1062 drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector, 1053 1063 struct hdmi_audio_infoframe *frame) 1054 1064 { 1065 + const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 1055 1066 struct drm_connector_hdmi_infoframe *infoframe = 1056 1067 &connector->hdmi.infoframes.audio; 1057 1068 struct drm_display_info *info = &connector->display_info; ··· 1061 1070 if (!info->is_hdmi) 1062 1071 return 0; 1063 1072 1073 + if (!funcs) { 1074 + drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n"); 1075 + return -EINVAL; 1076 + } 1077 + 1064 1078 mutex_lock(&connector->hdmi.infoframes.lock); 1065 1079 1066 1080 memcpy(&infoframe->data, frame, sizeof(infoframe->data)); 1067 1081 infoframe->set = true; 1068 1082 1069 - ret = write_infoframe(connector, infoframe); 1083 + ret = write_infoframe(connector, &funcs->audio, "Audio", infoframe); 1070 1084 1071 1085 mutex_unlock(&connector->hdmi.infoframes.lock); 1072 1086 ··· 1093 1097 int 1094 1098 drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector) 1095 1099 { 1100 + const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs; 1096 1101 struct drm_connector_hdmi_infoframe *infoframe = 1097 1102 &connector->hdmi.infoframes.audio; 1098 1103 struct drm_display_info *info = &connector->display_info; ··· 1102 1105 if (!info->is_hdmi) 1103 1106 return 0; 1104 1107 1108 + if (!funcs) { 1109 + drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n"); 1110 + return -EINVAL; 1111 + } 1112 + 1105 1113 mutex_lock(&connector->hdmi.infoframes.lock); 1106 1114 1107 1115 infoframe->set = false; 1108 1116 1109 - ret = clear_infoframe(connector, infoframe); 1117 + ret = clear_infoframe(connector, &funcs->audio, "Audio"); 1110 1118 1111 1119 memset(&infoframe->data, 0, sizeof(infoframe->data)); 1112 1120
+4 -2
drivers/gpu/drm/drm_connector.c
··· 600 600 if (!(max_bpc == 8 || max_bpc == 10 || max_bpc == 12)) 601 601 return -EINVAL; 602 602 603 - if (!hdmi_funcs->clear_infoframe || 604 - !hdmi_funcs->write_infoframe) 603 + if (!hdmi_funcs->avi.clear_infoframe || 604 + !hdmi_funcs->avi.write_infoframe || 605 + !hdmi_funcs->hdmi.clear_infoframe || 606 + !hdmi_funcs->hdmi.write_infoframe) 605 607 return -EINVAL; 606 608 607 609 ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
+26 -13
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
··· 40 40 #define drm_connector_to_sun4i_hdmi(c) \ 41 41 container_of_const(c, struct sun4i_hdmi, connector) 42 42 43 - static int sun4i_hdmi_clear_infoframe(struct drm_connector *connector, 44 - enum hdmi_infoframe_type type) 43 + static int sun4i_hdmi_clear_avi_infoframe(struct drm_connector *connector) 45 44 { 46 45 drm_warn_once(connector->dev, "clearing of AVI infoframe is not implemented\n"); 47 46 48 47 return 0; 49 48 } 50 49 51 - static int sun4i_hdmi_write_infoframe(struct drm_connector *connector, 52 - enum hdmi_infoframe_type type, 53 - const u8 *buffer, size_t len) 50 + static int sun4i_hdmi_write_avi_infoframe(struct drm_connector *connector, 51 + const u8 *buffer, size_t len) 54 52 { 55 53 struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); 56 54 int i; 57 - 58 - if (type != HDMI_INFOFRAME_TYPE_AVI) { 59 - drm_err(connector->dev, 60 - "Unsupported infoframe type: %u\n", type); 61 - return 0; 62 - } 63 55 64 56 for (i = 0; i < len; i++) 65 57 writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i)); 66 58 67 59 return 0; 68 60 61 + } 62 + 63 + static int sun4i_hdmi_clear_hdmi_infoframe(struct drm_connector *connector) 64 + { 65 + drm_warn_once(connector->dev, "HDMI VSI not implemented\n"); 66 + 67 + return 0; 68 + } 69 + 70 + static int sun4i_hdmi_write_hdmi_infoframe(struct drm_connector *connector, 71 + const u8 *buffer, size_t len) 72 + { 73 + drm_warn_once(connector->dev, "HDMI VSI not implemented\n"); 74 + 75 + return 0; 69 76 } 70 77 71 78 static void sun4i_hdmi_disable(struct drm_encoder *encoder, ··· 251 244 252 245 static const struct drm_connector_hdmi_funcs sun4i_hdmi_hdmi_connector_funcs = { 253 246 .tmds_char_rate_valid = sun4i_hdmi_connector_clock_valid, 254 - .clear_infoframe = sun4i_hdmi_clear_infoframe, 255 - .write_infoframe = sun4i_hdmi_write_infoframe, 247 + .avi = { 248 + .clear_infoframe = sun4i_hdmi_clear_avi_infoframe, 249 + .write_infoframe = sun4i_hdmi_write_avi_infoframe, 250 + }, 251 + .hdmi = { 252 + .clear_infoframe = sun4i_hdmi_clear_hdmi_infoframe, 253 + .write_infoframe = sun4i_hdmi_write_hdmi_infoframe, 254 + }, 256 255 }; 257 256 258 257 static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = {
+9 -5
drivers/gpu/drm/tests/drm_connector_test.c
··· 25 25 struct i2c_adapter ddc; 26 26 }; 27 27 28 - static int accept_infoframe_clear_infoframe(struct drm_connector *connector, 29 - enum hdmi_infoframe_type type) 28 + static int accept_infoframe_clear_infoframe(struct drm_connector *connector) 30 29 { 31 30 return 0; 32 31 } 33 32 34 33 static int accept_infoframe_write_infoframe(struct drm_connector *connector, 35 - enum hdmi_infoframe_type type, 36 34 const u8 *buffer, size_t len) 37 35 { 38 36 return 0; 39 37 } 40 38 41 39 static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = { 42 - .clear_infoframe = accept_infoframe_clear_infoframe, 43 - .write_infoframe = accept_infoframe_write_infoframe, 40 + .avi = { 41 + .clear_infoframe = accept_infoframe_clear_infoframe, 42 + .write_infoframe = accept_infoframe_write_infoframe, 43 + }, 44 + .hdmi = { 45 + .clear_infoframe = accept_infoframe_clear_infoframe, 46 + .write_infoframe = accept_infoframe_write_infoframe, 47 + }, 44 48 }; 45 49 46 50 static const struct drm_connector_funcs dummy_funcs = {
+60 -42
drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
··· 78 78 return ret; 79 79 } 80 80 81 - static int accept_infoframe_clear_infoframe(struct drm_connector *connector, 82 - enum hdmi_infoframe_type type) 81 + static int accept_infoframe_clear_infoframe(struct drm_connector *connector) 83 82 { 84 83 return 0; 85 84 } 86 85 87 86 static int accept_infoframe_write_infoframe(struct drm_connector *connector, 88 - enum hdmi_infoframe_type type, 89 87 const u8 *buffer, size_t len) 90 88 { 91 89 return 0; 92 90 } 93 91 94 92 static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = { 95 - .clear_infoframe = accept_infoframe_clear_infoframe, 96 - .write_infoframe = accept_infoframe_write_infoframe, 93 + .avi = { 94 + .clear_infoframe = accept_infoframe_clear_infoframe, 95 + .write_infoframe = accept_infoframe_write_infoframe, 96 + }, 97 + .hdmi = { 98 + .clear_infoframe = accept_infoframe_clear_infoframe, 99 + .write_infoframe = accept_infoframe_write_infoframe, 100 + }, 97 101 }; 98 102 99 103 static enum drm_mode_status ··· 110 106 111 107 static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = { 112 108 .tmds_char_rate_valid = reject_connector_tmds_char_rate_valid, 113 - .clear_infoframe = accept_infoframe_clear_infoframe, 114 - .write_infoframe = accept_infoframe_write_infoframe, 109 + .avi = { 110 + .clear_infoframe = accept_infoframe_clear_infoframe, 111 + .write_infoframe = accept_infoframe_write_infoframe, 112 + }, 113 + .hdmi = { 114 + .clear_infoframe = accept_infoframe_clear_infoframe, 115 + .write_infoframe = accept_infoframe_write_infoframe, 116 + }, 115 117 }; 116 118 117 119 static enum drm_mode_status ··· 130 120 131 121 static const struct drm_connector_hdmi_funcs reject_100mhz_connector_hdmi_funcs = { 132 122 .tmds_char_rate_valid = reject_100mhz_connector_tmds_char_rate_valid, 133 - .clear_infoframe = accept_infoframe_clear_infoframe, 134 - .write_infoframe = accept_infoframe_write_infoframe, 123 + .avi = { 124 + .clear_infoframe = accept_infoframe_clear_infoframe, 125 + .write_infoframe = accept_infoframe_write_infoframe, 126 + }, 127 + .hdmi = { 128 + .clear_infoframe = accept_infoframe_clear_infoframe, 129 + .write_infoframe = accept_infoframe_write_infoframe, 130 + }, 135 131 }; 136 132 137 133 static int dummy_connector_get_modes(struct drm_connector *connector) ··· 2465 2449 drm_modeset_acquire_fini(&ctx); 2466 2450 } 2467 2451 2468 - static int reject_avi_infoframe_write_infoframe(struct drm_connector *connector, 2469 - enum hdmi_infoframe_type type, 2470 - const u8 *buffer, size_t len) 2452 + static int reject_infoframe_write_infoframe(struct drm_connector *connector, 2453 + const u8 *buffer, size_t len) 2471 2454 { 2472 - if (type == HDMI_INFOFRAME_TYPE_AVI) 2473 - return -EOPNOTSUPP; 2474 - 2475 - return 0; 2455 + return -EOPNOTSUPP; 2476 2456 } 2477 2457 2478 2458 static const struct drm_connector_hdmi_funcs reject_avi_infoframe_hdmi_funcs = { 2479 - .clear_infoframe = accept_infoframe_clear_infoframe, 2480 - .write_infoframe = reject_avi_infoframe_write_infoframe, 2459 + .avi = { 2460 + .clear_infoframe = accept_infoframe_clear_infoframe, 2461 + .write_infoframe = reject_infoframe_write_infoframe, 2462 + }, 2463 + .hdmi = { 2464 + .clear_infoframe = accept_infoframe_clear_infoframe, 2465 + .write_infoframe = accept_infoframe_write_infoframe, 2466 + }, 2481 2467 }; 2482 2468 2483 2469 /* ··· 2570 2552 drm_modeset_acquire_fini(&ctx); 2571 2553 } 2572 2554 2573 - static int reject_hdr_infoframe_write_infoframe(struct drm_connector *connector, 2574 - enum hdmi_infoframe_type type, 2575 - const u8 *buffer, size_t len) 2576 - { 2577 - if (type == HDMI_INFOFRAME_TYPE_DRM) 2578 - return -EOPNOTSUPP; 2579 - 2580 - return 0; 2581 - } 2582 - 2583 2555 static const struct drm_connector_hdmi_funcs reject_hdr_infoframe_hdmi_funcs = { 2584 - .clear_infoframe = accept_infoframe_clear_infoframe, 2585 - .write_infoframe = reject_hdr_infoframe_write_infoframe, 2556 + .avi = { 2557 + .clear_infoframe = accept_infoframe_clear_infoframe, 2558 + .write_infoframe = accept_infoframe_write_infoframe, 2559 + }, 2560 + .hdmi = { 2561 + .clear_infoframe = accept_infoframe_clear_infoframe, 2562 + .write_infoframe = accept_infoframe_write_infoframe, 2563 + }, 2564 + .hdr_drm = { 2565 + .clear_infoframe = accept_infoframe_clear_infoframe, 2566 + .write_infoframe = reject_infoframe_write_infoframe, 2567 + }, 2586 2568 }; 2587 2569 2588 2570 /* ··· 2818 2800 drm_modeset_acquire_fini(&ctx); 2819 2801 } 2820 2802 2821 - static int reject_audio_infoframe_write_infoframe(struct drm_connector *connector, 2822 - enum hdmi_infoframe_type type, 2823 - const u8 *buffer, size_t len) 2824 - { 2825 - if (type == HDMI_INFOFRAME_TYPE_AUDIO) 2826 - return -EOPNOTSUPP; 2827 - 2828 - return 0; 2829 - } 2830 - 2831 2803 static const struct drm_connector_hdmi_funcs reject_audio_infoframe_hdmi_funcs = { 2832 - .clear_infoframe = accept_infoframe_clear_infoframe, 2833 - .write_infoframe = reject_audio_infoframe_write_infoframe, 2804 + .avi = { 2805 + .clear_infoframe = accept_infoframe_clear_infoframe, 2806 + .write_infoframe = accept_infoframe_write_infoframe, 2807 + }, 2808 + .hdmi = { 2809 + .clear_infoframe = accept_infoframe_clear_infoframe, 2810 + .write_infoframe = accept_infoframe_write_infoframe, 2811 + }, 2812 + .audio = { 2813 + .clear_infoframe = accept_infoframe_clear_infoframe, 2814 + .write_infoframe = reject_infoframe_write_infoframe, 2815 + }, 2834 2816 }; 2835 2817 2836 2818 /*
+80 -2
drivers/gpu/drm/vc4/vc4_hdmi.c
··· 727 727 return ret; 728 728 } 729 729 730 + static int vc4_hdmi_clear_avi_infoframe(struct drm_connector *connector) 731 + { 732 + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_AVI); 733 + } 734 + 735 + static int vc4_hdmi_clear_hdmi_infoframe(struct drm_connector *connector) 736 + { 737 + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_VENDOR); 738 + } 739 + 740 + static int vc4_hdmi_clear_audio_infoframe(struct drm_connector *connector) 741 + { 742 + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_AUDIO); 743 + } 744 + 745 + static int vc4_hdmi_clear_hdr_drm_infoframe(struct drm_connector *connector) 746 + { 747 + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_DRM); 748 + } 749 + 750 + static int vc4_hdmi_clear_spd_infoframe(struct drm_connector *connector) 751 + { 752 + return vc4_hdmi_clear_infoframe(connector, HDMI_INFOFRAME_TYPE_SPD); 753 + } 754 + 755 + static int vc4_hdmi_write_avi_infoframe(struct drm_connector *connector, 756 + const u8 *buffer, size_t len) 757 + { 758 + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_AVI, 759 + buffer, len); 760 + } 761 + 762 + static int vc4_hdmi_write_hdmi_infoframe(struct drm_connector *connector, 763 + const u8 *buffer, size_t len) 764 + { 765 + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_VENDOR, 766 + buffer, len); 767 + } 768 + 769 + static int vc4_hdmi_write_audio_infoframe(struct drm_connector *connector, 770 + const u8 *buffer, size_t len) 771 + { 772 + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_AUDIO, 773 + buffer, len); 774 + } 775 + 776 + static int vc4_hdmi_write_hdr_drm_infoframe(struct drm_connector *connector, 777 + const u8 *buffer, size_t len) 778 + { 779 + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_DRM, 780 + buffer, len); 781 + } 782 + 783 + static int vc4_hdmi_write_spd_infoframe(struct drm_connector *connector, 784 + const u8 *buffer, size_t len) 785 + { 786 + return vc4_hdmi_write_infoframe(connector, HDMI_INFOFRAME_TYPE_SPD, 787 + buffer, len); 788 + } 789 + 730 790 #define SCRAMBLING_POLLING_DELAY_MS 1000 731 791 732 792 static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) ··· 1744 1684 1745 1685 static const struct drm_connector_hdmi_funcs vc4_hdmi_hdmi_connector_funcs = { 1746 1686 .tmds_char_rate_valid = vc4_hdmi_connector_clock_valid, 1747 - .clear_infoframe = vc4_hdmi_clear_infoframe, 1748 - .write_infoframe = vc4_hdmi_write_infoframe, 1687 + .avi = { 1688 + .clear_infoframe = vc4_hdmi_clear_avi_infoframe, 1689 + .write_infoframe = vc4_hdmi_write_avi_infoframe, 1690 + }, 1691 + .hdmi = { 1692 + .clear_infoframe = vc4_hdmi_clear_hdmi_infoframe, 1693 + .write_infoframe = vc4_hdmi_write_hdmi_infoframe, 1694 + }, 1695 + .audio = { 1696 + .clear_infoframe = vc4_hdmi_clear_audio_infoframe, 1697 + .write_infoframe = vc4_hdmi_write_audio_infoframe, 1698 + }, 1699 + .hdr_drm = { 1700 + .clear_infoframe = vc4_hdmi_clear_hdr_drm_infoframe, 1701 + .write_infoframe = vc4_hdmi_write_hdr_drm_infoframe, 1702 + }, 1703 + .spd = { 1704 + .clear_infoframe = vc4_hdmi_clear_spd_infoframe, 1705 + .write_infoframe = vc4_hdmi_write_spd_infoframe, 1706 + }, 1749 1707 }; 1750 1708 1751 1709 #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL
+80 -35
include/drm/drm_connector.h
··· 1222 1222 }; 1223 1223 1224 1224 /** 1225 + * struct drm_connector_infoframe_funcs - InfoFrame-related functions 1226 + */ 1227 + struct drm_connector_infoframe_funcs { 1228 + /** 1229 + * @clear_infoframe: 1230 + * 1231 + * This callback is invoked through 1232 + * @drm_atomic_helper_connector_hdmi_update_infoframes during a 1233 + * commit to clear the infoframes into the hardware. It will be 1234 + * called once for each frame type to be disabled. 1235 + * 1236 + * The @clear_infoframe callback is mandatory for AVI and HDMI-VS 1237 + * InfoFrame types. 1238 + * 1239 + * Returns: 1240 + * 0 on success, a negative error code otherwise 1241 + */ 1242 + int (*clear_infoframe)(struct drm_connector *connector); 1243 + 1244 + /** 1245 + * @write_infoframe: 1246 + * 1247 + * This callback is invoked through 1248 + * @drm_atomic_helper_connector_hdmi_update_infoframes during a 1249 + * commit to program the infoframes into the hardware. It will 1250 + * be called for every updated infoframe type. 1251 + * 1252 + * The @write_infoframe callback is mandatory for AVI and HDMI-VS 1253 + * InfoFrame types. 1254 + * 1255 + * Returns: 1256 + * 0 on success, a negative error code otherwise 1257 + */ 1258 + int (*write_infoframe)(struct drm_connector *connector, 1259 + const u8 *buffer, size_t len); 1260 + 1261 + }; 1262 + 1263 + /** 1225 1264 * struct drm_connector_hdmi_funcs - drm_hdmi_connector control functions 1226 1265 */ 1227 1266 struct drm_connector_hdmi_funcs { ··· 1284 1245 unsigned long long tmds_rate); 1285 1246 1286 1247 /** 1287 - * @clear_infoframe: 1288 - * 1289 - * This callback is invoked through 1290 - * @drm_atomic_helper_connector_hdmi_update_infoframes during a 1291 - * commit to clear the infoframes into the hardware. It will be 1292 - * called multiple times, once for every disabled infoframe 1293 - * type. 1294 - * 1295 - * The @clear_infoframe callback is mandatory. 1296 - * 1297 - * Returns: 1298 - * 0 on success, a negative error code otherwise 1299 - */ 1300 - int (*clear_infoframe)(struct drm_connector *connector, 1301 - enum hdmi_infoframe_type type); 1302 - 1303 - /** 1304 - * @write_infoframe: 1305 - * 1306 - * This callback is invoked through 1307 - * @drm_atomic_helper_connector_hdmi_update_infoframes during a 1308 - * commit to program the infoframes into the hardware. It will 1309 - * be called multiple times, once for every updated infoframe 1310 - * type. 1311 - * 1312 - * The @write_infoframe callback is mandatory. 1313 - * 1314 - * Returns: 1315 - * 0 on success, a negative error code otherwise 1316 - */ 1317 - int (*write_infoframe)(struct drm_connector *connector, 1318 - enum hdmi_infoframe_type type, 1319 - const u8 *buffer, size_t len); 1320 - 1321 - /** 1322 1248 * @read_edid: 1323 1249 * 1324 1250 * This callback is used by the framework as a replacement for reading ··· 1297 1293 * Valid EDID on success, NULL in case of failure. 1298 1294 */ 1299 1295 const struct drm_edid *(*read_edid)(struct drm_connector *connector); 1296 + 1297 + /** 1298 + * @avi: 1299 + * 1300 + * Set of callbacks for handling the AVI InfoFrame. These callbacks are 1301 + * mandatory. 1302 + */ 1303 + struct drm_connector_infoframe_funcs avi; 1304 + 1305 + /** 1306 + * @hdmi: 1307 + * 1308 + * Set of callbacks for handling the HDMI Vendor-Specific InfoFrame. 1309 + * These callbacks are mandatory. 1310 + */ 1311 + struct drm_connector_infoframe_funcs hdmi; 1312 + 1313 + /** 1314 + * @audio: 1315 + * 1316 + * Set of callbacks for handling the Audio InfoFrame. These callbacks 1317 + * are optional, but they are required for drivers which use 1318 + * drm_atomic_helper_connector_hdmi_update_audio_infoframe(). 1319 + */ 1320 + struct drm_connector_infoframe_funcs audio; 1321 + 1322 + /** 1323 + * @hdr_drm: 1324 + * 1325 + * Set of callbacks for handling the HDR DRM InfoFrame. These callbacks 1326 + * are mandatory if HDR output is to be supported. 1327 + */ 1328 + struct drm_connector_infoframe_funcs hdr_drm; 1329 + 1330 + /** 1331 + * @spd: 1332 + * 1333 + * Set of callbacks for handling the SPD InfoFrame. These callbacks are 1334 + * optional. 1335 + */ 1336 + struct drm_connector_infoframe_funcs spd; 1300 1337 }; 1301 1338 1302 1339 /**