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 "intel_display_types.h" 38 #include "intel_dp_aux_backlight.h" 39 #include "intel_panel.h" 40 41 /* TODO: 42 * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we 43 * can make people's backlights work in the mean time 44 */ 45 46 /* 47 * DP AUX registers for Intel's proprietary HDR backlight interface. We define 48 * them here since we'll likely be the only driver to ever use these. 49 */ 50 #define INTEL_EDP_HDR_TCON_CAP0 0x340 51 52 #define INTEL_EDP_HDR_TCON_CAP1 0x341 53 # define INTEL_EDP_HDR_TCON_2084_DECODE_CAP BIT(0) 54 # define INTEL_EDP_HDR_TCON_2020_GAMUT_CAP BIT(1) 55 # define INTEL_EDP_HDR_TCON_TONE_MAPPING_CAP BIT(2) 56 # define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP BIT(3) 57 # define INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP BIT(4) 58 # define INTEL_EDP_HDR_TCON_OPTIMIZATION_CAP BIT(5) 59 # define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_CAP BIT(6) 60 # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_CONVERSION_CAP BIT(7) 61 62 #define INTEL_EDP_HDR_TCON_CAP2 0x342 63 # define INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP BIT(0) 64 65 #define INTEL_EDP_HDR_TCON_CAP3 0x343 66 67 #define INTEL_EDP_HDR_GETSET_CTRL_PARAMS 0x344 68 # define INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE BIT(0) 69 # define INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE BIT(1) 70 # define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) /* Pre-TGL+ */ 71 # define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE BIT(3) 72 # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) 73 # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLE BIT(5) 74 /* Bit 6 is reserved */ 75 # define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_ENABLE BIT(7) 76 77 #define INTEL_EDP_HDR_CONTENT_LUMINANCE 0x346 /* Pre-TGL+ */ 78 #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A 79 #define INTEL_EDP_SDR_LUMINANCE_LEVEL 0x352 80 #define INTEL_EDP_BRIGHTNESS_NITS_LSB 0x354 81 #define INTEL_EDP_BRIGHTNESS_NITS_MSB 0x355 82 #define INTEL_EDP_BRIGHTNESS_DELAY_FRAMES 0x356 83 #define INTEL_EDP_BRIGHTNESS_PER_FRAME_STEPS 0x357 84 85 #define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_0 0x358 86 # define INTEL_EDP_TCON_USAGE_MASK GENMASK(0, 3) 87 # define INTEL_EDP_TCON_USAGE_UNKNOWN 0x0 88 # define INTEL_EDP_TCON_USAGE_DESKTOP 0x1 89 # define INTEL_EDP_TCON_USAGE_FULL_SCREEN_MEDIA 0x2 90 # define INTEL_EDP_TCON_USAGE_FULL_SCREEN_GAMING 0x3 91 # define INTEL_EDP_TCON_POWER_MASK BIT(4) 92 # define INTEL_EDP_TCON_POWER_DC (0 << 4) 93 # define INTEL_EDP_TCON_POWER_AC (1 << 4) 94 # define INTEL_EDP_TCON_OPTIMIZATION_STRENGTH_MASK GENMASK(5, 7) 95 96 #define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_1 0x359 97 98 /* Intel EDP backlight callbacks */ 99 static bool 100 intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) 101 { 102 struct drm_i915_private *i915 = to_i915(connector->base.dev); 103 struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); 104 struct drm_dp_aux *aux = &intel_dp->aux; 105 struct intel_panel *panel = &connector->panel; 106 int ret; 107 u8 tcon_cap[4]; 108 109 ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); 110 if (ret < 0) 111 return false; 112 113 if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) 114 return false; 115 116 if (tcon_cap[0] >= 1) { 117 drm_dbg_kms(&i915->drm, "Detected Intel HDR backlight interface version %d\n", 118 tcon_cap[0]); 119 } else { 120 drm_dbg_kms(&i915->drm, "Detected unsupported HDR backlight interface version %d\n", 121 tcon_cap[0]); 122 return false; 123 } 124 125 panel->backlight.edp.intel.sdr_uses_aux = 126 tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; 127 128 return true; 129 } 130 131 static u32 132 intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe) 133 { 134 struct drm_i915_private *i915 = to_i915(connector->base.dev); 135 struct intel_panel *panel = &connector->panel; 136 struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); 137 u8 tmp; 138 u8 buf[2] = { 0 }; 139 140 if (drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp) < 0) { 141 drm_err(&i915->drm, "Failed to read current backlight mode from DPCD\n"); 142 return 0; 143 } 144 145 if (!(tmp & INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE)) { 146 if (!panel->backlight.edp.intel.sdr_uses_aux) { 147 u32 pwm_level = panel->backlight.pwm_funcs->get(connector, pipe); 148 149 return intel_panel_backlight_level_from_pwm(connector, pwm_level); 150 } 151 152 /* Assume 100% brightness if backlight controls aren't enabled yet */ 153 return panel->backlight.max; 154 } 155 156 if (drm_dp_dpcd_read(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, sizeof(buf)) < 0) { 157 drm_err(&i915->drm, "Failed to read brightness from DPCD\n"); 158 return 0; 159 } 160 161 return (buf[1] << 8 | buf[0]); 162 } 163 164 static void 165 intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, u32 level) 166 { 167 struct intel_connector *connector = to_intel_connector(conn_state->connector); 168 struct drm_device *dev = connector->base.dev; 169 struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); 170 u8 buf[4] = { 0 }; 171 172 buf[0] = level & 0xFF; 173 buf[1] = (level & 0xFF00) >> 8; 174 175 if (drm_dp_dpcd_write(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, 4) < 0) 176 drm_err(dev, "Failed to write brightness level to DPCD\n"); 177 } 178 179 static void 180 intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 level) 181 { 182 struct intel_connector *connector = to_intel_connector(conn_state->connector); 183 struct intel_panel *panel = &connector->panel; 184 185 if (panel->backlight.edp.intel.sdr_uses_aux) { 186 intel_dp_aux_hdr_set_aux_backlight(conn_state, level); 187 } else { 188 const u32 pwm_level = intel_panel_backlight_level_to_pwm(connector, level); 189 190 intel_panel_set_pwm_level(conn_state, pwm_level); 191 } 192 } 193 194 static void 195 intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, 196 const struct drm_connector_state *conn_state, u32 level) 197 { 198 struct intel_connector *connector = to_intel_connector(conn_state->connector); 199 struct intel_panel *panel = &connector->panel; 200 struct drm_i915_private *i915 = to_i915(connector->base.dev); 201 struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); 202 int ret; 203 u8 old_ctrl, ctrl; 204 205 ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); 206 if (ret < 0) { 207 drm_err(&i915->drm, "Failed to read current backlight control mode: %d\n", ret); 208 return; 209 } 210 211 ctrl = old_ctrl; 212 if (panel->backlight.edp.intel.sdr_uses_aux) { 213 ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; 214 intel_dp_aux_hdr_set_aux_backlight(conn_state, level); 215 } else { 216 u32 pwm_level = intel_panel_backlight_level_to_pwm(connector, level); 217 218 panel->backlight.pwm_funcs->enable(crtc_state, conn_state, pwm_level); 219 220 ctrl &= ~INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; 221 } 222 223 if (ctrl != old_ctrl) 224 if (drm_dp_dpcd_writeb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) < 0) 225 drm_err(&i915->drm, "Failed to configure DPCD brightness controls\n"); 226 } 227 228 static void 229 intel_dp_aux_hdr_disable_backlight(const struct drm_connector_state *conn_state, u32 level) 230 { 231 struct intel_connector *connector = to_intel_connector(conn_state->connector); 232 struct intel_panel *panel = &connector->panel; 233 234 /* Nothing to do for AUX based backlight controls */ 235 if (panel->backlight.edp.intel.sdr_uses_aux) 236 return; 237 238 /* Note we want the actual pwm_level to be 0, regardless of pwm_min */ 239 panel->backlight.pwm_funcs->disable(conn_state, intel_panel_invert_pwm_level(connector, 0)); 240 } 241 242 static int 243 intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pipe) 244 { 245 struct drm_i915_private *i915 = to_i915(connector->base.dev); 246 struct intel_panel *panel = &connector->panel; 247 int ret; 248 249 if (panel->backlight.edp.intel.sdr_uses_aux) { 250 drm_dbg_kms(&i915->drm, "SDR backlight is controlled through DPCD\n"); 251 } else { 252 drm_dbg_kms(&i915->drm, "SDR backlight is controlled through PWM\n"); 253 254 ret = panel->backlight.pwm_funcs->setup(connector, pipe); 255 if (ret < 0) { 256 drm_err(&i915->drm, 257 "Failed to setup SDR backlight controls through PWM: %d\n", ret); 258 return ret; 259 } 260 } 261 262 panel->backlight.max = 512; 263 panel->backlight.min = 0; 264 panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe); 265 panel->backlight.enabled = panel->backlight.level != 0; 266 267 return 0; 268 } 269 270 /* VESA backlight callbacks */ 271 static void set_vesa_backlight_enable(struct intel_dp *intel_dp, bool enable) 272 { 273 struct drm_i915_private *i915 = dp_to_i915(intel_dp); 274 u8 reg_val = 0; 275 276 /* Early return when display use other mechanism to enable backlight. */ 277 if (!(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP)) 278 return; 279 280 if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER, 281 ®_val) < 0) { 282 drm_dbg_kms(&i915->drm, "Failed to read DPCD register 0x%x\n", 283 DP_EDP_DISPLAY_CONTROL_REGISTER); 284 return; 285 } 286 if (enable) 287 reg_val |= DP_EDP_BACKLIGHT_ENABLE; 288 else 289 reg_val &= ~(DP_EDP_BACKLIGHT_ENABLE); 290 291 if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER, 292 reg_val) != 1) { 293 drm_dbg_kms(&i915->drm, "Failed to %s aux backlight\n", 294 enable ? "enable" : "disable"); 295 } 296 } 297 298 static bool intel_dp_aux_vesa_backlight_dpcd_mode(struct intel_connector *connector) 299 { 300 struct intel_dp *intel_dp = intel_attached_dp(connector); 301 struct drm_i915_private *i915 = dp_to_i915(intel_dp); 302 u8 mode_reg; 303 304 if (drm_dp_dpcd_readb(&intel_dp->aux, 305 DP_EDP_BACKLIGHT_MODE_SET_REGISTER, 306 &mode_reg) != 1) { 307 drm_dbg_kms(&i915->drm, 308 "Failed to read the DPCD register 0x%x\n", 309 DP_EDP_BACKLIGHT_MODE_SET_REGISTER); 310 return false; 311 } 312 313 return (mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) == 314 DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; 315 } 316 317 /* 318 * Read the current backlight value from DPCD register(s) based 319 * on if 8-bit(MSB) or 16-bit(MSB and LSB) values are supported 320 */ 321 static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, enum pipe unused) 322 { 323 struct intel_dp *intel_dp = intel_attached_dp(connector); 324 struct drm_i915_private *i915 = dp_to_i915(intel_dp); 325 u8 read_val[2] = { 0x0 }; 326 u16 level = 0; 327 328 /* 329 * If we're not in DPCD control mode yet, the programmed brightness 330 * value is meaningless and we should assume max brightness 331 */ 332 if (!intel_dp_aux_vesa_backlight_dpcd_mode(connector)) 333 return connector->panel.backlight.max; 334 335 if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB, 336 &read_val, sizeof(read_val)) < 0) { 337 drm_dbg_kms(&i915->drm, "Failed to read DPCD register 0x%x\n", 338 DP_EDP_BACKLIGHT_BRIGHTNESS_MSB); 339 return 0; 340 } 341 level = read_val[0]; 342 if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) 343 level = (read_val[0] << 8 | read_val[1]); 344 345 return level; 346 } 347 348 /* 349 * Sends the current backlight level over the aux channel, checking if its using 350 * 8-bit or 16 bit value (MSB and LSB) 351 */ 352 static void 353 intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, 354 u32 level) 355 { 356 struct intel_connector *connector = to_intel_connector(conn_state->connector); 357 struct intel_dp *intel_dp = intel_attached_dp(connector); 358 struct drm_i915_private *i915 = dp_to_i915(intel_dp); 359 u8 vals[2] = { 0x0 }; 360 361 vals[0] = level; 362 363 /* Write the MSB and/or LSB */ 364 if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) { 365 vals[0] = (level & 0xFF00) >> 8; 366 vals[1] = (level & 0xFF); 367 } 368 if (drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB, 369 vals, sizeof(vals)) < 0) { 370 drm_dbg_kms(&i915->drm, 371 "Failed to write aux backlight level\n"); 372 return; 373 } 374 } 375 376 /* 377 * Set PWM Frequency divider to match desired frequency in vbt. 378 * The PWM Frequency is calculated as 27Mhz / (F x P). 379 * - Where F = PWM Frequency Pre-Divider value programmed by field 7:0 of the 380 * EDP_BACKLIGHT_FREQ_SET register (DPCD Address 00728h) 381 * - Where P = 2^Pn, where Pn is the value programmed by field 4:0 of the 382 * EDP_PWMGEN_BIT_COUNT register (DPCD Address 00724h) 383 */ 384 static bool intel_dp_aux_vesa_set_pwm_freq(struct intel_connector *connector) 385 { 386 struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 387 struct intel_dp *intel_dp = intel_attached_dp(connector); 388 const u8 pn = connector->panel.backlight.edp.vesa.pwmgen_bit_count; 389 int freq, fxp, f, fxp_actual, fxp_min, fxp_max; 390 391 freq = dev_priv->vbt.backlight.pwm_freq_hz; 392 if (!freq) { 393 drm_dbg_kms(&dev_priv->drm, 394 "Use panel default backlight frequency\n"); 395 return false; 396 } 397 398 fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq); 399 f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); 400 fxp_actual = f << pn; 401 402 /* Ensure frequency is within 25% of desired value */ 403 fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); 404 fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); 405 406 if (fxp_min > fxp_actual || fxp_actual > fxp_max) { 407 drm_dbg_kms(&dev_priv->drm, "Actual frequency out of range\n"); 408 return false; 409 } 410 411 if (drm_dp_dpcd_writeb(&intel_dp->aux, 412 DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) { 413 drm_dbg_kms(&dev_priv->drm, 414 "Failed to write aux backlight freq\n"); 415 return false; 416 } 417 return true; 418 } 419 420 static void 421 intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state, 422 const struct drm_connector_state *conn_state, u32 level) 423 { 424 struct intel_connector *connector = to_intel_connector(conn_state->connector); 425 struct intel_dp *intel_dp = intel_attached_dp(connector); 426 struct drm_i915_private *i915 = dp_to_i915(intel_dp); 427 struct intel_panel *panel = &connector->panel; 428 u8 dpcd_buf, new_dpcd_buf, edp_backlight_mode; 429 u8 pwmgen_bit_count = panel->backlight.edp.vesa.pwmgen_bit_count; 430 431 if (drm_dp_dpcd_readb(&intel_dp->aux, 432 DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf) != 1) { 433 drm_dbg_kms(&i915->drm, "Failed to read DPCD register 0x%x\n", 434 DP_EDP_BACKLIGHT_MODE_SET_REGISTER); 435 return; 436 } 437 438 new_dpcd_buf = dpcd_buf; 439 edp_backlight_mode = dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; 440 441 switch (edp_backlight_mode) { 442 case DP_EDP_BACKLIGHT_CONTROL_MODE_PWM: 443 case DP_EDP_BACKLIGHT_CONTROL_MODE_PRESET: 444 case DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT: 445 new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; 446 new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; 447 448 if (drm_dp_dpcd_writeb(&intel_dp->aux, 449 DP_EDP_PWMGEN_BIT_COUNT, 450 pwmgen_bit_count) < 0) 451 drm_dbg_kms(&i915->drm, 452 "Failed to write aux pwmgen bit count\n"); 453 454 break; 455 456 /* Do nothing when it is already DPCD mode */ 457 case DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD: 458 default: 459 break; 460 } 461 462 if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP) 463 if (intel_dp_aux_vesa_set_pwm_freq(connector)) 464 new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE; 465 466 if (new_dpcd_buf != dpcd_buf) { 467 if (drm_dp_dpcd_writeb(&intel_dp->aux, 468 DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf) < 0) { 469 drm_dbg_kms(&i915->drm, 470 "Failed to write aux backlight mode\n"); 471 } 472 } 473 474 intel_dp_aux_vesa_set_backlight(conn_state, level); 475 set_vesa_backlight_enable(intel_dp, true); 476 } 477 478 static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state *old_conn_state, 479 u32 level) 480 { 481 set_vesa_backlight_enable(enc_to_intel_dp(to_intel_encoder(old_conn_state->best_encoder)), 482 false); 483 } 484 485 static u32 intel_dp_aux_vesa_calc_max_backlight(struct intel_connector *connector) 486 { 487 struct drm_i915_private *i915 = to_i915(connector->base.dev); 488 struct intel_dp *intel_dp = intel_attached_dp(connector); 489 struct intel_panel *panel = &connector->panel; 490 u32 max_backlight = 0; 491 int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1; 492 u8 pn, pn_min, pn_max; 493 494 if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT, &pn) == 1) { 495 pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK; 496 max_backlight = (1 << pn) - 1; 497 } 498 499 /* Find desired value of (F x P) 500 * Note that, if F x P is out of supported range, the maximum value or 501 * minimum value will applied automatically. So no need to check that. 502 */ 503 freq = i915->vbt.backlight.pwm_freq_hz; 504 drm_dbg_kms(&i915->drm, "VBT defined backlight frequency %u Hz\n", 505 freq); 506 if (!freq) { 507 drm_dbg_kms(&i915->drm, 508 "Use panel default backlight frequency\n"); 509 return max_backlight; 510 } 511 512 fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq); 513 514 /* Use highest possible value of Pn for more granularity of brightness 515 * adjustment while satifying the conditions below. 516 * - Pn is in the range of Pn_min and Pn_max 517 * - F is in the range of 1 and 255 518 * - FxP is within 25% of desired value. 519 * Note: 25% is arbitrary value and may need some tweak. 520 */ 521 if (drm_dp_dpcd_readb(&intel_dp->aux, 522 DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) { 523 drm_dbg_kms(&i915->drm, 524 "Failed to read pwmgen bit count cap min\n"); 525 return max_backlight; 526 } 527 if (drm_dp_dpcd_readb(&intel_dp->aux, 528 DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) { 529 drm_dbg_kms(&i915->drm, 530 "Failed to read pwmgen bit count cap max\n"); 531 return max_backlight; 532 } 533 pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK; 534 pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK; 535 536 fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); 537 fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); 538 if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) { 539 drm_dbg_kms(&i915->drm, 540 "VBT defined backlight frequency out of range\n"); 541 return max_backlight; 542 } 543 544 for (pn = pn_max; pn >= pn_min; pn--) { 545 f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); 546 fxp_actual = f << pn; 547 if (fxp_min <= fxp_actual && fxp_actual <= fxp_max) 548 break; 549 } 550 551 drm_dbg_kms(&i915->drm, "Using eDP pwmgen bit count of %d\n", pn); 552 if (drm_dp_dpcd_writeb(&intel_dp->aux, 553 DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) { 554 drm_dbg_kms(&i915->drm, 555 "Failed to write aux pwmgen bit count\n"); 556 return max_backlight; 557 } 558 panel->backlight.edp.vesa.pwmgen_bit_count = pn; 559 560 max_backlight = (1 << pn) - 1; 561 562 return max_backlight; 563 } 564 565 static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, 566 enum pipe pipe) 567 { 568 struct intel_panel *panel = &connector->panel; 569 570 panel->backlight.max = intel_dp_aux_vesa_calc_max_backlight(connector); 571 if (!panel->backlight.max) 572 return -ENODEV; 573 574 panel->backlight.min = 0; 575 panel->backlight.level = intel_dp_aux_vesa_get_backlight(connector, pipe); 576 panel->backlight.enabled = intel_dp_aux_vesa_backlight_dpcd_mode(connector) && 577 panel->backlight.level != 0; 578 579 return 0; 580 } 581 582 static bool 583 intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector) 584 { 585 struct intel_dp *intel_dp = intel_attached_dp(connector); 586 struct drm_i915_private *i915 = dp_to_i915(intel_dp); 587 588 /* Check the eDP Display control capabilities registers to determine if 589 * the panel can support backlight control over the aux channel. 590 * 591 * TODO: We currently only support AUX only backlight configurations, not backlights which 592 * require a mix of PWM and AUX controls to work. In the mean time, these machines typically 593 * work just fine using normal PWM controls anyway. 594 */ 595 if (intel_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP && 596 (intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && 597 (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) { 598 drm_dbg_kms(&i915->drm, "AUX Backlight Control Supported!\n"); 599 return true; 600 } 601 return false; 602 } 603 604 static const struct intel_panel_bl_funcs intel_dp_hdr_bl_funcs = { 605 .setup = intel_dp_aux_hdr_setup_backlight, 606 .enable = intel_dp_aux_hdr_enable_backlight, 607 .disable = intel_dp_aux_hdr_disable_backlight, 608 .set = intel_dp_aux_hdr_set_backlight, 609 .get = intel_dp_aux_hdr_get_backlight, 610 }; 611 612 static const struct intel_panel_bl_funcs intel_dp_vesa_bl_funcs = { 613 .setup = intel_dp_aux_vesa_setup_backlight, 614 .enable = intel_dp_aux_vesa_enable_backlight, 615 .disable = intel_dp_aux_vesa_disable_backlight, 616 .set = intel_dp_aux_vesa_set_backlight, 617 .get = intel_dp_aux_vesa_get_backlight, 618 }; 619 620 enum intel_dp_aux_backlight_modparam { 621 INTEL_DP_AUX_BACKLIGHT_AUTO = -1, 622 INTEL_DP_AUX_BACKLIGHT_OFF = 0, 623 INTEL_DP_AUX_BACKLIGHT_ON = 1, 624 INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2, 625 INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3, 626 }; 627 628 int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) 629 { 630 struct drm_device *dev = connector->base.dev; 631 struct intel_panel *panel = &connector->panel; 632 struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); 633 struct drm_i915_private *i915 = dp_to_i915(intel_dp); 634 bool try_intel_interface = false, try_vesa_interface = false; 635 636 /* Check the VBT and user's module parameters to figure out which 637 * interfaces to probe 638 */ 639 switch (i915->params.enable_dpcd_backlight) { 640 case INTEL_DP_AUX_BACKLIGHT_OFF: 641 return -ENODEV; 642 case INTEL_DP_AUX_BACKLIGHT_AUTO: 643 switch (i915->vbt.backlight.type) { 644 case INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE: 645 try_vesa_interface = true; 646 break; 647 case INTEL_BACKLIGHT_DISPLAY_DDI: 648 try_intel_interface = true; 649 break; 650 default: 651 return -ENODEV; 652 } 653 break; 654 case INTEL_DP_AUX_BACKLIGHT_ON: 655 if (i915->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE) 656 try_intel_interface = true; 657 658 try_vesa_interface = true; 659 break; 660 case INTEL_DP_AUX_BACKLIGHT_FORCE_VESA: 661 try_vesa_interface = true; 662 break; 663 case INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL: 664 try_intel_interface = true; 665 break; 666 } 667 668 /* 669 * A lot of eDP panels in the wild will report supporting both the 670 * Intel proprietary backlight control interface, and the VESA 671 * backlight control interface. Many of these panels are liars though, 672 * and will only work with the Intel interface. So, always probe for 673 * that first. 674 */ 675 if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector)) { 676 drm_dbg_kms(dev, "Using Intel proprietary eDP backlight controls\n"); 677 panel->backlight.funcs = &intel_dp_hdr_bl_funcs; 678 return 0; 679 } 680 681 if (try_vesa_interface && intel_dp_aux_supports_vesa_backlight(connector)) { 682 drm_dbg_kms(dev, "Using VESA eDP backlight controls\n"); 683 panel->backlight.funcs = &intel_dp_vesa_bl_funcs; 684 return 0; 685 } 686 687 return -ENODEV; 688 } 689