blob: d39f60a85c34d21602ec6ee97b411a29b564190f [file] [log] [blame]
Furquan Shaikhc82aabc2020-04-23 13:59:00 -07001/* SPDX-License-Identifier: GPL-2.0-or-later */
Furquan Shaikhc82aabc2020-04-23 13:59:00 -07002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi_device.h>
Aaron Durbin77a062e2020-08-20 10:15:06 -06004#include <acpi/acpigen.h>
Tim Wawrzynczak84428f72021-09-14 13:59:33 -06005#include <boot/coreboot_tables.h>
Furquan Shaikhc82aabc2020-04-23 13:59:00 -07006#include <device/pci.h>
7#include <device/pci_ids.h>
Nikolai Vyssotski95675d92021-02-09 13:01:07 -06008#include <console/console.h>
9#include <fsp/graphics.h>
Nikolai Vyssotskiad68e692021-01-15 11:39:33 -060010#include <soc/intel/common/vbt.h>
Nikolai Vyssotskib649d6a2021-03-11 19:15:03 -060011#include <timestamp.h>
Furquan Shaikhc82aabc2020-04-23 13:59:00 -070012
Aaron Durbin77a062e2020-08-20 10:15:06 -060013#define ATIF_FUNCTION_VERIFY_INTERFACE 0x0
14struct atif_verify_interface_output {
15 uint16_t size; /* Size of this object, including size field */
16 uint16_t version;
17 uint32_t supported_notifications;
18 uint32_t supported_functions; /* Bit n set if function n+1 supported. */
19};
20
21#define ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS 0x10
22# define ATIF_QBTC_REQUEST_LCD1 0
23/* error codes */
24# define ATIF_QBTC_ERROR_CODE_SUCCESS 0
25# define ATIF_QBTC_ERROR_CODE_FAILURE 1
26# define ATIF_QBTC_ERROR_CODE_DEVICE_NOT_SUPPORTED 2
27struct atif_brightness_input {
28 uint16_t size;
29 /* ATIF doc indicates this field is a word, but the kernel drivers uses a byte. */
30 uint8_t requested_display;
31};
32struct atif_brightness_output {
33 uint16_t size; /* Size of this object, including size field. */
34 uint16_t flags; /* Currently all reserved. */
35 uint8_t error_code;
36 /* default brightness fields currently ignored by Linux driver. */
37 uint8_t default_brightness_ac; /* Percentage brightness when connected to AC. */
38 uint8_t default_brightness_dc; /* Percentage brightness when connected to DC. */
39 /* The following 2 fields are the only ones honored by Linux driver currently. */
40 uint8_t min_input_signal_level; /* 0-255 corresponding to 0% */
41 uint8_t max_input_signal_level; /* 0-255 corresponding to 100% */
42 /* Array of data points consisting of:
43 * { uint8_t luminance_level; (percent)
44 * uint8_t input_signal_level; (0-255 in value) }
45 * Linux ignores these fields so no support currently. */
46 uint8_t count_data_points; /* Count of data points. */
47};
48
49static void generate_atif(const struct device *dev)
50{
51 struct atif_verify_interface_output verify_output = {
52 .size = sizeof(verify_output),
53 .version = 1,
54 .supported_functions =
55 BIT(ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS - 1),
56 };
57 struct atif_brightness_output brightness_error = {
58 .size = sizeof(brightness_error),
59 .error_code = ATIF_QBTC_ERROR_CODE_DEVICE_NOT_SUPPORTED,
60 };
61 struct atif_brightness_output brightness_out = {
62 .size = sizeof(brightness_out),
63 .error_code = ATIF_QBTC_ERROR_CODE_SUCCESS,
64 .min_input_signal_level = 0,
65 .max_input_signal_level = 255,
66 };
67
68 /* Scope (\_SB.PCI0.PBRA.IGFX) */
69 acpigen_write_scope(acpi_device_path(dev));
70 /* Method (ATIF, 2, NotSerialized) */
71 acpigen_write_method("ATIF", 2);
72 /* ToInteger (Arg0, Local0) */
73 acpigen_write_to_integer(ARG0_OP, LOCAL0_OP);
74
75 /* If ((Local0 == Zero)) */
76 acpigen_write_if_lequal_op_int(LOCAL0_OP, ATIF_FUNCTION_VERIFY_INTERFACE);
77 /* Return (Buffer (0x0C) { ... } */
78 acpigen_write_return_byte_buffer((uint8_t *)(void *)&verify_output,
79 sizeof(verify_output));
Aaron Durbin77a062e2020-08-20 10:15:06 -060080
81 /* ElseIf ((Local0 == 0x10)) */
82 acpigen_write_else();
83 acpigen_write_if_lequal_op_int(LOCAL0_OP,
84 ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS);
85 /* CreateByteField (Arg1, 0x02, DISP) */
86 acpigen_write_create_byte_field(ARG1_OP,
87 offsetof(struct atif_brightness_input, requested_display), "DISP");
88 /* ToInteger (DISP, Local1) */
89 acpigen_write_to_integer_from_namestring("DISP", LOCAL1_OP);
90 /* If ((Local1 == Zero)) */
91 acpigen_write_if_lequal_op_int(LOCAL1_OP, ATIF_QBTC_REQUEST_LCD1);
92 /* Return (Buffer (0x0A) { ... } */
93 acpigen_write_return_byte_buffer((uint8_t *)(void *)&brightness_out,
94 sizeof(brightness_out));
Aaron Durbin77a062e2020-08-20 10:15:06 -060095 /* Else */
96 acpigen_write_else();
97 /* Return (Buffer (0x0A) */
98 acpigen_write_return_byte_buffer((uint8_t *)(void *)&brightness_error,
99 sizeof(brightness_error));
100 acpigen_pop_len(); /* else */
101
102 acpigen_pop_len(); /* if (LEqual(Local0, 0x10) */
103 acpigen_pop_len(); /* else */
104
105 acpigen_pop_len(); /* Method */
106 acpigen_pop_len(); /* Scope */
107}
108
Raul E Rangelda5e07e2020-04-29 15:55:33 -0600109static void graphics_fill_ssdt(const struct device *dev)
Furquan Shaikhf939df72020-04-23 14:13:02 -0700110{
111 acpi_device_write_pci_dev(dev);
Raul E Rangela7659eb2021-03-16 13:20:23 -0600112
113 /* Use the VFCT copy when using GOP */
114 if (!CONFIG(RUN_FSP_GOP))
115 pci_rom_ssdt(dev);
116
Aaron Durbin77a062e2020-08-20 10:15:06 -0600117 if (CONFIG(SOC_AMD_COMMON_BLOCK_GRAPHICS_ATIF))
118 generate_atif(dev);
Furquan Shaikhf939df72020-04-23 14:13:02 -0700119}
120
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700121static const char *graphics_acpi_name(const struct device *dev)
122{
123 return "IGFX";
124}
125
Nikolai Vyssotskiad68e692021-01-15 11:39:33 -0600126/*
127 * Even though AMD does not need VBT we still need to implement the
128 * vbt_get() function to not break the build with GOP driver enabled
129 * (see fsps_return_value_handler() in fsp2_0/silicon_init.c
130 */
131void *vbt_get(void)
132{
133 return NULL;
134}
135
Nikolai Vyssotskib649d6a2021-03-11 19:15:03 -0600136static void graphics_set_resources(struct device *const dev)
137{
138 struct rom_header *rom, *ram;
139
140 pci_dev_set_resources(dev);
141
142 if (!CONFIG(RUN_FSP_GOP))
143 return;
144
145 timestamp_add_now(TS_OPROM_INITIALIZE);
146 rom = pci_rom_probe(dev);
147 if (rom == NULL)
148 return;
149 ram = pci_rom_load(dev, rom);
150 if (ram == NULL)
151 return;
152 timestamp_add_now(TS_OPROM_COPY_END);
153}
154
Nikolai Vyssotski95675d92021-02-09 13:01:07 -0600155static void graphics_dev_init(struct device *const dev)
156{
157 if (CONFIG(RUN_FSP_GOP)) {
158 struct resource *res = probe_resource(dev, PCI_BASE_ADDRESS_0);
159
160 if (res && res->base)
Tim Wawrzynczak84428f72021-09-14 13:59:33 -0600161 fsp_report_framebuffer_info(res->base, LB_FB_ORIENTATION_NORMAL);
Nikolai Vyssotski95675d92021-02-09 13:01:07 -0600162 else
163 printk(BIOS_ERR, "%s: Unable to find resource for %s\n",
164 __func__, dev_path(dev));
165 }
166
167 /* Initialize PCI device, load/execute BIOS Option ROM */
168 pci_dev_init(dev);
169}
170
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700171static const struct device_operations graphics_ops = {
172 .read_resources = pci_dev_read_resources,
Nikolai Vyssotskib649d6a2021-03-11 19:15:03 -0600173 .set_resources = graphics_set_resources,
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700174 .enable_resources = pci_dev_enable_resources,
Nikolai Vyssotski95675d92021-02-09 13:01:07 -0600175 .init = graphics_dev_init,
Kevin Chiue80e53c2022-02-11 20:09:32 +0800176 .scan_bus = scan_static_bus,
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700177 .ops_pci = &pci_dev_ops_pci,
178 .write_acpi_tables = pci_rom_write_acpi_tables,
Furquan Shaikhf939df72020-04-23 14:13:02 -0700179 .acpi_fill_ssdt = graphics_fill_ssdt,
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700180 .acpi_name = graphics_acpi_name,
181};
182
183static const unsigned short pci_device_ids[] = {
Felix Singer43b7f412022-03-07 04:34:52 +0100184 PCI_DID_ATI_FAM17H_MODEL18H_GPU,
185 PCI_DID_ATI_FAM17H_MODEL60H_GPU,
186 PCI_DID_ATI_FAM17H_MODEL68H_GPU,
187 PCI_DID_ATI_FAM17H_MODELA0H_GPU,
188 PCI_DID_ATI_FAM19H_MODEL51H_GPU_CEZANNE,
189 PCI_DID_ATI_FAM19H_MODEL51H_GPU_BARCELO,
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700190 0,
191};
192
193static const struct pci_driver graphics_driver __pci_driver = {
194 .ops = &graphics_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100195 .vendor = PCI_VID_ATI,
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700196 .devices = pci_device_ids,
197};