linux-acpi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Hans de Goede <hdegoede@redhat.com>
To: Thierry Reding <thierry.reding@gmail.com>
Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Jani Nikula" <jani.nikula@linux.intel.com>,
	"Joonas Lahtinen" <joonas.lahtinen@linux.intel.com>,
	"Rodrigo Vivi" <rodrigo.vivi@intel.com>,
	"Ville Syrjälä" <ville.syrjala@linux.intel.com>,
	"Rafael J . Wysocki" <rjw@rjwysocki.net>,
	"Len Brown" <lenb@kernel.org>,
	linux-pwm@vger.kernel.org,
	intel-gfx <intel-gfx@lists.freedesktop.org>,
	dri-devel@lists.freedesktop.org,
	"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
	"Mika Westerberg" <mika.westerberg@linux.intel.com>,
	linux-acpi@vger.kernel.org
Subject: Re: [PATCH v8 06/17] pwm: lpss: Use pwm_lpss_restore() when restoring state on resume
Date: Mon, 31 Aug 2020 13:46:28 +0200	[thread overview]
Message-ID: <d63a89d2-84e5-ca05-aa96-a06291503c5f@redhat.com> (raw)
In-Reply-To: <20200831111006.GD1688464@ulmo>

Hi,

On 8/31/20 1:10 PM, Thierry Reding wrote:
> On Sun, Aug 30, 2020 at 02:57:42PM +0200, Hans de Goede wrote:
>> Before this commit a suspend + resume of the LPSS PWM controller
>> would result in the controller being reset to its defaults of
>> output-freq = clock/256, duty-cycle=100%, until someone changes
>> to the output-freq and/or duty-cycle are made.
>>
>> This problem has been masked so far because the main consumer
>> (the i915 driver) was always making duty-cycle changes on resume.
>> With the conversion of the i915 driver to the atomic PWM API the
>> driver now only disables/enables the PWM on suspend/resume leaving
>> the output-freq and duty as is, triggering this problem.
> 
> Doesn't this imply that there's another bug at play here? At the PWM API
> level you're applying a state and it's up to the driver to ensure that
> the hardware state after ->apply() is what the software has requested.
> 
> If you only switch the enable state and that doesn't cause period and
> duty cycle to be updated it means that your driver isn't writing those
> registers when it should be.

Right, the driver was not committing those as it should *on resume*,
that and it skips setting the update bit on the subsequent enable,
which is an optimization which gets removed in 7/17.

Before switching the i915 driver over to atomic, when the LPSS-PWM
was used for the backlight we got the following order on suspend/resume

1. Set duty-cycle to 0%
2. Set enabled to 0
3. Save ctrl reg
4. Power-off PWM controller, it now looses all its state
5. Power-on PWM ctrl
6. Restore ctrl reg (as a single reg write)
7. Set enabled to 1, at this point one would expect the
duty/freq from the restored ctrl-reg to apply, but:
a) The resume code never sets the update bit (which this commit fixes); and
b) On applying the pwm_state with enabled=1 the code applying the
state does this (before setting the enabled bit in the ctrl reg):

	if (orig_ctrl != ctrl) {
		pwm_lpss_write(pwm, ctrl);
		pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE);
	}
and since the restore of the ctrl reg set the old duty/freq the
writes are skipped, so the update bit never gets set.

8. Set duty-cycle to the pre-suspend value (which is not 0)
this does cause a change in the ctrl-reg, so now the update flag
does get set.

Note that 1-2 and 7-8 are both done by the non atomic i915 code,
when moving the i915 code to atomic I decided that having these
2 separate steps here is non-sense, so the new i915 code just
toggles the enable bit. So in essence the new atomic PWM
i915 code drops step 1 and 8.

Dropping steps 8 means that the update bit never gets set and we
end up with the PWM running at its power-on-reset duty cycle.

You are correct in your remark to patch 7/17 that since that removes
the if (orig_ctrl != ctrl) for the writes that now step 7 will be
sufficient to get the PWM to work again. But that only takes the i915
usage into account.

What if the PWM is used through the sysfs userspace API?
Then only steps 3-6 will happen on suspend-resume and without
fixing step 6 to properly restore the PWM controller in its
pre-resume state (this patch) it will once again be running at
its power-on-reset defaults instead of the values from the
restored control register.

So at step 6, if the PWM was enabled before, we must set the update
bit, and then wait for it to clear again so the controller is
ready for subsequent updates. The waiting for it to clear again
needs to happen before or after setting the enable bit depending
on the hw generation, which leads to this patch.

I hope that helps explain why this patch is the correct thing
to do.


>> The LPSS PWM controller has a mechanism where the ctrl register value
>> and the actual base-unit and on-time-div values used are latched. When
>> software sets the SW_UPDATE bit then at the end of the current PWM cycle,
>> the new values from the ctrl-register will be latched into the actual
>> registers, and the SW_UPDATE bit will be cleared.
>>
>> The problem is that before this commit our suspend/resume handling
>> consisted of simply saving the PWM ctrl register on suspend and
>> restoring it on resume, without setting the PWM_SW_UPDATE bit.
>> When the controller has lost its state over a suspend/resume and thus
>> has been reset to the defaults, just restoring the register is not
>> enough. We must also set the SW_UPDATE bit to tell the controller to
>> latch the restored values into the actual registers.
>>
>> Fixing this problem is not as simple as just or-ing in the value which
>> is being restored with SW_UPDATE. If the PWM was enabled before we must
>> write the new settings + PWM_SW_UPDATE before setting PWM_ENABLE.
>> We must also wait for PWM_SW_UPDATE to become 0 again and depending on the
>> model we must do this either before or after the setting of PWM_ENABLE.
>>
>> All the necessary logic for doing this is already present inside
>> pwm_lpss_apply(), so instead of duplicating this inside the resume
>> handler, this commit adds a new pwm_lpss_restore() helper which mirrors
>> pwm_lpss_apply() minus the runtime-pm reference handling (which we should
>> not change on resume).
> 
> If this is all already implemented in pwm_lpss_apply(), why isn't it
> working for the suspend/resume case? It shouldn't matter that the
> consumer only changes the enable/disable state. After ->apply()
> successfully returns your hardware should be programmed with exactly
> the state that the consumer requested.

See above, apply() was trying to be smart but the restore of ctrl
on resume without setting the update bit was tricking it. That
being too smart for its own good is removed in 7/16 as you
rightfully point out. But this patch is still necessary for the
PWM controller to be in the expected state between resume and the
first apply() after resume (which may be quite a long time in
the future when using e.g. the sysfs API).

Regards,

Hans


  reply	other threads:[~2020-08-31 11:46 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-30 12:57 [PATCH v8 00/17] acpi/pwm/i915: Convert pwm-crc and i915 driver's PWM code to use the atomic PWM API Hans de Goede
2020-08-30 12:57 ` [PATCH v8 01/17] ACPI / LPSS: Resume Cherry Trail PWM controller in no-irq phase Hans de Goede
2020-08-30 12:57 ` [PATCH v8 02/17] ACPI / LPSS: Save Cherry Trail PWM ctx registers only once (at activation) Hans de Goede
2020-08-30 12:57 ` [PATCH v8 03/17] pwm: lpss: Fix off by one error in base_unit math in pwm_lpss_prepare() Hans de Goede
2020-08-31 11:01   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 04/17] pwm: lpss: Add range limit check for the base_unit register value Hans de Goede
2020-08-31 11:02   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 05/17] pwm: lpss: Add pwm_lpss_prepare_enable() helper Hans de Goede
2020-08-31 11:03   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 06/17] pwm: lpss: Use pwm_lpss_restore() when restoring state on resume Hans de Goede
2020-08-31 11:10   ` Thierry Reding
2020-08-31 11:46     ` Hans de Goede [this message]
2020-08-31 13:15       ` Thierry Reding
2020-08-31 17:57         ` Hans de Goede
2020-09-01  8:09           ` Andy Shevchenko
2020-08-30 12:57 ` [PATCH v8 07/17] pwm: lpss: Always update state and set update bit Hans de Goede
2020-08-31  8:56   ` Andy Shevchenko
2020-08-31 11:50     ` Hans de Goede
2020-08-31 11:13   ` Thierry Reding
2020-08-31 11:26     ` Hans de Goede
2020-08-31 13:31       ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 08/17] pwm: crc: Fix period / duty_cycle times being off by a factor of 256 Hans de Goede
2020-08-31 11:13   ` Thierry Reding
2020-08-31 11:14   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 09/17] pwm: crc: Fix off-by-one error in the clock-divider calculations Hans de Goede
2020-08-31 11:15   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 10/17] pwm: crc: Fix period changes not having any effect Hans de Goede
2020-08-31 11:15   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 11/17] pwm: crc: Enable/disable PWM output on enable/disable Hans de Goede
2020-08-31 11:16   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 12/17] pwm: crc: Implement apply() method to support the new atomic PWM API Hans de Goede
2020-08-31 11:17   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 13/17] pwm: crc: Implement get_state() method Hans de Goede
2020-08-31 11:18   ` Thierry Reding
2020-08-30 12:57 ` [PATCH v8 14/17] drm/i915: panel: Add get_vbt_pwm_freq() helper Hans de Goede
2020-08-30 12:57 ` [PATCH v8 15/17] drm/i915: panel: Honor the VBT PWM frequency for devs with an external PWM controller Hans de Goede
2020-08-30 12:57 ` [PATCH v8 16/17] drm/i915: panel: Honor the VBT PWM min setting " Hans de Goede
2020-08-30 12:57 ` [PATCH v8 17/17] drm/i915: panel: Use atomic PWM API " Hans de Goede

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d63a89d2-84e5-ca05-aa96-a06291503c5f@redhat.com \
    --to=hdegoede@redhat.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jani.nikula@linux.intel.com \
    --cc=joonas.lahtinen@linux.intel.com \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=mika.westerberg@linux.intel.com \
    --cc=rjw@rjwysocki.net \
    --cc=rodrigo.vivi@intel.com \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    --cc=ville.syrjala@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).