cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_dp_aux_backlight.c (19414B)


      1/*
      2 * Copyright © 2015 Intel Corporation
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice (including the next
     12 * paragraph) shall be included in all copies or substantial portions of the
     13 * Software.
     14 *
     15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21 * IN THE SOFTWARE.
     22 *
     23 */
     24
     25/*
     26 * Laptops with Intel GPUs which have panels that support controlling the
     27 * backlight through DP AUX can actually use two different interfaces: Intel's
     28 * proprietary DP AUX backlight interface, and the standard VESA backlight
     29 * interface. Unfortunately, at the time of writing this a lot of laptops will
     30 * advertise support for the standard VESA backlight interface when they
     31 * don't properly support it. However, on these systems the Intel backlight
     32 * interface generally does work properly. Additionally, these systems will
     33 * usually just indicate that they use PWM backlight controls in their VBIOS
     34 * for some reason.
     35 */
     36
     37#include "i915_drv.h"
     38#include "intel_backlight.h"
     39#include "intel_display_types.h"
     40#include "intel_dp.h"
     41#include "intel_dp_aux_backlight.h"
     42
     43/* TODO:
     44 * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we
     45 * can make people's backlights work in the mean time
     46 */
     47
     48/*
     49 * DP AUX registers for Intel's proprietary HDR backlight interface. We define
     50 * them here since we'll likely be the only driver to ever use these.
     51 */
     52#define INTEL_EDP_HDR_TCON_CAP0                                        0x340
     53
     54#define INTEL_EDP_HDR_TCON_CAP1                                        0x341
     55# define INTEL_EDP_HDR_TCON_2084_DECODE_CAP                           BIT(0)
     56# define INTEL_EDP_HDR_TCON_2020_GAMUT_CAP                            BIT(1)
     57# define INTEL_EDP_HDR_TCON_TONE_MAPPING_CAP                          BIT(2)
     58# define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP                   BIT(3)
     59# define INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP                       BIT(4)
     60# define INTEL_EDP_HDR_TCON_OPTIMIZATION_CAP                          BIT(5)
     61# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_CAP                       BIT(6)
     62# define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_CONVERSION_CAP        BIT(7)
     63
     64#define INTEL_EDP_HDR_TCON_CAP2                                        0x342
     65# define INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP                        BIT(0)
     66
     67#define INTEL_EDP_HDR_TCON_CAP3                                        0x343
     68
     69#define INTEL_EDP_HDR_GETSET_CTRL_PARAMS                               0x344
     70# define INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE                        BIT(0)
     71# define INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE                         BIT(1)
     72# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE                       BIT(2) /* Pre-TGL+ */
     73# define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE                BIT(3)
     74# define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE                     BIT(4)
     75# define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLE                BIT(5)
     76/* Bit 6 is reserved */
     77# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_ENABLE                    BIT(7)
     78
     79#define INTEL_EDP_HDR_CONTENT_LUMINANCE                                0x346 /* Pre-TGL+ */
     80#define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE                         0x34A
     81#define INTEL_EDP_SDR_LUMINANCE_LEVEL                                  0x352
     82#define INTEL_EDP_BRIGHTNESS_NITS_LSB                                  0x354
     83#define INTEL_EDP_BRIGHTNESS_NITS_MSB                                  0x355
     84#define INTEL_EDP_BRIGHTNESS_DELAY_FRAMES                              0x356
     85#define INTEL_EDP_BRIGHTNESS_PER_FRAME_STEPS                           0x357
     86
     87#define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_0                            0x358
     88# define INTEL_EDP_TCON_USAGE_MASK                             GENMASK(0, 3)
     89# define INTEL_EDP_TCON_USAGE_UNKNOWN                                    0x0
     90# define INTEL_EDP_TCON_USAGE_DESKTOP                                    0x1
     91# define INTEL_EDP_TCON_USAGE_FULL_SCREEN_MEDIA                          0x2
     92# define INTEL_EDP_TCON_USAGE_FULL_SCREEN_GAMING                         0x3
     93# define INTEL_EDP_TCON_POWER_MASK                                    BIT(4)
     94# define INTEL_EDP_TCON_POWER_DC                                    (0 << 4)
     95# define INTEL_EDP_TCON_POWER_AC                                    (1 << 4)
     96# define INTEL_EDP_TCON_OPTIMIZATION_STRENGTH_MASK             GENMASK(5, 7)
     97
     98#define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_1                            0x359
     99
    100enum intel_dp_aux_backlight_modparam {
    101	INTEL_DP_AUX_BACKLIGHT_AUTO = -1,
    102	INTEL_DP_AUX_BACKLIGHT_OFF = 0,
    103	INTEL_DP_AUX_BACKLIGHT_ON = 1,
    104	INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2,
    105	INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3,
    106};
    107
    108/* Intel EDP backlight callbacks */
    109static bool
    110intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector)
    111{
    112	struct drm_i915_private *i915 = to_i915(connector->base.dev);
    113	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
    114	struct drm_dp_aux *aux = &intel_dp->aux;
    115	struct intel_panel *panel = &connector->panel;
    116	int ret;
    117	u8 tcon_cap[4];
    118
    119	intel_dp_wait_source_oui(intel_dp);
    120
    121	ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap));
    122	if (ret != sizeof(tcon_cap))
    123		return false;
    124
    125	if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP))
    126		return false;
    127
    128	if (tcon_cap[0] >= 1) {
    129		drm_dbg_kms(&i915->drm, "Detected Intel HDR backlight interface version %d\n",
    130			    tcon_cap[0]);
    131	} else {
    132		drm_dbg_kms(&i915->drm, "Detected unsupported HDR backlight interface version %d\n",
    133			    tcon_cap[0]);
    134		return false;
    135	}
    136
    137	/*
    138	 * If we don't have HDR static metadata there is no way to
    139	 * runtime detect used range for nits based control. For now
    140	 * do not use Intel proprietary eDP backlight control if we
    141	 * don't have this data in panel EDID. In case we find panel
    142	 * which supports only nits based control, but doesn't provide
    143	 * HDR static metadata we need to start maintaining table of
    144	 * ranges for such panels.
    145	 */
    146	if (i915->params.enable_dpcd_backlight != INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL &&
    147	    !(connector->base.hdr_sink_metadata.hdmi_type1.metadata_type &
    148	      BIT(HDMI_STATIC_METADATA_TYPE1))) {
    149		drm_info(&i915->drm,
    150			 "Panel is missing HDR static metadata. Possible support for Intel HDR backlight interface is not used. If your backlight controls don't work try booting with i915.enable_dpcd_backlight=%d. needs this, please file a _new_ bug report on drm/i915, see " FDO_BUG_URL " for details.\n",
    151			 INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL);
    152		return false;
    153	}
    154
    155	panel->backlight.edp.intel.sdr_uses_aux =
    156		tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP;
    157
    158	return true;
    159}
    160
    161static u32
    162intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe)
    163{
    164	struct drm_i915_private *i915 = to_i915(connector->base.dev);
    165	struct intel_panel *panel = &connector->panel;
    166	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
    167	u8 tmp;
    168	u8 buf[2] = { 0 };
    169
    170	if (drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp) != 1) {
    171		drm_err(&i915->drm, "Failed to read current backlight mode from DPCD\n");
    172		return 0;
    173	}
    174
    175	if (!(tmp & INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE)) {
    176		if (!panel->backlight.edp.intel.sdr_uses_aux) {
    177			u32 pwm_level = panel->backlight.pwm_funcs->get(connector, pipe);
    178
    179			return intel_backlight_level_from_pwm(connector, pwm_level);
    180		}
    181
    182		/* Assume 100% brightness if backlight controls aren't enabled yet */
    183		return panel->backlight.max;
    184	}
    185
    186	if (drm_dp_dpcd_read(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf,
    187			     sizeof(buf)) != sizeof(buf)) {
    188		drm_err(&i915->drm, "Failed to read brightness from DPCD\n");
    189		return 0;
    190	}
    191
    192	return (buf[1] << 8 | buf[0]);
    193}
    194
    195static void
    196intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, u32 level)
    197{
    198	struct intel_connector *connector = to_intel_connector(conn_state->connector);
    199	struct drm_device *dev = connector->base.dev;
    200	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
    201	u8 buf[4] = { 0 };
    202
    203	buf[0] = level & 0xFF;
    204	buf[1] = (level & 0xFF00) >> 8;
    205
    206	if (drm_dp_dpcd_write(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf,
    207			      sizeof(buf)) != sizeof(buf))
    208		drm_err(dev, "Failed to write brightness level to DPCD\n");
    209}
    210
    211static void
    212intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 level)
    213{
    214	struct intel_connector *connector = to_intel_connector(conn_state->connector);
    215	struct intel_panel *panel = &connector->panel;
    216
    217	if (panel->backlight.edp.intel.sdr_uses_aux) {
    218		intel_dp_aux_hdr_set_aux_backlight(conn_state, level);
    219	} else {
    220		const u32 pwm_level = intel_backlight_level_to_pwm(connector, level);
    221
    222		intel_backlight_set_pwm_level(conn_state, pwm_level);
    223	}
    224}
    225
    226static void
    227intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state,
    228				  const struct drm_connector_state *conn_state, u32 level)
    229{
    230	struct intel_connector *connector = to_intel_connector(conn_state->connector);
    231	struct intel_panel *panel = &connector->panel;
    232	struct drm_i915_private *i915 = to_i915(connector->base.dev);
    233	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
    234	int ret;
    235	u8 old_ctrl, ctrl;
    236
    237	intel_dp_wait_source_oui(intel_dp);
    238
    239	ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl);
    240	if (ret != 1) {
    241		drm_err(&i915->drm, "Failed to read current backlight control mode: %d\n", ret);
    242		return;
    243	}
    244
    245	ctrl = old_ctrl;
    246	if (panel->backlight.edp.intel.sdr_uses_aux) {
    247		ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE;
    248		intel_dp_aux_hdr_set_aux_backlight(conn_state, level);
    249	} else {
    250		u32 pwm_level = intel_backlight_level_to_pwm(connector, level);
    251
    252		panel->backlight.pwm_funcs->enable(crtc_state, conn_state, pwm_level);
    253
    254		ctrl &= ~INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE;
    255	}
    256
    257	if (ctrl != old_ctrl)
    258		if (drm_dp_dpcd_writeb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) != 1)
    259			drm_err(&i915->drm, "Failed to configure DPCD brightness controls\n");
    260}
    261
    262static void
    263intel_dp_aux_hdr_disable_backlight(const struct drm_connector_state *conn_state, u32 level)
    264{
    265	struct intel_connector *connector = to_intel_connector(conn_state->connector);
    266	struct intel_panel *panel = &connector->panel;
    267
    268	/* Nothing to do for AUX based backlight controls */
    269	if (panel->backlight.edp.intel.sdr_uses_aux)
    270		return;
    271
    272	/* Note we want the actual pwm_level to be 0, regardless of pwm_min */
    273	panel->backlight.pwm_funcs->disable(conn_state, intel_backlight_invert_pwm_level(connector, 0));
    274}
    275
    276static int
    277intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pipe)
    278{
    279	struct drm_i915_private *i915 = to_i915(connector->base.dev);
    280	struct intel_panel *panel = &connector->panel;
    281	int ret;
    282
    283	if (panel->backlight.edp.intel.sdr_uses_aux) {
    284		drm_dbg_kms(&i915->drm, "SDR backlight is controlled through DPCD\n");
    285	} else {
    286		drm_dbg_kms(&i915->drm, "SDR backlight is controlled through PWM\n");
    287
    288		ret = panel->backlight.pwm_funcs->setup(connector, pipe);
    289		if (ret < 0) {
    290			drm_err(&i915->drm,
    291				"Failed to setup SDR backlight controls through PWM: %d\n", ret);
    292			return ret;
    293		}
    294	}
    295
    296	panel->backlight.max = 512;
    297	panel->backlight.min = 0;
    298	panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe);
    299	panel->backlight.enabled = panel->backlight.level != 0;
    300
    301	return 0;
    302}
    303
    304/* VESA backlight callbacks */
    305static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, enum pipe unused)
    306{
    307	return connector->panel.backlight.level;
    308}
    309
    310static void
    311intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, u32 level)
    312{
    313	struct intel_connector *connector = to_intel_connector(conn_state->connector);
    314	struct intel_panel *panel = &connector->panel;
    315	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
    316
    317	if (!panel->backlight.edp.vesa.info.aux_set) {
    318		const u32 pwm_level = intel_backlight_level_to_pwm(connector, level);
    319
    320		intel_backlight_set_pwm_level(conn_state, pwm_level);
    321	}
    322
    323	drm_edp_backlight_set_level(&intel_dp->aux, &panel->backlight.edp.vesa.info, level);
    324}
    325
    326static void
    327intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state,
    328				   const struct drm_connector_state *conn_state, u32 level)
    329{
    330	struct intel_connector *connector = to_intel_connector(conn_state->connector);
    331	struct intel_panel *panel = &connector->panel;
    332	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
    333
    334	if (!panel->backlight.edp.vesa.info.aux_enable) {
    335		u32 pwm_level;
    336
    337		if (!panel->backlight.edp.vesa.info.aux_set)
    338			pwm_level = intel_backlight_level_to_pwm(connector, level);
    339		else
    340			pwm_level = intel_backlight_invert_pwm_level(connector,
    341								     panel->backlight.pwm_level_max);
    342
    343		panel->backlight.pwm_funcs->enable(crtc_state, conn_state, pwm_level);
    344	}
    345
    346	drm_edp_backlight_enable(&intel_dp->aux, &panel->backlight.edp.vesa.info, level);
    347}
    348
    349static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state *old_conn_state,
    350						u32 level)
    351{
    352	struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
    353	struct intel_panel *panel = &connector->panel;
    354	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
    355
    356	drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info);
    357
    358	if (!panel->backlight.edp.vesa.info.aux_enable)
    359		panel->backlight.pwm_funcs->disable(old_conn_state,
    360						    intel_backlight_invert_pwm_level(connector, 0));
    361}
    362
    363static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, enum pipe pipe)
    364{
    365	struct intel_dp *intel_dp = intel_attached_dp(connector);
    366	struct intel_panel *panel = &connector->panel;
    367	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
    368	u16 current_level;
    369	u8 current_mode;
    370	int ret;
    371
    372	ret = drm_edp_backlight_init(&intel_dp->aux, &panel->backlight.edp.vesa.info,
    373				     i915->vbt.backlight.pwm_freq_hz, intel_dp->edp_dpcd,
    374				     &current_level, &current_mode);
    375	if (ret < 0)
    376		return ret;
    377
    378	if (!panel->backlight.edp.vesa.info.aux_set || !panel->backlight.edp.vesa.info.aux_enable) {
    379		ret = panel->backlight.pwm_funcs->setup(connector, pipe);
    380		if (ret < 0) {
    381			drm_err(&i915->drm,
    382				"Failed to setup PWM backlight controls for eDP backlight: %d\n",
    383				ret);
    384			return ret;
    385		}
    386	}
    387
    388	if (panel->backlight.edp.vesa.info.aux_set) {
    389		panel->backlight.max = panel->backlight.edp.vesa.info.max;
    390		panel->backlight.min = 0;
    391		if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) {
    392			panel->backlight.level = current_level;
    393			panel->backlight.enabled = panel->backlight.level != 0;
    394		} else {
    395			panel->backlight.level = panel->backlight.max;
    396			panel->backlight.enabled = false;
    397		}
    398	} else {
    399		panel->backlight.max = panel->backlight.pwm_level_max;
    400		panel->backlight.min = panel->backlight.pwm_level_min;
    401		if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_PWM) {
    402			panel->backlight.level = panel->backlight.pwm_funcs->get(connector, pipe);
    403			panel->backlight.enabled = panel->backlight.pwm_enabled;
    404		} else {
    405			panel->backlight.level = panel->backlight.max;
    406			panel->backlight.enabled = false;
    407		}
    408	}
    409
    410	return 0;
    411}
    412
    413static bool
    414intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector)
    415{
    416	struct intel_dp *intel_dp = intel_attached_dp(connector);
    417	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
    418
    419	if (drm_edp_backlight_supported(intel_dp->edp_dpcd)) {
    420		drm_dbg_kms(&i915->drm, "AUX Backlight Control Supported!\n");
    421		return true;
    422	}
    423	return false;
    424}
    425
    426static const struct intel_panel_bl_funcs intel_dp_hdr_bl_funcs = {
    427	.setup = intel_dp_aux_hdr_setup_backlight,
    428	.enable = intel_dp_aux_hdr_enable_backlight,
    429	.disable = intel_dp_aux_hdr_disable_backlight,
    430	.set = intel_dp_aux_hdr_set_backlight,
    431	.get = intel_dp_aux_hdr_get_backlight,
    432};
    433
    434static const struct intel_panel_bl_funcs intel_dp_vesa_bl_funcs = {
    435	.setup = intel_dp_aux_vesa_setup_backlight,
    436	.enable = intel_dp_aux_vesa_enable_backlight,
    437	.disable = intel_dp_aux_vesa_disable_backlight,
    438	.set = intel_dp_aux_vesa_set_backlight,
    439	.get = intel_dp_aux_vesa_get_backlight,
    440};
    441
    442int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
    443{
    444	struct drm_device *dev = connector->base.dev;
    445	struct intel_panel *panel = &connector->panel;
    446	struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
    447	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
    448	bool try_intel_interface = false, try_vesa_interface = false;
    449
    450	/* Check the VBT and user's module parameters to figure out which
    451	 * interfaces to probe
    452	 */
    453	switch (i915->params.enable_dpcd_backlight) {
    454	case INTEL_DP_AUX_BACKLIGHT_OFF:
    455		return -ENODEV;
    456	case INTEL_DP_AUX_BACKLIGHT_AUTO:
    457		switch (i915->vbt.backlight.type) {
    458		case INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE:
    459			try_vesa_interface = true;
    460			break;
    461		case INTEL_BACKLIGHT_DISPLAY_DDI:
    462			try_intel_interface = true;
    463			break;
    464		default:
    465			return -ENODEV;
    466		}
    467		break;
    468	case INTEL_DP_AUX_BACKLIGHT_ON:
    469		if (i915->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE)
    470			try_intel_interface = true;
    471
    472		try_vesa_interface = true;
    473		break;
    474	case INTEL_DP_AUX_BACKLIGHT_FORCE_VESA:
    475		try_vesa_interface = true;
    476		break;
    477	case INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL:
    478		try_intel_interface = true;
    479		break;
    480	}
    481
    482	/*
    483	 * Since Intel has their own backlight control interface, the majority of machines out there
    484	 * using DPCD backlight controls with Intel GPUs will be using this interface as opposed to
    485	 * the VESA interface. However, other GPUs (such as Nvidia's) will always use the VESA
    486	 * interface. This means that there's quite a number of panels out there that will advertise
    487	 * support for both interfaces, primarily systems with Intel/Nvidia hybrid GPU setups.
    488	 *
    489	 * There's a catch to this though: on many panels that advertise support for both
    490	 * interfaces, the VESA backlight interface will stop working once we've programmed the
    491	 * panel with Intel's OUI - which is also required for us to be able to detect Intel's
    492	 * backlight interface at all. This means that the only sensible way for us to detect both
    493	 * interfaces is to probe for Intel's first, and VESA's second.
    494	 */
    495	if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector)) {
    496		drm_dbg_kms(dev, "Using Intel proprietary eDP backlight controls\n");
    497		panel->backlight.funcs = &intel_dp_hdr_bl_funcs;
    498		return 0;
    499	}
    500
    501	if (try_vesa_interface && intel_dp_aux_supports_vesa_backlight(connector)) {
    502		drm_dbg_kms(dev, "Using VESA eDP backlight controls\n");
    503		panel->backlight.funcs = &intel_dp_vesa_bl_funcs;
    504		return 0;
    505	}
    506
    507	return -ENODEV;
    508}