drm/amdgpu/display: add support for multiple backlights
On platforms that support multiple backlights, register each one separately. This lets us manage them independently rather than registering a single backlight and applying the same settings to both. v2: fix typo: Reported-by: kernel test robot <lkp@intel.com> Reviewed-by: Roman Li <Roman.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
50dea4ec1a
commit
7fd13baeb7
3 changed files with 84 additions and 71 deletions
|
@ -854,8 +854,8 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
|
||||||
if (amdgpu_device_has_dc_support(adev)) {
|
if (amdgpu_device_has_dc_support(adev)) {
|
||||||
#if defined(CONFIG_DRM_AMD_DC)
|
#if defined(CONFIG_DRM_AMD_DC)
|
||||||
struct amdgpu_display_manager *dm = &adev->dm;
|
struct amdgpu_display_manager *dm = &adev->dm;
|
||||||
if (dm->backlight_dev)
|
if (dm->backlight_dev[0])
|
||||||
atif->bd = dm->backlight_dev;
|
atif->bd = dm->backlight_dev[0];
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
struct drm_encoder *tmp;
|
struct drm_encoder *tmp;
|
||||||
|
|
|
@ -2412,6 +2412,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
|
||||||
static const u8 pre_computed_values[] = {
|
static const u8 pre_computed_values[] = {
|
||||||
50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
|
50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
|
||||||
71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
|
71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!aconnector || !aconnector->dc_link)
|
if (!aconnector || !aconnector->dc_link)
|
||||||
return;
|
return;
|
||||||
|
@ -2423,7 +2424,13 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
|
||||||
conn_base = &aconnector->base;
|
conn_base = &aconnector->base;
|
||||||
adev = drm_to_adev(conn_base->dev);
|
adev = drm_to_adev(conn_base->dev);
|
||||||
dm = &adev->dm;
|
dm = &adev->dm;
|
||||||
caps = &dm->backlight_caps;
|
for (i = 0; i < dm->num_of_edps; i++) {
|
||||||
|
if (link == dm->backlight_link[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= dm->num_of_edps)
|
||||||
|
return;
|
||||||
|
caps = &dm->backlight_caps[i];
|
||||||
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
|
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
|
||||||
caps->aux_support = false;
|
caps->aux_support = false;
|
||||||
max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll;
|
max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll;
|
||||||
|
@ -3423,35 +3430,36 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
|
||||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
|
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
|
||||||
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
||||||
|
|
||||||
static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)
|
static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
|
||||||
|
int bl_idx)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_ACPI)
|
#if defined(CONFIG_ACPI)
|
||||||
struct amdgpu_dm_backlight_caps caps;
|
struct amdgpu_dm_backlight_caps caps;
|
||||||
|
|
||||||
memset(&caps, 0, sizeof(caps));
|
memset(&caps, 0, sizeof(caps));
|
||||||
|
|
||||||
if (dm->backlight_caps.caps_valid)
|
if (dm->backlight_caps[bl_idx].caps_valid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
amdgpu_acpi_get_backlight_caps(&caps);
|
amdgpu_acpi_get_backlight_caps(&caps);
|
||||||
if (caps.caps_valid) {
|
if (caps.caps_valid) {
|
||||||
dm->backlight_caps.caps_valid = true;
|
dm->backlight_caps[bl_idx].caps_valid = true;
|
||||||
if (caps.aux_support)
|
if (caps.aux_support)
|
||||||
return;
|
return;
|
||||||
dm->backlight_caps.min_input_signal = caps.min_input_signal;
|
dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal;
|
||||||
dm->backlight_caps.max_input_signal = caps.max_input_signal;
|
dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal;
|
||||||
} else {
|
} else {
|
||||||
dm->backlight_caps.min_input_signal =
|
dm->backlight_caps[bl_idx].min_input_signal =
|
||||||
AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
|
AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
|
||||||
dm->backlight_caps.max_input_signal =
|
dm->backlight_caps[bl_idx].max_input_signal =
|
||||||
AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
|
AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (dm->backlight_caps.aux_support)
|
if (dm->backlight_caps[bl_idx].aux_support)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
|
dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
|
||||||
dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
|
dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3502,41 +3510,31 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap
|
||||||
}
|
}
|
||||||
|
|
||||||
static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
|
static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
|
||||||
|
int bl_idx,
|
||||||
u32 user_brightness)
|
u32 user_brightness)
|
||||||
{
|
{
|
||||||
struct amdgpu_dm_backlight_caps caps;
|
struct amdgpu_dm_backlight_caps caps;
|
||||||
struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP];
|
struct dc_link *link;
|
||||||
u32 brightness[AMDGPU_DM_MAX_NUM_EDP];
|
u32 brightness;
|
||||||
bool rc;
|
bool rc;
|
||||||
int i;
|
|
||||||
|
|
||||||
amdgpu_dm_update_backlight_caps(dm);
|
amdgpu_dm_update_backlight_caps(dm, bl_idx);
|
||||||
caps = dm->backlight_caps;
|
caps = dm->backlight_caps[bl_idx];
|
||||||
|
|
||||||
for (i = 0; i < dm->num_of_edps; i++) {
|
dm->brightness[bl_idx] = user_brightness;
|
||||||
dm->brightness[i] = user_brightness;
|
brightness = convert_brightness_from_user(&caps, dm->brightness[bl_idx]);
|
||||||
brightness[i] = convert_brightness_from_user(&caps, dm->brightness[i]);
|
link = (struct dc_link *)dm->backlight_link[bl_idx];
|
||||||
link[i] = (struct dc_link *)dm->backlight_link[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Change brightness based on AUX property */
|
/* Change brightness based on AUX property */
|
||||||
if (caps.aux_support) {
|
if (caps.aux_support) {
|
||||||
for (i = 0; i < dm->num_of_edps; i++) {
|
rc = dc_link_set_backlight_level_nits(link, true, brightness,
|
||||||
rc = dc_link_set_backlight_level_nits(link[i], true, brightness[i],
|
AUX_BL_DEFAULT_TRANSITION_TIME_MS);
|
||||||
AUX_BL_DEFAULT_TRANSITION_TIME_MS);
|
if (!rc)
|
||||||
if (!rc) {
|
DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", bl_idx);
|
||||||
DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < dm->num_of_edps; i++) {
|
rc = dc_link_set_backlight_level(link, brightness, 0);
|
||||||
rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness[i], 0);
|
if (!rc)
|
||||||
if (!rc) {
|
DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx);
|
||||||
DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc ? 0 : 1;
|
return rc ? 0 : 1;
|
||||||
|
@ -3545,33 +3543,41 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
|
||||||
static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
|
static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
|
||||||
{
|
{
|
||||||
struct amdgpu_display_manager *dm = bl_get_data(bd);
|
struct amdgpu_display_manager *dm = bl_get_data(bd);
|
||||||
|
int i;
|
||||||
|
|
||||||
amdgpu_dm_backlight_set_level(dm, bd->props.brightness);
|
for (i = 0; i < dm->num_of_edps; i++) {
|
||||||
|
if (bd == dm->backlight_dev[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= AMDGPU_DM_MAX_NUM_EDP)
|
||||||
|
i = 0;
|
||||||
|
amdgpu_dm_backlight_set_level(dm, i, bd->props.brightness);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
|
static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm,
|
||||||
|
int bl_idx)
|
||||||
{
|
{
|
||||||
struct amdgpu_dm_backlight_caps caps;
|
struct amdgpu_dm_backlight_caps caps;
|
||||||
|
struct dc_link *link = (struct dc_link *)dm->backlight_link[bl_idx];
|
||||||
|
|
||||||
amdgpu_dm_update_backlight_caps(dm);
|
amdgpu_dm_update_backlight_caps(dm, bl_idx);
|
||||||
caps = dm->backlight_caps;
|
caps = dm->backlight_caps[bl_idx];
|
||||||
|
|
||||||
if (caps.aux_support) {
|
if (caps.aux_support) {
|
||||||
struct dc_link *link = (struct dc_link *)dm->backlight_link[0];
|
|
||||||
u32 avg, peak;
|
u32 avg, peak;
|
||||||
bool rc;
|
bool rc;
|
||||||
|
|
||||||
rc = dc_link_get_backlight_level_nits(link, &avg, &peak);
|
rc = dc_link_get_backlight_level_nits(link, &avg, &peak);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
return dm->brightness[0];
|
return dm->brightness[bl_idx];
|
||||||
return convert_brightness_to_user(&caps, avg);
|
return convert_brightness_to_user(&caps, avg);
|
||||||
} else {
|
} else {
|
||||||
int ret = dc_link_get_backlight_level(dm->backlight_link[0]);
|
int ret = dc_link_get_backlight_level(link);
|
||||||
|
|
||||||
if (ret == DC_ERROR_UNEXPECTED)
|
if (ret == DC_ERROR_UNEXPECTED)
|
||||||
return dm->brightness[0];
|
return dm->brightness[bl_idx];
|
||||||
return convert_brightness_to_user(&caps, ret);
|
return convert_brightness_to_user(&caps, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3579,8 +3585,15 @@ static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
|
||||||
static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
|
static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
|
||||||
{
|
{
|
||||||
struct amdgpu_display_manager *dm = bl_get_data(bd);
|
struct amdgpu_display_manager *dm = bl_get_data(bd);
|
||||||
|
int i;
|
||||||
|
|
||||||
return amdgpu_dm_backlight_get_level(dm);
|
for (i = 0; i < dm->num_of_edps; i++) {
|
||||||
|
if (bd == dm->backlight_dev[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= AMDGPU_DM_MAX_NUM_EDP)
|
||||||
|
i = 0;
|
||||||
|
return amdgpu_dm_backlight_get_level(dm, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct backlight_ops amdgpu_dm_backlight_ops = {
|
static const struct backlight_ops amdgpu_dm_backlight_ops = {
|
||||||
|
@ -3594,31 +3607,28 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
|
||||||
{
|
{
|
||||||
char bl_name[16];
|
char bl_name[16];
|
||||||
struct backlight_properties props = { 0 };
|
struct backlight_properties props = { 0 };
|
||||||
int i;
|
|
||||||
|
|
||||||
amdgpu_dm_update_backlight_caps(dm);
|
amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps);
|
||||||
for (i = 0; i < dm->num_of_edps; i++)
|
dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL;
|
||||||
dm->brightness[i] = AMDGPU_MAX_BL_LEVEL;
|
|
||||||
|
|
||||||
props.max_brightness = AMDGPU_MAX_BL_LEVEL;
|
props.max_brightness = AMDGPU_MAX_BL_LEVEL;
|
||||||
props.brightness = AMDGPU_MAX_BL_LEVEL;
|
props.brightness = AMDGPU_MAX_BL_LEVEL;
|
||||||
props.type = BACKLIGHT_RAW;
|
props.type = BACKLIGHT_RAW;
|
||||||
|
|
||||||
snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
|
snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
|
||||||
adev_to_drm(dm->adev)->primary->index);
|
adev_to_drm(dm->adev)->primary->index + dm->num_of_edps);
|
||||||
|
|
||||||
dm->backlight_dev = backlight_device_register(bl_name,
|
dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name,
|
||||||
adev_to_drm(dm->adev)->dev,
|
adev_to_drm(dm->adev)->dev,
|
||||||
dm,
|
dm,
|
||||||
&amdgpu_dm_backlight_ops,
|
&amdgpu_dm_backlight_ops,
|
||||||
&props);
|
&props);
|
||||||
|
|
||||||
if (IS_ERR(dm->backlight_dev))
|
if (IS_ERR(dm->backlight_dev[dm->num_of_edps]))
|
||||||
DRM_ERROR("DM: Backlight registration failed!\n");
|
DRM_ERROR("DM: Backlight registration failed!\n");
|
||||||
else
|
else
|
||||||
DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name);
|
DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int initialize_plane(struct amdgpu_display_manager *dm,
|
static int initialize_plane(struct amdgpu_display_manager *dm,
|
||||||
|
@ -3675,10 +3685,10 @@ static void register_backlight_device(struct amdgpu_display_manager *dm,
|
||||||
* DM initialization because not having a backlight control
|
* DM initialization because not having a backlight control
|
||||||
* is better then a black screen.
|
* is better then a black screen.
|
||||||
*/
|
*/
|
||||||
if (!dm->backlight_dev)
|
if (!dm->backlight_dev[dm->num_of_edps])
|
||||||
amdgpu_dm_register_backlight_device(dm);
|
amdgpu_dm_register_backlight_device(dm);
|
||||||
|
|
||||||
if (dm->backlight_dev) {
|
if (dm->backlight_dev[dm->num_of_edps]) {
|
||||||
dm->backlight_link[dm->num_of_edps] = link;
|
dm->backlight_link[dm->num_of_edps] = link;
|
||||||
dm->num_of_edps++;
|
dm->num_of_edps++;
|
||||||
}
|
}
|
||||||
|
@ -6198,6 +6208,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
|
||||||
const struct dc_link *link = aconnector->dc_link;
|
const struct dc_link *link = aconnector->dc_link;
|
||||||
struct amdgpu_device *adev = drm_to_adev(connector->dev);
|
struct amdgpu_device *adev = drm_to_adev(connector->dev);
|
||||||
struct amdgpu_display_manager *dm = &adev->dm;
|
struct amdgpu_display_manager *dm = &adev->dm;
|
||||||
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call only if mst_mgr was iniitalized before since it's not done
|
* Call only if mst_mgr was iniitalized before since it's not done
|
||||||
|
@ -6208,12 +6219,11 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
|
||||||
|
|
||||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
|
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
|
||||||
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
||||||
|
for (i = 0; i < dm->num_of_edps; i++) {
|
||||||
if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) &&
|
if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) {
|
||||||
link->type != dc_connection_none &&
|
backlight_device_unregister(dm->backlight_dev[i]);
|
||||||
dm->backlight_dev) {
|
dm->backlight_dev[i] = NULL;
|
||||||
backlight_device_unregister(dm->backlight_dev);
|
}
|
||||||
dm->backlight_dev = NULL;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9193,8 +9203,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
||||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
|
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
|
||||||
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
|
||||||
/* restore the backlight level */
|
/* restore the backlight level */
|
||||||
if (dm->backlight_dev && (amdgpu_dm_backlight_get_level(dm) != dm->brightness[0]))
|
for (i = 0; i < dm->num_of_edps; i++) {
|
||||||
amdgpu_dm_backlight_set_level(dm, dm->brightness[0]);
|
if (dm->backlight_dev[i] &&
|
||||||
|
(amdgpu_dm_backlight_get_level(dm, i) != dm->brightness[i]))
|
||||||
|
amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* send vblank event on all events not handled in flip and
|
* send vblank event on all events not handled in flip and
|
||||||
|
|
|
@ -365,13 +365,13 @@ struct amdgpu_display_manager {
|
||||||
|
|
||||||
spinlock_t irq_handler_list_table_lock;
|
spinlock_t irq_handler_list_table_lock;
|
||||||
|
|
||||||
struct backlight_device *backlight_dev;
|
struct backlight_device *backlight_dev[AMDGPU_DM_MAX_NUM_EDP];
|
||||||
|
|
||||||
const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP];
|
const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP];
|
||||||
|
|
||||||
uint8_t num_of_edps;
|
uint8_t num_of_edps;
|
||||||
|
|
||||||
struct amdgpu_dm_backlight_caps backlight_caps;
|
struct amdgpu_dm_backlight_caps backlight_caps[AMDGPU_DM_MAX_NUM_EDP];
|
||||||
|
|
||||||
struct mod_freesync *freesync_module;
|
struct mod_freesync *freesync_module;
|
||||||
#ifdef CONFIG_DRM_AMD_DC_HDCP
|
#ifdef CONFIG_DRM_AMD_DC_HDCP
|
||||||
|
|
Loading…
Add table
Reference in a new issue