On 2018-11-20 10:16 a.m., David Francis wrote:
> ACPI ATIF has a function called query
> backlight transfer characteristics.  Among the
> information returned by this function is
> the minimum and maximum input signals for the
> backlight
> 
> Call that function on ACPI init.  When DM
> backlight device is updated, copy over the
> backlight caps into DM, but only once.  Use
> the backlight caps in the backlight-to-dc
> calculation.
> 
> Signed-off-by: David Francis <david.fran...@amd.com>

Reviewed-by: Harry Wentland <harry.wentl...@amd.com>

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h           |  3 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c      | 83 +++++++++++++++++++
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 59 ++++++++++---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 13 +++
>  drivers/gpu/drm/amd/include/amd_acpi.h        | 24 ++++++
>  5 files changed, 170 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 2c80453ca350..adbad0e2d4ea 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1255,6 +1255,9 @@ bool 
> amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *ade
>  int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,
>                                               u8 perf_req, bool advertise);
>  int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
> +
> +void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev,
> +             struct amdgpu_dm_backlight_caps *caps);
>  #else
>  static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
>  static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> index 471266901d1b..47db65926d71 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
> @@ -65,6 +65,7 @@ struct amdgpu_atif {
>       struct amdgpu_atif_functions functions;
>       struct amdgpu_atif_notification_cfg notification_cfg;
>       struct amdgpu_encoder *encoder_for_bl;
> +     struct amdgpu_dm_backlight_caps backlight_caps;
>  };
>  
>  /* Call the ATIF method
> @@ -297,6 +298,65 @@ static int amdgpu_atif_get_notification_params(struct 
> amdgpu_atif *atif)
>       return err;
>  }
>  
> +/**
> + * amdgpu_atif_query_backlight_caps - get min and max backlight input signal
> + *
> + * @handle: acpi handle
> + *
> + * Execute the QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS ATIF function
> + * to determine the acceptable range of backlight values
> + *
> + * Backlight_caps.caps_valid will be set to true if the query is successful
> + *
> + * The input signals are in range 0-255
> + *
> + * This function assumes the display with backlight is the first LCD
> + *
> + * Returns 0 on success, error on failure.
> + */
> +static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
> +{
> +     union acpi_object *info;
> +     struct atif_qbtc_output characteristics;
> +     struct atif_qbtc_arguments arguments;
> +     struct acpi_buffer params;
> +     size_t size;
> +     int err = 0;
> +
> +     arguments.size = sizeof(arguments);
> +     arguments.requested_display = ATIF_QBTC_REQUEST_LCD1;
> +
> +     params.length = sizeof(arguments);
> +     params.pointer = (void *)&arguments;
> +
> +     info = amdgpu_atif_call(atif,
> +             ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS,
> +             &params);
> +     if (!info) {
> +             err = -EIO;
> +             goto out;
> +     }
> +
> +     size = *(u16 *) info->buffer.pointer;
> +     if (size < 10) {
> +             err = -EINVAL;
> +             goto out;
> +     }
> +
> +     memset(&characteristics, 0, sizeof(characteristics));
> +     size = min(sizeof(characteristics), size);
> +     memcpy(&characteristics, info->buffer.pointer, size);
> +
> +     atif->backlight_caps.caps_valid = true;
> +     atif->backlight_caps.min_input_signal =
> +                     characteristics.min_input_signal;
> +     atif->backlight_caps.max_input_signal =
> +                     characteristics.max_input_signal;
> +out:
> +     kfree(info);
> +     return err;
> +}
> +
>  /**
>   * amdgpu_atif_get_sbios_requests - get requested sbios event
>   *
> @@ -786,6 +846,17 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
>               }
>       }
>  
> +     if (atif->functions.query_backlight_transfer_characteristics) {
> +             ret = amdgpu_atif_query_backlight_caps(atif);
> +             if (ret) {
> +                     DRM_DEBUG_DRIVER("Call to 
> QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS failed: %d\n",
> +                                     ret);
> +                     atif->backlight_caps.caps_valid = false;
> +             }
> +     } else {
> +             atif->backlight_caps.caps_valid = false;
> +     }
> +
>  out:
>       adev->acpi_nb.notifier_call = amdgpu_acpi_event;
>       register_acpi_notifier(&adev->acpi_nb);
> @@ -793,6 +864,18 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
>       return ret;
>  }
>  
> +void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev,
> +             struct amdgpu_dm_backlight_caps *caps)
> +{
> +     if (!adev->atif) {
> +             caps->caps_valid = false;
> +             return;
> +     }
> +     caps->caps_valid = adev->atif->backlight_caps.caps_valid;
> +     caps->min_input_signal = adev->atif->backlight_caps.min_input_signal;
> +     caps->max_input_signal = adev->atif->backlight_caps.max_input_signal;
> +}
> +
>  /**
>   * amdgpu_acpi_fini - tear down driver acpi support
>   *
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 090a602f3014..0bccea073f9d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -1590,27 +1590,60 @@ static int amdgpu_dm_mode_config_init(struct 
> amdgpu_device *adev)
>       return 0;
>  }
>  
> +#define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 12
> +#define AMDGPU_DM_DEFAULT_MAX_BACKLIGHT 255
> +
>  #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
>       defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
>  
> +static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager 
> *dm)
> +{
> +#if defined(CONFIG_ACPI)
> +     struct amdgpu_dm_backlight_caps caps;
> +
> +     if (dm->backlight_caps.caps_valid)
> +             return;
> +
> +     amdgpu_acpi_get_backlight_caps(dm->adev, &caps);
> +     if (caps.caps_valid) {
> +             dm->backlight_caps.min_input_signal = caps.min_input_signal;
> +             dm->backlight_caps.max_input_signal = caps.max_input_signal;
> +             dm->backlight_caps.caps_valid = true;
> +     } else {
> +             dm->backlight_caps.min_input_signal =
> +                             AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
> +             dm->backlight_caps.max_input_signal =
> +                             AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
> +     }
> +#else
> +     dm->backlight_min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
> +     dm->backlight_max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
> +#endif
> +}
> +
>  static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
>  {
>       struct amdgpu_display_manager *dm = bl_get_data(bd);
> +     struct amdgpu_dm_backlight_caps caps;
> +     uint32_t brightness = bd->props.brightness;
>  
> -     /* backlight_pwm_u16_16 parameter is in unsigned 32 bit, 16 bit integer
> -      * and 16 bit fractional, where 1.0 is max backlight value.
> -      * bd->props.brightness is 8 bit format and needs to be converted by
> -      * scaling via copy lower byte to upper byte of 16 bit value.
> -      */
> -     uint32_t brightness = bd->props.brightness * 0x101;
> -
> +     amdgpu_dm_update_backlight_caps(dm);
> +     caps = dm->backlight_caps;
>       /*
> -      * PWM interperts 0 as 100% rather than 0% because of HW
> -      * limitation for level 0.  So limiting minimum brightness level
> -      * to 1.
> +      * The brightness input is in the range 0-255
> +      * It needs to be rescaled to be between the
> +      * requested min and max input signal
> +      *
> +      * It also needs to be scaled up by 0x101 to
> +      * match the DC interface which has a range of
> +      * 0 to 0xffff
>        */
> -     if (bd->props.brightness < 1)
> -             brightness = 0x101;
> +     brightness =
> +             brightness
> +             * 0x101
> +             * (caps.max_input_signal - caps.min_input_signal)
> +             / AMDGPU_MAX_BL_LEVEL
> +             + caps.min_input_signal * 0x101;
>  
>       if (dc_link_set_backlight_level(dm->backlight_link,
>                       brightness, 0, 0))
> @@ -1640,6 +1673,8 @@ amdgpu_dm_register_backlight_device(struct 
> amdgpu_display_manager *dm)
>       char bl_name[16];
>       struct backlight_properties props = { 0 };
>  
> +     amdgpu_dm_update_backlight_caps(dm);
> +
>       props.max_brightness = AMDGPU_MAX_BL_LEVEL;
>       props.brightness = AMDGPU_MAX_BL_LEVEL;
>       props.type = BACKLIGHT_RAW;
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> index 3c2fbfac938f..b8e724a5fd6d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -83,6 +83,18 @@ struct dm_comressor_info {
>       uint64_t gpu_addr;
>  };
>  
> +/**
> + * struct amdgpu_dm_backlight_caps - Usable range of backlight values from 
> ACPI
> + * @min_input_signal: minimum possible input in range 0-255
> + * @max_input_signal: maximum possible input in range 0-255
> + * @caps_valid: true if these values are from the ACPI interface
> + */
> +struct amdgpu_dm_backlight_caps {
> +     int min_input_signal;
> +     int max_input_signal;
> +     bool caps_valid;
> +};
> +
>  /**
>   * struct amdgpu_display_manager - Central amdgpu display manager device
>   *
> @@ -158,6 +170,7 @@ struct amdgpu_display_manager {
>       struct backlight_device *backlight_dev;
>  
>       const struct dc_link *backlight_link;
> +     struct amdgpu_dm_backlight_caps backlight_caps;
>  
>       struct mod_freesync *freesync_module;
>  
> diff --git a/drivers/gpu/drm/amd/include/amd_acpi.h 
> b/drivers/gpu/drm/amd/include/amd_acpi.h
> index 8980edfe5fa9..c72cbfe8f684 100644
> --- a/drivers/gpu/drm/amd/include/amd_acpi.h
> +++ b/drivers/gpu/drm/amd/include/amd_acpi.h
> @@ -52,6 +52,30 @@ struct atif_sbios_requests {
>       u8 backlight_level;     /* panel backlight level (0-255) */
>  } __packed;
>  
> +struct atif_qbtc_arguments {
> +     u16 size;               /* structure size in bytes (includes size 
> field) */
> +     u8 requested_display;   /* which display is requested */
> +} __packed;
> +
> +#define ATIF_QBTC_MAX_DATA_POINTS 99
> +
> +struct atif_qbtc_data_point {
> +     u8 luminance;           /* luminance in percent */
> +     u8 ipnut_signal;        /* input signal in range 0-255 */
> +} __packed;
> +
> +struct atif_qbtc_output {
> +     u16 size;               /* structure size in bytes (includes size 
> field) */
> +     u16 flags;              /* all zeroes */
> +     u8 error_code;          /* error code */
> +     u8 ac_level;            /* default brightness on AC power */
> +     u8 dc_level;            /* default brightness on DC power */
> +     u8 min_input_signal;    /* max input signal in range 0-255 */
> +     u8 max_input_signal;    /* min input signal in range 0-255 */
> +     u8 number_of_points;    /* number of data points */
> +     struct atif_qbtc_data_point data_points[ATIF_QBTC_MAX_DATA_POINTS];
> +} __packed;
> +
>  #define ATIF_NOTIFY_MASK     0x3
>  #define ATIF_NOTIFY_NONE     0
>  #define ATIF_NOTIFY_81               1
> 
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to