2 * Copyright © 2015 Intel Corporation
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:
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
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
25 #include "intel_drv.h"
27 static void set_aux_backlight_enable(struct intel_dp
*intel_dp
, bool enable
)
31 if (drm_dp_dpcd_readb(&intel_dp
->aux
, DP_EDP_DISPLAY_CONTROL_REGISTER
,
33 DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
34 DP_EDP_DISPLAY_CONTROL_REGISTER
);
38 reg_val
|= DP_EDP_BACKLIGHT_ENABLE
;
40 reg_val
&= ~(DP_EDP_BACKLIGHT_ENABLE
);
42 if (drm_dp_dpcd_writeb(&intel_dp
->aux
, DP_EDP_DISPLAY_CONTROL_REGISTER
,
44 DRM_DEBUG_KMS("Failed to %s aux backlight\n",
45 enable
? "enable" : "disable");
50 * Read the current backlight value from DPCD register(s) based
51 * on if 8-bit(MSB) or 16-bit(MSB and LSB) values are supported
53 static uint32_t intel_dp_aux_get_backlight(struct intel_connector
*connector
)
55 struct intel_dp
*intel_dp
= enc_to_intel_dp(&connector
->encoder
->base
);
56 uint8_t read_val
[2] = { 0x0 };
59 if (drm_dp_dpcd_read(&intel_dp
->aux
, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB
,
60 &read_val
, sizeof(read_val
)) < 0) {
61 DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
62 DP_EDP_BACKLIGHT_BRIGHTNESS_MSB
);
66 if (intel_dp
->edp_dpcd
[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT
)
67 level
= (read_val
[0] << 8 | read_val
[1]);
73 * Sends the current backlight level over the aux channel, checking if its using
74 * 8-bit or 16 bit value (MSB and LSB)
77 intel_dp_aux_set_backlight(struct intel_connector
*connector
, u32 level
)
79 struct intel_dp
*intel_dp
= enc_to_intel_dp(&connector
->encoder
->base
);
80 uint8_t vals
[2] = { 0x0 };
84 /* Write the MSB and/or LSB */
85 if (intel_dp
->edp_dpcd
[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT
) {
86 vals
[0] = (level
& 0xFF00) >> 8;
87 vals
[1] = (level
& 0xFF);
89 if (drm_dp_dpcd_write(&intel_dp
->aux
, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB
,
90 vals
, sizeof(vals
)) < 0) {
91 DRM_DEBUG_KMS("Failed to write aux backlight level\n");
96 static void intel_dp_aux_enable_backlight(struct intel_connector
*connector
)
98 struct intel_dp
*intel_dp
= enc_to_intel_dp(&connector
->encoder
->base
);
101 set_aux_backlight_enable(intel_dp
, true);
103 if ((drm_dp_dpcd_readb(&intel_dp
->aux
,
104 DP_EDP_BACKLIGHT_MODE_SET_REGISTER
, &dpcd_buf
) == 1) &&
105 ((dpcd_buf
& DP_EDP_BACKLIGHT_CONTROL_MODE_MASK
) ==
106 DP_EDP_BACKLIGHT_CONTROL_MODE_PRESET
))
107 drm_dp_dpcd_writeb(&intel_dp
->aux
, DP_EDP_BACKLIGHT_MODE_SET_REGISTER
,
108 (dpcd_buf
| DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD
));
111 static void intel_dp_aux_disable_backlight(struct intel_connector
*connector
)
113 set_aux_backlight_enable(enc_to_intel_dp(&connector
->encoder
->base
), false);
116 static int intel_dp_aux_setup_backlight(struct intel_connector
*connector
,
119 struct intel_dp
*intel_dp
= enc_to_intel_dp(&connector
->encoder
->base
);
120 struct intel_panel
*panel
= &connector
->panel
;
122 intel_dp_aux_enable_backlight(connector
);
124 if (intel_dp
->edp_dpcd
[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT
)
125 panel
->backlight
.max
= 0xFFFF;
127 panel
->backlight
.max
= 0xFF;
129 panel
->backlight
.min
= 0;
130 panel
->backlight
.level
= intel_dp_aux_get_backlight(connector
);
132 panel
->backlight
.enabled
= panel
->backlight
.level
!= 0;
138 intel_dp_aux_display_control_capable(struct intel_connector
*connector
)
140 struct intel_dp
*intel_dp
= enc_to_intel_dp(&connector
->encoder
->base
);
142 /* Check the eDP Display control capabilities registers to determine if
143 * the panel can support backlight control over the aux channel
145 if (intel_dp
->edp_dpcd
[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP
&&
146 (intel_dp
->edp_dpcd
[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP
) &&
147 !((intel_dp
->edp_dpcd
[1] & DP_EDP_BACKLIGHT_PIN_ENABLE_CAP
) ||
148 (intel_dp
->edp_dpcd
[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP
))) {
149 DRM_DEBUG_KMS("AUX Backlight Control Supported!\n");
155 int intel_dp_aux_init_backlight_funcs(struct intel_connector
*intel_connector
)
157 struct intel_panel
*panel
= &intel_connector
->panel
;
159 if (!i915
.enable_dpcd_backlight
)
162 if (!intel_dp_aux_display_control_capable(intel_connector
))
165 panel
->backlight
.setup
= intel_dp_aux_setup_backlight
;
166 panel
->backlight
.enable
= intel_dp_aux_enable_backlight
;
167 panel
->backlight
.disable
= intel_dp_aux_disable_backlight
;
168 panel
->backlight
.set
= intel_dp_aux_set_backlight
;
169 panel
->backlight
.get
= intel_dp_aux_get_backlight
;