Commit 8dbd72cb authored by Mario Limonciello's avatar Mario Limonciello Committed by Alex Deucher
Browse files

drm/amd/display: Export full brightness range to userspace



[WHY]
Userspace currently is offered a range from 0-0xFF but the PWM is
programmed from 0-0xFFFF.  This can be limiting to some software
that wants to apply greater granularity.

[HOW]
Convert internally to firmware values only when mapping custom
brightness curves because these are in 0-0xFF range. Advertise full
PWM range to userspace.

Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarRoman Li <roman.li@amd.com>
Signed-off-by: default avatarMario Limonciello <mario.limonciello@amd.com>
Signed-off-by: default avatarAlex Hung <alex.hung@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 148144f6
Loading
Loading
Loading
Loading
+27 −14
Original line number Diff line number Diff line
@@ -4721,9 +4721,23 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
	return 1;
}

/* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */
static inline u32 scale_input_to_fw(int min, int max, u64 input)
{
	return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max - min);
}

/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */
static inline u32 scale_fw_to_input(int min, int max, u64 input)
{
	return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), AMDGPU_MAX_BL_LEVEL);
}

static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps,
				      uint32_t *brightness)
				      unsigned int min, unsigned int max,
				      uint32_t *user_brightness)
{
	u32 brightness = scale_input_to_fw(min, max, *user_brightness);
	u8 prev_signal = 0, prev_lum = 0;
	int i = 0;

@@ -4734,7 +4748,7 @@ static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *cap
		return;

	/* choose start to run less interpolation steps */
	if (caps->luminance_data[caps->data_points/2].input_signal > *brightness)
	if (caps->luminance_data[caps->data_points/2].input_signal > brightness)
		i = caps->data_points/2;
	do {
		u8 signal = caps->luminance_data[i].input_signal;
@@ -4745,17 +4759,18 @@ static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *cap
		 * brightness < signal: interpolate between previous and current luminance numerator
		 * brightness > signal: find next data point
		 */
		if (*brightness > signal) {
		if (brightness > signal) {
			prev_signal = signal;
			prev_lum = lum;
			i++;
			continue;
		}
		if (*brightness < signal)
		if (brightness < signal)
			lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) *
							   (*brightness - prev_signal),
							   (brightness - prev_signal),
							   signal - prev_signal);
		*brightness = DIV_ROUND_CLOSEST(lum * *brightness, 101);
		*user_brightness = scale_fw_to_input(min, max,
						     DIV_ROUND_CLOSEST(lum * brightness, 101));
		return;
	} while (i < caps->data_points);
}
@@ -4768,11 +4783,10 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c
	if (!get_brightness_range(caps, &min, &max))
		return brightness;

	convert_custom_brightness(caps, &brightness);
	convert_custom_brightness(caps, min, max, &brightness);

	// Rescale 0..255 to min..max
	return min + DIV_ROUND_CLOSEST((max - min) * brightness,
				       AMDGPU_MAX_BL_LEVEL);
	// Rescale 0..max to min..max
	return min + DIV_ROUND_CLOSEST_ULL((u64)(max - min) * brightness, max);
}

static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
@@ -4785,8 +4799,8 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap

	if (brightness < min)
		return 0;
	// Rescale min..max to 0..255
	return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min),
	// Rescale min..max to 0..max
	return DIV_ROUND_CLOSEST_ULL((u64)max * (brightness - min),
				 max - min);
}

@@ -4936,11 +4950,10 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
		drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max,
			caps->ac_level, caps->dc_level);
	} else
		props.brightness = AMDGPU_MAX_BL_LEVEL;
		props.brightness = props.max_brightness = AMDGPU_MAX_BL_LEVEL;

	if (caps->data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE))
		drm_info(drm, "Using custom brightness curve\n");
	props.max_brightness = AMDGPU_MAX_BL_LEVEL;
	props.type = BACKLIGHT_RAW;

	snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",