^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (c) 2006 Luc Verhaegen (quirks list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2007-2008 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Jesse Barnes <jesse.barnes@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2010 Red Hat, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * FB layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Permission is hereby granted, free of charge, to any person obtaining a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * copy of this software and associated documentation files (the "Software"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * to deal in the Software without restriction, including without limitation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * the rights to use, copy, modify, merge, publish, distribute, sub license,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * and/or sell copies of the Software, and to permit persons to whom the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Software is furnished to do so, subject to the following conditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * The above copyright notice and this permission notice (including the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * next paragraph) shall be included in all copies or substantial portions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * of the Software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * DEALINGS IN THE SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/hdmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/vga_switcheroo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <drm/drm_displayid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <drm/drm_drv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <drm/drm_edid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <drm/drm_encoder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <drm/drm_print.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <drm/drm_scdc_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include "drm_crtc_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define version_greater(edid, maj, min) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) (((edid)->version > (maj)) || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ((edid)->version == (maj) && (edid)->revision > (min)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define EDID_EST_TIMINGS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define EDID_STD_TIMINGS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define EDID_DETAILED_TIMINGS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * EDID blocks out in the wild have a variety of bugs, try to collect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * them here (note that userspace may work around broken monitors first,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * but fixes should make their way here so that the kernel "just works"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * on as many displays as possible).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* First detailed mode wrong, use largest 60Hz mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define EDID_QUIRK_PREFER_LARGE_60 (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* Reported 135MHz pixel clock is too high, needs adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* Prefer the largest mode at 75 Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define EDID_QUIRK_PREFER_LARGE_75 (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* Detail timing is in cm not mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define EDID_QUIRK_DETAILED_IN_CM (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* Detailed timing descriptors have bogus size values, so just take the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * maximum size and use that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* use +hsync +vsync for detailed mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Force reduced-blanking timings for detailed modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* Force 8bpc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define EDID_QUIRK_FORCE_8BPC (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Force 12bpc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define EDID_QUIRK_FORCE_12BPC (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Force 6bpc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define EDID_QUIRK_FORCE_6BPC (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Force 10bpc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define EDID_QUIRK_FORCE_10BPC (1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Non desktop display (i.e. HMD) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define EDID_QUIRK_NON_DESKTOP (1 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct detailed_mode_closure {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct drm_connector *connector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct edid *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) bool preferred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u32 quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define LEVEL_DMT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define LEVEL_GTF 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define LEVEL_GTF2 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define LEVEL_CVT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static const struct edid_quirk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) char vendor[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int product_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) } edid_quirk_list[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* Acer AL1706 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Acer F51 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { "AEO", 0, EDID_QUIRK_FORCE_6BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* BOE model on HP Pavilion 15-n233sl reports 8 bpc, but is a 6 bpc panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) { "BOE", 0x78b, EDID_QUIRK_FORCE_6BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* CPT panel of Asus UX303LA reports 8 bpc, but is a 6 bpc panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { "CPT", 0x17df, EDID_QUIRK_FORCE_6BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { "SDC", 0x3652, EDID_QUIRK_FORCE_6BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* BOE model 0x0771 reports 8 bpc, but is a 6 bpc panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { "BOE", 0x0771, EDID_QUIRK_FORCE_6BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* Belinea 10 15 55 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Envision Peripherals, Inc. EN-7100e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* Envision EN2028 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { "EPI", 8232, EDID_QUIRK_PREFER_LARGE_60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* Funai Electronics PM36B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) EDID_QUIRK_DETAILED_IN_CM },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) { "LGD", 764, EDID_QUIRK_FORCE_10BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* LG Philips LCD LP154W01-A5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* Samsung SyncMaster 205BW. Note: irony */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Samsung SyncMaster 22[5-6]BW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Sony PVM-2541A does up to 12 bpc, but only reports max 8 bpc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { "SNY", 0x2541, EDID_QUIRK_FORCE_12BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* ViewSonic VA2026w */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Medion MD 30217 PG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Lenovo G50 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { "SDC", 18514, EDID_QUIRK_FORCE_6BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) { "ETR", 13896, EDID_QUIRK_FORCE_8BPC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Valve Index Headset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) { "VLV", 0x91a8, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) { "VLV", 0x91b0, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) { "VLV", 0x91b1, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) { "VLV", 0x91b2, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) { "VLV", 0x91b3, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) { "VLV", 0x91b4, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) { "VLV", 0x91b5, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) { "VLV", 0x91b6, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) { "VLV", 0x91b7, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) { "VLV", 0x91b8, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) { "VLV", 0x91b9, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { "VLV", 0x91ba, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { "VLV", 0x91bb, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) { "VLV", 0x91bc, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { "VLV", 0x91bd, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { "VLV", 0x91be, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { "VLV", 0x91bf, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* HTC Vive and Vive Pro VR Headsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) { "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) { "HVR", 0xaa02, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* Oculus Rift DK1, DK2, CV1 and Rift S VR Headsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { "OVR", 0x0001, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) { "OVR", 0x0003, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { "OVR", 0x0004, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) { "OVR", 0x0012, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* Windows Mixed Reality Headsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { "ACR", 0x7fce, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { "HPN", 0x3515, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { "LEN", 0x0408, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) { "LEN", 0xb800, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { "FUJ", 0x1970, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) { "DEL", 0x7fce, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) { "SEC", 0x144a, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) { "AUS", 0xc102, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Sony PlayStation VR Headset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) { "SNY", 0x0704, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Sensics VR Headsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) { "SEN", 0x1019, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* OSVR HDK and HDK2 VR Headsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { "SVR", 0x1019, EDID_QUIRK_NON_DESKTOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * Autogenerated from the DMT spec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * This table is copied from xfree86/modes/xf86EdidModes.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static const struct drm_display_mode drm_dmt_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* 0x01 - 640x350@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 736, 832, 0, 350, 382, 385, 445, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* 0x02 - 640x400@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 736, 832, 0, 400, 401, 404, 445, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* 0x03 - 720x400@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 828, 936, 0, 400, 401, 404, 446, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* 0x04 - 640x480@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 752, 800, 0, 480, 490, 492, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* 0x05 - 640x480@72Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 704, 832, 0, 480, 489, 492, 520, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* 0x06 - 640x480@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 720, 840, 0, 480, 481, 484, 500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* 0x07 - 640x480@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 752, 832, 0, 480, 481, 484, 509, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* 0x08 - 800x600@56Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 896, 1024, 0, 600, 601, 603, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* 0x09 - 800x600@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 968, 1056, 0, 600, 601, 605, 628, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* 0x0a - 800x600@72Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 976, 1040, 0, 600, 637, 643, 666, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* 0x0b - 800x600@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 896, 1056, 0, 600, 601, 604, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* 0x0c - 800x600@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 896, 1048, 0, 600, 601, 604, 631, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* 0x0d - 800x600@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 73250, 800, 848,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 880, 960, 0, 600, 603, 607, 636, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* 0x0e - 848x480@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) { DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 976, 1088, 0, 480, 486, 494, 517, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* 0x0f - 1024x768@43Hz, interlace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) { DRM_MODE("1024x768i", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 1208, 1264, 0, 768, 768, 776, 817, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) DRM_MODE_FLAG_INTERLACE) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* 0x10 - 1024x768@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 1184, 1344, 0, 768, 771, 777, 806, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /* 0x11 - 1024x768@70Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 1184, 1328, 0, 768, 771, 777, 806, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* 0x12 - 1024x768@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 1136, 1312, 0, 768, 769, 772, 800, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* 0x13 - 1024x768@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 1168, 1376, 0, 768, 769, 772, 808, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /* 0x14 - 1024x768@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 115500, 1024, 1072,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 1104, 1184, 0, 768, 771, 775, 813, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* 0x15 - 1152x864@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 1344, 1600, 0, 864, 865, 868, 900, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* 0x55 - 1280x720@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 1430, 1650, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* 0x16 - 1280x768@60Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 68250, 1280, 1328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 1360, 1440, 0, 768, 771, 778, 790, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* 0x17 - 1280x768@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 1472, 1664, 0, 768, 771, 778, 798, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* 0x18 - 1280x768@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 1488, 1696, 0, 768, 771, 778, 805, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* 0x19 - 1280x768@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 1496, 1712, 0, 768, 771, 778, 809, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* 0x1a - 1280x768@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 140250, 1280, 1328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 1360, 1440, 0, 768, 771, 778, 813, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* 0x1b - 1280x800@60Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 71000, 1280, 1328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 1360, 1440, 0, 800, 803, 809, 823, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* 0x1c - 1280x800@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 1480, 1680, 0, 800, 803, 809, 831, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* 0x1d - 1280x800@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 1488, 1696, 0, 800, 803, 809, 838, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* 0x1e - 1280x800@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 1496, 1712, 0, 800, 803, 809, 843, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* 0x1f - 1280x800@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 146250, 1280, 1328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 1360, 1440, 0, 800, 803, 809, 847, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* 0x20 - 1280x960@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 1488, 1800, 0, 960, 961, 964, 1000, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* 0x21 - 1280x960@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 1504, 1728, 0, 960, 961, 964, 1011, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* 0x22 - 1280x960@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 175500, 1280, 1328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 1360, 1440, 0, 960, 963, 967, 1017, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* 0x23 - 1280x1024@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* 0x24 - 1280x1024@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* 0x25 - 1280x1024@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 1504, 1728, 0, 1024, 1025, 1028, 1072, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* 0x26 - 1280x1024@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 187250, 1280, 1328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 1360, 1440, 0, 1024, 1027, 1034, 1084, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* 0x27 - 1360x768@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 1536, 1792, 0, 768, 771, 777, 795, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* 0x28 - 1360x768@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 148250, 1360, 1408,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 1440, 1520, 0, 768, 771, 776, 813, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* 0x51 - 1366x768@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 85500, 1366, 1436,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 1579, 1792, 0, 768, 771, 774, 798, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* 0x56 - 1366x768@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 72000, 1366, 1380,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 1436, 1500, 0, 768, 769, 772, 800, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* 0x29 - 1400x1050@60Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 101000, 1400, 1448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 1480, 1560, 0, 1050, 1053, 1057, 1080, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* 0x2a - 1400x1050@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* 0x2b - 1400x1050@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 1648, 1896, 0, 1050, 1053, 1057, 1099, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* 0x2c - 1400x1050@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 1656, 1912, 0, 1050, 1053, 1057, 1105, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* 0x2d - 1400x1050@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 208000, 1400, 1448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 1480, 1560, 0, 1050, 1053, 1057, 1112, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* 0x2e - 1440x900@60Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 88750, 1440, 1488,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 1520, 1600, 0, 900, 903, 909, 926, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* 0x2f - 1440x900@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 1672, 1904, 0, 900, 903, 909, 934, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* 0x30 - 1440x900@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 1688, 1936, 0, 900, 903, 909, 942, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /* 0x31 - 1440x900@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 1696, 1952, 0, 900, 903, 909, 948, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* 0x32 - 1440x900@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 182750, 1440, 1488,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 1520, 1600, 0, 900, 903, 909, 953, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* 0x53 - 1600x900@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) { DRM_MODE("1600x900", DRM_MODE_TYPE_DRIVER, 108000, 1600, 1624,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 1704, 1800, 0, 900, 901, 904, 1000, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /* 0x33 - 1600x1200@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* 0x34 - 1600x1200@65Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* 0x35 - 1600x1200@70Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* 0x36 - 1600x1200@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 202500, 1600, 1664,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /* 0x37 - 1600x1200@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* 0x38 - 1600x1200@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 268250, 1600, 1648,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 1680, 1760, 0, 1200, 1203, 1207, 1271, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* 0x39 - 1680x1050@60Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 119000, 1680, 1728,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 1760, 1840, 0, 1050, 1053, 1059, 1080, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* 0x3a - 1680x1050@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* 0x3b - 1680x1050@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 1976, 2272, 0, 1050, 1053, 1059, 1099, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /* 0x3c - 1680x1050@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 1984, 2288, 0, 1050, 1053, 1059, 1105, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* 0x3d - 1680x1050@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 245500, 1680, 1728,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 1760, 1840, 0, 1050, 1053, 1059, 1112, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* 0x3e - 1792x1344@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* 0x3f - 1792x1344@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 2104, 2456, 0, 1344, 1345, 1348, 1417, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* 0x40 - 1792x1344@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 333250, 1792, 1840,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 1872, 1952, 0, 1344, 1347, 1351, 1423, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* 0x41 - 1856x1392@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* 0x42 - 1856x1392@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 2208, 2560, 0, 1392, 1393, 1396, 1500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* 0x43 - 1856x1392@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 356500, 1856, 1904,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 1936, 2016, 0, 1392, 1395, 1399, 1474, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* 0x52 - 1920x1080@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /* 0x44 - 1920x1200@60Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 154000, 1920, 1968,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 2000, 2080, 0, 1200, 1203, 1209, 1235, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* 0x45 - 1920x1200@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* 0x46 - 1920x1200@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 2264, 2608, 0, 1200, 1203, 1209, 1255, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /* 0x47 - 1920x1200@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 2272, 2624, 0, 1200, 1203, 1209, 1262, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* 0x48 - 1920x1200@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 317000, 1920, 1968,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 2000, 2080, 0, 1200, 1203, 1209, 1271, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* 0x49 - 1920x1440@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* 0x4a - 1920x1440@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 2288, 2640, 0, 1440, 1441, 1444, 1500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* 0x4b - 1920x1440@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 380500, 1920, 1968,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 2000, 2080, 0, 1440, 1443, 1447, 1525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* 0x54 - 2048x1152@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) { DRM_MODE("2048x1152", DRM_MODE_TYPE_DRIVER, 162000, 2048, 2074,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 2154, 2250, 0, 1152, 1153, 1156, 1200, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* 0x4c - 2560x1600@60Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 268500, 2560, 2608,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 2640, 2720, 0, 1600, 1603, 1609, 1646, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* 0x4d - 2560x1600@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* 0x4e - 2560x1600@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 3048, 3536, 0, 1600, 1603, 1609, 1672, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* 0x4f - 2560x1600@85Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* 0x50 - 2560x1600@120Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 552750, 2560, 2608,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 2640, 2720, 0, 1600, 1603, 1609, 1694, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* 0x57 - 4096x2160@60Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 556744, 4096, 4104,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 4136, 4176, 0, 2160, 2208, 2216, 2222, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) /* 0x58 - 4096x2160@59.94Hz RB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 556188, 4096, 4104,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 4136, 4176, 0, 2160, 2208, 2216, 2222, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * These more or less come from the DMT spec. The 720x400 modes are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * inferred from historical 80x25 practice. The 640x480@67 and 832x624@75
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * modes are old-school Mac modes. The EDID spec says the 1152x864@75 mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * should be 1152x870, again for the Mac, but instead we use the x864 DMT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * The DMT modes have been fact-checked; the rest are mild guesses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static const struct drm_display_mode edid_est_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 968, 1056, 0, 600, 601, 605, 628, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 896, 1024, 0, 600, 601, 603, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 720, 840, 0, 480, 481, 484, 500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 704, 832, 0, 480, 489, 492, 520, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 768, 864, 0, 480, 483, 486, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 752, 800, 0, 480, 490, 492, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 846, 900, 0, 400, 421, 423, 449, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 846, 900, 0, 400, 412, 414, 449, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 1136, 1312, 0, 768, 769, 772, 800, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 1184, 1328, 0, 768, 771, 777, 806, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 1184, 1344, 0, 768, 771, 777, 806, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) { DRM_MODE("1024x768i", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 1208, 1264, 0, 768, 768, 776, 817, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 928, 1152, 0, 624, 625, 628, 667, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 896, 1056, 0, 600, 601, 604, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 976, 1040, 0, 600, 637, 643, 666, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 1344, 1600, 0, 864, 865, 868, 900, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct minimode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) short w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) short h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) short r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) short rb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static const struct minimode est3_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* byte 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) { 640, 350, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) { 640, 400, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) { 720, 400, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) { 640, 480, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) { 848, 480, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) { 800, 600, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) { 1024, 768, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) { 1152, 864, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /* byte 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) { 1280, 768, 60, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) { 1280, 768, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) { 1280, 768, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) { 1280, 768, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) { 1280, 960, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) { 1280, 960, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) { 1280, 1024, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) { 1280, 1024, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /* byte 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) { 1360, 768, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) { 1440, 900, 60, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) { 1440, 900, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) { 1440, 900, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) { 1440, 900, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) { 1400, 1050, 60, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) { 1400, 1050, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) { 1400, 1050, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* byte 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) { 1400, 1050, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) { 1680, 1050, 60, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) { 1680, 1050, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) { 1680, 1050, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) { 1680, 1050, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) { 1600, 1200, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) { 1600, 1200, 65, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) { 1600, 1200, 70, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* byte 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) { 1600, 1200, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) { 1600, 1200, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) { 1792, 1344, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) { 1792, 1344, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) { 1856, 1392, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) { 1856, 1392, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) { 1920, 1200, 60, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) { 1920, 1200, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* byte 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) { 1920, 1200, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) { 1920, 1200, 85, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) { 1920, 1440, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) { 1920, 1440, 75, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) static const struct minimode extra_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) { 1024, 576, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) { 1366, 768, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) { 1600, 900, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) { 1680, 945, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) { 1920, 1080, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) { 2048, 1152, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) { 2048, 1536, 60, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * From CEA/CTA-861 spec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * Do not access directly, instead always use cea_mode_for_vic().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static const struct drm_display_mode edid_cea_modes_1[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /* 1 - 640x480@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 752, 800, 0, 480, 490, 492, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* 2 - 720x480@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 798, 858, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* 3 - 720x480@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 798, 858, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* 4 - 1280x720@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 1430, 1650, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* 5 - 1920x1080i@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /* 6 - 720(1440)x480i@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 801, 858, 0, 480, 488, 494, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* 7 - 720(1440)x480i@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 801, 858, 0, 480, 488, 494, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /* 8 - 720(1440)x240@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) { DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 801, 858, 0, 240, 244, 247, 262, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* 9 - 720(1440)x240@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) { DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 801, 858, 0, 240, 244, 247, 262, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* 10 - 2880x480i@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 3204, 3432, 0, 480, 488, 494, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /* 11 - 2880x480i@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 3204, 3432, 0, 480, 488, 494, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /* 12 - 2880x240@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 3204, 3432, 0, 240, 244, 247, 262, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /* 13 - 2880x240@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 3204, 3432, 0, 240, 244, 247, 262, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /* 14 - 1440x480@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 1596, 1716, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* 15 - 1440x480@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 1596, 1716, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) /* 16 - 1920x1080@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* 17 - 720x576@50Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 796, 864, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* 18 - 720x576@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 796, 864, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* 19 - 1280x720@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 1760, 1980, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) /* 20 - 1920x1080i@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* 21 - 720(1440)x576i@50Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 795, 864, 0, 576, 580, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /* 22 - 720(1440)x576i@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 795, 864, 0, 576, 580, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* 23 - 720(1440)x288@50Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) { DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 795, 864, 0, 288, 290, 293, 312, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /* 24 - 720(1440)x288@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) { DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 795, 864, 0, 288, 290, 293, 312, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* 25 - 2880x576i@50Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 3180, 3456, 0, 576, 580, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) /* 26 - 2880x576i@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 3180, 3456, 0, 576, 580, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /* 27 - 2880x288@50Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 3180, 3456, 0, 288, 290, 293, 312, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /* 28 - 2880x288@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 3180, 3456, 0, 288, 290, 293, 312, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /* 29 - 1440x576@50Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 1592, 1728, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /* 30 - 1440x576@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 1592, 1728, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* 31 - 1920x1080@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* 32 - 1920x1080@24Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) /* 33 - 1920x1080@25Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) 2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* 34 - 1920x1080@30Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) /* 35 - 2880x480@60Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 3192, 3432, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /* 36 - 2880x480@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 3192, 3432, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) /* 37 - 2880x576@50Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 3184, 3456, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* 38 - 2880x576@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 3184, 3456, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /* 39 - 1920x1080i@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 2120, 2304, 0, 1080, 1126, 1136, 1250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* 40 - 1920x1080i@100Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* 41 - 1280x720@100Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 1760, 1980, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /* 42 - 720x576@100Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 796, 864, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /* 43 - 720x576@100Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) 796, 864, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /* 44 - 720(1440)x576i@100Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) 795, 864, 0, 576, 580, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) /* 45 - 720(1440)x576i@100Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) 795, 864, 0, 576, 580, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /* 46 - 1920x1080i@120Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) 2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) DRM_MODE_FLAG_INTERLACE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /* 47 - 1280x720@120Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) 1430, 1650, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* 48 - 720x480@120Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) 798, 858, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /* 49 - 720x480@120Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) 798, 858, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /* 50 - 720(1440)x480i@120Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 27000, 720, 739,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) 801, 858, 0, 480, 488, 494, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* 51 - 720(1440)x480i@120Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 27000, 720, 739,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) 801, 858, 0, 480, 488, 494, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) /* 52 - 720x576@200Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) 796, 864, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) /* 53 - 720x576@200Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 796, 864, 0, 576, 581, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /* 54 - 720(1440)x576i@200Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 795, 864, 0, 576, 580, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) /* 55 - 720(1440)x576i@200Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) { DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 795, 864, 0, 576, 580, 586, 625, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) /* 56 - 720x480@240Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 798, 858, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* 57 - 720x480@240Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 798, 858, 0, 480, 489, 495, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /* 58 - 720(1440)x480i@240Hz 4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 54000, 720, 739,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 801, 858, 0, 480, 488, 494, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) /* 59 - 720(1440)x480i@240Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 54000, 720, 739,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 801, 858, 0, 480, 488, 494, 525, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) /* 60 - 1280x720@24Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 3080, 3300, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /* 61 - 1280x720@25Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 3740, 3960, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) /* 62 - 1280x720@30Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 3080, 3300, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) /* 63 - 1920x1080@120Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /* 64 - 1920x1080@100Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /* 65 - 1280x720@24Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 3080, 3300, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /* 66 - 1280x720@25Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 3740, 3960, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* 67 - 1280x720@30Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 3080, 3300, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* 68 - 1280x720@50Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 1760, 1980, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) /* 69 - 1280x720@60Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 1430, 1650, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* 70 - 1280x720@100Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 1760, 1980, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) /* 71 - 1280x720@120Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 1430, 1650, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) /* 72 - 1920x1080@24Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) /* 73 - 1920x1080@25Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) /* 74 - 1920x1080@30Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) /* 75 - 1920x1080@50Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) /* 76 - 1920x1080@60Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /* 77 - 1920x1080@100Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /* 78 - 1920x1080@120Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) /* 79 - 1680x720@24Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 3040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 3080, 3300, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) /* 80 - 1680x720@25Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2908,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 2948, 3168, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /* 81 - 1680x720@30Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2380,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 2420, 2640, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* 82 - 1680x720@50Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 82500, 1680, 1940,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 1980, 2200, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /* 83 - 1680x720@60Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 99000, 1680, 1940,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 1980, 2200, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /* 84 - 1680x720@100Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 165000, 1680, 1740,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 1780, 2000, 0, 720, 725, 730, 825, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) /* 85 - 1680x720@120Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 198000, 1680, 1740,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 1780, 2000, 0, 720, 725, 730, 825, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /* 86 - 2560x1080@24Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 99000, 2560, 3558,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 3602, 3750, 0, 1080, 1084, 1089, 1100, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* 87 - 2560x1080@25Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 90000, 2560, 3008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 3052, 3200, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) /* 88 - 2560x1080@30Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 118800, 2560, 3328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 3372, 3520, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) /* 89 - 2560x1080@50Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 185625, 2560, 3108,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 3152, 3300, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) /* 90 - 2560x1080@60Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 198000, 2560, 2808,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 2852, 3000, 0, 1080, 1084, 1089, 1100, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) /* 91 - 2560x1080@100Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 371250, 2560, 2778,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 2822, 2970, 0, 1080, 1084, 1089, 1250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* 92 - 2560x1080@120Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 495000, 2560, 3108,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 3152, 3300, 0, 1080, 1084, 1089, 1250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) /* 93 - 3840x2160@24Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) /* 94 - 3840x2160@25Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) /* 95 - 3840x2160@30Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /* 96 - 3840x2160@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) /* 97 - 3840x2160@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) /* 98 - 4096x2160@24Hz 256:135 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) /* 99 - 4096x2160@25Hz 256:135 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) /* 100 - 4096x2160@30Hz 256:135 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) /* 101 - 4096x2160@50Hz 256:135 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) /* 102 - 4096x2160@60Hz 256:135 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /* 103 - 3840x2160@24Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /* 104 - 3840x2160@25Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) /* 105 - 3840x2160@30Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) /* 106 - 3840x2160@50Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /* 107 - 3840x2160@60Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /* 108 - 1280x720@48Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 90000, 1280, 2240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 2280, 2500, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /* 109 - 1280x720@48Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 90000, 1280, 2240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 2280, 2500, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) /* 110 - 1680x720@48Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) { DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 99000, 1680, 2490,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 2530, 2750, 0, 720, 725, 730, 750, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) /* 111 - 1920x1080@48Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2558,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) /* 112 - 1920x1080@48Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2558,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) /* 113 - 2560x1080@48Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) { DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 198000, 2560, 3558,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 3602, 3750, 0, 1080, 1084, 1089, 1100, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) /* 114 - 3840x2160@48Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 5116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) /* 115 - 4096x2160@48Hz 256:135 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) /* 116 - 3840x2160@48Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 5116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) /* 117 - 3840x2160@100Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4896,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) /* 118 - 3840x2160@120Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4016,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) /* 119 - 3840x2160@100Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4896,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) /* 120 - 3840x2160@120Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 1188000, 3840, 4016,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) /* 121 - 5120x2160@24Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 396000, 5120, 7116,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 7204, 7500, 0, 2160, 2168, 2178, 2200, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) /* 122 - 5120x2160@25Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 396000, 5120, 6816,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 6904, 7200, 0, 2160, 2168, 2178, 2200, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) /* 123 - 5120x2160@30Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 396000, 5120, 5784,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 5872, 6000, 0, 2160, 2168, 2178, 2200, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) /* 124 - 5120x2160@48Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 742500, 5120, 5866,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 5954, 6250, 0, 2160, 2168, 2178, 2475, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) /* 125 - 5120x2160@50Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 742500, 5120, 6216,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 6304, 6600, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /* 126 - 5120x2160@60Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 742500, 5120, 5284,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 5372, 5500, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) /* 127 - 5120x2160@100Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 1485000, 5120, 6216,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 6304, 6600, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * From CEA/CTA-861 spec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * Do not access directly, instead always use cea_mode_for_vic().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) static const struct drm_display_mode edid_cea_modes_193[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) /* 193 - 5120x2160@120Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 1485000, 5120, 5284,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 5372, 5500, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) /* 194 - 7680x4320@24Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) /* 195 - 7680x4320@25Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10032,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) /* 196 - 7680x4320@30Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 8232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) /* 197 - 7680x4320@48Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) /* 198 - 7680x4320@50Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10032,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /* 199 - 7680x4320@60Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 8232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) /* 200 - 7680x4320@100Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 9792,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 9968, 10560, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) /* 201 - 7680x4320@120Hz 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 8032,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 8208, 8800, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) /* 202 - 7680x4320@24Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) /* 203 - 7680x4320@25Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10032,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /* 204 - 7680x4320@30Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 8232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) /* 205 - 7680x4320@48Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 10408, 11000, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) /* 206 - 7680x4320@50Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10032,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 10208, 10800, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) /* 207 - 7680x4320@60Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 8232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 8408, 9000, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) /* 208 - 7680x4320@100Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 9792,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 9968, 10560, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) /* 209 - 7680x4320@120Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 8032,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 8208, 8800, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) /* 210 - 10240x4320@24Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 11732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 11908, 12500, 0, 4320, 4336, 4356, 4950, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) /* 211 - 10240x4320@25Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 12732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 12908, 13500, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) /* 212 - 10240x4320@30Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 10528,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) /* 213 - 10240x4320@48Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 11732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 11908, 12500, 0, 4320, 4336, 4356, 4950, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) /* 214 - 10240x4320@50Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 12732,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 12908, 13500, 0, 4320, 4336, 4356, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) /* 215 - 10240x4320@60Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 10528,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) /* 216 - 10240x4320@100Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 5940000, 10240, 12432,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 12608, 13200, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) /* 217 - 10240x4320@120Hz 64:27 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 5940000, 10240, 10528,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 10704, 11000, 0, 4320, 4336, 4356, 4500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) /* 218 - 4096x2160@100Hz 256:135 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4896,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) /* 219 - 4096x2160@120Hz 256:135 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4184,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) * HDMI 1.4 4k modes. Index using the VIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) static const struct drm_display_mode edid_4k_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) /* 0 - dummy, VICs start at 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) /* 1 - 3840x2160@30Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 3840, 4016, 4104, 4400, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) /* 2 - 3840x2160@25Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 3840, 4896, 4984, 5280, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) /* 3 - 3840x2160@24Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) 3840, 5116, 5204, 5500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) /* 4 - 4096x2160@24Hz (SMPTE) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 4096, 5116, 5204, 5500, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 2160, 2168, 2178, 2250, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) /*** DDC fetch and block validation ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) static const u8 edid_header[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) * drm_edid_header_is_valid - sanity check the header of the base EDID block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) * @raw_edid: pointer to raw base EDID block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) * Sanity check the header of the base EDID block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) * Return: 8 if the header is perfect, down to 0 if it's totally wrong.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) int drm_edid_header_is_valid(const u8 *raw_edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) int i, score = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) for (i = 0; i < sizeof(edid_header); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) if (raw_edid[i] == edid_header[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) score++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) return score;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) EXPORT_SYMBOL(drm_edid_header_is_valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) static int edid_fixup __read_mostly = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) module_param_named(edid_fixup, edid_fixup, int, 0400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) MODULE_PARM_DESC(edid_fixup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) "Minimum number of valid EDID header bytes (0-8, default 6)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) static int validate_displayid(u8 *displayid, int length, int idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) static int drm_edid_block_checksum(const u8 *raw_edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) u8 csum = 0, crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) for (i = 0; i < EDID_LENGTH - 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) csum += raw_edid[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) crc = 0x100 - csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) return crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) static bool drm_edid_block_checksum_diff(const u8 *raw_edid, u8 real_checksum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) if (raw_edid[EDID_LENGTH - 1] != real_checksum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) static bool drm_edid_is_zero(const u8 *in_edid, int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (memchr_inv(in_edid, 0, length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) * drm_edid_are_equal - compare two edid blobs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) * @edid1: pointer to first blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) * @edid2: pointer to second blob
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) * This helper can be used during probing to determine if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) * edid had changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) int edid1_len, edid2_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) bool edid1_present = edid1 != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) bool edid2_present = edid2 != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (edid1_present != edid2_present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) if (edid1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) edid1_len = EDID_LENGTH * (1 + edid1->extensions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) edid2_len = EDID_LENGTH * (1 + edid2->extensions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) if (edid1_len != edid2_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (memcmp(edid1, edid2, edid1_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) EXPORT_SYMBOL(drm_edid_are_equal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * drm_edid_block_valid - Sanity check the EDID block (base or extension)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) * @raw_edid: pointer to raw EDID block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) * @block: type of block to validate (0 for base, extension otherwise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) * @print_bad_edid: if true, dump bad EDID blocks to the console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * @edid_corrupt: if true, the header or checksum is invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) * Validate a base or extension EDID block and optionally dump bad blocks to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) * the console.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) * Return: True if the block is valid, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) bool *edid_corrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) u8 csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) struct edid *edid = (struct edid *)raw_edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (WARN_ON(!raw_edid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) if (edid_fixup > 8 || edid_fixup < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) edid_fixup = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) if (block == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) int score = drm_edid_header_is_valid(raw_edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (score == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) if (edid_corrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) *edid_corrupt = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) } else if (score >= edid_fixup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) /* Displayport Link CTS Core 1.2 rev1.1 test 4.2.2.6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) * The corrupt flag needs to be set here otherwise, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) * fix-up code here will correct the problem, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) * checksum is correct and the test fails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) if (edid_corrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) *edid_corrupt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) memcpy(raw_edid, edid_header, sizeof(edid_header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) if (edid_corrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) *edid_corrupt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) csum = drm_edid_block_checksum(raw_edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) if (drm_edid_block_checksum_diff(raw_edid, csum)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) if (edid_corrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) *edid_corrupt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) /* allow CEA to slide through, switches mangle this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) if (raw_edid[0] == CEA_EXT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) DRM_DEBUG("EDID checksum is invalid, remainder is %d\n", csum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) DRM_DEBUG("Assuming a KVM switch modified the CEA block but left the original checksum\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) if (print_bad_edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) DRM_NOTE("EDID checksum is invalid, remainder is %d\n", csum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) /* per-block-type checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) switch (raw_edid[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) case 0: /* base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) if (edid->version != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) DRM_NOTE("EDID has major version %d, instead of 1\n", edid->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) if (edid->revision > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) bad:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) if (print_bad_edid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) if (drm_edid_is_zero(raw_edid, EDID_LENGTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) pr_notice("EDID block is all zeroes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) pr_notice("Raw EDID:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) print_hex_dump(KERN_NOTICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) " \t", DUMP_PREFIX_NONE, 16, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) raw_edid, EDID_LENGTH, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) EXPORT_SYMBOL(drm_edid_block_valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) * drm_edid_is_valid - sanity check EDID data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) * @edid: EDID data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) * Sanity-check an entire EDID record (including extensions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) * Return: True if the EDID data is valid, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) bool drm_edid_is_valid(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) u8 *raw = (u8 *)edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) if (!edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) for (i = 0; i <= edid->extensions; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i, true, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) EXPORT_SYMBOL(drm_edid_is_valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) #define DDC_SEGMENT_ADDR 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) * drm_do_probe_ddc_edid() - get EDID information via I2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) * @data: I2C device adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) * @buf: EDID data buffer to be filled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) * @block: 128 byte EDID block to start fetching from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) * @len: EDID data buffer length to fetch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) * Try to fetch EDID information by calling I2C driver functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) * Return: 0 on success or -1 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) drm_do_probe_ddc_edid(void *data, u8 *buf, unsigned int block, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) struct i2c_adapter *adapter = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) unsigned char start = block * EDID_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) unsigned char segment = block >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) unsigned char xfers = segment ? 3 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) int ret, retries = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) * The core I2C driver will automatically retry the transfer if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) * adapter reports EAGAIN. However, we find that bit-banging transfers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) * are susceptible to errors under a heavily loaded machine and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) * generate spurious NAKs and timeouts. Retrying the transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) * of the individual block a few times seems to overcome this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) struct i2c_msg msgs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) .addr = DDC_SEGMENT_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) .len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) .buf = &segment,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) .addr = DDC_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) .len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) .buf = &start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) .addr = DDC_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) .len = len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) * Avoid sending the segment addr to not upset non-compliant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) * DDC monitors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) if (ret == -ENXIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) adapter->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) } while (ret != xfers && --retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) return ret == xfers ? 0 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) static void connector_bad_edid(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) u8 *edid, int num_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) u8 last_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) * 0x7e in the EDID is the number of extension blocks. The EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) * is 1 (base block) + num_ext_blocks big. That means we can think
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) * of 0x7e in the EDID of the _index_ of the last block in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) * combined chunk of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) last_block = edid[0x7e];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) /* Calculate real checksum for the last edid extension block data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) if (last_block < num_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) connector->real_edid_checksum =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) drm_edid_block_checksum(edid + last_block * EDID_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) drm_warn(connector->dev, "%s: EDID is invalid:\n", connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) for (i = 0; i < num_blocks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) u8 *block = edid + i * EDID_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) char prefix[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) if (drm_edid_is_zero(block, EDID_LENGTH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) sprintf(prefix, "\t[%02x] ZERO ", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) else if (!drm_edid_block_valid(block, i, false, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) sprintf(prefix, "\t[%02x] BAD ", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) sprintf(prefix, "\t[%02x] GOOD ", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) print_hex_dump(KERN_WARNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) prefix, DUMP_PREFIX_NONE, 16, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) block, EDID_LENGTH, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) /* Get override or firmware EDID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) static struct edid *drm_get_override_edid(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) struct edid *override = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) if (connector->override_edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) override = drm_edid_duplicate(connector->edid_blob_ptr->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) if (!override)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) override = drm_load_edid_firmware(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) return IS_ERR(override) ? NULL : override;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) * drm_add_override_edid_modes - add modes from override/firmware EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) * @connector: connector we're probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) * Add modes from the override/firmware EDID, if available. Only to be used from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) * drm_helper_probe_single_connector_modes() as a fallback for when DDC probe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) * failed during drm_get_edid() and caused the override/firmware EDID to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) * skipped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) * Return: The number of modes added or 0 if we couldn't find any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) int drm_add_override_edid_modes(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) struct edid *override;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) int num_modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) override = drm_get_override_edid(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) if (override) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) drm_connector_update_edid_property(connector, override);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) num_modes = drm_add_edid_modes(connector, override);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) kfree(override);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) DRM_DEBUG_KMS("[CONNECTOR:%d:%s] adding %d modes via fallback override/firmware EDID\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) connector->base.id, connector->name, num_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) return num_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) EXPORT_SYMBOL(drm_add_override_edid_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) * drm_do_get_edid - get EDID data using a custom EDID block read function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) * @connector: connector we're probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) * @get_edid_block: EDID block read function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) * @data: private data passed to the block read function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) * When the I2C adapter connected to the DDC bus is hidden behind a device that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) * exposes a different interface to read EDID blocks this function can be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) * to get EDID data using a custom block read function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) * As in the general case the DDC bus is accessible by the kernel at the I2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) * level, drivers must make all reasonable efforts to expose it as an I2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) * adapter and use drm_get_edid() instead of abusing this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) * The EDID may be overridden using debugfs override_edid or firmare EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) * (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) * order. Having either of them bypasses actual EDID reads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) * Return: Pointer to valid EDID or NULL if we couldn't find any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) struct edid *drm_do_get_edid(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) size_t len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) int i, j = 0, valid_extensions = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) u8 *edid, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) struct edid *override;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) override = drm_get_override_edid(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) if (override)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) return override;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) /* base block fetch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) if (get_edid_block(data, edid, 0, EDID_LENGTH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) if (drm_edid_block_valid(edid, 0, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) &connector->edid_corrupt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) connector->null_edid_counter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) goto carp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) if (i == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) goto carp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) /* if there's no extensions, we're done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) valid_extensions = edid[0x7e];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) if (valid_extensions == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) return (struct edid *)edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) edid = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) for (j = 1; j <= edid[0x7e]; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) u8 *block = edid + j * EDID_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) if (get_edid_block(data, block, j, EDID_LENGTH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) if (drm_edid_block_valid(block, j, false, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) if (i == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) valid_extensions--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) if (valid_extensions != edid[0x7e]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) u8 *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) connector_bad_edid(connector, edid, edid[0x7e] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) edid[0x7e] = valid_extensions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) new = kmalloc_array(valid_extensions + 1, EDID_LENGTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) base = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) for (i = 0; i <= edid[0x7e]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) u8 *block = edid + i * EDID_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) if (!drm_edid_block_valid(block, i, false, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) memcpy(base, block, EDID_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) base += EDID_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) kfree(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) edid = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) return (struct edid *)edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) carp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) connector_bad_edid(connector, edid, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) kfree(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) EXPORT_SYMBOL_GPL(drm_do_get_edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) * drm_probe_ddc() - probe DDC presence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) * @adapter: I2C adapter to probe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) * Return: True on success, false on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) drm_probe_ddc(struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) unsigned char out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) EXPORT_SYMBOL(drm_probe_ddc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) * drm_get_edid - get EDID data, if available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) * @connector: connector we're probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) * @adapter: I2C adapter to use for DDC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) * Poke the given I2C channel to grab EDID data if possible. If found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) * attach it to the connector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) * Return: Pointer to valid EDID or NULL if we couldn't find any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) struct edid *drm_get_edid(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) struct edid *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) if (connector->force == DRM_FORCE_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) drm_connector_update_edid_property(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) return edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) EXPORT_SYMBOL(drm_get_edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) * drm_get_edid_switcheroo - get EDID data for a vga_switcheroo output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) * @connector: connector we're probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) * @adapter: I2C adapter to use for DDC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) * Wrapper around drm_get_edid() for laptops with dual GPUs using one set of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) * outputs. The wrapper adds the requisite vga_switcheroo calls to temporarily
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) * switch DDC to the GPU which is retrieving EDID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) * Return: Pointer to valid EDID or %NULL if we couldn't find any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) struct edid *drm_get_edid_switcheroo(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) struct pci_dev *pdev = connector->dev->pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) struct edid *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) vga_switcheroo_lock_ddc(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) edid = drm_get_edid(connector, adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) vga_switcheroo_unlock_ddc(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) return edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) EXPORT_SYMBOL(drm_get_edid_switcheroo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) * drm_edid_duplicate - duplicate an EDID and the extensions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) * @edid: EDID to duplicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) * Return: Pointer to duplicated EDID or NULL on allocation failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) struct edid *drm_edid_duplicate(const struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) return kmemdup(edid, (edid->extensions + 1) * EDID_LENGTH, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) EXPORT_SYMBOL(drm_edid_duplicate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) /*** EDID parsing ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) * edid_vendor - match a string against EDID's obfuscated vendor field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) * @edid: EDID to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) * @vendor: vendor string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) * Returns true if @vendor is in @edid, false otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) static bool edid_vendor(const struct edid *edid, const char *vendor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) char edid_vendor[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) ((edid->mfg_id[1] & 0xe0) >> 5)) + '@';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) edid_vendor[2] = (edid->mfg_id[1] & 0x1f) + '@';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) return !strncmp(edid_vendor, vendor, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) * edid_get_quirks - return quirk flags for a given EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) * @edid: EDID to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) * This tells subsequent routines what fixes they need to apply.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) static u32 edid_get_quirks(const struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) const struct edid_quirk *quirk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) quirk = &edid_quirk_list[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) if (edid_vendor(edid, quirk->vendor) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) (EDID_PRODUCT_ID(edid) == quirk->product_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) return quirk->quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) #define MODE_REFRESH_DIFF(c,t) (abs((c) - (t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) * edid_fixup_preferred - set preferred modes based on quirk list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) * @connector: has mode list to fix up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) * @quirks: quirks list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) * Walk the mode list for @connector, clearing the preferred status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) * on existing modes and setting it anew for the right mode ala @quirks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) static void edid_fixup_preferred(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) u32 quirks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) struct drm_display_mode *t, *cur_mode, *preferred_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) int target_refresh = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) int cur_vrefresh, preferred_vrefresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) if (list_empty(&connector->probed_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) if (quirks & EDID_QUIRK_PREFER_LARGE_60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) target_refresh = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) if (quirks & EDID_QUIRK_PREFER_LARGE_75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) target_refresh = 75;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) preferred_mode = list_first_entry(&connector->probed_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) struct drm_display_mode, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) if (cur_mode == preferred_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) /* Largest mode is preferred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) preferred_mode = cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) cur_vrefresh = drm_mode_vrefresh(cur_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) preferred_vrefresh = drm_mode_vrefresh(preferred_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) /* At a given size, try to get closest to target refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) MODE_REFRESH_DIFF(cur_vrefresh, target_refresh) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) MODE_REFRESH_DIFF(preferred_vrefresh, target_refresh)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) preferred_mode = cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) preferred_mode->type |= DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) mode_is_rb(const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) return (mode->htotal - mode->hdisplay == 160) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) (mode->hsync_end - mode->hdisplay == 80) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) (mode->hsync_end - mode->hsync_start == 32) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) (mode->vsync_start - mode->vdisplay == 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) * drm_mode_find_dmt - Create a copy of a mode if present in DMT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) * @dev: Device to duplicate against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) * @hsize: Mode width
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) * @vsize: Mode height
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) * @fresh: Mode refresh rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) * @rb: Mode reduced-blanking-ness
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) * Walk the DMT mode list looking for a match for the given parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) * Return: A newly allocated copy of the mode, or NULL if not found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) int hsize, int vsize, int fresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) bool rb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) for (i = 0; i < ARRAY_SIZE(drm_dmt_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) const struct drm_display_mode *ptr = &drm_dmt_modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) if (hsize != ptr->hdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) if (vsize != ptr->vdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) if (fresh != drm_mode_vrefresh(ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) if (rb != mode_is_rb(ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) return drm_mode_duplicate(dev, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) EXPORT_SYMBOL(drm_mode_find_dmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) static bool is_display_descriptor(const u8 d[18], u8 tag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) return d[0] == 0x00 && d[1] == 0x00 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) d[2] == 0x00 && d[3] == tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) static bool is_detailed_timing_descriptor(const u8 d[18])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) return d[0] != 0x00 || d[1] != 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) typedef void detailed_cb(struct detailed_timing *timing, void *closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) int i, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) u8 d = ext[0x02];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) u8 *det_base = ext + d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) if (d < 4 || d > 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) n = (127 - d) / 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) for (i = 0; i < n; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) cb((struct detailed_timing *)(det_base + 18 * i), closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) vtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) unsigned int i, n = min((int)ext[0x02], 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) u8 *det_base = ext + 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) if (ext[0x01] != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) return; /* unknown version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) for (i = 0; i < n; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) cb((struct detailed_timing *)(det_base + 18 * i), closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) struct edid *edid = (struct edid *)raw_edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) if (edid == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) for (i = 0; i < EDID_DETAILED_TIMINGS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) cb(&(edid->detailed_timings[i]), closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) for (i = 1; i <= raw_edid[0x7e]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) u8 *ext = raw_edid + (i * EDID_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) switch (*ext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) case CEA_EXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) cea_for_each_detailed_block(ext, cb, closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) case VTB_EXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) vtb_for_each_detailed_block(ext, cb, closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) is_rb(struct detailed_timing *t, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) u8 *r = (u8 *)t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) if (r[15] & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) *(bool *)data = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) /* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) drm_monitor_supports_rb(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) if (edid->revision >= 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) bool ret = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) drm_for_each_detailed_block((u8 *)edid, is_rb, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) return ((edid->input & DRM_EDID_INPUT_DIGITAL) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) find_gtf2(struct detailed_timing *t, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) u8 *r = (u8 *)t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) if (r[10] == 0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) *(u8 **)data = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) /* Secondary GTF curve kicks in above some break frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) drm_gtf2_hbreak(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) u8 *r = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) return r ? (r[12] * 2) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) drm_gtf2_2c(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) u8 *r = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) return r ? r[13] : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) drm_gtf2_m(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) u8 *r = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) return r ? (r[15] << 8) + r[14] : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) drm_gtf2_k(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) u8 *r = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) return r ? r[16] : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) drm_gtf2_2j(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) u8 *r = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) return r ? r[17] : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) * standard_timing_level - get std. timing level(CVT/GTF/DMT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) * @edid: EDID block to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) static int standard_timing_level(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) if (edid->revision >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) return LEVEL_CVT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) if (drm_gtf2_hbreak(edid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) return LEVEL_GTF2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) return LEVEL_GTF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) return LEVEL_DMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) * 0 is reserved. The spec says 0x01 fill for unused timings. Some old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) * monitors fill with ascii space (0x20) instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) bad_std_timing(u8 a, u8 b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) return (a == 0x00 && b == 0x00) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) (a == 0x01 && b == 0x01) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) (a == 0x20 && b == 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) static int drm_mode_hsync(const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) if (mode->htotal <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) return DIV_ROUND_CLOSEST(mode->clock, mode->htotal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) * drm_mode_std - convert standard mode info (width, height, refresh) into mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) * @connector: connector of for the EDID block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) * @edid: EDID block to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) * @t: standard timing params
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) * Take the standard timing params (in this case width, aspect, and refresh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) * and convert them into a real mode using CVT/GTF/DMT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) static struct drm_display_mode *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) drm_mode_std(struct drm_connector *connector, struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) struct std_timing *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) struct drm_display_mode *m, *mode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) int hsize, vsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) int vrefresh_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) >> EDID_TIMING_ASPECT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) >> EDID_TIMING_VFREQ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) int timing_level = standard_timing_level(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) if (bad_std_timing(t->hsize, t->vfreq_aspect))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) /* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) hsize = t->hsize * 8 + 248;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) /* vrefresh_rate = vfreq + 60 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) vrefresh_rate = vfreq + 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) /* the vdisplay is calculated based on the aspect ratio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) if (aspect_ratio == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) if (edid->revision < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) vsize = hsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) vsize = (hsize * 10) / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) } else if (aspect_ratio == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) vsize = (hsize * 3) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) else if (aspect_ratio == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) vsize = (hsize * 4) / 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) vsize = (hsize * 9) / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) /* HDTV hack, part 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) if (vrefresh_rate == 60 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) ((hsize == 1360 && vsize == 765) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) (hsize == 1368 && vsize == 769))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) hsize = 1366;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) vsize = 768;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) * If this connector already has a mode for this size and refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) * rate (because it came from detailed or CVT info), use that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) * instead. This way we don't have to guess at interlace or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) * reduced blanking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) list_for_each_entry(m, &connector->probed_modes, head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) if (m->hdisplay == hsize && m->vdisplay == vsize &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) drm_mode_vrefresh(m) == vrefresh_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) /* HDTV hack, part 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) mode->hdisplay = 1366;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) mode->hsync_start = mode->hsync_start - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) mode->hsync_end = mode->hsync_end - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) /* check whether it can be found in default mode table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) if (drm_monitor_supports_rb(edid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) if (mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) if (mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) /* okay, generate it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) switch (timing_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) case LEVEL_DMT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) case LEVEL_GTF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) case LEVEL_GTF2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) * This is potentially wrong if there's ever a monitor with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) * more than one ranges section, each claiming a different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) * secondary GTF curve. Please don't do that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) drm_mode_destroy(dev, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) mode = drm_gtf_mode_complex(dev, hsize, vsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) vrefresh_rate, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) drm_gtf2_m(edid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) drm_gtf2_2c(edid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) drm_gtf2_k(edid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) drm_gtf2_2j(edid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) case LEVEL_CVT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) * EDID is delightfully ambiguous about how interlaced modes are to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) * encoded. Our internal representation is of frame height, but some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) * HDTV detailed timings are encoded as field height.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) * The format list here is from CEA, in frame size. Technically we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) * should be checking refresh rate too. Whatever.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) drm_mode_do_interlace_quirk(struct drm_display_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) struct detailed_pixel_timing *pt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) int w, h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) } cea_interlaced[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) { 1920, 1080 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) { 720, 480 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) { 1440, 480 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) { 2880, 480 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) { 720, 576 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) { 1440, 576 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) { 2880, 576 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) if (!(pt->misc & DRM_EDID_PT_INTERLACED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) for (i = 0; i < ARRAY_SIZE(cea_interlaced); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) if ((mode->hdisplay == cea_interlaced[i].w) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) (mode->vdisplay == cea_interlaced[i].h / 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) mode->vdisplay *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) mode->vsync_start *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) mode->vsync_end *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) mode->vtotal *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) mode->vtotal |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) mode->flags |= DRM_MODE_FLAG_INTERLACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) * drm_mode_detailed - create a new mode from an EDID detailed timing section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) * @dev: DRM device (needed to create new mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) * @edid: EDID block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) * @timing: EDID detailed timing info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) * @quirks: quirks to apply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) * An EDID detailed timing block contains enough info for us to create and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) * return a new struct drm_display_mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) struct detailed_timing *timing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) u32 quirks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) struct detailed_pixel_timing *pt = &timing->data.pixel_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 2 | pt->vsync_offset_pulse_width_lo >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) /* ignore tiny modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) if (hactive < 64 || vactive < 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) if (pt->misc & DRM_EDID_PT_STEREO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) DRM_DEBUG_KMS("stereo mode not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) DRM_DEBUG_KMS("composite sync not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) /* it is incorrect if hsync/vsync width is zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) if (!hsync_pulse_width || !vsync_pulse_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) DRM_DEBUG_KMS("Incorrect Detailed timing. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) "Wrong Hsync/Vsync pulse width\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) goto set_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) mode = drm_mode_create(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) timing->pixel_clock = cpu_to_le16(1088);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) mode->hdisplay = hactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) mode->hsync_start = mode->hdisplay + hsync_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) mode->hsync_end = mode->hsync_start + hsync_pulse_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) mode->htotal = mode->hdisplay + hblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) mode->vdisplay = vactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) mode->vsync_start = mode->vdisplay + vsync_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) mode->vsync_end = mode->vsync_start + vsync_pulse_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) mode->vtotal = mode->vdisplay + vblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) /* Some EDIDs have bogus h/vtotal values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) if (mode->hsync_end > mode->htotal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) mode->htotal = mode->hsync_end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) if (mode->vsync_end > mode->vtotal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) mode->vtotal = mode->vsync_end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) drm_mode_do_interlace_quirk(mode, pt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) set_size:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) if (quirks & EDID_QUIRK_DETAILED_IN_CM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) mode->width_mm *= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) mode->height_mm *= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) mode->width_mm = edid->width_cm * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) mode->height_mm = edid->height_cm * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) mode->type = DRM_MODE_TYPE_DRIVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) drm_mode_set_name(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) mode_in_hsync_range(const struct drm_display_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) struct edid *edid, u8 *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) int hsync, hmin, hmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) hmin = t[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) if (edid->revision >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) hmin += ((t[4] & 0x04) ? 255 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) hmax = t[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) if (edid->revision >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) hmax += ((t[4] & 0x08) ? 255 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) hsync = drm_mode_hsync(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) return (hsync <= hmax && hsync >= hmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) mode_in_vsync_range(const struct drm_display_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) struct edid *edid, u8 *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) int vsync, vmin, vmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) vmin = t[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) if (edid->revision >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) vmin += ((t[4] & 0x01) ? 255 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) vmax = t[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) if (edid->revision >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) vmax += ((t[4] & 0x02) ? 255 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) vsync = drm_mode_vrefresh(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) return (vsync <= vmax && vsync >= vmin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) static u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) range_pixel_clock(struct edid *edid, u8 *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) /* unspecified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) if (t[9] == 0 || t[9] == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) /* 1.4 with CVT support gives us real precision, yay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) if (edid->revision >= 4 && t[10] == 0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) return (t[9] * 10000) - ((t[12] >> 2) * 250);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) /* 1.3 is pathetic, so fuzz up a bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) return t[9] * 10000 + 5001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) struct detailed_timing *timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) u32 max_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) u8 *t = (u8 *)timing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) if (!mode_in_hsync_range(mode, edid, t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) if (!mode_in_vsync_range(mode, edid, t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) if ((max_clock = range_pixel_clock(edid, t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) if (mode->clock > max_clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) /* 1.4 max horizontal check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) if (edid->revision >= 4 && t[10] == 0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) if (mode_is_rb(mode) && !drm_monitor_supports_rb(edid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) static bool valid_inferred_mode(const struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) const struct drm_display_mode *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) bool ok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) list_for_each_entry(m, &connector->probed_modes, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) if (mode->hdisplay == m->hdisplay &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) mode->vdisplay == m->vdisplay &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) drm_mode_vrefresh(mode) == drm_mode_vrefresh(m))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) return false; /* duplicated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) if (mode->hdisplay <= m->hdisplay &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) mode->vdisplay <= m->vdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) ok = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) return ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) struct detailed_timing *timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) int i, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) for (i = 0; i < ARRAY_SIZE(drm_dmt_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) if (mode_in_range(drm_dmt_modes + i, edid, timing) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) valid_inferred_mode(connector, drm_dmt_modes + i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) /* fix up 1366x768 mode from 1368x768;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) * GFT/CVT can't express 1366 width which isn't dividable by 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) void drm_mode_fixup_1366x768(struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) if (mode->hdisplay == 1368 && mode->vdisplay == 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) mode->hdisplay = 1366;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) mode->hsync_start--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) mode->hsync_end--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) drm_mode_set_name(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) struct detailed_timing *timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) int i, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) for (i = 0; i < ARRAY_SIZE(extra_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) const struct minimode *m = &extra_modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) newmode = drm_gtf_mode(dev, m->w, m->h, m->r, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) drm_mode_fixup_1366x768(newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) if (!mode_in_range(newmode, edid, timing) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) !valid_inferred_mode(connector, newmode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) drm_mode_destroy(dev, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) struct detailed_timing *timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) int i, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) bool rb = drm_monitor_supports_rb(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) for (i = 0; i < ARRAY_SIZE(extra_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) const struct minimode *m = &extra_modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) newmode = drm_cvt_mode(dev, m->w, m->h, m->r, rb, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) drm_mode_fixup_1366x768(newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) if (!mode_in_range(newmode, edid, timing) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) !valid_inferred_mode(connector, newmode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) drm_mode_destroy(dev, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) do_inferred_modes(struct detailed_timing *timing, void *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) struct detailed_mode_closure *closure = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) struct detailed_non_pixel *data = &timing->data.other_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) struct detailed_data_monitor_range *range = &data->data.range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_MONITOR_RANGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) closure->modes += drm_dmt_modes_for_range(closure->connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) closure->edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) if (!version_greater(closure->edid, 1, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) return; /* GTF not defined yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) switch (range->flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) case 0x02: /* secondary gtf, XXX could do more */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) case 0x00: /* default gtf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) closure->modes += drm_gtf_modes_for_range(closure->connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) closure->edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) case 0x04: /* cvt, only in 1.4+ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) if (!version_greater(closure->edid, 1, 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) closure->modes += drm_cvt_modes_for_range(closure->connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) closure->edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) case 0x01: /* just the ranges, no formula */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) add_inferred_modes(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) struct detailed_mode_closure closure = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) .connector = connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) .edid = edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) if (version_greater(edid, 1, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) drm_for_each_detailed_block((u8 *)edid, do_inferred_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) &closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) return closure.modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) int i, j, m, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) u8 *est = ((u8 *)timing) + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) for (j = 7; j >= 0; j--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) m = (i * 8) + (7 - j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) if (m >= ARRAY_SIZE(est3_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) if (est[i] & (1 << j)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) mode = drm_mode_find_dmt(connector->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) est3_modes[m].w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) est3_modes[m].h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) est3_modes[m].r,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) est3_modes[m].rb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) if (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) do_established_modes(struct detailed_timing *timing, void *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) struct detailed_mode_closure *closure = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_EST_TIMINGS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) closure->modes += drm_est3_modes(closure->connector, timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) * add_established_modes - get est. modes from EDID and add them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) * @connector: connector to add mode(s) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) * @edid: EDID block to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) * Each EDID block contains a bitmap of the supported "established modes" list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) * (defined above). Tease them out and add them to the global modes list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) add_established_modes(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) unsigned long est_bits = edid->established_timings.t1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) (edid->established_timings.t2 << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) ((edid->established_timings.mfg_rsvd & 0x80) << 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) int i, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) struct detailed_mode_closure closure = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) .connector = connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) .edid = edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) for (i = 0; i <= EDID_EST_TIMINGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) if (est_bits & (1<<i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) if (version_greater(edid, 1, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) drm_for_each_detailed_block((u8 *)edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) do_established_modes, &closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) return modes + closure.modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) do_standard_modes(struct detailed_timing *timing, void *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) struct detailed_mode_closure *closure = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) struct detailed_non_pixel *data = &timing->data.other_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) struct drm_connector *connector = closure->connector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) struct edid *edid = closure->edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_STD_MODES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) struct std_timing *std = &data->data.timings[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) newmode = drm_mode_std(connector, edid, std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) closure->modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) * add_standard_modes - get std. modes from EDID and add them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) * @connector: connector to add mode(s) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) * @edid: EDID block to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) * Standard modes can be calculated using the appropriate standard (DMT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) * GTF or CVT. Grab them from @edid and add them to the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) add_standard_modes(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) int i, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) struct detailed_mode_closure closure = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) .connector = connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) .edid = edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) for (i = 0; i < EDID_STD_TIMINGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) newmode = drm_mode_std(connector, edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) &edid->standard_timings[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) if (version_greater(edid, 1, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) drm_for_each_detailed_block((u8 *)edid, do_standard_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) &closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) /* XXX should also look for standard codes in VTB blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) return modes + closure.modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) static int drm_cvt_modes(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) struct detailed_timing *timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) int i, j, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) struct cvt_timing *cvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) const int rates[] = { 60, 85, 75, 60, 50 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) const u8 empty[3] = { 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) int width, height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) cvt = &(timing->data.other_data.data.cvt[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) if (!memcmp(cvt->code, empty, 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) switch (cvt->code[1] & 0x0c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) /* default - because compiler doesn't see that we've enumerated all cases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) width = height * 4 / 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) case 0x04:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) width = height * 16 / 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) case 0x08:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) width = height * 16 / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) case 0x0c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) width = height * 15 / 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) for (j = 1; j < 5; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) if (cvt->code[2] & (1 << j)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) newmode = drm_cvt_mode(dev, width, height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) rates[j], j == 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) false, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) do_cvt_mode(struct detailed_timing *timing, void *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) struct detailed_mode_closure *closure = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_CVT_3BYTE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) closure->modes += drm_cvt_modes(closure->connector, timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) add_cvt_modes(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) struct detailed_mode_closure closure = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) .connector = connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) .edid = edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) if (version_greater(edid, 1, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) drm_for_each_detailed_block((u8 *)edid, do_cvt_mode, &closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) /* XXX should also look for CVT codes in VTB blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) return closure.modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) do_detailed_mode(struct detailed_timing *timing, void *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) struct detailed_mode_closure *closure = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) if (!is_detailed_timing_descriptor((const u8 *)timing))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) newmode = drm_mode_detailed(closure->connector->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) closure->edid, timing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) closure->quirks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) if (closure->preferred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) newmode->type |= DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) * Detailed modes are limited to 10kHz pixel clock resolution,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) * so fix up anything that looks like CEA/HDMI mode, but the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) * is just slightly off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) fixup_detailed_cea_mode_clock(newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) drm_mode_probed_add(closure->connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) closure->modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) closure->preferred = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) * add_detailed_modes - Add modes from detailed timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) * @connector: attached connector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) * @edid: EDID block to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) * @quirks: quirks to apply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) add_detailed_modes(struct drm_connector *connector, struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) u32 quirks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) struct detailed_mode_closure closure = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) .connector = connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) .edid = edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) .preferred = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) .quirks = quirks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) if (closure.preferred && !version_greater(edid, 1, 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) closure.preferred =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) drm_for_each_detailed_block((u8 *)edid, do_detailed_mode, &closure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) return closure.modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) #define AUDIO_BLOCK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) #define VIDEO_BLOCK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) #define VENDOR_BLOCK 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) #define SPEAKER_BLOCK 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) #define HDR_STATIC_METADATA_BLOCK 0x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) #define USE_EXTENDED_TAG 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) #define EXT_VIDEO_CAPABILITY_BLOCK 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) #define EXT_VIDEO_DATA_BLOCK_420 0x0E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) #define EXT_VIDEO_CAP_BLOCK_Y420CMDB 0x0F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) #define EDID_BASIC_AUDIO (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) #define EDID_CEA_YCRCB444 (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) #define EDID_CEA_YCRCB422 (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) #define EDID_CEA_VCDB_QS (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) * Search EDID for CEA extension block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) static u8 *drm_find_edid_extension(const struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) int ext_id, int *ext_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) u8 *edid_ext = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) /* No EDID or EDID extensions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) if (edid == NULL || edid->extensions == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) /* Find CEA extension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) for (i = *ext_index; i < edid->extensions; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) if (edid_ext[0] == ext_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) if (i >= edid->extensions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) *ext_index = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) return edid_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) static u8 *drm_find_displayid_extension(const struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) int *length, int *idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) int *ext_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT, ext_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) struct displayid_hdr *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) if (!displayid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) /* EDID extensions block checksum isn't for us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) *length = EDID_LENGTH - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) *idx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) ret = validate_displayid(displayid, *length, *idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) base = (struct displayid_hdr *)&displayid[*idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) *length = *idx + sizeof(*base) + base->bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) return displayid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) static u8 *drm_find_cea_extension(const struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) int length, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) struct displayid_block *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) u8 *cea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) u8 *displayid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) int ext_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) /* Look for a top level CEA extension block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) /* FIXME: make callers iterate through multiple CEA ext blocks? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) ext_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) cea = drm_find_edid_extension(edid, CEA_EXT, &ext_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) if (cea)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) return cea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) /* CEA blocks can also be found embedded in a DisplayID block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) ext_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) displayid = drm_find_displayid_extension(edid, &length, &idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) &ext_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) if (!displayid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) idx += sizeof(struct displayid_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) for_each_displayid_db(displayid, block, idx, length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) if (block->tag == DATA_BLOCK_CTA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) return (u8 *)block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) static __always_inline const struct drm_display_mode *cea_mode_for_vic(u8 vic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) BUILD_BUG_ON(1 + ARRAY_SIZE(edid_cea_modes_1) - 1 != 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) BUILD_BUG_ON(193 + ARRAY_SIZE(edid_cea_modes_193) - 1 != 219);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) if (vic >= 1 && vic < 1 + ARRAY_SIZE(edid_cea_modes_1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) return &edid_cea_modes_1[vic - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) if (vic >= 193 && vic < 193 + ARRAY_SIZE(edid_cea_modes_193))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) return &edid_cea_modes_193[vic - 193];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) static u8 cea_num_vics(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) return 193 + ARRAY_SIZE(edid_cea_modes_193);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) static u8 cea_next_vic(u8 vic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) if (++vic == 1 + ARRAY_SIZE(edid_cea_modes_1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) vic = 193;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) return vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) * Calculate the alternate clock for the CEA mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) * (60Hz vs. 59.94Hz etc.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) unsigned int clock = cea_mode->clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) if (drm_mode_vrefresh(cea_mode) % 6 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) return clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) * edid_cea_modes contains the 59.94Hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) * variant for 240 and 480 line modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) * and the 60Hz variant otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) if (cea_mode->vdisplay == 240 || cea_mode->vdisplay == 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) clock = DIV_ROUND_CLOSEST(clock * 1001, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) clock = DIV_ROUND_CLOSEST(clock * 1000, 1001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) return clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) cea_mode_alternate_timings(u8 vic, struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) * For certain VICs the spec allows the vertical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) * front porch to vary by one or two lines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) * cea_modes[] stores the variant with the shortest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) * vertical front porch. We can adjust the mode to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) * get the other variants by simply increasing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) * vertical front porch length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) BUILD_BUG_ON(cea_mode_for_vic(8)->vtotal != 262 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) cea_mode_for_vic(9)->vtotal != 262 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) cea_mode_for_vic(12)->vtotal != 262 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) cea_mode_for_vic(13)->vtotal != 262 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) cea_mode_for_vic(23)->vtotal != 312 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) cea_mode_for_vic(24)->vtotal != 312 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) cea_mode_for_vic(27)->vtotal != 312 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) cea_mode_for_vic(28)->vtotal != 312);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) if (((vic == 8 || vic == 9 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) vic == 12 || vic == 13) && mode->vtotal < 263) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) ((vic == 23 || vic == 24 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) vic == 27 || vic == 28) && mode->vtotal < 314)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) mode->vsync_start++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) mode->vsync_end++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) mode->vtotal++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) unsigned int clock_tolerance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) unsigned int match_flags = DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_FLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) u8 vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) if (!to_match->clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) if (to_match->picture_aspect_ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) for (vic = 1; vic < cea_num_vics(); vic = cea_next_vic(vic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) struct drm_display_mode cea_mode = *cea_mode_for_vic(vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) unsigned int clock1, clock2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) /* Check both 60Hz and 59.94Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) clock1 = cea_mode.clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) clock2 = cea_mode_alternate_clock(&cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) if (abs(to_match->clock - clock1) > clock_tolerance &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) abs(to_match->clock - clock2) > clock_tolerance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) if (drm_mode_match(to_match, &cea_mode, match_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) return vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) } while (cea_mode_alternate_timings(vic, &cea_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) * drm_match_cea_mode - look for a CEA mode matching given mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) * @to_match: display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) * Return: The CEA Video ID (VIC) of the mode or 0 if it isn't a CEA-861
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) * mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) unsigned int match_flags = DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_FLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) u8 vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) if (!to_match->clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) if (to_match->picture_aspect_ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) for (vic = 1; vic < cea_num_vics(); vic = cea_next_vic(vic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) struct drm_display_mode cea_mode = *cea_mode_for_vic(vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) unsigned int clock1, clock2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) /* Check both 60Hz and 59.94Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) clock1 = cea_mode.clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) clock2 = cea_mode_alternate_clock(&cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) if (KHZ2PICOS(to_match->clock) != KHZ2PICOS(clock1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) KHZ2PICOS(to_match->clock) != KHZ2PICOS(clock2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) if (drm_mode_match(to_match, &cea_mode, match_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) return vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) } while (cea_mode_alternate_timings(vic, &cea_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) EXPORT_SYMBOL(drm_match_cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) static bool drm_valid_cea_vic(u8 vic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) return cea_mode_for_vic(vic) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) static enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) const struct drm_display_mode *mode = cea_mode_for_vic(video_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) if (mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) return mode->picture_aspect_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) return HDMI_PICTURE_ASPECT_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) static enum hdmi_picture_aspect drm_get_hdmi_aspect_ratio(const u8 video_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) return edid_4k_modes[video_code].picture_aspect_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) * Calculate the alternate clock for HDMI modes (those from the HDMI vendor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) * specific block).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) hdmi_mode_alternate_clock(const struct drm_display_mode *hdmi_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) return cea_mode_alternate_clock(hdmi_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode *to_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) unsigned int clock_tolerance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) unsigned int match_flags = DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_FLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) u8 vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) if (!to_match->clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) if (to_match->picture_aspect_ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) for (vic = 1; vic < ARRAY_SIZE(edid_4k_modes); vic++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) const struct drm_display_mode *hdmi_mode = &edid_4k_modes[vic];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) unsigned int clock1, clock2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) /* Make sure to also match alternate clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) clock1 = hdmi_mode->clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) clock2 = hdmi_mode_alternate_clock(hdmi_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) if (abs(to_match->clock - clock1) > clock_tolerance &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) abs(to_match->clock - clock2) > clock_tolerance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) if (drm_mode_match(to_match, hdmi_mode, match_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) return vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) * drm_match_hdmi_mode - look for a HDMI mode matching given mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) * @to_match: display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) * An HDMI mode is one defined in the HDMI vendor specific block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) * Returns the HDMI Video ID (VIC) of the mode or 0 if it isn't one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) unsigned int match_flags = DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_FLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) u8 vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) if (!to_match->clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) if (to_match->picture_aspect_ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) for (vic = 1; vic < ARRAY_SIZE(edid_4k_modes); vic++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) const struct drm_display_mode *hdmi_mode = &edid_4k_modes[vic];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) unsigned int clock1, clock2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) /* Make sure to also match alternate clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) clock1 = hdmi_mode->clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) clock2 = hdmi_mode_alternate_clock(hdmi_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) drm_mode_match(to_match, hdmi_mode, match_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) return vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) static bool drm_valid_hdmi_vic(u8 vic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) return vic > 0 && vic < ARRAY_SIZE(edid_4k_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) struct drm_display_mode *mode, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) LIST_HEAD(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) int modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) /* Don't add CEA modes if the CEA extension block is missing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) if (!drm_find_cea_extension(edid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) * Go through all probed modes and create a new mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) * with the alternate clock for certain CEA modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) list_for_each_entry(mode, &connector->probed_modes, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) const struct drm_display_mode *cea_mode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) u8 vic = drm_match_cea_mode(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) unsigned int clock1, clock2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) if (drm_valid_cea_vic(vic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) cea_mode = cea_mode_for_vic(vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) clock2 = cea_mode_alternate_clock(cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) vic = drm_match_hdmi_mode(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) if (drm_valid_hdmi_vic(vic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) cea_mode = &edid_4k_modes[vic];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) clock2 = hdmi_mode_alternate_clock(cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) if (!cea_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) clock1 = cea_mode->clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) if (clock1 == clock2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) if (mode->clock != clock1 && mode->clock != clock2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) newmode = drm_mode_duplicate(dev, cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) /* Carry over the stereo flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) newmode->flags |= mode->flags & DRM_MODE_FLAG_3D_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) * The current mode could be either variant. Make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) * sure to pick the "other" clock for the new mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) if (mode->clock != clock1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) newmode->clock = clock1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) newmode->clock = clock2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) list_add_tail(&newmode->head, &list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) list_for_each_entry_safe(mode, tmp, &list, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) list_del(&mode->head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) static u8 svd_to_vic(u8 svd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) /* 0-6 bit vic, 7th bit native mode indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) if ((svd >= 1 && svd <= 64) || (svd >= 129 && svd <= 192))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) return svd & 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) return svd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) static struct drm_display_mode *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) drm_display_mode_from_vic_index(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) const u8 *video_db, u8 video_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) u8 video_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) u8 vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) if (video_db == NULL || video_index >= video_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) /* CEA modes are numbered 1..127 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) vic = svd_to_vic(video_db[video_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) if (!drm_valid_cea_vic(vic))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) return newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) * do_y420vdb_modes - Parse YCBCR 420 only modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) * @connector: connector corresponding to the HDMI sink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) * @svds: start of the data block of CEA YCBCR 420 VDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) * @len: length of the CEA YCBCR 420 VDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) * Parse the CEA-861-F YCBCR 420 Video Data Block (Y420VDB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) * which contains modes which can be supported in YCBCR 420
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) * output format only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) static int do_y420vdb_modes(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) const u8 *svds, u8 svds_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) int modes = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) struct drm_hdmi_info *hdmi = &info->hdmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) for (i = 0; i < svds_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) u8 vic = svd_to_vic(svds[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) if (!drm_valid_cea_vic(vic))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) bitmap_set(hdmi->y420_vdb_modes, vic, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) if (modes > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) * drm_add_cmdb_modes - Add a YCBCR 420 mode into bitmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) * @connector: connector corresponding to the HDMI sink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) * @vic: CEA vic for the video mode to be added in the map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) * Makes an entry for a videomode in the YCBCR 420 bitmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) u8 vic = svd_to_vic(svd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) if (!drm_valid_cea_vic(vic))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) * drm_display_mode_from_cea_vic() - return a mode for CEA VIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) * @dev: DRM device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) * @video_code: CEA VIC of the mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) * Creates a new mode matching the specified CEA VIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) * Returns: A new drm_display_mode on success or NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) struct drm_display_mode *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) drm_display_mode_from_cea_vic(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) u8 video_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) const struct drm_display_mode *cea_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) cea_mode = cea_mode_for_vic(video_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) if (!cea_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) newmode = drm_mode_duplicate(dev, cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) return newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) EXPORT_SYMBOL(drm_display_mode_from_cea_vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) int i, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) mode = drm_display_mode_from_vic_index(connector, db, len, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) if (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) * YCBCR420 capability block contains a bitmap which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) * gives the index of CEA modes from CEA VDB, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) * can support YCBCR 420 sampling output also (apart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) * from RGB/YCBCR444 etc).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) * For example, if the bit 0 in bitmap is set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) * first mode in VDB can support YCBCR420 output too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) * Add YCBCR420 modes only if sink is HDMI 2.0 capable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) if (i < 64 && hdmi->y420_cmdb_map & (1ULL << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) drm_add_cmdb_modes(connector, db[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) struct stereo_mandatory_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) int width, height, vrefresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) static const struct stereo_mandatory_mode stereo_mandatory_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) { 1920, 1080, 24, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) { 1920, 1080, 24, DRM_MODE_FLAG_3D_FRAME_PACKING },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) { 1920, 1080, 50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) { 1920, 1080, 60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) { 1280, 720, 50, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) { 1280, 720, 50, DRM_MODE_FLAG_3D_FRAME_PACKING },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) { 1280, 720, 60, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) { 1280, 720, 60, DRM_MODE_FLAG_3D_FRAME_PACKING }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) stereo_match_mandatory(const struct drm_display_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) const struct stereo_mandatory_mode *stereo_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) unsigned int interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) return mode->hdisplay == stereo_mode->width &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) mode->vdisplay == stereo_mode->height &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) interlaced == (stereo_mode->flags & DRM_MODE_FLAG_INTERLACE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) drm_mode_vrefresh(mode) == stereo_mode->vrefresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) static int add_hdmi_mandatory_stereo_modes(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) const struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) struct list_head stereo_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) int modes = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) INIT_LIST_HEAD(&stereo_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) list_for_each_entry(mode, &connector->probed_modes, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) for (i = 0; i < ARRAY_SIZE(stereo_mandatory_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) const struct stereo_mandatory_mode *mandatory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) struct drm_display_mode *new_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) if (!stereo_match_mandatory(mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) &stereo_mandatory_modes[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) mandatory = &stereo_mandatory_modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) new_mode = drm_mode_duplicate(dev, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) if (!new_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) new_mode->flags |= mandatory->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) list_add_tail(&new_mode->head, &stereo_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) list_splice_tail(&stereo_modes, &connector->probed_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) static int add_hdmi_mode(struct drm_connector *connector, u8 vic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) if (!drm_valid_hdmi_vic(vic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) newmode = drm_mode_duplicate(dev, &edid_4k_modes[vic]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) const u8 *video_db, u8 video_len, u8 video_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) int modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) if (structure & (1 << 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) newmode = drm_display_mode_from_vic_index(connector, video_db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) video_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) video_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) newmode->flags |= DRM_MODE_FLAG_3D_FRAME_PACKING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) if (structure & (1 << 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) newmode = drm_display_mode_from_vic_index(connector, video_db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) video_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) video_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) newmode->flags |= DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) if (structure & (1 << 8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) newmode = drm_display_mode_from_vic_index(connector, video_db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) video_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) video_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) * do_hdmi_vsdb_modes - Parse the HDMI Vendor Specific data block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) * @connector: connector corresponding to the HDMI sink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) * @db: start of the CEA vendor specific block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) * @len: length of the CEA block payload, ie. one can access up to db[len]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) * Parses the HDMI VSDB looking for modes to add to @connector. This function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) * also adds the stereo 3d modes when applicable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) const u8 *video_db, u8 video_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) int modes = 0, offset = 0, i, multi_present = 0, multi_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) u8 vic_len, hdmi_3d_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) u16 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) u16 structure_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) if (len < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) /* no HDMI_Video_Present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) if (!(db[8] & (1 << 5)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) /* Latency_Fields_Present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) if (db[8] & (1 << 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) offset += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) /* I_Latency_Fields_Present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) if (db[8] & (1 << 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) offset += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) /* the declared length is not long enough for the 2 first bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) * of additional video format capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) if (len < (8 + offset + 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) /* 3D_Present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) if (db[8 + offset] & (1 << 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) modes += add_hdmi_mandatory_stereo_modes(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) /* 3D_Multi_present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) multi_present = (db[8 + offset] & 0x60) >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) vic_len = db[8 + offset] >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) hdmi_3d_len = db[8 + offset] & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) for (i = 0; i < vic_len && len >= (9 + offset + i); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) u8 vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) vic = db[9 + offset + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) modes += add_hdmi_mode(connector, vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) offset += 1 + vic_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) if (multi_present == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) multi_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) else if (multi_present == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) multi_len = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) multi_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) if (len < (8 + offset + hdmi_3d_len - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) if (hdmi_3d_len < multi_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) if (multi_present == 1 || multi_present == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) /* 3D_Structure_ALL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) structure_all = (db[8 + offset] << 8) | db[9 + offset];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) /* check if 3D_MASK is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) if (multi_present == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) mask = (db[10 + offset] << 8) | db[11 + offset];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) mask = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) if (mask & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) modes += add_3d_struct_modes(connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) structure_all,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) video_db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) video_len, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) offset += multi_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) for (i = 0; i < (hdmi_3d_len - multi_len); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) int vic_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) struct drm_display_mode *newmode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) unsigned int newflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) bool detail_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) detail_present = ((db[8 + offset + i] & 0x0f) > 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) if (detail_present && (i + 1 == hdmi_3d_len - multi_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) /* 2D_VIC_order_X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) vic_index = db[8 + offset + i] >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) /* 3D_Structure_X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) switch (db[8 + offset + i] & 0x0f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) newflag = DRM_MODE_FLAG_3D_FRAME_PACKING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) newflag = DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) /* 3D_Detail_X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) if ((db[9 + offset + i] >> 4) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) newflag = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) if (newflag != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) newmode = drm_display_mode_from_vic_index(connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) video_db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) video_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) vic_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) if (newmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) newmode->flags |= newflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) if (detail_present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) if (modes > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) info->has_hdmi_infoframe = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) cea_db_payload_len(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) return db[0] & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) cea_db_extended_tag(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) return db[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) cea_db_tag(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) return db[0] >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) cea_revision(const u8 *cea)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) * FIXME is this correct for the DispID variant?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) * The DispID spec doesn't really specify whether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) * this is the revision of the CEA extension or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) * the DispID CEA data block. And the only value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) * given as an example is 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) return cea[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) cea_db_offsets(const u8 *cea, int *start, int *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) /* DisplayID CTA extension blocks and top-level CEA EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) * block header definitions differ in the following bytes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) * 1) Byte 2 of the header specifies length differently,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) * 2) Byte 3 is only present in the CEA top level block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) * The different definitions for byte 2 follow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) * DisplayID CTA extension block defines byte 2 as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) * Number of payload bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) * CEA EDID block defines byte 2 as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) * Byte number (decimal) within this block where the 18-byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) * DTDs begin. If no non-DTD data is present in this extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) * block, the value should be set to 04h (the byte after next).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) * If set to 00h, there are no DTDs present in this block and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) * no non-DTD data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) if (cea[0] == DATA_BLOCK_CTA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) * for_each_displayid_db() has already verified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) * that these stay within expected bounds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) *start = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) *end = *start + cea[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) } else if (cea[0] == CEA_EXT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) /* Data block offset in CEA extension block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) *start = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) *end = cea[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) if (*end == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) *end = 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) if (*end < 4 || *end > 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) static bool cea_db_is_hdmi_vsdb(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) int hdmi_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) if (cea_db_tag(db) != VENDOR_BLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) if (cea_db_payload_len(db) < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) return hdmi_id == HDMI_IEEE_OUI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) unsigned int oui;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) if (cea_db_tag(db) != VENDOR_BLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) if (cea_db_payload_len(db) < 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) oui = db[3] << 16 | db[2] << 8 | db[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) return oui == HDMI_FORUM_IEEE_OUI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) static bool cea_db_is_vcdb(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) if (cea_db_tag(db) != USE_EXTENDED_TAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) if (cea_db_payload_len(db) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) if (cea_db_extended_tag(db) != EXT_VIDEO_CAPABILITY_BLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) static bool cea_db_is_y420cmdb(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) if (cea_db_tag(db) != USE_EXTENDED_TAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) if (!cea_db_payload_len(db))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) if (cea_db_extended_tag(db) != EXT_VIDEO_CAP_BLOCK_Y420CMDB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) static bool cea_db_is_y420vdb(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) if (cea_db_tag(db) != USE_EXTENDED_TAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) if (!cea_db_payload_len(db))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) if (cea_db_extended_tag(db) != EXT_VIDEO_DATA_BLOCK_420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) #define for_each_cea_db(cea, i, start, end) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228) static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232) struct drm_hdmi_info *hdmi = &info->hdmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) u8 map_len = cea_db_payload_len(db) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) u8 count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) u64 map = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) if (map_len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) /* All CEA modes support ycbcr420 sampling also.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) hdmi->y420_cmdb_map = U64_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240) info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) * This map indicates which of the existing CEA block modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) * from VDB can support YCBCR420 output too. So if bit=0 is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) * set, first mode from VDB can support YCBCR420 output too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) * We will parse and keep this map, before parsing VDB itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) * to avoid going through the same block again and again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) * Spec is not clear about max possible size of this block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) * Clamping max bitmap block size at 8 bytes. Every byte can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) * address 8 CEA modes, in this way this map can address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) * 8*8 = first 64 SVDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) if (WARN_ON_ONCE(map_len > 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) map_len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) for (count = 0; count < map_len; count++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) map |= (u64)db[2 + count] << (8 * count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) if (map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) hdmi->y420_cmdb_map = map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) #ifdef CONFIG_NO_GKI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) static int drm_find_all_edid_extension(const struct edid *edid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270) int ext_id, int *ext_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) u8 *edid_ext = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) int i, count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) /* No EDID or EDID extensions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) if (edid == NULL || edid->extensions == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) /* too many EDID extensions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) if (edid->extensions > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) /* Find CEA extension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) for (i = 0; i < edid->extensions; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) if (edid_ext[0] == ext_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) *ext_list = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) ext_list++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) add_cea_modes(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) const u8 *cea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) const u8 *db, *hdmi = NULL, *video = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) u8 dbl, hdmi_len, video_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) int i, count = 0, modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) int ext_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304) int ext_list[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) count = drm_find_all_edid_extension(edid, CEA_EXT, ext_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308) ext_index = ext_list[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) cea = drm_find_edid_extension(edid, CEA_EXT, &ext_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) if (cea && cea_revision(cea) >= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) int i, start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) if (cea_db_offsets(cea, &start, &end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) for_each_cea_db(cea, i, start, end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317) db = &cea[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) dbl = cea_db_payload_len(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320) if (cea_db_tag(db) == VIDEO_BLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) video = db + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) video_len = dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323) modes += do_cea_modes(connector, video, dbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324) } else if (cea_db_is_hdmi_vsdb(db)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325) hdmi = db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) hdmi_len = dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327) } else if (cea_db_is_y420vdb(db)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) const u8 *vdb420 = &db[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330) /* Add 4:2:0(only) modes present in EDID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331) modes += do_y420vdb_modes(connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) vdb420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333) dbl - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339) * We parse the HDMI VSDB after having added the cea modes as we will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) * be patching their flags when the sink supports stereo 3D.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) if (hdmi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343) modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len, video,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) video_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353) add_cea_modes(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) const u8 *cea = drm_find_cea_extension(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356) const u8 *db, *hdmi = NULL, *video = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357) u8 dbl, hdmi_len, video_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) int modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360) if (cea && cea_revision(cea) >= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) int i, start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363) if (cea_db_offsets(cea, &start, &end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) for_each_cea_db(cea, i, start, end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367) db = &cea[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) dbl = cea_db_payload_len(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370) if (cea_db_tag(db) == VIDEO_BLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371) video = db + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372) video_len = dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373) modes += do_cea_modes(connector, video, dbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374) } else if (cea_db_is_hdmi_vsdb(db)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) hdmi = db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376) hdmi_len = dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) } else if (cea_db_is_y420vdb(db)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378) const u8 *vdb420 = &db[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380) /* Add 4:2:0(only) modes present in EDID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381) modes += do_y420vdb_modes(connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382) vdb420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383) dbl - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389) * We parse the HDMI VSDB after having added the cea modes as we will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) * be patching their flags when the sink supports stereo 3D.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392) if (hdmi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393) modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len, video,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394) video_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396) return modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400) static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402) const struct drm_display_mode *cea_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403) int clock1, clock2, clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404) u8 vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405) const char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408) * allow 5kHz clock difference either way to account for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) * the 10kHz clock resolution limit of detailed timings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411) vic = drm_match_cea_mode_clock_tolerance(mode, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412) if (drm_valid_cea_vic(vic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413) type = "CEA";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414) cea_mode = cea_mode_for_vic(vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415) clock1 = cea_mode->clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) clock2 = cea_mode_alternate_clock(cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) vic = drm_match_hdmi_mode_clock_tolerance(mode, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419) if (drm_valid_hdmi_vic(vic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) type = "HDMI";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) cea_mode = &edid_4k_modes[vic];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422) clock1 = cea_mode->clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423) clock2 = hdmi_mode_alternate_clock(cea_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429) /* pick whichever is closest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430) if (abs(mode->clock - clock1) < abs(mode->clock - clock2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431) clock = clock1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433) clock = clock2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) if (mode->clock == clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438) DRM_DEBUG("detailed mode matches %s VIC %d, adjusting clock %d -> %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) type, vic, mode->clock, clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440) mode->clock = clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443) static bool cea_db_is_hdmi_hdr_metadata_block(const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445) if (cea_db_tag(db) != USE_EXTENDED_TAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) if (db[1] != HDR_STATIC_METADATA_BLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451) if (cea_db_payload_len(db) < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) static uint8_t eotf_supported(const u8 *edid_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) return edid_ext[2] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) (BIT(HDMI_EOTF_TRADITIONAL_GAMMA_SDR) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461) BIT(HDMI_EOTF_TRADITIONAL_GAMMA_HDR) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462) BIT(HDMI_EOTF_SMPTE_ST2084) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463) BIT(HDMI_EOTF_BT_2100_HLG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) static uint8_t hdr_metadata_type(const u8 *edid_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468) return edid_ext[3] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469) BIT(HDMI_STATIC_METADATA_TYPE1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473) drm_parse_hdr_metadata_block(struct drm_connector *connector, const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) u16 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477) len = cea_db_payload_len(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479) connector->hdr_sink_metadata.hdmi_type1.eotf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480) eotf_supported(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481) connector->hdr_sink_metadata.hdmi_type1.metadata_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) hdr_metadata_type(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484) if (len >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485) connector->hdr_sink_metadata.hdmi_type1.max_cll = db[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) if (len >= 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487) connector->hdr_sink_metadata.hdmi_type1.max_fall = db[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488) if (len >= 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489) connector->hdr_sink_metadata.hdmi_type1.min_cll = db[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495) u8 len = cea_db_payload_len(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) if (len >= 6 && (db[6] & (1 << 7)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_SUPPORTS_AI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499) if (len >= 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) connector->latency_present[0] = db[8] >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501) connector->latency_present[1] = (db[8] >> 6) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503) if (len >= 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504) connector->video_latency[0] = db[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505) if (len >= 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506) connector->audio_latency[0] = db[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) if (len >= 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508) connector->video_latency[1] = db[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) if (len >= 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510) connector->audio_latency[1] = db[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) DRM_DEBUG_KMS("HDMI: latency present %d %d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) "video latency %d %d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514) "audio latency %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) connector->latency_present[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) connector->latency_present[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517) connector->video_latency[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518) connector->video_latency[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) connector->audio_latency[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520) connector->audio_latency[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) monitor_name(struct detailed_timing *t, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4526) if (!is_display_descriptor((const u8 *)t, EDID_DETAIL_MONITOR_NAME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4527) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4529) *(u8 **)data = t->data.other_data.data.str.str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4532) static int get_monitor_name(struct edid *edid, char name[13])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4534) char *edid_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4535) int mnl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4537) if (!edid || !name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4538) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4540) drm_for_each_detailed_block((u8 *)edid, monitor_name, &edid_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4541) for (mnl = 0; edid_name && mnl < 13; mnl++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4542) if (edid_name[mnl] == 0x0a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4545) name[mnl] = edid_name[mnl];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4548) return mnl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4551) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4552) * drm_edid_get_monitor_name - fetch the monitor name from the edid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4553) * @edid: monitor EDID information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4554) * @name: pointer to a character array to hold the name of the monitor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4555) * @bufsize: The size of the name buffer (should be at least 14 chars.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4556) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4557) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4558) void drm_edid_get_monitor_name(struct edid *edid, char *name, int bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4560) int name_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4561) char buf[13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4563) if (bufsize <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4564) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4566) name_length = min(get_monitor_name(edid, buf), bufsize - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4567) memcpy(name, buf, name_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4568) name[name_length] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4570) EXPORT_SYMBOL(drm_edid_get_monitor_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4572) static void clear_eld(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4574) memset(connector->eld, 0, sizeof(connector->eld));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4576) connector->latency_present[0] = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4577) connector->latency_present[1] = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4578) connector->video_latency[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4579) connector->audio_latency[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4580) connector->video_latency[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4581) connector->audio_latency[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4584) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4585) * drm_edid_to_eld - build ELD from EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4586) * @connector: connector corresponding to the HDMI/DP sink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4587) * @edid: EDID to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4588) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4589) * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4590) * HDCP and Port_ID ELD fields are left for the graphics driver to fill in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4592) static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4594) uint8_t *eld = connector->eld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4595) u8 *cea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4596) u8 *db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4597) int total_sad_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4598) int mnl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4599) int dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4601) clear_eld(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4603) if (!edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4604) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4606) cea = drm_find_cea_extension(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4607) if (!cea) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4608) DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4609) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4612) mnl = get_monitor_name(edid, &eld[DRM_ELD_MONITOR_NAME_STRING]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4613) DRM_DEBUG_KMS("ELD monitor %s\n", &eld[DRM_ELD_MONITOR_NAME_STRING]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4615) eld[DRM_ELD_CEA_EDID_VER_MNL] = cea[1] << DRM_ELD_CEA_EDID_VER_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4616) eld[DRM_ELD_CEA_EDID_VER_MNL] |= mnl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4618) eld[DRM_ELD_VER] = DRM_ELD_VER_CEA861D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4620) eld[DRM_ELD_MANUFACTURER_NAME0] = edid->mfg_id[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4621) eld[DRM_ELD_MANUFACTURER_NAME1] = edid->mfg_id[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4622) eld[DRM_ELD_PRODUCT_CODE0] = edid->prod_code[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4623) eld[DRM_ELD_PRODUCT_CODE1] = edid->prod_code[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4625) if (cea_revision(cea) >= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4626) int i, start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4627) int sad_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4629) if (cea_db_offsets(cea, &start, &end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4630) start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4631) end = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4634) for_each_cea_db(cea, i, start, end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4635) db = &cea[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4636) dbl = cea_db_payload_len(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4638) switch (cea_db_tag(db)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4639) case AUDIO_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4640) /* Audio Data Block, contains SADs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4641) sad_count = min(dbl / 3, 15 - total_sad_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4642) if (sad_count >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4643) memcpy(&eld[DRM_ELD_CEA_SAD(mnl, total_sad_count)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4644) &db[1], sad_count * 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4645) total_sad_count += sad_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4646) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4647) case SPEAKER_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4648) /* Speaker Allocation Data Block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4649) if (dbl >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4650) eld[DRM_ELD_SPEAKER] = db[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4652) case VENDOR_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4653) /* HDMI Vendor-Specific Data Block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4654) if (cea_db_is_hdmi_vsdb(db))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4655) drm_parse_hdmi_vsdb_audio(connector, db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4656) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4657) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4658) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4662) eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= total_sad_count << DRM_ELD_SAD_COUNT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4664) if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4665) connector->connector_type == DRM_MODE_CONNECTOR_eDP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4666) eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_CONN_TYPE_DP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4667) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4668) eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_CONN_TYPE_HDMI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4670) eld[DRM_ELD_BASELINE_ELD_LEN] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4671) DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4673) DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4674) drm_eld_size(eld), total_sad_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4677) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4678) * drm_edid_to_sad - extracts SADs from EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4679) * @edid: EDID to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4680) * @sads: pointer that will be set to the extracted SADs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4681) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4682) * Looks for CEA EDID block and extracts SADs (Short Audio Descriptors) from it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4683) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4684) * Note: The returned pointer needs to be freed using kfree().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4685) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4686) * Return: The number of found SADs or negative number on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4688) int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4690) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4691) int i, start, end, dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4692) u8 *cea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4694) cea = drm_find_cea_extension(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4695) if (!cea) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4696) DRM_DEBUG_KMS("SAD: no CEA Extension found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4697) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4700) if (cea_revision(cea) < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4701) DRM_DEBUG_KMS("SAD: wrong CEA revision\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4702) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4705) if (cea_db_offsets(cea, &start, &end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4706) DRM_DEBUG_KMS("SAD: invalid data block offsets\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4707) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4710) for_each_cea_db(cea, i, start, end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4711) u8 *db = &cea[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4713) if (cea_db_tag(db) == AUDIO_BLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4714) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4716) dbl = cea_db_payload_len(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4718) count = dbl / 3; /* SAD is 3B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4719) *sads = kcalloc(count, sizeof(**sads), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4720) if (!*sads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4721) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4722) for (j = 0; j < count; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4723) u8 *sad = &db[1 + j * 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4725) (*sads)[j].format = (sad[0] & 0x78) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4726) (*sads)[j].channels = sad[0] & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4727) (*sads)[j].freq = sad[1] & 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4728) (*sads)[j].byte2 = sad[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4730) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4734) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4736) EXPORT_SYMBOL(drm_edid_to_sad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4738) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4739) * drm_edid_to_speaker_allocation - extracts Speaker Allocation Data Blocks from EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4740) * @edid: EDID to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4741) * @sadb: pointer to the speaker block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4742) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4743) * Looks for CEA EDID block and extracts the Speaker Allocation Data Block from it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4744) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4745) * Note: The returned pointer needs to be freed using kfree().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4746) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4747) * Return: The number of found Speaker Allocation Blocks or negative number on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4748) * error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4749) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4750) int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4752) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4753) int i, start, end, dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4754) const u8 *cea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4756) cea = drm_find_cea_extension(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4757) if (!cea) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4758) DRM_DEBUG_KMS("SAD: no CEA Extension found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4759) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4762) if (cea_revision(cea) < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4763) DRM_DEBUG_KMS("SAD: wrong CEA revision\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4764) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4767) if (cea_db_offsets(cea, &start, &end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4768) DRM_DEBUG_KMS("SAD: invalid data block offsets\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4769) return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4772) for_each_cea_db(cea, i, start, end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4773) const u8 *db = &cea[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4775) if (cea_db_tag(db) == SPEAKER_BLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4776) dbl = cea_db_payload_len(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4778) /* Speaker Allocation Data Block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4779) if (dbl == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4780) *sadb = kmemdup(&db[1], dbl, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4781) if (!*sadb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4782) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4783) count = dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4789) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4791) EXPORT_SYMBOL(drm_edid_to_speaker_allocation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4793) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4794) * drm_av_sync_delay - compute the HDMI/DP sink audio-video sync delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4795) * @connector: connector associated with the HDMI/DP sink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4796) * @mode: the display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4797) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4798) * Return: The HDMI/DP sink's audio-video sync delay in milliseconds or 0 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4799) * the sink doesn't support audio or video.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4800) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4801) int drm_av_sync_delay(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4802) const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4803) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4804) int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4805) int a, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4807) if (!connector->latency_present[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4809) if (!connector->latency_present[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4810) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4812) a = connector->audio_latency[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4813) v = connector->video_latency[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4815) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4816) * HDMI/DP sink doesn't support audio or video?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4817) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4818) if (a == 255 || v == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4819) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4821) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4822) * Convert raw EDID values to millisecond.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4823) * Treat unknown latency as 0ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4824) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4825) if (a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4826) a = min(2 * (a - 1), 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4827) if (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4828) v = min(2 * (v - 1), 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4830) return max(v - a, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4832) EXPORT_SYMBOL(drm_av_sync_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4834) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4835) * drm_detect_hdmi_monitor - detect whether monitor is HDMI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4836) * @edid: monitor EDID information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4837) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4838) * Parse the CEA extension according to CEA-861-B.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4839) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4840) * Drivers that have added the modes parsed from EDID to drm_display_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4841) * should use &drm_display_info.is_hdmi instead of calling this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4842) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4843) * Return: True if the monitor is HDMI, false if not or unknown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4844) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4845) bool drm_detect_hdmi_monitor(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4847) u8 *edid_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4848) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4849) int start_offset, end_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4851) edid_ext = drm_find_cea_extension(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4852) if (!edid_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4853) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4855) if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4856) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4858) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4859) * Because HDMI identifier is in Vendor Specific Block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4860) * search it from all data blocks of CEA extension.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4861) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4862) for_each_cea_db(edid_ext, i, start_offset, end_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4863) if (cea_db_is_hdmi_vsdb(&edid_ext[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4864) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4867) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4869) EXPORT_SYMBOL(drm_detect_hdmi_monitor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4871) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4872) * drm_detect_monitor_audio - check monitor audio capability
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4873) * @edid: EDID block to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4874) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4875) * Monitor should have CEA extension block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4876) * If monitor has 'basic audio', but no CEA audio blocks, it's 'basic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4877) * audio' only. If there is any audio extension block and supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4878) * audio format, assume at least 'basic audio' support, even if 'basic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4879) * audio' is not defined in EDID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4880) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4881) * Return: True if the monitor supports audio, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4882) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4883) bool drm_detect_monitor_audio(struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4885) u8 *edid_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4886) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4887) bool has_audio = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4888) int start_offset, end_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4890) edid_ext = drm_find_cea_extension(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4891) if (!edid_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4892) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4894) has_audio = (edid_ext[0] == CEA_EXT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4895) (edid_ext[3] & EDID_BASIC_AUDIO) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4897) if (has_audio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4898) DRM_DEBUG_KMS("Monitor has basic audio support\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4899) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4902) if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4903) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4905) for_each_cea_db(edid_ext, i, start_offset, end_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4906) if (cea_db_tag(&edid_ext[i]) == AUDIO_BLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4907) has_audio = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4908) for (j = 1; j < cea_db_payload_len(&edid_ext[i]) + 1; j += 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4909) DRM_DEBUG_KMS("CEA audio format %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4910) (edid_ext[i + j] >> 3) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4911) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4914) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4915) return has_audio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4917) EXPORT_SYMBOL(drm_detect_monitor_audio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4920) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4921) * drm_default_rgb_quant_range - default RGB quantization range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4922) * @mode: display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4923) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4924) * Determine the default RGB quantization range for the mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4925) * as specified in CEA-861.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4926) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4927) * Return: The default RGB quantization range for the mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4928) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4929) enum hdmi_quantization_range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4930) drm_default_rgb_quant_range(const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4932) /* All CEA modes other than VIC 1 use limited quantization range. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4933) return drm_match_cea_mode(mode) > 1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4934) HDMI_QUANTIZATION_RANGE_LIMITED :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4935) HDMI_QUANTIZATION_RANGE_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4937) EXPORT_SYMBOL(drm_default_rgb_quant_range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4939) static void drm_parse_vcdb(struct drm_connector *connector, const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4941) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4943) DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", db[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4945) if (db[2] & EDID_CEA_VCDB_QS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4946) info->rgb_quant_range_selectable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4949) #ifdef CONFIG_NO_GKI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4950) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4951) void drm_get_max_frl_rate(int max_frl_rate, u8 *max_lanes, u8 *max_rate_per_lane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4953) switch (max_frl_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4954) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4955) *max_lanes = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4956) *max_rate_per_lane = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4957) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4958) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4959) *max_lanes = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4960) *max_rate_per_lane = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4961) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4962) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4963) *max_lanes = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4964) *max_rate_per_lane = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4965) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4966) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4967) *max_lanes = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4968) *max_rate_per_lane = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4969) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4970) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4971) *max_lanes = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4972) *max_rate_per_lane = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4973) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4974) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4975) *max_lanes = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4976) *max_rate_per_lane = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4977) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4978) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4979) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4980) *max_lanes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4981) *max_rate_per_lane = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4984) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4986) static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4987) const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4989) u8 dc_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4990) struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4992) dc_mask = db[7] & DRM_EDID_YCBCR420_DC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4993) hdmi->y420_dc_modes = dc_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4996) static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4997) const u8 *hf_vsdb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4999) struct drm_display_info *display = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5000) struct drm_hdmi_info *hdmi = &display->hdmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5002) display->has_hdmi_infoframe = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5004) if (hf_vsdb[6] & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5005) hdmi->scdc.supported = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5006) if (hf_vsdb[6] & 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5007) hdmi->scdc.read_request = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5010) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5011) * All HDMI 2.0 monitors must support scrambling at rates > 340 MHz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5012) * And as per the spec, three factors confirm this:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5013) * * Availability of a HF-VSDB block in EDID (check)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5014) * * Non zero Max_TMDS_Char_Rate filed in HF-VSDB (let's check)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5015) * * SCDC support available (let's check)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5016) * Lets check it out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5017) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5019) if (hf_vsdb[5]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5020) /* max clock is 5000 KHz times block value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5021) u32 max_tmds_clock = hf_vsdb[5] * 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5022) struct drm_scdc *scdc = &hdmi->scdc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5024) if (max_tmds_clock > 340000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5025) display->max_tmds_clock = max_tmds_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5026) DRM_DEBUG_KMS("HF-VSDB: max TMDS clock %d kHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5027) display->max_tmds_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5030) if (scdc->supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5031) scdc->scrambling.supported = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5033) /* Few sinks support scrambling for clocks < 340M */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5034) if ((hf_vsdb[6] & 0x8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5035) scdc->scrambling.low_rates = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5039) #ifdef CONFIG_NO_GKI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5040) if (hf_vsdb[7]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5041) u8 max_frl_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5042) u8 dsc_max_frl_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5043) u8 dsc_max_slices;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5044) struct drm_hdmi_dsc_cap *hdmi_dsc = &hdmi->dsc_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5046) DRM_DEBUG_KMS("hdmi_21 sink detected. parsing edid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5047) max_frl_rate = (hf_vsdb[7] & DRM_EDID_MAX_FRL_RATE_MASK) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5048) drm_get_max_frl_rate(max_frl_rate, &hdmi->max_lanes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5049) &hdmi->max_frl_rate_per_lane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5050) hdmi_dsc->v_1p2 = hf_vsdb[11] & DRM_EDID_DSC_1P2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5052) if (hdmi_dsc->v_1p2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5053) hdmi_dsc->native_420 = hf_vsdb[11] & DRM_EDID_DSC_NATIVE_420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5054) hdmi_dsc->all_bpp = hf_vsdb[11] & DRM_EDID_DSC_ALL_BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5056) if (hf_vsdb[11] & DRM_EDID_DSC_16BPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5057) hdmi_dsc->bpc_supported = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5058) else if (hf_vsdb[11] & DRM_EDID_DSC_12BPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5059) hdmi_dsc->bpc_supported = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5060) else if (hf_vsdb[11] & DRM_EDID_DSC_10BPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5061) hdmi_dsc->bpc_supported = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5062) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5063) hdmi_dsc->bpc_supported = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5065) dsc_max_frl_rate = (hf_vsdb[12] & DRM_EDID_DSC_MAX_FRL_RATE_MASK) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5066) drm_get_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->max_lanes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5067) &hdmi_dsc->max_frl_rate_per_lane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5068) hdmi_dsc->total_chunk_kbytes = hf_vsdb[13] & DRM_EDID_DSC_TOTAL_CHUNK_KBYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5070) dsc_max_slices = hf_vsdb[12] & DRM_EDID_DSC_MAX_SLICES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5071) switch (dsc_max_slices) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5072) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5073) hdmi_dsc->max_slices = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5074) hdmi_dsc->clk_per_slice = 340;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5075) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5076) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5077) hdmi_dsc->max_slices = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5078) hdmi_dsc->clk_per_slice = 340;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5079) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5080) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5081) hdmi_dsc->max_slices = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5082) hdmi_dsc->clk_per_slice = 340;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5083) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5084) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5085) hdmi_dsc->max_slices = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5086) hdmi_dsc->clk_per_slice = 340;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5087) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5088) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5089) hdmi_dsc->max_slices = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5090) hdmi_dsc->clk_per_slice = 400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5091) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5092) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5093) hdmi_dsc->max_slices = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5094) hdmi_dsc->clk_per_slice = 400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5095) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5096) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5097) hdmi_dsc->max_slices = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5098) hdmi_dsc->clk_per_slice = 400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5099) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5100) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5101) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5102) hdmi_dsc->max_slices = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5103) hdmi_dsc->clk_per_slice = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5107) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5109) drm_parse_ycbcr420_deep_color_info(connector, hf_vsdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5112) static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5113) const u8 *hdmi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5115) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5116) unsigned int dc_bpc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5118) /* HDMI supports at least 8 bpc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5119) info->bpc = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5121) if (cea_db_payload_len(hdmi) < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5122) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5124) if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5125) dc_bpc = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5126) info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5127) DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5128) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5131) if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5132) dc_bpc = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5133) info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5134) DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5135) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5138) if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5139) dc_bpc = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5140) info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5141) DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5142) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5145) if (dc_bpc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5146) DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5147) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5148) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5151) DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5152) connector->name, dc_bpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5153) info->bpc = dc_bpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5155) /* YCRCB444 is optional according to spec. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5156) if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5157) DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5158) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5162) * Spec says that if any deep color mode is supported at all,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5163) * then deep color 36 bit must be supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5165) if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5166) DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5167) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5171) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5172) drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5174) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5175) u8 len = cea_db_payload_len(db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5177) info->is_hdmi = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5179) if (len >= 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5180) info->dvi_dual = db[6] & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5181) if (len >= 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5182) info->max_tmds_clock = db[7] * 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5184) DRM_DEBUG_KMS("HDMI: DVI dual %d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5185) "max TMDS clock %d kHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5186) info->dvi_dual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5187) info->max_tmds_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5189) drm_parse_hdmi_deep_color_info(connector, db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5192) static void drm_parse_cea_ext(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5193) const struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5195) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5196) const u8 *edid_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5197) int i, start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5199) edid_ext = drm_find_cea_extension(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5200) if (!edid_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5201) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5203) info->cea_rev = edid_ext[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5205) /* The existence of a CEA block should imply RGB support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5206) info->color_formats = DRM_COLOR_FORMAT_RGB444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5207) if (edid_ext[3] & EDID_CEA_YCRCB444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5208) info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5209) if (edid_ext[3] & EDID_CEA_YCRCB422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5210) info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5212) if (cea_db_offsets(edid_ext, &start, &end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5213) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5215) for_each_cea_db(edid_ext, i, start, end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5216) const u8 *db = &edid_ext[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5218) if (cea_db_is_hdmi_vsdb(db))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5219) drm_parse_hdmi_vsdb_video(connector, db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5220) if (cea_db_is_hdmi_forum_vsdb(db))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5221) drm_parse_hdmi_forum_vsdb(connector, db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5222) if (cea_db_is_y420cmdb(db))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5223) drm_parse_y420cmdb_bitmap(connector, db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5224) if (cea_db_is_vcdb(db))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5225) drm_parse_vcdb(connector, db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5226) if (cea_db_is_hdmi_hdr_metadata_block(db))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5227) drm_parse_hdr_metadata_block(connector, db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5231) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5232) void get_monitor_range(struct detailed_timing *timing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5233) void *info_monitor_range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5235) struct drm_monitor_range_info *monitor_range = info_monitor_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5236) const struct detailed_non_pixel *data = &timing->data.other_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5237) const struct detailed_data_monitor_range *range = &data->data.range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5239) if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_MONITOR_RANGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5240) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5243) * Check for flag range limits only. If flag == 1 then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5244) * no additional timing information provided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5245) * Default GTF, GTF Secondary curve and CVT are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5246) * supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5248) if (range->flags != DRM_EDID_RANGE_LIMITS_ONLY_FLAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5249) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5251) monitor_range->min_vfreq = range->min_vfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5252) monitor_range->max_vfreq = range->max_vfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5255) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5256) void drm_get_monitor_range(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5257) const struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5259) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5261) if (!version_greater(edid, 1, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5262) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5264) drm_for_each_detailed_block((u8 *)edid, get_monitor_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5265) &info->monitor_range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5267) DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5268) info->monitor_range.min_vfreq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5269) info->monitor_range.max_vfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5272) /* A connector has no EDID information, so we've got no EDID to compute quirks from. Reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5273) * all of the values which would have been set from EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5274) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5275) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5276) drm_reset_display_info(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5278) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5280) info->width_mm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5281) info->height_mm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5283) info->bpc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5284) info->color_formats = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5285) info->cea_rev = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5286) info->max_tmds_clock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5287) info->dvi_dual = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5288) info->is_hdmi = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5289) info->has_hdmi_infoframe = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5290) info->rgb_quant_range_selectable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5291) memset(&info->hdmi, 0, sizeof(info->hdmi));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5293) info->non_desktop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5294) memset(&info->monitor_range, 0, sizeof(info->monitor_range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5297) u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5299) struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5301) u32 quirks = edid_get_quirks(edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5303) drm_reset_display_info(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5305) info->width_mm = edid->width_cm * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5306) info->height_mm = edid->height_cm * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5308) info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5310) drm_get_monitor_range(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5312) DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5314) if (edid->revision < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5315) return quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5317) if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5318) return quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5320) info->color_formats |= DRM_COLOR_FORMAT_RGB444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5321) drm_parse_cea_ext(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5324) * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5325) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5326) * For such displays, the DFP spec 1.0, section 3.10 "EDID support"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5327) * tells us to assume 8 bpc color depth if the EDID doesn't have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5328) * extensions which tell otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5330) if (info->bpc == 0 && edid->revision == 3 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5331) edid->input & DRM_EDID_DIGITAL_DFP_1_X) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5332) info->bpc = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5333) DRM_DEBUG("%s: Assigning DFP sink color depth as %d bpc.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5334) connector->name, info->bpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5337) /* Only defined for 1.4 with digital displays */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5338) if (edid->revision < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5339) return quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5341) switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5342) case DRM_EDID_DIGITAL_DEPTH_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5343) info->bpc = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5344) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5345) case DRM_EDID_DIGITAL_DEPTH_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5346) info->bpc = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5347) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5348) case DRM_EDID_DIGITAL_DEPTH_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5349) info->bpc = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5351) case DRM_EDID_DIGITAL_DEPTH_12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5352) info->bpc = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5354) case DRM_EDID_DIGITAL_DEPTH_14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5355) info->bpc = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5356) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5357) case DRM_EDID_DIGITAL_DEPTH_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5358) info->bpc = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5360) case DRM_EDID_DIGITAL_DEPTH_UNDEF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5361) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5362) info->bpc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5366) DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5367) connector->name, info->bpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5369) if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5370) info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5371) if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5372) info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5373) return quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5376) static int validate_displayid(u8 *displayid, int length, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5378) int i, dispid_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5379) u8 csum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5380) struct displayid_hdr *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5382) base = (struct displayid_hdr *)&displayid[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5384) DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5385) base->rev, base->bytes, base->prod_id, base->ext_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5387) /* +1 for DispID checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5388) dispid_length = sizeof(*base) + base->bytes + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5389) if (dispid_length > length - idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5390) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5392) for (i = 0; i < dispid_length; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5393) csum += displayid[idx + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5394) if (csum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5395) DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5396) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5399) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5402) static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5403) struct displayid_detailed_timings_1 *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5405) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5406) unsigned pixel_clock = (timings->pixel_clock[0] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5407) (timings->pixel_clock[1] << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5408) (timings->pixel_clock[2] << 16)) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5409) unsigned hactive = (timings->hactive[0] | timings->hactive[1] << 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5410) unsigned hblank = (timings->hblank[0] | timings->hblank[1] << 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5411) unsigned hsync = (timings->hsync[0] | (timings->hsync[1] & 0x7f) << 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5412) unsigned hsync_width = (timings->hsw[0] | timings->hsw[1] << 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5413) unsigned vactive = (timings->vactive[0] | timings->vactive[1] << 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5414) unsigned vblank = (timings->vblank[0] | timings->vblank[1] << 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5415) unsigned vsync = (timings->vsync[0] | (timings->vsync[1] & 0x7f) << 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5416) unsigned vsync_width = (timings->vsw[0] | timings->vsw[1] << 8) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5417) bool hsync_positive = (timings->hsync[1] >> 7) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5418) bool vsync_positive = (timings->vsync[1] >> 7) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5420) mode = drm_mode_create(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5421) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5422) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5424) mode->clock = pixel_clock * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5425) mode->hdisplay = hactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5426) mode->hsync_start = mode->hdisplay + hsync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5427) mode->hsync_end = mode->hsync_start + hsync_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5428) mode->htotal = mode->hdisplay + hblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5430) mode->vdisplay = vactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5431) mode->vsync_start = mode->vdisplay + vsync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5432) mode->vsync_end = mode->vsync_start + vsync_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5433) mode->vtotal = mode->vdisplay + vblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5435) mode->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5436) mode->flags |= hsync_positive ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5437) mode->flags |= vsync_positive ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5438) mode->type = DRM_MODE_TYPE_DRIVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5440) if (timings->flags & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5441) mode->type |= DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5442) drm_mode_set_name(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5444) return mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5447) static int add_displayid_detailed_1_modes(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5448) struct displayid_block *block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5450) struct displayid_detailed_timing_block *det = (struct displayid_detailed_timing_block *)block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5451) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5452) int num_timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5453) struct drm_display_mode *newmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5454) int num_modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5455) /* blocks must be multiple of 20 bytes length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5456) if (block->num_bytes % 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5457) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5459) num_timings = block->num_bytes / 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5460) for (i = 0; i < num_timings; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5461) struct displayid_detailed_timings_1 *timings = &det->timings[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5463) newmode = drm_mode_displayid_detailed(connector->dev, timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5464) if (!newmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5465) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5467) drm_mode_probed_add(connector, newmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5468) num_modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5470) return num_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5473) static int add_displayid_detailed_modes(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5474) struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5476) u8 *displayid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5477) int length, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5478) struct displayid_block *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5479) int num_modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5480) int ext_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5482) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5483) displayid = drm_find_displayid_extension(edid, &length, &idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5484) &ext_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5485) if (!displayid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5486) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5488) idx += sizeof(struct displayid_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5489) for_each_displayid_db(displayid, block, idx, length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5490) switch (block->tag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5491) case DATA_BLOCK_TYPE_1_DETAILED_TIMING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5492) num_modes += add_displayid_detailed_1_modes(connector, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5498) return num_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5501) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5502) * drm_add_edid_modes - add modes from EDID data, if available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5503) * @connector: connector we're probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5504) * @edid: EDID data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5505) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5506) * Add the specified modes to the connector's mode list. Also fills out the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5507) * &drm_display_info structure and ELD in @connector with any information which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5508) * can be derived from the edid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5509) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5510) * Return: The number of modes added or 0 if we couldn't find any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5512) int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5514) int num_modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5515) u32 quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5517) if (edid == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5518) clear_eld(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5521) if (!drm_edid_is_valid(edid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5522) clear_eld(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5523) drm_warn(connector->dev, "%s: EDID invalid.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5524) connector->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5525) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5528) drm_edid_to_eld(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5530) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5531) * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5532) * To avoid multiple parsing of same block, lets parse that map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5533) * from sink info, before parsing CEA modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5534) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5535) quirks = drm_add_display_info(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5538) * EDID spec says modes should be preferred in this order:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5539) * - preferred detailed mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5540) * - other detailed modes from base block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5541) * - detailed modes from extension blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5542) * - CVT 3-byte code modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5543) * - standard timing codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5544) * - established timing codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5545) * - modes inferred from GTF or CVT range information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5546) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5547) * We get this pretty much right.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5548) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5549) * XXX order for additional mode types in extension blocks?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5550) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5551) num_modes += add_detailed_modes(connector, edid, quirks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5552) num_modes += add_cvt_modes(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5553) num_modes += add_standard_modes(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5554) num_modes += add_established_modes(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5555) num_modes += add_cea_modes(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5556) num_modes += add_alternate_cea_modes(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5557) num_modes += add_displayid_detailed_modes(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5558) if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5559) num_modes += add_inferred_modes(connector, edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5561) if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5562) edid_fixup_preferred(connector, quirks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5564) if (quirks & EDID_QUIRK_FORCE_6BPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5565) connector->display_info.bpc = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5567) if (quirks & EDID_QUIRK_FORCE_8BPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5568) connector->display_info.bpc = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5570) if (quirks & EDID_QUIRK_FORCE_10BPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5571) connector->display_info.bpc = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5573) if (quirks & EDID_QUIRK_FORCE_12BPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5574) connector->display_info.bpc = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5576) return num_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5578) EXPORT_SYMBOL(drm_add_edid_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5580) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5581) * drm_add_modes_noedid - add modes for the connectors without EDID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5582) * @connector: connector we're probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5583) * @hdisplay: the horizontal display limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5584) * @vdisplay: the vertical display limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5585) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5586) * Add the specified modes to the connector's mode list. Only when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5587) * hdisplay/vdisplay is not beyond the given limit, it will be added.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5588) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5589) * Return: The number of modes added or 0 if we couldn't find any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5591) int drm_add_modes_noedid(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5592) int hdisplay, int vdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5594) int i, count, num_modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5595) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5596) struct drm_device *dev = connector->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5598) count = ARRAY_SIZE(drm_dmt_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5599) if (hdisplay < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5600) hdisplay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5601) if (vdisplay < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5602) vdisplay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5604) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5605) const struct drm_display_mode *ptr = &drm_dmt_modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5607) if (hdisplay && vdisplay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5608) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5609) * Only when two are valid, they will be used to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5610) * whether the mode should be added to the mode list of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5611) * the connector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5612) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5613) if (ptr->hdisplay > hdisplay ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5614) ptr->vdisplay > vdisplay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5615) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5617) if (drm_mode_vrefresh(ptr) > 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5618) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5619) mode = drm_mode_duplicate(dev, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5620) if (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5621) drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5622) num_modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5625) return num_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5627) EXPORT_SYMBOL(drm_add_modes_noedid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5629) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5630) * drm_set_preferred_mode - Sets the preferred mode of a connector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5631) * @connector: connector whose mode list should be processed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5632) * @hpref: horizontal resolution of preferred mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5633) * @vpref: vertical resolution of preferred mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5634) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5635) * Marks a mode as preferred if it matches the resolution specified by @hpref
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5636) * and @vpref.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5637) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5638) void drm_set_preferred_mode(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5639) int hpref, int vpref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5641) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5643) list_for_each_entry(mode, &connector->probed_modes, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5644) if (mode->hdisplay == hpref &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5645) mode->vdisplay == vpref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5646) mode->type |= DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5649) EXPORT_SYMBOL(drm_set_preferred_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5651) static bool is_hdmi2_sink(const struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5653) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5654) * FIXME: sil-sii8620 doesn't have a connector around when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5655) * we need one, so we have to be prepared for a NULL connector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5656) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5657) if (!connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5658) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5660) return connector->display_info.hdmi.scdc.supported ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5661) connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5664) static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5666) return sink_eotf & BIT(output_eotf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5669) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5670) * drm_hdmi_infoframe_set_hdr_metadata() - fill an HDMI DRM infoframe with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5671) * HDR metadata from userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5672) * @frame: HDMI DRM infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5673) * @conn_state: Connector state containing HDR metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5674) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5675) * Return: 0 on success or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5677) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5678) drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5679) const struct drm_connector_state *conn_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5681) struct drm_connector *connector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5682) struct hdr_output_metadata *hdr_metadata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5683) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5685) if (!frame || !conn_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5686) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5688) connector = conn_state->connector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5690) if (!conn_state->hdr_output_metadata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5691) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5693) hdr_metadata = conn_state->hdr_output_metadata->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5695) if (!hdr_metadata || !connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5696) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5698) /* Sink EOTF is Bit map while infoframe is absolute values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5699) if (!is_eotf_supported(hdr_metadata->hdmi_metadata_type1.eotf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5700) connector->hdr_sink_metadata.hdmi_type1.eotf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5701) DRM_DEBUG_KMS("EOTF Not Supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5702) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5705) err = hdmi_drm_infoframe_init(frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5706) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5707) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5709) frame->eotf = hdr_metadata->hdmi_metadata_type1.eotf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5710) frame->metadata_type = hdr_metadata->hdmi_metadata_type1.metadata_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5712) BUILD_BUG_ON(sizeof(frame->display_primaries) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5713) sizeof(hdr_metadata->hdmi_metadata_type1.display_primaries));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5714) BUILD_BUG_ON(sizeof(frame->white_point) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5715) sizeof(hdr_metadata->hdmi_metadata_type1.white_point));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5717) memcpy(&frame->display_primaries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5718) &hdr_metadata->hdmi_metadata_type1.display_primaries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5719) sizeof(frame->display_primaries));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5721) memcpy(&frame->white_point,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5722) &hdr_metadata->hdmi_metadata_type1.white_point,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5723) sizeof(frame->white_point));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5725) frame->max_display_mastering_luminance =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5726) hdr_metadata->hdmi_metadata_type1.max_display_mastering_luminance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5727) frame->min_display_mastering_luminance =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5728) hdr_metadata->hdmi_metadata_type1.min_display_mastering_luminance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5729) frame->max_fall = hdr_metadata->hdmi_metadata_type1.max_fall;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5730) frame->max_cll = hdr_metadata->hdmi_metadata_type1.max_cll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5732) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5734) EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5736) static u8 drm_mode_hdmi_vic(const struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5737) const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5739) bool has_hdmi_infoframe = connector ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5740) connector->display_info.has_hdmi_infoframe : false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5742) if (!has_hdmi_infoframe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5743) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5745) /* No HDMI VIC when signalling 3D video format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5746) if (mode->flags & DRM_MODE_FLAG_3D_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5747) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5749) return drm_match_hdmi_mode(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5752) static u8 drm_mode_cea_vic(const struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5753) const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5755) u8 vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5757) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5758) * HDMI spec says if a mode is found in HDMI 1.4b 4K modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5759) * we should send its VIC in vendor infoframes, else send the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5760) * VIC in AVI infoframes. Lets check if this mode is present in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5761) * HDMI 1.4b 4K modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5762) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5763) if (drm_mode_hdmi_vic(connector, mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5764) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5766) vic = drm_match_cea_mode(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5768) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5769) * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5770) * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5771) * have to make sure we dont break HDMI 1.4 sinks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5772) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5773) if (!is_hdmi2_sink(connector) && vic > 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5774) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5776) return vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5779) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5780) * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5781) * data from a DRM display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5782) * @frame: HDMI AVI infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5783) * @connector: the connector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5784) * @mode: DRM display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5785) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5786) * Return: 0 on success or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5787) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5788) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5789) drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5790) const struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5791) const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5793) enum hdmi_picture_aspect picture_aspect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5794) u8 vic, hdmi_vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5796) if (!frame || !mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5797) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5799) hdmi_avi_infoframe_init(frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5801) if (mode->flags & DRM_MODE_FLAG_DBLCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5802) frame->pixel_repeat = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5804) vic = drm_mode_cea_vic(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5805) hdmi_vic = drm_mode_hdmi_vic(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5807) frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5809) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5810) * As some drivers don't support atomic, we can't use connector state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5811) * So just initialize the frame with default values, just the same way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5812) * as it's done with other properties here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5813) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5814) frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5815) frame->itc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5817) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5818) * Populate picture aspect ratio from either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5819) * user input (if specified) or from the CEA/HDMI mode lists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5820) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5821) picture_aspect = mode->picture_aspect_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5822) if (picture_aspect == HDMI_PICTURE_ASPECT_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5823) if (vic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5824) picture_aspect = drm_get_cea_aspect_ratio(vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5825) else if (hdmi_vic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5826) picture_aspect = drm_get_hdmi_aspect_ratio(hdmi_vic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5829) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5830) * The infoframe can't convey anything but none, 4:3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5831) * and 16:9, so if the user has asked for anything else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5832) * we can only satisfy it by specifying the right VIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5833) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5834) if (picture_aspect > HDMI_PICTURE_ASPECT_16_9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5835) if (vic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5836) if (picture_aspect != drm_get_cea_aspect_ratio(vic))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5837) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5838) } else if (hdmi_vic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5839) if (picture_aspect != drm_get_hdmi_aspect_ratio(hdmi_vic))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5840) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5841) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5842) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5845) picture_aspect = HDMI_PICTURE_ASPECT_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5848) frame->video_code = vic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5849) frame->picture_aspect = picture_aspect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5850) frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5851) frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5853) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5855) EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5857) /* HDMI Colorspace Spec Definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5858) #define FULL_COLORIMETRY_MASK 0x1FF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5859) #define NORMAL_COLORIMETRY_MASK 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5860) #define EXTENDED_COLORIMETRY_MASK 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5861) #define EXTENDED_ACE_COLORIMETRY_MASK 0xF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5863) #define C(x) ((x) << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5864) #define EC(x) ((x) << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5865) #define ACE(x) ((x) << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5867) #define HDMI_COLORIMETRY_NO_DATA 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5868) #define HDMI_COLORIMETRY_SMPTE_170M_YCC (C(1) | EC(0) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5869) #define HDMI_COLORIMETRY_BT709_YCC (C(2) | EC(0) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5870) #define HDMI_COLORIMETRY_XVYCC_601 (C(3) | EC(0) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5871) #define HDMI_COLORIMETRY_XVYCC_709 (C(3) | EC(1) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5872) #define HDMI_COLORIMETRY_SYCC_601 (C(3) | EC(2) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5873) #define HDMI_COLORIMETRY_OPYCC_601 (C(3) | EC(3) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5874) #define HDMI_COLORIMETRY_OPRGB (C(3) | EC(4) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5875) #define HDMI_COLORIMETRY_BT2020_CYCC (C(3) | EC(5) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5876) #define HDMI_COLORIMETRY_BT2020_RGB (C(3) | EC(6) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5877) #define HDMI_COLORIMETRY_BT2020_YCC (C(3) | EC(6) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5878) #define HDMI_COLORIMETRY_DCI_P3_RGB_D65 (C(3) | EC(7) | ACE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5879) #define HDMI_COLORIMETRY_DCI_P3_RGB_THEATER (C(3) | EC(7) | ACE(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5881) static const u32 hdmi_colorimetry_val[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5882) [DRM_MODE_COLORIMETRY_NO_DATA] = HDMI_COLORIMETRY_NO_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5883) [DRM_MODE_COLORIMETRY_SMPTE_170M_YCC] = HDMI_COLORIMETRY_SMPTE_170M_YCC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5884) [DRM_MODE_COLORIMETRY_BT709_YCC] = HDMI_COLORIMETRY_BT709_YCC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5885) [DRM_MODE_COLORIMETRY_XVYCC_601] = HDMI_COLORIMETRY_XVYCC_601,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5886) [DRM_MODE_COLORIMETRY_XVYCC_709] = HDMI_COLORIMETRY_XVYCC_709,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5887) [DRM_MODE_COLORIMETRY_SYCC_601] = HDMI_COLORIMETRY_SYCC_601,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5888) [DRM_MODE_COLORIMETRY_OPYCC_601] = HDMI_COLORIMETRY_OPYCC_601,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5889) [DRM_MODE_COLORIMETRY_OPRGB] = HDMI_COLORIMETRY_OPRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5890) [DRM_MODE_COLORIMETRY_BT2020_CYCC] = HDMI_COLORIMETRY_BT2020_CYCC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5891) [DRM_MODE_COLORIMETRY_BT2020_RGB] = HDMI_COLORIMETRY_BT2020_RGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5892) [DRM_MODE_COLORIMETRY_BT2020_YCC] = HDMI_COLORIMETRY_BT2020_YCC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5893) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5895) #undef C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5896) #undef EC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5897) #undef ACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5899) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5900) * drm_hdmi_avi_infoframe_colorspace() - fill the HDMI AVI infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5901) * colorspace information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5902) * @frame: HDMI AVI infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5903) * @conn_state: connector state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5905) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5906) drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5907) const struct drm_connector_state *conn_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5909) u32 colorimetry_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5910) u32 colorimetry_index = conn_state->colorspace & FULL_COLORIMETRY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5912) if (colorimetry_index >= ARRAY_SIZE(hdmi_colorimetry_val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5913) colorimetry_val = HDMI_COLORIMETRY_NO_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5914) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5915) colorimetry_val = hdmi_colorimetry_val[colorimetry_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5917) frame->colorimetry = colorimetry_val & NORMAL_COLORIMETRY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5918) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5919) * ToDo: Extend it for ACE formats as well. Modify the infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5920) * structure and extend it in drivers/video/hdmi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5921) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5922) frame->extended_colorimetry = (colorimetry_val >> 2) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5923) EXTENDED_COLORIMETRY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5925) EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorspace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5927) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5928) * drm_hdmi_avi_infoframe_quant_range() - fill the HDMI AVI infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5929) * quantization range information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5930) * @frame: HDMI AVI infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5931) * @connector: the connector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5932) * @mode: DRM display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5933) * @rgb_quant_range: RGB quantization range (Q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5934) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5935) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5936) drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5937) const struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5938) const struct drm_display_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5939) enum hdmi_quantization_range rgb_quant_range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5941) const struct drm_display_info *info = &connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5943) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5944) * CEA-861:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5945) * "A Source shall not send a non-zero Q value that does not correspond
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5946) * to the default RGB Quantization Range for the transmitted Picture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5947) * unless the Sink indicates support for the Q bit in a Video
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5948) * Capabilities Data Block."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5949) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5950) * HDMI 2.0 recommends sending non-zero Q when it does match the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5951) * default RGB quantization range for the mode, even when QS=0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5952) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5953) if (info->rgb_quant_range_selectable ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5954) rgb_quant_range == drm_default_rgb_quant_range(mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5955) frame->quantization_range = rgb_quant_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5956) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5957) frame->quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5959) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5960) * CEA-861-F:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5961) * "When transmitting any RGB colorimetry, the Source should set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5962) * YQ-field to match the RGB Quantization Range being transmitted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5963) * (e.g., when Limited Range RGB, set YQ=0 or when Full Range RGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5964) * set YQ=1) and the Sink shall ignore the YQ-field."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5965) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5966) * Unfortunate certain sinks (eg. VIZ Model 67/E261VA) get confused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5967) * by non-zero YQ when receiving RGB. There doesn't seem to be any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5968) * good way to tell which version of CEA-861 the sink supports, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5969) * we limit non-zero YQ to HDMI 2.0 sinks only as HDMI 2.0 is based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5970) * on on CEA-861-F.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5971) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5972) if (!is_hdmi2_sink(connector) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5973) rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5974) frame->ycc_quantization_range =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5975) HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5976) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5977) frame->ycc_quantization_range =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5978) HDMI_YCC_QUANTIZATION_RANGE_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5980) EXPORT_SYMBOL(drm_hdmi_avi_infoframe_quant_range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5982) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5983) * drm_hdmi_avi_infoframe_bars() - fill the HDMI AVI infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5984) * bar information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5985) * @frame: HDMI AVI infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5986) * @conn_state: connector state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5987) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5988) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5989) drm_hdmi_avi_infoframe_bars(struct hdmi_avi_infoframe *frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5990) const struct drm_connector_state *conn_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5992) frame->right_bar = conn_state->tv.margins.right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5993) frame->left_bar = conn_state->tv.margins.left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5994) frame->top_bar = conn_state->tv.margins.top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5995) frame->bottom_bar = conn_state->tv.margins.bottom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5997) EXPORT_SYMBOL(drm_hdmi_avi_infoframe_bars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5999) static enum hdmi_3d_structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6000) s3d_structure_from_display_mode(const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6002) u32 layout = mode->flags & DRM_MODE_FLAG_3D_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6004) switch (layout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6005) case DRM_MODE_FLAG_3D_FRAME_PACKING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6006) return HDMI_3D_STRUCTURE_FRAME_PACKING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6007) case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6008) return HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6009) case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6010) return HDMI_3D_STRUCTURE_LINE_ALTERNATIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6011) case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6012) return HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6013) case DRM_MODE_FLAG_3D_L_DEPTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6014) return HDMI_3D_STRUCTURE_L_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6015) case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6016) return HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6017) case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6018) return HDMI_3D_STRUCTURE_TOP_AND_BOTTOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6019) case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6020) return HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6021) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6022) return HDMI_3D_STRUCTURE_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6026) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6027) * drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6028) * data from a DRM display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6029) * @frame: HDMI vendor infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6030) * @connector: the connector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6031) * @mode: DRM display mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6032) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6033) * Note that there's is a need to send HDMI vendor infoframes only when using a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6034) * 4k or stereoscopic 3D mode. So when giving any other mode as input this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6035) * function will return -EINVAL, error that can be safely ignored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6036) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6037) * Return: 0 on success or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6038) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6039) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6040) drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6041) const struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6042) const struct drm_display_mode *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6043) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6044) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6045) * FIXME: sil-sii8620 doesn't have a connector around when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6046) * we need one, so we have to be prepared for a NULL connector.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6048) bool has_hdmi_infoframe = connector ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6049) connector->display_info.has_hdmi_infoframe : false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6050) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6052) if (!frame || !mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6053) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6055) if (!has_hdmi_infoframe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6056) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6058) err = hdmi_vendor_infoframe_init(frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6059) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6060) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6062) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6063) * Even if it's not absolutely necessary to send the infoframe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6064) * (ie.vic==0 and s3d_struct==0) we will still send it if we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6065) * know that the sink can handle it. This is based on a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6066) * suggestion in HDMI 2.0 Appendix F. Apparently some sinks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6067) * have trouble realizing that they shuld switch from 3D to 2D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6068) * mode if the source simply stops sending the infoframe when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6069) * it wants to switch from 3D to 2D.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6070) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6071) frame->vic = drm_mode_hdmi_vic(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6072) frame->s3d_struct = s3d_structure_from_display_mode(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6074) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6076) EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6078) static void drm_parse_tiled_block(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6079) const struct displayid_block *block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6081) const struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6082) u16 w, h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6083) u8 tile_v_loc, tile_h_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6084) u8 num_v_tile, num_h_tile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6085) struct drm_tile_group *tg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6087) w = tile->tile_size[0] | tile->tile_size[1] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6088) h = tile->tile_size[2] | tile->tile_size[3] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6090) num_v_tile = (tile->topo[0] & 0xf) | (tile->topo[2] & 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6091) num_h_tile = (tile->topo[0] >> 4) | ((tile->topo[2] >> 2) & 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6092) tile_v_loc = (tile->topo[1] & 0xf) | ((tile->topo[2] & 0x3) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6093) tile_h_loc = (tile->topo[1] >> 4) | (((tile->topo[2] >> 2) & 0x3) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6095) connector->has_tile = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6096) if (tile->tile_cap & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6097) connector->tile_is_single_monitor = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6099) connector->num_h_tile = num_h_tile + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6100) connector->num_v_tile = num_v_tile + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6101) connector->tile_h_loc = tile_h_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6102) connector->tile_v_loc = tile_v_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6103) connector->tile_h_size = w + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6104) connector->tile_v_size = h + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6106) DRM_DEBUG_KMS("tile cap 0x%x\n", tile->tile_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6107) DRM_DEBUG_KMS("tile_size %d x %d\n", w + 1, h + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6108) DRM_DEBUG_KMS("topo num tiles %dx%d, location %dx%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6109) num_h_tile + 1, num_v_tile + 1, tile_h_loc, tile_v_loc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6110) DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6112) tg = drm_mode_get_tile_group(connector->dev, tile->topology_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6113) if (!tg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6114) tg = drm_mode_create_tile_group(connector->dev, tile->topology_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6115) if (!tg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6116) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6118) if (connector->tile_group != tg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6119) /* if we haven't got a pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6120) take the reference, drop ref to old tile group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6121) if (connector->tile_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6122) drm_mode_put_tile_group(connector->dev, connector->tile_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6123) connector->tile_group = tg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6124) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6125) /* if same tile group, then release the ref we just took. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6126) drm_mode_put_tile_group(connector->dev, tg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6130) static void drm_displayid_parse_tiled(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6131) const u8 *displayid, int length, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6133) const struct displayid_block *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6135) idx += sizeof(struct displayid_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6136) for_each_displayid_db(displayid, block, idx, length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6137) DRM_DEBUG_KMS("block id 0x%x, rev %d, len %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6138) block->tag, block->rev, block->num_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6140) switch (block->tag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6141) case DATA_BLOCK_TILED_DISPLAY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6142) drm_parse_tiled_block(connector, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6143) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6144) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6145) DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n", block->tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6151) void drm_update_tile_info(struct drm_connector *connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6152) const struct edid *edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6154) const void *displayid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6155) int ext_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6156) int length, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6158) connector->has_tile = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6159) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6160) displayid = drm_find_displayid_extension(edid, &length, &idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6161) &ext_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6162) if (!displayid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6165) drm_displayid_parse_tiled(connector, displayid, length, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6168) if (!connector->has_tile && connector->tile_group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6169) drm_mode_put_tile_group(connector->dev, connector->tile_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6170) connector->tile_group = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6172) }