Path: blob/master/drivers/gpu/drm/display/drm_hdmi_state_helper.c
50953 views
// SPDX-License-Identifier: MIT12#include <linux/export.h>34#include <drm/drm_atomic.h>5#include <drm/drm_connector.h>6#include <drm/drm_edid.h>7#include <drm/drm_modes.h>8#include <drm/drm_print.h>910#include <drm/display/drm_hdmi_audio_helper.h>11#include <drm/display/drm_hdmi_cec_helper.h>12#include <drm/display/drm_hdmi_helper.h>13#include <drm/display/drm_hdmi_state_helper.h>1415/**16* DOC: hdmi helpers17*18* These functions contain an implementation of the HDMI specification19* in the form of KMS helpers.20*21* It contains TMDS character rate computation, automatic selection of22* output formats, infoframes generation, etc.23*24* Infoframes Compliance25* ~~~~~~~~~~~~~~~~~~~~~26*27* Drivers using the helpers will expose the various infoframes28* generated according to the HDMI specification in debugfs.29*30* Compliance can then be tested using ``edid-decode`` from the ``v4l-utils`` project31* (https://git.linuxtv.org/v4l-utils.git/). A sample run would look like:32*33* .. code-block:: bash34*35* # edid-decode \36* -I /sys/kernel/debug/dri/1/HDMI-A-1/infoframes/audio \37* -I /sys/kernel/debug/dri/1/HDMI-A-1/infoframes/avi \38* -I /sys/kernel/debug/dri/1/HDMI-A-1/infoframes/hdmi \39* -I /sys/kernel/debug/dri/1/HDMI-A-1/infoframes/hdr_drm \40* -I /sys/kernel/debug/dri/1/HDMI-A-1/infoframes/spd \41* /sys/class/drm/card1-HDMI-A-1/edid \42* -c43*44* edid-decode (hex):45*46* 00 ff ff ff ff ff ff 00 1e 6d f4 5b 1e ef 06 0047* 07 20 01 03 80 2f 34 78 ea 24 05 af 4f 42 ab 2548* 0f 50 54 21 08 00 d1 c0 61 40 45 40 01 01 01 0149* 01 01 01 01 01 01 98 d0 00 40 a1 40 d4 b0 30 2050* 3a 00 d1 0b 12 00 00 1a 00 00 00 fd 00 3b 3d 1e51* b2 31 00 0a 20 20 20 20 20 20 00 00 00 fc 00 4c52* 47 20 53 44 51 48 44 0a 20 20 20 20 00 00 00 ff53* 00 32 30 37 4e 54 52 4c 44 43 34 33 30 0a 01 4654*55* 02 03 42 72 23 09 07 07 4d 01 03 04 90 12 13 1f56* 22 5d 5e 5f 60 61 83 01 00 00 6d 03 0c 00 10 0057* b8 3c 20 00 60 01 02 03 67 d8 5d c4 01 78 80 0358* e3 0f 00 18 e2 00 6a e3 05 c0 00 e6 06 05 01 5259* 52 51 11 5d 00 a0 a0 40 29 b0 30 20 3a 00 d1 0b60* 12 00 00 1a 00 00 00 00 00 00 00 00 00 00 00 0061* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0062* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c363*64* ----------------65*66* Block 0, Base EDID:67* EDID Structure Version & Revision: 1.368* Vendor & Product Identification:69* Manufacturer: GSM70* Model: 2354071* Serial Number: 454430 (0x0006ef1e)72* Made in: week 7 of 202273* Basic Display Parameters & Features:74* Digital display75* Maximum image size: 47 cm x 52 cm76* Gamma: 2.2077* DPMS levels: Standby Suspend Off78* RGB color display79* First detailed timing is the preferred timing80* Color Characteristics:81* Red : 0.6835, 0.310582* Green: 0.2587, 0.667983* Blue : 0.1445, 0.058584* White: 0.3134, 0.329185* Established Timings I & II:86* DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz87* DMT 0x09: 800x600 60.316541 Hz 4:3 37.879 kHz 40.000000 MHz88* DMT 0x10: 1024x768 60.003840 Hz 4:3 48.363 kHz 65.000000 MHz89* Standard Timings:90* DMT 0x52: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz91* DMT 0x10: 1024x768 60.003840 Hz 4:3 48.363 kHz 65.000000 MHz92* DMT 0x09: 800x600 60.316541 Hz 4:3 37.879 kHz 40.000000 MHz93* Detailed Timing Descriptors:94* DTD 1: 2560x2880 59.966580 Hz 8:9 185.417 kHz 534.000000 MHz (465 mm x 523 mm)95* Hfront 48 Hsync 32 Hback 240 Hpol P96* Vfront 3 Vsync 10 Vback 199 Vpol N97* Display Range Limits:98* Monitor ranges (GTF): 59-61 Hz V, 30-178 kHz H, max dotclock 490 MHz99* Display Product Name: 'LG SDQHD'100* Display Product Serial Number: '207NTRLDC430'101* Extension blocks: 1102* Checksum: 0x46103*104* ----------------105*106* Block 1, CTA-861 Extension Block:107* Revision: 3108* Basic audio support109* Supports YCbCr 4:4:4110* Supports YCbCr 4:2:2111* Native detailed modes: 2112* Audio Data Block:113* Linear PCM:114* Max channels: 2115* Supported sample rates (kHz): 48 44.1 32116* Supported sample sizes (bits): 24 20 16117* Video Data Block:118* VIC 1: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz119* VIC 3: 720x480 59.940060 Hz 16:9 31.469 kHz 27.000000 MHz120* VIC 4: 1280x720 60.000000 Hz 16:9 45.000 kHz 74.250000 MHz121* VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (native)122* VIC 18: 720x576 50.000000 Hz 16:9 31.250 kHz 27.000000 MHz123* VIC 19: 1280x720 50.000000 Hz 16:9 37.500 kHz 74.250000 MHz124* VIC 31: 1920x1080 50.000000 Hz 16:9 56.250 kHz 148.500000 MHz125* VIC 34: 1920x1080 30.000000 Hz 16:9 33.750 kHz 74.250000 MHz126* VIC 93: 3840x2160 24.000000 Hz 16:9 54.000 kHz 297.000000 MHz127* VIC 94: 3840x2160 25.000000 Hz 16:9 56.250 kHz 297.000000 MHz128* VIC 95: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz129* VIC 96: 3840x2160 50.000000 Hz 16:9 112.500 kHz 594.000000 MHz130* VIC 97: 3840x2160 60.000000 Hz 16:9 135.000 kHz 594.000000 MHz131* Speaker Allocation Data Block:132* FL/FR - Front Left/Right133* Vendor-Specific Data Block (HDMI), OUI 00-0C-03:134* Source physical address: 1.0.0.0135* Supports_AI136* DC_36bit137* DC_30bit138* DC_Y444139* Maximum TMDS clock: 300 MHz140* Extended HDMI video details:141* HDMI VICs:142* HDMI VIC 1: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz143* HDMI VIC 2: 3840x2160 25.000000 Hz 16:9 56.250 kHz 297.000000 MHz144* HDMI VIC 3: 3840x2160 24.000000 Hz 16:9 54.000 kHz 297.000000 MHz145* Vendor-Specific Data Block (HDMI Forum), OUI C4-5D-D8:146* Version: 1147* Maximum TMDS Character Rate: 600 MHz148* SCDC Present149* Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding150* Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding151* YCbCr 4:2:0 Capability Map Data Block:152* VIC 96: 3840x2160 50.000000 Hz 16:9 112.500 kHz 594.000000 MHz153* VIC 97: 3840x2160 60.000000 Hz 16:9 135.000 kHz 594.000000 MHz154* Video Capability Data Block:155* YCbCr quantization: No Data156* RGB quantization: Selectable (via AVI Q)157* PT scan behavior: Always Underscanned158* IT scan behavior: Always Underscanned159* CE scan behavior: Always Underscanned160* Colorimetry Data Block:161* BT2020YCC162* BT2020RGB163* HDR Static Metadata Data Block:164* Electro optical transfer functions:165* Traditional gamma - SDR luminance range166* SMPTE ST2084167* Supported static metadata descriptors:168* Static metadata type 1169* Desired content max luminance: 82 (295.365 cd/m^2)170* Desired content max frame-average luminance: 82 (295.365 cd/m^2)171* Desired content min luminance: 81 (0.298 cd/m^2)172* Detailed Timing Descriptors:173* DTD 2: 2560x2880 29.986961 Hz 8:9 87.592 kHz 238.250000 MHz (465 mm x 523 mm)174* Hfront 48 Hsync 32 Hback 80 Hpol P175* Vfront 3 Vsync 10 Vback 28 Vpol N176* Checksum: 0xc3 Unused space in Extension Block: 43 bytes177*178* ----------------179*180* edid-decode 1.29.0-5346181* edid-decode SHA: c363e9aa6d70 2025-03-11 11:41:18182*183* Warnings:184*185* Block 1, CTA-861 Extension Block:186* IT Video Formats are overscanned by default, but normally this should be underscanned.187* Video Data Block: VIC 1 and the first DTD are not identical. Is this intended?188* Video Data Block: All VICs are in ascending order, and the first (preferred) VIC <= 4, is that intended?189* Video Capability Data Block: Set Selectable YCbCr Quantization to avoid interop issues.190* Video Capability Data Block: S_PT is equal to S_IT and S_CE, so should be set to 0 instead.191* Colorimetry Data Block: Set the sRGB colorimetry bit to avoid interop issues.192* Display Product Serial Number is set, so the Serial Number in the Base EDID should be 0.193* EDID:194* Base EDID: Some timings are out of range of the Monitor Ranges:195* Vertical Freq: 24.000 - 60.317 Hz (Monitor: 59.000 - 61.000 Hz)196* Horizontal Freq: 31.250 - 185.416 kHz (Monitor: 30.000 - 178.000 kHz)197* Maximum Clock: 594.000 MHz (Monitor: 490.000 MHz)198*199* Failures:200*201* Block 1, CTA-861 Extension Block:202* Video Capability Data Block: IT video formats are always underscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to overscanned.203* EDID:204* CTA-861: Native progressive timings are a mix of several resolutions.205*206* EDID conformity: FAIL207*208* ================209*210* InfoFrame of '/sys/kernel/debug/dri/1/HDMI-A-1/infoframes/audio' was empty.211*212* ================213*214* edid-decode InfoFrame (hex):215*216* 82 02 0d 31 12 28 04 00 00 00 00 00 00 00 00 00217* 00218*219* ----------------220*221* HDMI InfoFrame Checksum: 0x31222*223* AVI InfoFrame224* Version: 2225* Length: 13226* Y: Color Component Sample Format: RGB227* A: Active Format Information Present: Yes228* B: Bar Data Present: Bar Data not present229* S: Scan Information: Composed for an underscanned display230* C: Colorimetry: No Data231* M: Picture Aspect Ratio: 16:9232* R: Active Portion Aspect Ratio: 8233* ITC: IT Content: No Data234* EC: Extended Colorimetry: xvYCC601235* Q: RGB Quantization Range: Limited Range236* SC: Non-Uniform Picture Scaling: No Known non-uniform scaling237* YQ: YCC Quantization Range: Limited Range238* CN: IT Content Type: Graphics239* PR: Pixel Data Repetition Count: 0240* Line Number of End of Top Bar: 0241* Line Number of Start of Bottom Bar: 0242* Pixel Number of End of Left Bar: 0243* Pixel Number of Start of Right Bar: 0244*245* ----------------246*247* AVI InfoFrame conformity: PASS248*249* ================250*251* edid-decode InfoFrame (hex):252*253* 81 01 05 49 03 0c 00 20 01254*255* ----------------256*257* HDMI InfoFrame Checksum: 0x49258*259* Vendor-Specific InfoFrame (HDMI), OUI 00-0C-03260* Version: 1261* Length: 5262* HDMI Video Format: HDMI_VIC is present263* HDMI VIC 1: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz264*265* ----------------266*267* Vendor-Specific InfoFrame (HDMI), OUI 00-0C-03 conformity: PASS268*269* ================270*271* InfoFrame of '/sys/kernel/debug/dri/1/HDMI-A-1/infoframes/hdr_drm' was empty.272*273* ================274*275* edid-decode InfoFrame (hex):276*277* 83 01 19 93 42 72 6f 61 64 63 6f 6d 56 69 64 65278* 6f 63 6f 72 65 00 00 00 00 00 00 00 09279*280* ----------------281*282* HDMI InfoFrame Checksum: 0x93283*284* Source Product Description InfoFrame285* Version: 1286* Length: 25287* Vendor Name: 'Broadcom'288* Product Description: 'Videocore'289* Source Information: PC general290*291* ----------------292*293* Source Product Description InfoFrame conformity: PASS294*295* Testing296* ~~~~~~~297*298* The helpers have unit testing and can be tested using kunit with:299*300* .. code-block:: bash301*302* $ ./tools/testing/kunit/kunit.py run \303* --kunitconfig=drivers/gpu/drm/tests \304* drm_atomic_helper_connector_hdmi_*305*/306307/**308* __drm_atomic_helper_connector_hdmi_reset() - Initializes all HDMI @drm_connector_state resources309* @connector: DRM connector310* @new_conn_state: connector state to reset311*312* Initializes all HDMI resources from a @drm_connector_state without313* actually allocating it. This is useful for HDMI drivers, in314* combination with __drm_atomic_helper_connector_reset() or315* drm_atomic_helper_connector_reset().316*/317void __drm_atomic_helper_connector_hdmi_reset(struct drm_connector *connector,318struct drm_connector_state *new_conn_state)319{320unsigned int max_bpc = connector->max_bpc;321322new_conn_state->max_bpc = max_bpc;323new_conn_state->max_requested_bpc = max_bpc;324new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_AUTO;325}326EXPORT_SYMBOL(__drm_atomic_helper_connector_hdmi_reset);327328static const struct drm_display_mode *329connector_state_get_mode(const struct drm_connector_state *conn_state)330{331struct drm_atomic_state *state;332struct drm_crtc_state *crtc_state;333struct drm_crtc *crtc;334335state = conn_state->state;336if (!state)337return NULL;338339crtc = conn_state->crtc;340if (!crtc)341return NULL;342343crtc_state = drm_atomic_get_new_crtc_state(state, crtc);344if (!crtc_state)345return NULL;346347return &crtc_state->mode;348}349350static bool hdmi_is_limited_range(const struct drm_connector *connector,351const struct drm_connector_state *conn_state)352{353const struct drm_display_info *info = &connector->display_info;354const struct drm_display_mode *mode =355connector_state_get_mode(conn_state);356357/*358* The Broadcast RGB property only applies to RGB format, and359* i915 just assumes limited range for YCbCr output, so let's360* just do the same.361*/362if (conn_state->hdmi.output_format != HDMI_COLORSPACE_RGB)363return true;364365if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_FULL)366return false;367368if (conn_state->hdmi.broadcast_rgb == DRM_HDMI_BROADCAST_RGB_LIMITED)369return true;370371if (!info->is_hdmi)372return false;373374return drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED;375}376377static bool378sink_supports_format_bpc(const struct drm_connector *connector,379const struct drm_display_info *info,380const struct drm_display_mode *mode,381unsigned int format, unsigned int bpc)382{383struct drm_device *dev = connector->dev;384u8 vic = drm_match_cea_mode(mode);385386/*387* CTA-861-F, section 5.4 - Color Coding & Quantization states388* that the bpc must be 8, 10, 12 or 16 except for the default389* 640x480 VIC1 where the value must be 8.390*391* The definition of default here is ambiguous but the spec392* refers to VIC1 being the default timing in several occasions393* so our understanding is that for the default timing (ie,394* VIC1), the bpc must be 8.395*/396if (vic == 1 && bpc != 8) {397drm_dbg_kms(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);398return false;399}400401if (!info->is_hdmi &&402(format != HDMI_COLORSPACE_RGB || bpc != 8)) {403drm_dbg_kms(dev, "DVI Monitors require an RGB output at 8 bpc\n");404return false;405}406407if (!(connector->hdmi.supported_formats & BIT(format))) {408drm_dbg_kms(dev, "%s format unsupported by the connector.\n",409drm_hdmi_connector_get_output_format_name(format));410return false;411}412413if (drm_mode_is_420_only(info, mode) && format != HDMI_COLORSPACE_YUV420) {414drm_dbg_kms(dev, "Mode can be only supported in YUV420 format.\n");415return false;416}417418switch (format) {419case HDMI_COLORSPACE_RGB:420drm_dbg_kms(dev, "RGB Format, checking the constraints.\n");421422/*423* In some cases, like when the EDID readout fails, or424* is not an HDMI compliant EDID for some reason, the425* color_formats field will be blank and not report any426* format supported. In such a case, assume that RGB is427* supported so we can keep things going and light up428* the display.429*/430if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444))431drm_warn(dev, "HDMI Sink doesn't support RGB, something's wrong.\n");432433if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) {434drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n");435return false;436}437438if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) {439drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n");440return false;441}442443drm_dbg_kms(dev, "RGB format supported in that configuration.\n");444445return true;446447case HDMI_COLORSPACE_YUV420:448drm_dbg_kms(dev, "YUV420 format, checking the constraints.\n");449450if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR420)) {451drm_dbg_kms(dev, "Sink doesn't support YUV420.\n");452return false;453}454455if (!drm_mode_is_420(info, mode)) {456drm_dbg_kms(dev, "Mode cannot be supported in YUV420 format.\n");457return false;458}459460if (bpc == 10 && !(info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) {461drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n");462return false;463}464465if (bpc == 12 && !(info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) {466drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n");467return false;468}469470if (bpc == 16 && !(info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) {471drm_dbg_kms(dev, "16 BPC but sink doesn't support Deep Color 48.\n");472return false;473}474475drm_dbg_kms(dev, "YUV420 format supported in that configuration.\n");476477return true;478479case HDMI_COLORSPACE_YUV422:480drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n");481482if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {483drm_dbg_kms(dev, "Sink doesn't support YUV422.\n");484return false;485}486487if (bpc > 12) {488drm_dbg_kms(dev, "YUV422 only supports 12 bpc or lower.\n");489return false;490}491492/*493* HDMI Spec 1.3 - Section 6.5 Pixel Encodings and Color Depth494* states that Deep Color is not relevant for YUV422 so we495* don't need to check the Deep Color bits in the EDIDs here.496*/497498drm_dbg_kms(dev, "YUV422 format supported in that configuration.\n");499500return true;501502case HDMI_COLORSPACE_YUV444:503drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n");504505if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {506drm_dbg_kms(dev, "Sink doesn't support YUV444.\n");507return false;508}509510if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) {511drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n");512return false;513}514515if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) {516drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n");517return false;518}519520drm_dbg_kms(dev, "YUV444 format supported in that configuration.\n");521522return true;523}524525drm_dbg_kms(dev, "Unsupported pixel format.\n");526return false;527}528529static enum drm_mode_status530hdmi_clock_valid(const struct drm_connector *connector,531const struct drm_display_mode *mode,532unsigned long long clock)533{534const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;535const struct drm_display_info *info = &connector->display_info;536537if (info->max_tmds_clock && clock > info->max_tmds_clock * 1000)538return MODE_CLOCK_HIGH;539540if (funcs && funcs->tmds_char_rate_valid) {541enum drm_mode_status status;542543status = funcs->tmds_char_rate_valid(connector, mode, clock);544if (status != MODE_OK)545return status;546}547548return MODE_OK;549}550551static int552hdmi_compute_clock(const struct drm_connector *connector,553struct drm_connector_state *conn_state,554const struct drm_display_mode *mode,555unsigned int bpc, enum hdmi_colorspace fmt)556{557enum drm_mode_status status;558unsigned long long clock;559560clock = drm_hdmi_compute_mode_clock(mode, bpc, fmt);561if (!clock)562return -EINVAL;563564status = hdmi_clock_valid(connector, mode, clock);565if (status != MODE_OK)566return -EINVAL;567568conn_state->hdmi.tmds_char_rate = clock;569570return 0;571}572573static bool574hdmi_try_format_bpc(const struct drm_connector *connector,575struct drm_connector_state *conn_state,576const struct drm_display_mode *mode,577unsigned int bpc, enum hdmi_colorspace fmt)578{579const struct drm_display_info *info = &connector->display_info;580struct drm_device *dev = connector->dev;581int ret;582583drm_dbg_kms(dev, "Trying %s output format with %u bpc\n",584drm_hdmi_connector_get_output_format_name(fmt),585bpc);586587if (!sink_supports_format_bpc(connector, info, mode, fmt, bpc)) {588drm_dbg_kms(dev, "%s output format not supported with %u bpc\n",589drm_hdmi_connector_get_output_format_name(fmt),590bpc);591return false;592}593594ret = hdmi_compute_clock(connector, conn_state, mode, bpc, fmt);595if (ret) {596drm_dbg_kms(dev, "Couldn't compute clock for %s output format and %u bpc\n",597drm_hdmi_connector_get_output_format_name(fmt),598bpc);599return false;600}601602drm_dbg_kms(dev, "%s output format supported with %u bpc (TMDS char rate: %llu Hz)\n",603drm_hdmi_connector_get_output_format_name(fmt),604bpc, conn_state->hdmi.tmds_char_rate);605606return true;607}608609static int610hdmi_compute_format_bpc(const struct drm_connector *connector,611struct drm_connector_state *conn_state,612const struct drm_display_mode *mode,613unsigned int max_bpc, enum hdmi_colorspace fmt)614{615struct drm_device *dev = connector->dev;616unsigned int bpc;617int ret;618619for (bpc = max_bpc; bpc >= 8; bpc -= 2) {620ret = hdmi_try_format_bpc(connector, conn_state, mode, bpc, fmt);621if (!ret)622continue;623624conn_state->hdmi.output_bpc = bpc;625conn_state->hdmi.output_format = fmt;626627drm_dbg_kms(dev,628"Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n",629mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),630conn_state->hdmi.output_bpc,631drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format),632conn_state->hdmi.tmds_char_rate);633634return 0;635}636637drm_dbg_kms(dev, "Failed. %s output format not supported for any bpc count.\n",638drm_hdmi_connector_get_output_format_name(fmt));639640return -EINVAL;641}642643static int644hdmi_compute_config(const struct drm_connector *connector,645struct drm_connector_state *conn_state,646const struct drm_display_mode *mode)647{648unsigned int max_bpc = clamp_t(unsigned int,649conn_state->max_bpc,6508, connector->max_bpc);651int ret;652653ret = hdmi_compute_format_bpc(connector, conn_state, mode, max_bpc,654HDMI_COLORSPACE_RGB);655if (ret) {656if (connector->ycbcr_420_allowed) {657ret = hdmi_compute_format_bpc(connector, conn_state,658mode, max_bpc,659HDMI_COLORSPACE_YUV420);660if (ret)661drm_dbg_kms(connector->dev,662"YUV420 output format doesn't work.\n");663} else {664drm_dbg_kms(connector->dev,665"YUV420 output format not allowed for connector.\n");666ret = -EINVAL;667}668}669670return ret;671}672673static int hdmi_generate_avi_infoframe(const struct drm_connector *connector,674struct drm_connector_state *conn_state)675{676const struct drm_display_mode *mode =677connector_state_get_mode(conn_state);678struct drm_connector_hdmi_infoframe *infoframe =679&conn_state->hdmi.infoframes.avi;680struct hdmi_avi_infoframe *frame =681&infoframe->data.avi;682bool is_limited_range = conn_state->hdmi.is_limited_range;683enum hdmi_quantization_range rgb_quant_range =684is_limited_range ? HDMI_QUANTIZATION_RANGE_LIMITED : HDMI_QUANTIZATION_RANGE_FULL;685int ret;686687infoframe->set = false;688689ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, mode);690if (ret)691return ret;692693frame->colorspace = conn_state->hdmi.output_format;694695/*696* FIXME: drm_hdmi_avi_infoframe_quant_range() doesn't handle697* YUV formats at all at the moment, so if we ever support YUV698* formats this needs to be revised.699*/700drm_hdmi_avi_infoframe_quant_range(frame, connector, mode, rgb_quant_range);701drm_hdmi_avi_infoframe_colorimetry(frame, conn_state);702drm_hdmi_avi_infoframe_bars(frame, conn_state);703704infoframe->set = true;705706return 0;707}708709static int hdmi_generate_spd_infoframe(const struct drm_connector *connector,710struct drm_connector_state *conn_state)711{712struct drm_connector_hdmi_infoframe *infoframe =713&conn_state->hdmi.infoframes.spd;714struct hdmi_spd_infoframe *frame =715&infoframe->data.spd;716int ret;717718infoframe->set = false;719720if (!connector->hdmi.funcs->spd.write_infoframe)721return 0;722723ret = hdmi_spd_infoframe_init(frame,724connector->hdmi.vendor,725connector->hdmi.product);726if (ret)727return ret;728729frame->sdi = HDMI_SPD_SDI_PC;730731infoframe->set = true;732733return 0;734}735736static int hdmi_generate_hdr_infoframe(const struct drm_connector *connector,737struct drm_connector_state *conn_state)738{739struct drm_connector_hdmi_infoframe *infoframe =740&conn_state->hdmi.infoframes.hdr_drm;741struct hdmi_drm_infoframe *frame =742&infoframe->data.drm;743int ret;744745infoframe->set = false;746747if (!connector->hdmi.funcs->hdr_drm.write_infoframe)748return 0;749750if (connector->max_bpc < 10)751return 0;752753if (!conn_state->hdr_output_metadata)754return 0;755756ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_state);757if (ret)758return ret;759760infoframe->set = true;761762return 0;763}764765static int hdmi_generate_hdmi_vendor_infoframe(const struct drm_connector *connector,766struct drm_connector_state *conn_state)767{768const struct drm_display_info *info = &connector->display_info;769const struct drm_display_mode *mode =770connector_state_get_mode(conn_state);771struct drm_connector_hdmi_infoframe *infoframe =772&conn_state->hdmi.infoframes.hdmi;773struct hdmi_vendor_infoframe *frame =774&infoframe->data.vendor.hdmi;775int ret;776777infoframe->set = false;778779if (!info->has_hdmi_infoframe)780return 0;781782ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, connector, mode);783if (ret)784return ret;785786infoframe->set = true;787788return 0;789}790791static int792hdmi_generate_infoframes(const struct drm_connector *connector,793struct drm_connector_state *conn_state)794{795const struct drm_display_info *info = &connector->display_info;796int ret;797798if (!info->is_hdmi)799return 0;800801ret = hdmi_generate_avi_infoframe(connector, conn_state);802if (ret)803return ret;804805ret = hdmi_generate_spd_infoframe(connector, conn_state);806if (ret)807return ret;808809/*810* Audio Infoframes will be generated by ALSA, and updated by811* drm_atomic_helper_connector_hdmi_update_audio_infoframe().812*/813814ret = hdmi_generate_hdr_infoframe(connector, conn_state);815if (ret)816return ret;817818ret = hdmi_generate_hdmi_vendor_infoframe(connector, conn_state);819if (ret)820return ret;821822return 0;823}824825/**826* drm_atomic_helper_connector_hdmi_check() - Helper to check HDMI connector atomic state827* @connector: DRM Connector828* @state: the DRM State object829*830* Provides a default connector state check handler for HDMI connectors.831* Checks that a desired connector update is valid, and updates various832* fields of derived state.833*834* RETURNS:835* Zero on success, or an errno code otherwise.836*/837int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,838struct drm_atomic_state *state)839{840struct drm_connector_state *old_conn_state =841drm_atomic_get_old_connector_state(state, connector);842struct drm_connector_state *new_conn_state =843drm_atomic_get_new_connector_state(state, connector);844const struct drm_display_mode *mode =845connector_state_get_mode(new_conn_state);846int ret;847848if (!new_conn_state->crtc || !new_conn_state->best_encoder)849return 0;850851ret = hdmi_compute_config(connector, new_conn_state, mode);852if (ret)853return ret;854855new_conn_state->hdmi.is_limited_range = hdmi_is_limited_range(connector, new_conn_state);856857ret = hdmi_generate_infoframes(connector, new_conn_state);858if (ret)859return ret;860861if (old_conn_state->hdmi.broadcast_rgb != new_conn_state->hdmi.broadcast_rgb ||862old_conn_state->hdmi.output_bpc != new_conn_state->hdmi.output_bpc ||863old_conn_state->hdmi.output_format != new_conn_state->hdmi.output_format) {864struct drm_crtc *crtc = new_conn_state->crtc;865struct drm_crtc_state *crtc_state;866867crtc_state = drm_atomic_get_crtc_state(state, crtc);868if (IS_ERR(crtc_state))869return PTR_ERR(crtc_state);870871crtc_state->mode_changed = true;872}873874return 0;875}876EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);877878/**879* drm_hdmi_connector_mode_valid() - Check if mode is valid for HDMI connector880* @connector: DRM connector to validate the mode881* @mode: Display mode to validate882*883* Generic .mode_valid implementation for HDMI connectors.884*/885enum drm_mode_status886drm_hdmi_connector_mode_valid(struct drm_connector *connector,887const struct drm_display_mode *mode)888{889unsigned long long clock;890891clock = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);892if (!clock)893return MODE_ERROR;894895return hdmi_clock_valid(connector, mode, clock);896}897EXPORT_SYMBOL(drm_hdmi_connector_mode_valid);898899static int clear_infoframe(struct drm_connector *connector,900const struct drm_connector_infoframe_funcs *funcs,901const char *type)902{903struct drm_device *dev = connector->dev;904int ret;905906drm_dbg_kms(dev, "Clearing %s InfoFrame\n", type);907908if (!funcs->clear_infoframe) {909drm_dbg_kms(dev, "Function not implemented, bailing.\n");910return -EOPNOTSUPP;911}912913ret = funcs->clear_infoframe(connector);914if (ret) {915drm_dbg_kms(dev, "Call failed: %d\n", ret);916return ret;917}918919return 0;920}921922static int write_infoframe(struct drm_connector *connector,923const struct drm_connector_infoframe_funcs *funcs,924const char *type,925struct drm_connector_hdmi_infoframe *new_frame)926{927struct drm_device *dev = connector->dev;928u8 buffer[HDMI_INFOFRAME_SIZE(MAX)];929int ret;930int len;931932drm_dbg_kms(dev, "Writing %s InfoFrame\n", type);933934if (!funcs->write_infoframe) {935drm_dbg_kms(dev, "Function not implemented, bailing.\n");936return -EOPNOTSUPP;937}938939len = hdmi_infoframe_pack(&new_frame->data, buffer, sizeof(buffer));940if (len < 0)941return len;942943ret = funcs->write_infoframe(connector, buffer, len);944if (ret) {945drm_dbg_kms(dev, "Call failed: %d\n", ret);946return ret;947}948949return 0;950}951952static int write_or_clear_infoframe(struct drm_connector *connector,953const struct drm_connector_infoframe_funcs *funcs,954const char *type,955struct drm_connector_hdmi_infoframe *old_frame,956struct drm_connector_hdmi_infoframe *new_frame)957{958if (new_frame->set)959return write_infoframe(connector, funcs, type, new_frame);960961if (old_frame->set && !new_frame->set)962return clear_infoframe(connector, funcs, type);963964return 0;965}966967/**968* drm_atomic_helper_connector_hdmi_update_infoframes - Update the Infoframes969* @connector: A pointer to the HDMI connector970* @state: The HDMI connector state to generate the infoframe from971*972* This function is meant for HDMI connector drivers to write their973* infoframes. It will typically be used in a974* @drm_connector_helper_funcs.atomic_enable implementation.975*976* Returns:977* Zero on success, error code on failure.978*/979int drm_atomic_helper_connector_hdmi_update_infoframes(struct drm_connector *connector,980struct drm_atomic_state *state)981{982const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;983struct drm_connector_state *old_conn_state =984drm_atomic_get_old_connector_state(state, connector);985struct drm_connector_state *new_conn_state =986drm_atomic_get_new_connector_state(state, connector);987struct drm_display_info *info = &connector->display_info;988int ret;989990if (!info->is_hdmi)991return 0;992993if (!funcs) {994drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n");995return -EINVAL;996}997998mutex_lock(&connector->hdmi.infoframes.lock);9991000ret = write_or_clear_infoframe(connector,1001&funcs->avi, "AVI",1002&old_conn_state->hdmi.infoframes.avi,1003&new_conn_state->hdmi.infoframes.avi);1004if (ret)1005goto out;10061007if (connector->hdmi.infoframes.audio.set) {1008ret = write_infoframe(connector,1009&funcs->audio, "Audio",1010&connector->hdmi.infoframes.audio);1011if (ret)1012goto out;1013}10141015ret = write_or_clear_infoframe(connector,1016&funcs->hdr_drm, "HDR DRM",1017&old_conn_state->hdmi.infoframes.hdr_drm,1018&new_conn_state->hdmi.infoframes.hdr_drm);1019if (ret)1020goto out;10211022ret = write_or_clear_infoframe(connector,1023&funcs->spd, "SPD",1024&old_conn_state->hdmi.infoframes.spd,1025&new_conn_state->hdmi.infoframes.spd);1026if (ret)1027goto out;10281029if (info->has_hdmi_infoframe) {1030ret = write_or_clear_infoframe(connector,1031&funcs->hdmi, "HDMI-VS",1032&old_conn_state->hdmi.infoframes.hdmi,1033&new_conn_state->hdmi.infoframes.hdmi);1034if (ret)1035goto out;1036}10371038out:1039mutex_unlock(&connector->hdmi.infoframes.lock);1040return ret;1041}1042EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_infoframes);10431044/**1045* drm_atomic_helper_connector_hdmi_update_audio_infoframe - Update the Audio Infoframe1046* @connector: A pointer to the HDMI connector1047* @frame: A pointer to the audio infoframe to write1048*1049* This function is meant for HDMI connector drivers to update their1050* audio infoframe. It will typically be used in one of the ALSA hooks1051* (most likely prepare).1052*1053* Returns:1054* Zero on success, error code on failure.1055*/1056int1057drm_atomic_helper_connector_hdmi_update_audio_infoframe(struct drm_connector *connector,1058struct hdmi_audio_infoframe *frame)1059{1060const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;1061struct drm_connector_hdmi_infoframe *infoframe =1062&connector->hdmi.infoframes.audio;1063struct drm_display_info *info = &connector->display_info;1064int ret;10651066if (!info->is_hdmi)1067return 0;10681069if (!funcs || !funcs->audio.write_infoframe) {1070drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n");1071return -EINVAL;1072}10731074mutex_lock(&connector->hdmi.infoframes.lock);10751076memcpy(&infoframe->data, frame, sizeof(infoframe->data));1077infoframe->set = true;10781079ret = write_infoframe(connector, &funcs->audio, "Audio", infoframe);10801081mutex_unlock(&connector->hdmi.infoframes.lock);10821083return ret;1084}1085EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_update_audio_infoframe);10861087/**1088* drm_atomic_helper_connector_hdmi_clear_audio_infoframe - Stop sending the Audio Infoframe1089* @connector: A pointer to the HDMI connector1090*1091* This function is meant for HDMI connector drivers to stop sending their1092* audio infoframe. It will typically be used in one of the ALSA hooks1093* (most likely shutdown).1094*1095* Returns:1096* Zero on success, error code on failure.1097*/1098int1099drm_atomic_helper_connector_hdmi_clear_audio_infoframe(struct drm_connector *connector)1100{1101const struct drm_connector_hdmi_funcs *funcs = connector->hdmi.funcs;1102struct drm_connector_hdmi_infoframe *infoframe =1103&connector->hdmi.infoframes.audio;1104struct drm_display_info *info = &connector->display_info;1105int ret;11061107if (!info->is_hdmi)1108return 0;11091110if (!funcs || !funcs->audio.write_infoframe) {1111drm_dbg_kms(connector->dev, "Function not implemented, bailing.\n");1112return -EINVAL;1113}11141115mutex_lock(&connector->hdmi.infoframes.lock);11161117infoframe->set = false;11181119ret = clear_infoframe(connector, &funcs->audio, "Audio");11201121memset(&infoframe->data, 0, sizeof(infoframe->data));11221123mutex_unlock(&connector->hdmi.infoframes.lock);11241125return ret;1126}1127EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_clear_audio_infoframe);11281129static void1130drm_atomic_helper_connector_hdmi_update(struct drm_connector *connector,1131enum drm_connector_status status)1132{1133const struct drm_edid *drm_edid;11341135if (status == connector_status_disconnected) {1136// TODO: also handle scramber, HDMI sink disconnected.1137drm_connector_hdmi_audio_plugged_notify(connector, false);1138drm_edid_connector_update(connector, NULL);1139drm_connector_cec_phys_addr_invalidate(connector);1140return;1141}11421143if (connector->hdmi.funcs->read_edid)1144drm_edid = connector->hdmi.funcs->read_edid(connector);1145else1146drm_edid = drm_edid_read(connector);11471148drm_edid_connector_update(connector, drm_edid);11491150drm_edid_free(drm_edid);11511152if (status == connector_status_connected) {1153// TODO: also handle scramber, HDMI sink is now connected.1154drm_connector_hdmi_audio_plugged_notify(connector, true);1155drm_connector_cec_phys_addr_set(connector);1156}1157}11581159/**1160* drm_atomic_helper_connector_hdmi_hotplug - Handle the hotplug event for the HDMI connector1161* @connector: A pointer to the HDMI connector1162* @status: Connection status1163*1164* This function should be called as a part of the .detect() / .detect_ctx()1165* callbacks for all status changes.1166*/1167void drm_atomic_helper_connector_hdmi_hotplug(struct drm_connector *connector,1168enum drm_connector_status status)1169{1170drm_atomic_helper_connector_hdmi_update(connector, status);1171}1172EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_hotplug);11731174/**1175* drm_atomic_helper_connector_hdmi_force - HDMI Connector implementation of the force callback1176* @connector: A pointer to the HDMI connector1177*1178* This function implements the .force() callback for the HDMI connectors. It1179* can either be used directly as the callback or should be called from within1180* the .force() callback implementation to maintain the HDMI-specific1181* connector's data.1182*/1183void drm_atomic_helper_connector_hdmi_force(struct drm_connector *connector)1184{1185drm_atomic_helper_connector_hdmi_update(connector, connector->status);1186}1187EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_force);118811891190