nb/intel/hsw,soc/intel/{bdw,skl,apl},mb/*: unify dt panel settings

There are multiple different devicetree setting formats for graphics
panel settings present in coreboot. Replace the ones for the platforms
that already have (mostly) unified gma/graphics setup code by a unified
struct in the gma driver. Hook it up in HSW, BDW, SKL, and APL and adapt
the devicetrees accordingly.

Always ensure that values don't overflow by applying appropriate masks.

The remaining platforms implementing panel settings (GM45, i945, ILK and
SNB) can be migrated later after unifying their gma/graphics setup code.

Signed-off-by: Michael Niewöhner <foss@mniewoehner.de>
Change-Id: I445defe01d5fbf9a69cf05cf1b5bd6c7c2c1725e
Reviewed-on: https://review.coreboot.org/c/coreboot/+/48885
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index 6e4c82d..c94b7ef 100644
--- a/src/soc/intel/apollolake/chip.h
+++ b/src/soc/intel/apollolake/chip.h
@@ -4,6 +4,7 @@
 #define _SOC_APOLLOLAKE_CHIP_H_
 
 #include <commonlib/helpers.h>
+#include <drivers/intel/gma/gma.h>
 #include <intelblocks/cfg.h>
 #include <intelblocks/gspi.h>
 #include <soc/gpe.h>
@@ -24,22 +25,6 @@
 	PNP_PERF_POWER,
 };
 
-struct soc_intel_apl_pp {
-	unsigned int up_delay_ms;
-	unsigned int down_delay_ms;
-	unsigned int cycle_delay_ms;
-	unsigned int backlight_on_delay_ms;
-	unsigned int backlight_off_delay_ms;
-};
-
-struct soc_intel_apl_blc {
-	unsigned int pwm_hz;
-	enum {
-		GPU_BACKLIGHT_POLARITY_HIGH = 0,
-		GPU_BACKLIGHT_POLARITY_LOW,
-	} polarity;
-};
-
 struct soc_intel_apollolake_config {
 
 	/* Common structure containing soc config data required by common code*/
@@ -48,12 +33,13 @@
 	/* Common struct containing power limits configuration info */
 	struct soc_power_limits_config power_limits_config;
 
-	/* IGD panel configuration */
-	struct soc_intel_apl_pp gpu_pp[2];
-	/* Second backlight control shares logic with other pins (aka. display
-	   utility pin). Be sure it's used for PWM before setting any value for
-	   the secondary controls. */
-	struct soc_intel_apl_blc gpu_blc[2];
+	/*
+	 * IGD panel configuration
+	 *
+	 * Second backlight control shares logic with other pins (aka. display utility pin).
+	 * Be sure it's used for PWM before setting any secondary backlight value.
+	 */
+	struct i915_gpu_panel_config panel_cfg[2];
 
 	/*
 	 * Mapping from PCIe root port to CLKREQ input on the SOC. The SOC has
diff --git a/src/soc/intel/apollolake/graphics.c b/src/soc/intel/apollolake/graphics.c
index 4144479..c24ccdf 100644
--- a/src/soc/intel/apollolake/graphics.c
+++ b/src/soc/intel/apollolake/graphics.c
@@ -11,37 +11,37 @@
 #include "chip.h"
 
 static void graphics_configure_panelpower(
-		const struct soc_intel_apl_pp *const pp,
+		const struct i915_gpu_panel_config *const panel_cfg,
 		uint8_t *const mmio, const unsigned int panel_idx)
 {
 	const unsigned int offset = panel_idx * 0x100;
 	uint32_t reg32;
 
-	reg32 = (DIV_ROUND_UP(pp->cycle_delay_ms, 100) + 1) << 4 & 0x1f0;
+	reg32 = ((DIV_ROUND_UP(panel_cfg->cycle_delay_ms, 100) + 1) & 0x1f) << 4;
 	reg32 |= PANEL_POWER_RESET;
 	write32(mmio + PCH_PP_CONTROL + offset, reg32);
 
-	reg32 = pp->up_delay_ms * 10 << 16;
-	reg32 |= pp->backlight_on_delay_ms * 10;
+	reg32 = ((panel_cfg->up_delay_ms * 10) & 0x1fff) << 16;
+	reg32 |= (panel_cfg->backlight_on_delay_ms * 10) & 0x1fff;
 	write32(mmio + PCH_PP_ON_DELAYS + offset, reg32);
 
-	reg32 = pp->down_delay_ms * 10 << 16;
-	reg32 |= pp->backlight_off_delay_ms * 10;
+	reg32 = ((panel_cfg->down_delay_ms * 10) & 0x1fff) << 16;
+	reg32 |= (panel_cfg->backlight_off_delay_ms * 10) & 0x1fff;
 	write32(mmio + PCH_PP_OFF_DELAYS + offset, reg32);
 }
 
 static void graphics_configure_backlight(
-		const struct soc_intel_apl_blc *const blc,
+		const struct i915_gpu_panel_config *const panel_cfg,
 		uint8_t *const mmio, const unsigned int panel_idx)
 {
-	if (!blc->pwm_hz)
+	if (!panel_cfg->backlight_pwm_hz)
 		return;
 
-	const unsigned int pwm_period = 19200 * 1000 / blc->pwm_hz;
+	const unsigned int pwm_period = 19200 * 1000 / panel_cfg->backlight_pwm_hz;
 	write32(mmio + BXT_BLC_PWM_FREQ(panel_idx), pwm_period);
 	write32(mmio + BXT_BLC_PWM_DUTY(panel_idx), pwm_period / 2);
 	write32(mmio + BXT_BLC_PWM_CTL(panel_idx),
-		(blc->polarity ? BXT_BLC_PWM_POLARITY : 0));
+		panel_cfg->backlight_polarity ? BXT_BLC_PWM_POLARITY : 0);
 
 	/* Second backlight control uses display utility pin. */
 	if (panel_idx == 1) {
@@ -68,9 +68,9 @@
 		return;
 	mmio = (void *)(uintptr_t)mmio_res->base;
 
-	for (i = 0; i < ARRAY_SIZE(conf->gpu_pp); ++i)
-		graphics_configure_panelpower(&conf->gpu_pp[i], mmio, i);
+	for (i = 0; i < ARRAY_SIZE(conf->panel_cfg); ++i)
+		graphics_configure_panelpower(&conf->panel_cfg[i], mmio, i);
 
-	for (i = 0; i < ARRAY_SIZE(conf->gpu_blc); ++i)
-		graphics_configure_backlight(&conf->gpu_blc[i], mmio, i);
+	for (i = 0; i < ARRAY_SIZE(conf->panel_cfg); ++i)
+		graphics_configure_backlight(&conf->panel_cfg[i], mmio, i);
 }
diff --git a/src/soc/intel/broadwell/chip.h b/src/soc/intel/broadwell/chip.h
index b77cb71..9f6c58d 100644
--- a/src/soc/intel/broadwell/chip.h
+++ b/src/soc/intel/broadwell/chip.h
@@ -3,7 +3,7 @@
 #ifndef _SOC_INTEL_BROADWELL_CHIP_H_
 #define _SOC_INTEL_BROADWELL_CHIP_H_
 
-#include <drivers/intel/gma/i915.h>
+#include <drivers/intel/gma/gma.h>
 #include <stdint.h>
 
 struct soc_intel_broadwell_config {
@@ -18,19 +18,8 @@
 	u8 gpu_dp_c_hotplug;
 	u8 gpu_dp_d_hotplug;
 
-	/* Panel power sequence timings */
-	u16 gpu_panel_power_cycle_delay_ms;
-	u16 gpu_panel_power_up_delay_ms;
-	u16 gpu_panel_power_down_delay_ms;
-	u16 gpu_panel_power_backlight_on_delay_ms;
-	u16 gpu_panel_power_backlight_off_delay_ms;
-
-	/* Panel backlight settings */
-	unsigned int gpu_pch_backlight_pwm_hz;
-	enum {
-		GPU_BACKLIGHT_POLARITY_HIGH = 0,
-		GPU_BACKLIGHT_POLARITY_LOW,
-	} gpu_pch_backlight_polarity;
+	/* IGD panel configuration */
+	struct i915_gpu_panel_config panel_cfg;
 
 	/*
 	 * Graphics CD Clock Frequency
diff --git a/src/soc/intel/broadwell/gma.c b/src/soc/intel/broadwell/gma.c
index 9866ed3..bbb6678 100644
--- a/src/soc/intel/broadwell/gma.c
+++ b/src/soc/intel/broadwell/gma.c
@@ -285,6 +285,7 @@
 static void gma_setup_panel(struct device *dev)
 {
 	config_t *conf = config_of(dev);
+	const struct i915_gpu_panel_config *panel_cfg = &conf->panel_cfg;
 	u32 reg32;
 
 	/* Setup Digital Port Hotplug */
@@ -299,30 +300,30 @@
 	/* Setup Panel Power On Delays */
 	reg32 = gtt_read(PCH_PP_ON_DELAYS);
 	if (!reg32) {
-		reg32 |= ((conf->gpu_panel_power_up_delay_ms * 10) & 0x1fff) << 16;
-		reg32 |= (conf->gpu_panel_power_backlight_on_delay_ms * 10) & 0x1fff;
+		reg32 |= ((panel_cfg->up_delay_ms * 10) & 0x1fff) << 16;
+		reg32 |= (panel_cfg->backlight_on_delay_ms * 10) & 0x1fff;
 		gtt_write(PCH_PP_ON_DELAYS, reg32);
 	}
 
 	/* Setup Panel Power Off Delays */
 	reg32 = gtt_read(PCH_PP_OFF_DELAYS);
 	if (!reg32) {
-		reg32 = ((conf->gpu_panel_power_down_delay_ms * 10) & 0x1fff) << 16;
-		reg32 |= (conf->gpu_panel_power_backlight_off_delay_ms * 10) & 0x1fff;
+		reg32 = ((panel_cfg->down_delay_ms * 10) & 0x1fff) << 16;
+		reg32 |= (panel_cfg->backlight_off_delay_ms * 10) & 0x1fff;
 		gtt_write(PCH_PP_OFF_DELAYS, reg32);
 	}
 
 	/* Setup Panel Power Cycle Delay */
-	if (conf->gpu_panel_power_cycle_delay_ms) {
+	if (panel_cfg->cycle_delay_ms) {
 		reg32 = gtt_read(PCH_PP_DIVISOR);
 		reg32 &= ~0x1f;
-		reg32 |= (DIV_ROUND_UP(conf->gpu_panel_power_cycle_delay_ms, 100) + 1) & 0x1f;
+		reg32 |= (DIV_ROUND_UP(panel_cfg->cycle_delay_ms, 100) + 1) & 0x1f;
 		gtt_write(PCH_PP_DIVISOR, reg32);
 	}
 
 	/* So far all devices seem to use the PCH PWM function.
 	   The CPU PWM registers are all zero after reset.      */
-	if (conf->gpu_pch_backlight_pwm_hz) {
+	if (panel_cfg->backlight_pwm_hz) {
 		/* For Lynx Point-LP:
 		   Reference clock is 24MHz. We can choose either a 16
 		   or a 128 step increment. Use 16 if we would have less
@@ -333,7 +334,7 @@
 		u32 south_chicken2;
 
 		south_chicken2 = gtt_read(SOUTH_CHICKEN2);
-		if (conf->gpu_pch_backlight_pwm_hz > hz_limit) {
+		if (panel_cfg->backlight_pwm_hz > hz_limit) {
 			pwm_increment = 16;
 			south_chicken2 |= 1 << 5;
 		} else {
@@ -342,7 +343,7 @@
 		}
 		gtt_write(SOUTH_CHICKEN2, south_chicken2);
 
-		pwm_period = refclock / pwm_increment / conf->gpu_pch_backlight_pwm_hz;
+		pwm_period = refclock / pwm_increment / panel_cfg->backlight_pwm_hz;
 		printk(BIOS_INFO,
 			"GMA: Setting backlight PWM frequency to %uMHz / %u / %u = %uHz\n",
 			refclock / MHz, pwm_increment, pwm_period,
@@ -352,7 +353,7 @@
 		gtt_write(BLC_PWM_PCH_CTL2, pwm_period << 16 | pwm_period / 2);
 
 		gtt_write(BLC_PWM_PCH_CTL1,
-			(conf->gpu_pch_backlight_polarity == GPU_BACKLIGHT_POLARITY_LOW) << 29 |
+			(panel_cfg->backlight_polarity == GPU_BACKLIGHT_POLARITY_LOW) << 29 |
 			BLM_PCH_OVERRIDE_ENABLE | BLM_PCH_PWM_ENABLE);
 	}
 }
diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h
index 7d9d934..027a2e2 100644
--- a/src/soc/intel/skylake/chip.h
+++ b/src/soc/intel/skylake/chip.h
@@ -6,7 +6,7 @@
 #include <acpi/acpi_device.h>
 #include <device/i2c_simple.h>
 #include <drivers/i2c/designware/dw_i2c.h>
-#include <drivers/intel/gma/i915.h>
+#include <drivers/intel/gma/gma.h>
 #include <intelblocks/cfg.h>
 #include <intelblocks/gspi.h>
 #include <intelblocks/lpc_lib.h>
@@ -37,16 +37,7 @@
 	struct soc_power_limits_config power_limits_config;
 
 	/* IGD panel configuration */
-	unsigned int gpu_pp_up_delay_ms;
-	unsigned int gpu_pp_down_delay_ms;
-	unsigned int gpu_pp_cycle_delay_ms;
-	unsigned int gpu_pp_backlight_on_delay_ms;
-	unsigned int gpu_pp_backlight_off_delay_ms;
-	unsigned int gpu_pch_backlight_pwm_hz;
-	enum {
-		GPU_BACKLIGHT_POLARITY_HIGH = 0,
-		GPU_BACKLIGHT_POLARITY_LOW,
-	} gpu_pch_backlight_polarity;
+	struct i915_gpu_panel_config panel_cfg;
 
 	/* Gpio group routed to each dword of the GPE0 block. Values are
 	 * of the form GPP_[A:G] or GPD. */
diff --git a/src/soc/intel/skylake/graphics.c b/src/soc/intel/skylake/graphics.c
index 46dc9db..d41c4aa 100644
--- a/src/soc/intel/skylake/graphics.c
+++ b/src/soc/intel/skylake/graphics.c
@@ -15,6 +15,7 @@
 void graphics_soc_panel_init(struct device *dev)
 {
 	struct soc_intel_skylake_config *conf = config_of(dev);
+	const struct i915_gpu_panel_config *panel_cfg;
 	struct resource *mmio_res;
 	uint8_t *base;
 	u32 reg32;
@@ -22,27 +23,29 @@
 	if (!conf)
 		return;
 
+	panel_cfg = &conf->panel_cfg;
+
 	mmio_res = find_resource(dev, PCI_BASE_ADDRESS_0);
 	if (!mmio_res || !mmio_res->base)
 		return;
 	base = (void *)(uintptr_t)mmio_res->base;
 
-	reg32 = conf->gpu_pp_up_delay_ms * 10 << 16;
-	reg32 |= conf->gpu_pp_backlight_on_delay_ms * 10;
+	reg32 = ((panel_cfg->up_delay_ms * 10) & 0x1fff) << 16;
+	reg32 |= (panel_cfg->backlight_on_delay_ms * 10) & 0x1fff;
 	write32(base + PCH_PP_ON_DELAYS, reg32);
 
-	reg32 = conf->gpu_pp_down_delay_ms * 10 << 16;
-	reg32 |= conf->gpu_pp_backlight_off_delay_ms * 10;
+	reg32 = ((panel_cfg->down_delay_ms * 10) & 0x1fff) << 16;
+	reg32 |= (panel_cfg->backlight_off_delay_ms * 10) & 0x1fff;
 	write32(base + PCH_PP_OFF_DELAYS, reg32);
 
 	reg32 = read32(base + PCH_PP_DIVISOR);
 	reg32 &= ~0x1f;
-	reg32 |= (DIV_ROUND_UP(conf->gpu_pp_cycle_delay_ms, 100) + 1) & 0x1f;
+	reg32 |= (DIV_ROUND_UP(panel_cfg->cycle_delay_ms, 100) + 1) & 0x1f;
 	write32(base + PCH_PP_DIVISOR, reg32);
 
 	/* So far all devices seem to use the PCH PWM function.
 	   The CPU PWM registers are all zero after reset.      */
-	if (conf->gpu_pch_backlight_pwm_hz) {
+	if (panel_cfg->backlight_pwm_hz) {
 		/* Reference clock is 24MHz. We can choose either a 16
 		   or a 128 step increment. Use 16 if we would have less
 		   than 100 steps otherwise. */
@@ -51,7 +54,7 @@
 		u32 south_chicken1;
 
 		south_chicken1 = read32(base + SOUTH_CHICKEN1);
-		if (conf->gpu_pch_backlight_pwm_hz > hz_limit) {
+		if (panel_cfg->backlight_pwm_hz > hz_limit) {
 			pwm_increment = 16;
 			south_chicken1 &= ~1;
 		} else {
@@ -60,15 +63,12 @@
 		}
 		write32(base + SOUTH_CHICKEN1, south_chicken1);
 
-		pwm_period = 24 * 1000 * 1000 / pwm_increment
-				/ conf->gpu_pch_backlight_pwm_hz;
+		pwm_period = 24 * 1000 * 1000 / pwm_increment / panel_cfg->backlight_pwm_hz;
 		/* Start with a 50% duty cycle. */
-		write32(base + BLC_PWM_PCH_CTL2,
-			pwm_period << 16 | pwm_period / 2);
+		write32(base + BLC_PWM_PCH_CTL2, pwm_period << 16 | pwm_period / 2);
 
 		write32(base + BLC_PWM_PCH_CTL1,
-			!!conf->gpu_pch_backlight_polarity << 29 |
-			BLM_PCH_PWM_ENABLE);
+			!!panel_cfg->backlight_polarity << 29 | BLM_PCH_PWM_ENABLE);
 	}
 }