gma broxton: Avoid invalid state of PWM HW counter

This implements display workaround #0854 [1]. The original descrip-
tion only mentions that the PWM might stop in a logical high state.
Which shouldn't be a problem, as long as there is a separate signal
toggling the on/off state of the backlight.

However, it turns out that with the clock gating, the PWM counter is
also not reset when the frequency divider in BLC_PWM_FREQ is updated.
This can result in a counter value out of range, effectively leaving
the PWM signal low until a 32-bit overflow at 19.2 MHz (almost 4min).

[1] https://cdrdv2-public.intel.com/685505/intel-gfx-prm-osrc-bxt-vol08-workarounds_7.pdf
    May 2017, Revision 1.0

Change-Id: I38b51c5afb072fb3c7b87caca028adba557aeebf
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.sourcearcade.org/c/libgfxinit/+/539
Tested-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Thomas Heijligen <src@posteo.de>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
diff --git a/common/broxton/hw-gfx-gma-power_and_clocks.adb b/common/broxton/hw-gfx-gma-power_and_clocks.adb
index 279071a..73192ff 100644
--- a/common/broxton/hw-gfx-gma-power_and_clocks.adb
+++ b/common/broxton/hw-gfx-gma-power_and_clocks.adb
@@ -314,6 +314,24 @@
 
    ----------------------------------------------------------------------------
 
+   -- WA #0854
+   -- Backlight PWM may stop in the asserted state, causing backlight
+   -- to stay fully on.
+   --
+   -- It was also observed that the PWM counter is not reset on writes
+   -- to the BLC_PWM_FREQ register. This can result in a counter value
+   -- out of range, effectively leaving the PWM signal low until a 32-
+   -- bit overflow at 19.2 MHz (almost 4min).
+   procedure Apply_Workaround_0854
+   is
+      PWM1_GATING_DIS : constant := 1 * 2 ** 13;
+      PWM2_GATING_DIS : constant := 1 * 2 ** 14;
+   begin
+      Registers.Set_Mask
+        (Register => Registers.GEN9_CLKGATE_DIS_0,
+         Mask     => PWM1_GATING_DIS or PWM2_GATING_DIS);
+   end Apply_Workaround_0854;
+
    procedure Pre_All_Off is
    begin
       pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
@@ -355,6 +373,8 @@
       Set_Mask (DBUF_CTL_S0, DBUF_CTL_DBUF_POWER_REQUEST);
       Wait_Set_Mask (DBUF_CTL_S0, DBUF_CTL_DBUF_POWER_STATE);
 
+      Apply_Workaround_0854;
+
       Config.Raw_Clock := Config.Default_RawClk_Freq;
    end Initialize;