coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
gma.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
11 #include <string.h>
12 #include <device/pci_ops.h>
13 #include <commonlib/helpers.h>
14 #include <types.h>
15 
17 #include "chip.h"
18 #include "gm45.h"
19 
20 static struct resource *gtt_res = NULL;
21 
23 {
24  return read32(res2mmio(gtt_res, reg, 0));
25 }
26 
27 void gtt_write(u32 reg, u32 data)
28 {
29  write32(res2mmio(gtt_res, reg, 0), data);
30 }
31 
32 static u32 get_cdclk(struct device *const dev)
33 {
34  const u16 cdclk_sel = pci_read_config16(dev, GCFGC_OFFSET) & GCFGC_CD_MASK;
35 
36  switch (mchbar_read8(HPLLVCO_MCHBAR) & 0x7) {
37  case VCO_2666:
38  case VCO_4000:
39  case VCO_5333:
40  return cdclk_sel ? 333333333 : 222222222;
41  case VCO_3200:
42  return cdclk_sel ? 320000000 : 228571429;
43  default:
45  "Unknown VCO frequency, using default cdclk.\n");
46  return 222222222;
47  }
48 }
49 
50 static u32 freq_to_blc_pwm_ctl(struct device *const dev,
51  u16 pwm_freq, u8 duty_perc)
52 {
53  u32 blc_mod;
54 
55  blc_mod = get_cdclk(dev) / (128 * pwm_freq);
56 
57  if (duty_perc <= 100)
58  return (blc_mod << 16) | (blc_mod * duty_perc / 100);
59  else
60  return (blc_mod << 16) | blc_mod;
61 }
62 
63 u16 get_blc_pwm_freq_value(const char *edid_ascii_string)
64 {
65  static u16 blc_pwm_freq;
66  const struct blc_pwm_t *blc_pwm;
67  int i;
68  int blc_array_len;
69 
70  if (blc_pwm_freq > 0)
71  return blc_pwm_freq;
72 
73  blc_array_len = get_blc_values(&blc_pwm);
74  /* Find EDID string and pwm freq in lookup table */
75  for (i = 0; i < blc_array_len; i++) {
76  if (!strcmp(blc_pwm[i].ascii_string, edid_ascii_string)) {
77  blc_pwm_freq = blc_pwm[i].pwm_freq;
78  printk(BIOS_DEBUG, "Found EDID string: %s in lookup table, pwm: %dHz\n",
79  blc_pwm[i].ascii_string, blc_pwm_freq);
80  break;
81  }
82  }
83 
84  if (i == blc_array_len)
85  printk(BIOS_NOTICE, "Your panels EDID `%s` wasn't found in the"
86  "lookup table.\n You may have issues with your panels"
87  "backlight.\n If you want to help improving coreboot"
88  "please report: this EDID string\n and the result"
89  "of `intel_read read BLC_PWM_CTL`"
90  "(from intel-gpu-tools)\n while running vendor BIOS\n",
91  edid_ascii_string);
92 
93  return blc_pwm_freq;
94 }
95 
96 static void gma_pm_init_post_vbios(struct device *const dev,
97  const char *edid_ascii_string)
98 {
99  const struct northbridge_intel_gm45_config *const conf = dev->chip_info;
100 
101  u32 reg32;
102  u8 reg8;
103  u16 pwm_freq;
104 
105  /* Setup Panel Power On Delays */
106  reg32 = gtt_read(PP_ON_DELAYS);
107  if (!reg32) {
108  reg32 = (conf->gpu_panel_power_up_delay & 0x1fff) << 16;
109  reg32 |= (conf->gpu_panel_power_backlight_on_delay & 0x1fff);
110  gtt_write(PP_ON_DELAYS, reg32);
111  }
112 
113  /* Setup Panel Power Off Delays */
114  reg32 = gtt_read(PP_OFF_DELAYS);
115  if (!reg32) {
116  reg32 = (conf->gpu_panel_power_down_delay & 0x1fff) << 16;
117  reg32 |= (conf->gpu_panel_power_backlight_off_delay & 0x1fff);
118  gtt_write(PP_OFF_DELAYS, reg32);
119  }
120 
121  /* Setup Panel Power Cycle Delay */
122  if (conf->gpu_panel_power_cycle_delay) {
123  reg32 = (get_cdclk(dev) / 20000 - 1)
125  reg32 |= conf->gpu_panel_power_cycle_delay & 0x1f;
126  gtt_write(PP_DIVISOR, reg32);
127  }
128 
129  /* Enable Backlight */
130  gtt_write(BLC_PWM_CTL2, (1 << 31));
131  reg8 = 100;
132  if (conf->duty_cycle != 0)
133  reg8 = conf->duty_cycle;
134  pwm_freq = get_blc_pwm_freq_value(edid_ascii_string);
135  if (pwm_freq == 0 && conf->default_pwm_freq != 0)
136  pwm_freq = conf->default_pwm_freq;
137 
138  if (pwm_freq == 0)
139  gtt_write(BLC_PWM_CTL, 0x06100610);
140  else
142  reg8));
143 }
144 
145 static void gma_func0_init(struct device *dev)
146 {
147  u8 *mmio;
148  u8 edid_data_lvds[128];
149  struct edid edid_lvds;
150  const struct northbridge_intel_gm45_config *const conf = dev->chip_info;
151 
153 
155  if (gtt_res == NULL)
156  return;
157  mmio = res2mmio(gtt_res, 0, 0);
158 
159  if (!CONFIG(NO_GFX_INIT))
161 
162  if (!CONFIG(MAINBOARD_USE_LIBGFXINIT)) {
163  /* PCI Init, will run VBIOS */
164  printk(BIOS_DEBUG, "Initialising IGD using VBIOS\n");
165  pci_dev_init(dev);
166  }
167 
168  printk(BIOS_DEBUG, "LVDS EDID\n");
170  edid_data_lvds, sizeof(edid_data_lvds));
171  intel_gmbus_stop(mmio + GMBUS0);
172  decode_edid(edid_data_lvds, sizeof(edid_data_lvds), &edid_lvds);
173 
174  /* Post VBIOS init */
175  gma_pm_init_post_vbios(dev, edid_lvds.ascii_string);
176 
177  if (CONFIG(MAINBOARD_USE_LIBGFXINIT) && !acpi_is_wakeup_s3()) {
178  int vga_disable = (pci_read_config16(dev, D0F0_GGC) & 2) >> 1;
179  if (vga_disable) {
181  "IGD is not decoding legacy VGA MEM and IO: skipping NATIVE graphic init\n");
182  } else {
183  int lightup_ok;
184  gma_gfxinit(&lightup_ok);
185  /* Linux relies on VBT for panel info. */
186  generate_fake_intel_oprom(&conf->gfx, dev, "$VBT CANTIGA");
187  }
188  }
189 }
190 
191 static void gma_generate_ssdt(const struct device *device)
192 {
194 
196 }
197 
198 static const char *gma_acpi_name(const struct device *dev)
199 {
200  return "GFX0";
201 }
202 
203 static struct device_operations gma_func0_ops = {
205  .set_resources = pci_dev_set_resources,
206  .enable_resources = pci_dev_enable_resources,
207  .acpi_fill_ssdt = gma_generate_ssdt,
208  .init = gma_func0_init,
209  .ops_pci = &pci_dev_ops_pci,
210  .acpi_name = gma_acpi_name,
211 };
212 
213 static const unsigned short pci_device_ids[] =
214 {
215  0x2a42, 0
216 };
217 
218 static const struct pci_driver gma __pci_driver = {
219  .ops = &gma_func0_ops,
220  .vendor = PCI_VID_INTEL,
221  .devices = pci_device_ids,
222 };
static int acpi_is_wakeup_s3(void)
Definition: acpi.h:9
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define printk(level,...)
Definition: stdlib.h:16
struct resource * probe_resource(const struct device *dev, unsigned int index)
See if a resource structure already exists for a given index.
Definition: device_util.c:323
void drivers_intel_gma_displays_ssdt_generate(const struct i915_gpu_controller_info *conf)
Definition: acpi.c:8
void intel_gmbus_read_edid(u8 *mmio, u8 bus, u8 slave, u8 *edid, u32 edid_size)
Definition: edid.c:54
void intel_gmbus_stop(u8 *mmio)
Definition: edid.c:48
@ CONFIG
Definition: dsi_common.h:201
static __always_inline uint8_t mchbar_read8(const uintptr_t offset)
Definition: fixed_bars.h:11
#define GCFGC_OFFSET
Definition: gm45.h:207
#define GCFGC_CD_MASK
Definition: gm45.h:213
#define HPLLVCO_MCHBAR
Definition: gm45.h:223
@ VCO_4000
Definition: gm45.h:158
@ VCO_3200
Definition: gm45.h:157
@ VCO_2666
Definition: gm45.h:156
@ VCO_5333
Definition: gm45.h:159
#define D0F0_GGC
Definition: gm45.h:176
static struct tpm_chip chip
Definition: tis.c:17
void generate_fake_intel_oprom(const struct i915_gpu_controller_info *conf, struct device *dev, const char *idstr)
Definition: vbt.c:62
#define GMBUS_PORT_PANEL
Definition: i915_reg.h:834
#define BLC_PWM_CTL2
Definition: i915_reg.h:1587
#define PP_ON_DELAYS
Definition: i915_reg.h:1547
#define BLC_PWM_CTL
Definition: i915_reg.h:1606
#define PP_REFERENCE_DIVIDER_SHIFT
Definition: i915_reg.h:3787
#define PP_OFF_DELAYS
Definition: i915_reg.h:1548
#define GMBUS0
Definition: i915_reg.h:824
#define PP_DIVISOR
Definition: i915_reg.h:1549
static __always_inline void pci_or_config16(const struct device *dev, u16 reg, u16 ormask)
Definition: pci_ops.h:180
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
int decode_edid(unsigned char *edid, int size, struct edid *out)
Definition: edid.c:1104
int get_blc_values(const struct blc_pwm_t **entries)
Definition: blc.c:30
void gma_gfxinit(int *lightup_ok)
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_NOTICE
BIOS_NOTICE - Unexpected but relatively insignificant.
Definition: loglevel.h:100
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
static u32 get_cdclk(struct device *const dev)
Definition: gma.c:32
static const char * gma_acpi_name(const struct device *dev)
Definition: gma.c:198
static struct resource * gtt_res
Definition: gma.c:20
static void gma_func0_init(struct device *dev)
Definition: gma.c:145
u32 gtt_read(u32 reg)
Definition: gma.c:22
static void gma_pm_init_post_vbios(struct device *const dev, const char *edid_ascii_string)
Definition: gma.c:96
static const struct pci_driver gma __pci_driver
Definition: gma.c:218
static u32 freq_to_blc_pwm_ctl(struct device *const dev, u16 pwm_freq, u8 duty_perc)
Definition: gma.c:50
static const unsigned short pci_device_ids[]
Definition: gma.c:213
void gtt_write(u32 reg, u32 data)
Definition: gma.c:27
u16 get_blc_pwm_freq_value(const char *edid_ascii_string)
Definition: gma.c:63
static struct device_operations gma_func0_ops
Definition: gma.c:203
static void gma_generate_ssdt(const struct device *device)
Definition: gma.c:191
enum cb_err intel_gma_init_igd_opregion(void)
Definition: opregion.c:310
#define PCI_COMMAND_MASTER
Definition: pci_def.h:13
#define PCI_BASE_ADDRESS_0
Definition: pci_def.h:63
#define PCI_COMMAND
Definition: pci_def.h:10
void pci_dev_init(struct device *dev)
Default handler: only runs the relevant PCI BIOS.
Definition: pci_device.c:873
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_dev_read_resources(struct device *dev)
Definition: pci_device.c:534
struct pci_operations pci_dev_ops_pci
Default device operation for PCI devices.
Definition: pci_device.c:911
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
#define PCI_VID_INTEL
Definition: pci_ids.h:2157
static void * res2mmio(const struct resource *res, unsigned long offset, unsigned long mask)
Definition: resource.h:87
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
int strcmp(const char *s1, const char *s2)
Definition: string.c:103
char ascii_string[13]
Definition: gm45.h:431
int pwm_freq
Definition: gm45.h:432
void(* read_resources)(struct device *dev)
Definition: device.h:39
Definition: device.h:107
DEVTREE_CONST void * chip_info
Definition: device.h:164
Definition: edid.h:49
char ascii_string[EDID_ASCII_STRING_LENGTH+1]
Definition: edid.h:85
u16 gpu_panel_power_backlight_on_delay
Definition: chip.h:11
struct i915_gpu_controller_info gfx
Definition: chip.h:14
u16 gpu_panel_power_backlight_off_delay
Definition: chip.h:12