Commit 118b4627 authored by Mikita Lipski's avatar Mikita Lipski Committed by Alex Deucher

drm/amd/display: multi-eDP backlight support

[why]
Currently the assumption is that we are using a single eDP
connector so there will only be one backlight object. Need changes
to allow brightness update and reading for multiple eDP connectors.

[how]
- register a single device
- turn backlight link from a pointer to an array of pointers
- update brightness of all eDP links at the same time when request
is registered
- read brightness level only of the primary eDP panel
- turn current_backlight_pwm and targer_backlight_pwm debugfs enteries
into per connector enteries.
Signed-off-by: default avatarMikita Lipski <mikita.lipski@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: default avatarWayne Lin <waynelin@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f50160cf
...@@ -3415,22 +3415,37 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) ...@@ -3415,22 +3415,37 @@ 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);
struct amdgpu_dm_backlight_caps caps; struct amdgpu_dm_backlight_caps caps;
struct dc_link *link = NULL; struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP];
u32 brightness; u32 brightness;
bool rc; bool rc;
int i;
amdgpu_dm_update_backlight_caps(dm); amdgpu_dm_update_backlight_caps(dm);
caps = dm->backlight_caps; caps = dm->backlight_caps;
link = (struct dc_link *)dm->backlight_link; for (i = 0; i < dm->num_of_edps; i++)
link[i] = (struct dc_link *)dm->backlight_link[i];
brightness = convert_brightness_from_user(&caps, bd->props.brightness); brightness = convert_brightness_from_user(&caps, bd->props.brightness);
// Change brightness based on AUX property // Change brightness based on AUX property
if (caps.aux_support) if (caps.aux_support) {
rc = dc_link_set_backlight_level_nits(link, true, brightness, for (i = 0; i < dm->num_of_edps; i++) {
rc = dc_link_set_backlight_level_nits(link[i], true, brightness,
AUX_BL_DEFAULT_TRANSITION_TIME_MS); AUX_BL_DEFAULT_TRANSITION_TIME_MS);
else if (!rc) {
rc = dc_link_set_backlight_level(dm->backlight_link, brightness, 0); DRM_ERROR("DM: Failed to update backlight via AUX on eDP[%d]\n", i);
break;
}
}
} else {
for (i = 0; i < dm->num_of_edps; i++) {
rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness, 0);
if (!rc) {
DRM_ERROR("DM: Failed to update backlight on eDP[%d]\n", i);
break;
}
}
}
return rc ? 0 : 1; return rc ? 0 : 1;
} }
...@@ -3444,7 +3459,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) ...@@ -3444,7 +3459,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
caps = dm->backlight_caps; caps = dm->backlight_caps;
if (caps.aux_support) { if (caps.aux_support) {
struct dc_link *link = (struct dc_link *)dm->backlight_link; struct dc_link *link = (struct dc_link *)dm->backlight_link[0];
u32 avg, peak; u32 avg, peak;
bool rc; bool rc;
...@@ -3453,7 +3468,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) ...@@ -3453,7 +3468,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
return bd->props.brightness; return bd->props.brightness;
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); int ret = dc_link_get_backlight_level(dm->backlight_link[0]);
if (ret == DC_ERROR_UNEXPECTED) if (ret == DC_ERROR_UNEXPECTED)
return bd->props.brightness; return bd->props.brightness;
...@@ -3550,10 +3565,13 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, ...@@ -3550,10 +3565,13 @@ 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)
amdgpu_dm_register_backlight_device(dm); amdgpu_dm_register_backlight_device(dm);
if (dm->backlight_dev) if (dm->backlight_dev) {
dm->backlight_link = link; dm->backlight_link[dm->num_of_edps] = link;
dm->num_of_edps++;
}
} }
#endif #endif
} }
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define AMDGPU_DM_MAX_CRTC 6 #define AMDGPU_DM_MAX_CRTC 6
#define AMDGPU_DM_MAX_NUM_EDP 2
/* /*
#include "include/amdgpu_dal_power_if.h" #include "include/amdgpu_dal_power_if.h"
#include "amdgpu_dm_irq.h" #include "amdgpu_dm_irq.h"
...@@ -354,7 +355,10 @@ struct amdgpu_display_manager { ...@@ -354,7 +355,10 @@ struct amdgpu_display_manager {
struct backlight_device *backlight_dev; struct backlight_device *backlight_dev;
const struct dc_link *backlight_link; const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP];
uint8_t num_of_edps;
struct amdgpu_dm_backlight_caps backlight_caps; struct amdgpu_dm_backlight_caps backlight_caps;
struct mod_freesync *freesync_module; struct mod_freesync *freesync_module;
......
...@@ -2377,6 +2377,44 @@ static ssize_t dp_max_bpc_write(struct file *f, const char __user *buf, ...@@ -2377,6 +2377,44 @@ static ssize_t dp_max_bpc_write(struct file *f, const char __user *buf,
return size; return size;
} }
/*
* Backlight at this moment. Read only.
* As written to display, taking ABM and backlight lut into account.
* Ranges from 0x0 to 0x10000 (= 100% PWM)
*
* Example usage: cat /sys/kernel/debug/dri/0/eDP-1/current_backlight
*/
static int current_backlight_show(struct seq_file *m, void *unused)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(m->private);
struct dc_link *link = aconnector->dc_link;
unsigned int backlight;
backlight = dc_link_get_backlight_level(link);
seq_printf(m, "0x%x\n", backlight);
return 0;
}
/*
* Backlight value that is being approached. Read only.
* As written to display, taking ABM and backlight lut into account.
* Ranges from 0x0 to 0x10000 (= 100% PWM)
*
* Example usage: cat /sys/kernel/debug/dri/0/eDP-1/target_backlight
*/
static int target_backlight_show(struct seq_file *m, void *unused)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(m->private);
struct dc_link *link = aconnector->dc_link;
unsigned int backlight;
backlight = dc_link_get_target_backlight_pwm(link);
seq_printf(m, "0x%x\n", backlight);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support); DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support);
DEFINE_SHOW_ATTRIBUTE(dmub_fw_state); DEFINE_SHOW_ATTRIBUTE(dmub_fw_state);
DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer); DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer);
...@@ -2611,6 +2649,9 @@ DEFINE_DEBUGFS_ATTRIBUTE(dmcub_trace_event_state_fops, dmcub_trace_event_state_g ...@@ -2611,6 +2649,9 @@ DEFINE_DEBUGFS_ATTRIBUTE(dmcub_trace_event_state_fops, dmcub_trace_event_state_g
DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n"); DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n");
DEFINE_SHOW_ATTRIBUTE(current_backlight);
DEFINE_SHOW_ATTRIBUTE(target_backlight);
static const struct { static const struct {
char *name; char *name;
const struct file_operations *fops; const struct file_operations *fops;
...@@ -2634,8 +2675,13 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector) ...@@ -2634,8 +2675,13 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
dp_debugfs_entries[i].fops); dp_debugfs_entries[i].fops);
} }
} }
if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops); debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops);
debugfs_create_file("amdgpu_current_backlight_pwm", 0444, dir, connector,
&current_backlight_fops);
debugfs_create_file("amdgpu_target_backlight_pwm", 0444, dir, connector,
&target_backlight_fops);
}
for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) { for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) {
debugfs_create_file(connector_debugfs_entries[i].name, debugfs_create_file(connector_debugfs_entries[i].name,
...@@ -2938,38 +2984,6 @@ static ssize_t dtn_log_write( ...@@ -2938,38 +2984,6 @@ static ssize_t dtn_log_write(
return size; return size;
} }
/*
* Backlight at this moment. Read only.
* As written to display, taking ABM and backlight lut into account.
* Ranges from 0x0 to 0x10000 (= 100% PWM)
*/
static int current_backlight_show(struct seq_file *m, void *unused)
{
struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
struct amdgpu_display_manager *dm = &adev->dm;
unsigned int backlight = dc_link_get_backlight_level(dm->backlight_link);
seq_printf(m, "0x%x\n", backlight);
return 0;
}
/*
* Backlight value that is being approached. Read only.
* As written to display, taking ABM and backlight lut into account.
* Ranges from 0x0 to 0x10000 (= 100% PWM)
*/
static int target_backlight_show(struct seq_file *m, void *unused)
{
struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
struct amdgpu_display_manager *dm = &adev->dm;
unsigned int backlight = dc_link_get_target_backlight_pwm(dm->backlight_link);
seq_printf(m, "0x%x\n", backlight);
return 0;
}
static int mst_topo_show(struct seq_file *m, void *unused) static int mst_topo_show(struct seq_file *m, void *unused)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)m->private; struct amdgpu_device *adev = (struct amdgpu_device *)m->private;
...@@ -3152,8 +3166,6 @@ static int visual_confirm_get(void *data, u64 *val) ...@@ -3152,8 +3166,6 @@ static int visual_confirm_get(void *data, u64 *val)
return 0; return 0;
} }
DEFINE_SHOW_ATTRIBUTE(current_backlight);
DEFINE_SHOW_ATTRIBUTE(target_backlight);
DEFINE_SHOW_ATTRIBUTE(mst_topo); DEFINE_SHOW_ATTRIBUTE(mst_topo);
DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get, DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get,
visual_confirm_set, "%llu\n"); visual_confirm_set, "%llu\n");
...@@ -3233,10 +3245,6 @@ void dtn_debugfs_init(struct amdgpu_device *adev) ...@@ -3233,10 +3245,6 @@ void dtn_debugfs_init(struct amdgpu_device *adev)
struct drm_minor *minor = adev_to_drm(adev)->primary; struct drm_minor *minor = adev_to_drm(adev)->primary;
struct dentry *root = minor->debugfs_root; struct dentry *root = minor->debugfs_root;
debugfs_create_file("amdgpu_current_backlight_pwm", 0444,
root, adev, &current_backlight_fops);
debugfs_create_file("amdgpu_target_backlight_pwm", 0444,
root, adev, &target_backlight_fops);
debugfs_create_file("amdgpu_mst_topology", 0444, root, debugfs_create_file("amdgpu_mst_topology", 0444, root,
adev, &mst_topo_fops); adev, &mst_topo_fops);
debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev, debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev,
......
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