Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 
0003 #include <linux/module.h>
0004 
0005 #include <drm/display/drm_hdmi_helper.h>
0006 #include <drm/drm_connector.h>
0007 #include <drm/drm_edid.h>
0008 #include <drm/drm_modes.h>
0009 #include <drm/drm_print.h>
0010 #include <drm/drm_property.h>
0011 
0012 static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf)
0013 {
0014     return sink_eotf & BIT(output_eotf);
0015 }
0016 
0017 /**
0018  * drm_hdmi_infoframe_set_hdr_metadata() - fill an HDMI DRM infoframe with
0019  *                                         HDR metadata from userspace
0020  * @frame: HDMI DRM infoframe
0021  * @conn_state: Connector state containing HDR metadata
0022  *
0023  * Return: 0 on success or a negative error code on failure.
0024  */
0025 int drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame,
0026                     const struct drm_connector_state *conn_state)
0027 {
0028     struct drm_connector *connector;
0029     struct hdr_output_metadata *hdr_metadata;
0030     int err;
0031 
0032     if (!frame || !conn_state)
0033         return -EINVAL;
0034 
0035     connector = conn_state->connector;
0036 
0037     if (!conn_state->hdr_output_metadata)
0038         return -EINVAL;
0039 
0040     hdr_metadata = conn_state->hdr_output_metadata->data;
0041 
0042     if (!hdr_metadata || !connector)
0043         return -EINVAL;
0044 
0045     /* Sink EOTF is Bit map while infoframe is absolute values */
0046     if (!is_eotf_supported(hdr_metadata->hdmi_metadata_type1.eotf,
0047         connector->hdr_sink_metadata.hdmi_type1.eotf)) {
0048         DRM_DEBUG_KMS("EOTF Not Supported\n");
0049         return -EINVAL;
0050     }
0051 
0052     err = hdmi_drm_infoframe_init(frame);
0053     if (err < 0)
0054         return err;
0055 
0056     frame->eotf = hdr_metadata->hdmi_metadata_type1.eotf;
0057     frame->metadata_type = hdr_metadata->hdmi_metadata_type1.metadata_type;
0058 
0059     BUILD_BUG_ON(sizeof(frame->display_primaries) !=
0060              sizeof(hdr_metadata->hdmi_metadata_type1.display_primaries));
0061     BUILD_BUG_ON(sizeof(frame->white_point) !=
0062              sizeof(hdr_metadata->hdmi_metadata_type1.white_point));
0063 
0064     memcpy(&frame->display_primaries,
0065            &hdr_metadata->hdmi_metadata_type1.display_primaries,
0066            sizeof(frame->display_primaries));
0067 
0068     memcpy(&frame->white_point,
0069            &hdr_metadata->hdmi_metadata_type1.white_point,
0070            sizeof(frame->white_point));
0071 
0072     frame->max_display_mastering_luminance =
0073         hdr_metadata->hdmi_metadata_type1.max_display_mastering_luminance;
0074     frame->min_display_mastering_luminance =
0075         hdr_metadata->hdmi_metadata_type1.min_display_mastering_luminance;
0076     frame->max_fall = hdr_metadata->hdmi_metadata_type1.max_fall;
0077     frame->max_cll = hdr_metadata->hdmi_metadata_type1.max_cll;
0078 
0079     return 0;
0080 }
0081 EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata);
0082 
0083 /* HDMI Colorspace Spec Definitions */
0084 #define FULL_COLORIMETRY_MASK       0x1FF
0085 #define NORMAL_COLORIMETRY_MASK     0x3
0086 #define EXTENDED_COLORIMETRY_MASK   0x7
0087 #define EXTENDED_ACE_COLORIMETRY_MASK   0xF
0088 
0089 #define C(x) ((x) << 0)
0090 #define EC(x) ((x) << 2)
0091 #define ACE(x) ((x) << 5)
0092 
0093 #define HDMI_COLORIMETRY_NO_DATA        0x0
0094 #define HDMI_COLORIMETRY_SMPTE_170M_YCC     (C(1) | EC(0) | ACE(0))
0095 #define HDMI_COLORIMETRY_BT709_YCC      (C(2) | EC(0) | ACE(0))
0096 #define HDMI_COLORIMETRY_XVYCC_601      (C(3) | EC(0) | ACE(0))
0097 #define HDMI_COLORIMETRY_XVYCC_709      (C(3) | EC(1) | ACE(0))
0098 #define HDMI_COLORIMETRY_SYCC_601       (C(3) | EC(2) | ACE(0))
0099 #define HDMI_COLORIMETRY_OPYCC_601      (C(3) | EC(3) | ACE(0))
0100 #define HDMI_COLORIMETRY_OPRGB          (C(3) | EC(4) | ACE(0))
0101 #define HDMI_COLORIMETRY_BT2020_CYCC        (C(3) | EC(5) | ACE(0))
0102 #define HDMI_COLORIMETRY_BT2020_RGB     (C(3) | EC(6) | ACE(0))
0103 #define HDMI_COLORIMETRY_BT2020_YCC     (C(3) | EC(6) | ACE(0))
0104 #define HDMI_COLORIMETRY_DCI_P3_RGB_D65     (C(3) | EC(7) | ACE(0))
0105 #define HDMI_COLORIMETRY_DCI_P3_RGB_THEATER (C(3) | EC(7) | ACE(1))
0106 
0107 static const u32 hdmi_colorimetry_val[] = {
0108     [DRM_MODE_COLORIMETRY_NO_DATA] = HDMI_COLORIMETRY_NO_DATA,
0109     [DRM_MODE_COLORIMETRY_SMPTE_170M_YCC] = HDMI_COLORIMETRY_SMPTE_170M_YCC,
0110     [DRM_MODE_COLORIMETRY_BT709_YCC] = HDMI_COLORIMETRY_BT709_YCC,
0111     [DRM_MODE_COLORIMETRY_XVYCC_601] = HDMI_COLORIMETRY_XVYCC_601,
0112     [DRM_MODE_COLORIMETRY_XVYCC_709] = HDMI_COLORIMETRY_XVYCC_709,
0113     [DRM_MODE_COLORIMETRY_SYCC_601] = HDMI_COLORIMETRY_SYCC_601,
0114     [DRM_MODE_COLORIMETRY_OPYCC_601] = HDMI_COLORIMETRY_OPYCC_601,
0115     [DRM_MODE_COLORIMETRY_OPRGB] = HDMI_COLORIMETRY_OPRGB,
0116     [DRM_MODE_COLORIMETRY_BT2020_CYCC] = HDMI_COLORIMETRY_BT2020_CYCC,
0117     [DRM_MODE_COLORIMETRY_BT2020_RGB] = HDMI_COLORIMETRY_BT2020_RGB,
0118     [DRM_MODE_COLORIMETRY_BT2020_YCC] = HDMI_COLORIMETRY_BT2020_YCC,
0119 };
0120 
0121 #undef C
0122 #undef EC
0123 #undef ACE
0124 
0125 /**
0126  * drm_hdmi_avi_infoframe_colorimetry() - fill the HDMI AVI infoframe
0127  *                                       colorimetry information
0128  * @frame: HDMI AVI infoframe
0129  * @conn_state: connector state
0130  */
0131 void drm_hdmi_avi_infoframe_colorimetry(struct hdmi_avi_infoframe *frame,
0132                     const struct drm_connector_state *conn_state)
0133 {
0134     u32 colorimetry_val;
0135     u32 colorimetry_index = conn_state->colorspace & FULL_COLORIMETRY_MASK;
0136 
0137     if (colorimetry_index >= ARRAY_SIZE(hdmi_colorimetry_val))
0138         colorimetry_val = HDMI_COLORIMETRY_NO_DATA;
0139     else
0140         colorimetry_val = hdmi_colorimetry_val[colorimetry_index];
0141 
0142     frame->colorimetry = colorimetry_val & NORMAL_COLORIMETRY_MASK;
0143     /*
0144      * ToDo: Extend it for ACE formats as well. Modify the infoframe
0145      * structure and extend it in drivers/video/hdmi
0146      */
0147     frame->extended_colorimetry = (colorimetry_val >> 2) &
0148                     EXTENDED_COLORIMETRY_MASK;
0149 }
0150 EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorimetry);
0151 
0152 /**
0153  * drm_hdmi_avi_infoframe_bars() - fill the HDMI AVI infoframe
0154  *                                 bar information
0155  * @frame: HDMI AVI infoframe
0156  * @conn_state: connector state
0157  */
0158 void drm_hdmi_avi_infoframe_bars(struct hdmi_avi_infoframe *frame,
0159                  const struct drm_connector_state *conn_state)
0160 {
0161     frame->right_bar = conn_state->tv.margins.right;
0162     frame->left_bar = conn_state->tv.margins.left;
0163     frame->top_bar = conn_state->tv.margins.top;
0164     frame->bottom_bar = conn_state->tv.margins.bottom;
0165 }
0166 EXPORT_SYMBOL(drm_hdmi_avi_infoframe_bars);
0167 
0168 /**
0169  * drm_hdmi_avi_infoframe_content_type() - fill the HDMI AVI infoframe
0170  *                                         content type information, based
0171  *                                         on correspondent DRM property.
0172  * @frame: HDMI AVI infoframe
0173  * @conn_state: DRM display connector state
0174  *
0175  */
0176 void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
0177                      const struct drm_connector_state *conn_state)
0178 {
0179     switch (conn_state->content_type) {
0180     case DRM_MODE_CONTENT_TYPE_GRAPHICS:
0181         frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
0182         break;
0183     case DRM_MODE_CONTENT_TYPE_CINEMA:
0184         frame->content_type = HDMI_CONTENT_TYPE_CINEMA;
0185         break;
0186     case DRM_MODE_CONTENT_TYPE_GAME:
0187         frame->content_type = HDMI_CONTENT_TYPE_GAME;
0188         break;
0189     case DRM_MODE_CONTENT_TYPE_PHOTO:
0190         frame->content_type = HDMI_CONTENT_TYPE_PHOTO;
0191         break;
0192     default:
0193         /* Graphics is the default(0) */
0194         frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
0195     }
0196 
0197     frame->itc = conn_state->content_type != DRM_MODE_CONTENT_TYPE_NO_DATA;
0198 }
0199 EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type);