Commit 6b51e7d2 authored by Hans de Goede's avatar Hans de Goede

drm/i915: panel: Honor the VBT PWM frequency for devs with an external PWM controller

So far for devices using an external PWM controller (devices using
pwm_setup_backlight()), we have been hardcoding the period-time passed to
pwm_config() to 21333 ns.

I suspect this was done because many VBTs set the PWM frequency to 200
which corresponds to a period-time of 5000000 ns, which greatly exceeds
the PWM_MAX_PERIOD_NS define in the Crystal Cove PMIC PWM driver, which
used to be 21333.

This PWM_MAX_PERIOD_NS define was actually based on a bug in the PWM
driver where its period and duty-cycle times where off by a factor of 256.

Due to this bug the hardcoded CRC_PMIC_PWM_PERIOD_NS value of 21333 would
result in the PWM driver using its divider of 128, which would result in
a PWM output frequency of 6000000 Hz / 256 / 128 = 183 Hz. So actually
pretty close to the default VBT value of 200 Hz.

Now that this bug in the pwm-crc driver is fixed, we can actually use
the VBT defined frequency.

This is important because:

a) With the pwm-crc driver fixed it will now translate the hardcoded
CRC_PMIC_PWM_PERIOD_NS value of 21333 ns / 46 Khz to a PWM output
frequency of 23 KHz (the max it can do).

b) The pwm-lpss driver used on many models has always honored the
21333 ns / 46 Khz request

Some panels do not like such high output frequencies. E.g. on a Terra
Pad 1061 tablet, using the LPSS PWM controller, the backlight would go
from off to max, when changing the sysfs backlight brightness value from
90-100%, anything under aprox. 90% would turn the backlight fully off.

Honoring the VBT specified PWM frequency will also hopefully fix the
various bug reports which we have received about users perceiving the
backlight to flicker after a suspend/resume cycle.
Acked-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-16-hdegoede@redhat.com
parent 27a79cbc
......@@ -223,6 +223,7 @@ struct intel_panel {
bool util_pin_active_low; /* bxt+ */
u8 controller; /* bxt+ only */
struct pwm_device *pwm;
int pwm_period_ns;
/* DPCD backlight */
u8 pwmgen_bit_count;
......
......@@ -40,8 +40,6 @@
#include "intel_dsi_dcs_backlight.h"
#include "intel_panel.h"
#define CRC_PMIC_PWM_PERIOD_NS 21333
void
intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
struct drm_display_mode *adjusted_mode)
......@@ -597,7 +595,7 @@ static u32 pwm_get_backlight(struct intel_connector *connector)
int duty_ns;
duty_ns = pwm_get_duty_cycle(panel->backlight.pwm);
return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS);
return DIV_ROUND_UP(duty_ns * 100, panel->backlight.pwm_period_ns);
}
static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level)
......@@ -671,9 +669,10 @@ static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32
static void pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level)
{
struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100);
int duty_ns = DIV_ROUND_UP(level * panel->backlight.pwm_period_ns, 100);
pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS);
pwm_config(panel->backlight.pwm, duty_ns,
panel->backlight.pwm_period_ns);
}
static void
......@@ -1917,6 +1916,9 @@ static int pwm_setup_backlight(struct intel_connector *connector,
return -ENODEV;
}
panel->backlight.pwm_period_ns = NSEC_PER_SEC /
get_vbt_pwm_freq(dev_priv);
/*
* FIXME: pwm_apply_args() should be removed when switching to
* the atomic PWM API.
......@@ -1926,9 +1928,10 @@ static int pwm_setup_backlight(struct intel_connector *connector,
panel->backlight.min = 0; /* 0% */
panel->backlight.max = 100; /* 100% */
level = intel_panel_compute_brightness(connector, 100);
ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100);
ns = DIV_ROUND_UP(level * panel->backlight.pwm_period_ns, 100);
retval = pwm_config(panel->backlight.pwm, ns, CRC_PMIC_PWM_PERIOD_NS);
retval = pwm_config(panel->backlight.pwm, ns,
panel->backlight.pwm_period_ns);
if (retval < 0) {
drm_err(&dev_priv->drm, "Failed to configure the pwm chip\n");
pwm_put(panel->backlight.pwm);
......@@ -1937,7 +1940,7 @@ static int pwm_setup_backlight(struct intel_connector *connector,
}
level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100,
CRC_PMIC_PWM_PERIOD_NS);
panel->backlight.pwm_period_ns);
panel->backlight.level =
intel_panel_compute_brightness(connector, level);
panel->backlight.enabled = panel->backlight.level != 0;
......
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