Commit 867cf9cd authored by Lyude Paul's avatar Lyude Paul

drm/dp: Extract i915's eDP backlight code into DRM helpers

Since we're about to implement eDP backlight support in nouveau using the
standard protocol from VESA, we might as well just take the code that's
already written for this and move it into a set of shared DRM helpers.

Note that these helpers are intended to handle DPCD related backlight
control bits such as setting the brightness level over AUX, probing the
backlight's TCON, enabling/disabling the backlight over AUX if supported,
etc. Any PWM-related portions of backlight control are explicitly left up
to the driver, as these will vary from platform to platform.

The only exception to this is the calculation of the PWM frequency
pre-divider value. This is because the only platform-specific information
required for this is the PWM frequency of the panel, which the driver is
expected to provide if available. The actual algorithm for calculating this
value is standard and is defined in the eDP specification from VESA.

Note that these helpers do not yet implement the full range of features
the VESA backlight interface provides, and only provide the following
functionality (all of which was already present in i915's DPCD backlight
support):

* Basic control of brightness levels
* Basic probing of backlight capabilities
* Helpers for enabling and disabling the backlight

v3:
* Split out changes to i915's backlight code to separate patches to make it
  easier to review
v4:
* Style/spelling changes from Thomas Zimmermann
v5:
* Start using new drm_dbg_*() functions
Signed-off-by: default avatarLyude Paul <lyude@redhat.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Dave Airlie <airlied@gmail.com>
Cc: greg.depoire@gmail.com
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210514181504.565252-9-lyude@redhat.com
parent 837f9324
This diff is collapsed.
...@@ -310,10 +310,7 @@ struct intel_panel { ...@@ -310,10 +310,7 @@ struct intel_panel {
/* DPCD backlight */ /* DPCD backlight */
union { union {
struct { struct {
u8 pwmgen_bit_count; struct drm_edp_backlight_info info;
u8 pwm_freq_pre_divider;
bool lsb_reg_used;
bool aux_enable;
} vesa; } vesa;
struct { struct {
bool sdr_uses_aux; bool sdr_uses_aux;
......
...@@ -1801,6 +1801,24 @@ drm_dp_sink_can_do_video_without_timing_msa(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) ...@@ -1801,6 +1801,24 @@ drm_dp_sink_can_do_video_without_timing_msa(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
DP_MSA_TIMING_PAR_IGNORED; DP_MSA_TIMING_PAR_IGNORED;
} }
/**
* drm_edp_backlight_supported() - Check an eDP DPCD for VESA backlight support
* @edp_dpcd: The DPCD to check
*
* Note that currently this function will return %false for panels which support various DPCD
* backlight features but which require the brightness be set through PWM, and don't support setting
* the brightness level via the DPCD. This is a TODO.
*
* Returns: %True if @edp_dpcd indicates that VESA backlight controls are supported, %false
* otherwise
*/
static inline bool
drm_edp_backlight_supported(const u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE])
{
return (edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP) &&
(edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP);
}
/* /*
* DisplayPort AUX channel * DisplayPort AUX channel
*/ */
...@@ -2107,6 +2125,36 @@ drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk) ...@@ -2107,6 +2125,36 @@ drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk)
return desc->quirks & BIT(quirk); return desc->quirks & BIT(quirk);
} }
/**
* struct drm_edp_backlight_info - Probed eDP backlight info struct
* @pwmgen_bit_count: The pwmgen bit count
* @pwm_freq_pre_divider: The PWM frequency pre-divider value being used for this backlight, if any
* @max: The maximum backlight level that may be set
* @lsb_reg_used: Do we also write values to the DP_EDP_BACKLIGHT_BRIGHTNESS_LSB register?
* @aux_enable: Does the panel support the AUX enable cap?
*
* This structure contains various data about an eDP backlight, which can be populated by using
* drm_edp_backlight_init().
*/
struct drm_edp_backlight_info {
u8 pwmgen_bit_count;
u8 pwm_freq_pre_divider;
u16 max;
bool lsb_reg_used : 1;
bool aux_enable : 1;
};
int
drm_edp_backlight_init(struct drm_dp_aux *aux, struct drm_edp_backlight_info *bl,
u16 driver_pwm_freq_hz, const u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE],
u16 *current_level, u8 *current_mode);
int drm_edp_backlight_set_level(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl,
u16 level);
int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl,
u16 level);
int drm_edp_backlight_disable(struct drm_dp_aux *aux, const struct drm_edp_backlight_info *bl);
#ifdef CONFIG_DRM_DP_CEC #ifdef CONFIG_DRM_DP_CEC
void drm_dp_cec_irq(struct drm_dp_aux *aux); void drm_dp_cec_irq(struct drm_dp_aux *aux);
void drm_dp_cec_register_connector(struct drm_dp_aux *aux, void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment