blob: 24cabfe454b5083e3855614b5e201b455ac6eff4 [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>
Furquan Shaikhc82aabc2020-04-23 13:59:00 -07005#include <device/pci.h>
6#include <device/pci_ids.h>
7
Aaron Durbin77a062e2020-08-20 10:15:06 -06008#define ATIF_FUNCTION_VERIFY_INTERFACE 0x0
9struct atif_verify_interface_output {
10 uint16_t size; /* Size of this object, including size field */
11 uint16_t version;
12 uint32_t supported_notifications;
13 uint32_t supported_functions; /* Bit n set if function n+1 supported. */
14};
15
16#define ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS 0x10
17# define ATIF_QBTC_REQUEST_LCD1 0
18/* error codes */
19# define ATIF_QBTC_ERROR_CODE_SUCCESS 0
20# define ATIF_QBTC_ERROR_CODE_FAILURE 1
21# define ATIF_QBTC_ERROR_CODE_DEVICE_NOT_SUPPORTED 2
22struct atif_brightness_input {
23 uint16_t size;
24 /* ATIF doc indicates this field is a word, but the kernel drivers uses a byte. */
25 uint8_t requested_display;
26};
27struct atif_brightness_output {
28 uint16_t size; /* Size of this object, including size field. */
29 uint16_t flags; /* Currently all reserved. */
30 uint8_t error_code;
31 /* default brightness fields currently ignored by Linux driver. */
32 uint8_t default_brightness_ac; /* Percentage brightness when connected to AC. */
33 uint8_t default_brightness_dc; /* Percentage brightness when connected to DC. */
34 /* The following 2 fields are the only ones honored by Linux driver currently. */
35 uint8_t min_input_signal_level; /* 0-255 corresponding to 0% */
36 uint8_t max_input_signal_level; /* 0-255 corresponding to 100% */
37 /* Array of data points consisting of:
38 * { uint8_t luminance_level; (percent)
39 * uint8_t input_signal_level; (0-255 in value) }
40 * Linux ignores these fields so no support currently. */
41 uint8_t count_data_points; /* Count of data points. */
42};
43
44static void generate_atif(const struct device *dev)
45{
46 struct atif_verify_interface_output verify_output = {
47 .size = sizeof(verify_output),
48 .version = 1,
49 .supported_functions =
50 BIT(ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS - 1),
51 };
52 struct atif_brightness_output brightness_error = {
53 .size = sizeof(brightness_error),
54 .error_code = ATIF_QBTC_ERROR_CODE_DEVICE_NOT_SUPPORTED,
55 };
56 struct atif_brightness_output brightness_out = {
57 .size = sizeof(brightness_out),
58 .error_code = ATIF_QBTC_ERROR_CODE_SUCCESS,
59 .min_input_signal_level = 0,
60 .max_input_signal_level = 255,
61 };
62
63 /* Scope (\_SB.PCI0.PBRA.IGFX) */
64 acpigen_write_scope(acpi_device_path(dev));
65 /* Method (ATIF, 2, NotSerialized) */
66 acpigen_write_method("ATIF", 2);
67 /* ToInteger (Arg0, Local0) */
68 acpigen_write_to_integer(ARG0_OP, LOCAL0_OP);
69
70 /* If ((Local0 == Zero)) */
71 acpigen_write_if_lequal_op_int(LOCAL0_OP, ATIF_FUNCTION_VERIFY_INTERFACE);
72 /* Return (Buffer (0x0C) { ... } */
73 acpigen_write_return_byte_buffer((uint8_t *)(void *)&verify_output,
74 sizeof(verify_output));
75 acpigen_pop_len(); /* if (LEqual(Local0, 0) */
76
77 /* ElseIf ((Local0 == 0x10)) */
78 acpigen_write_else();
79 acpigen_write_if_lequal_op_int(LOCAL0_OP,
80 ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS);
81 /* CreateByteField (Arg1, 0x02, DISP) */
82 acpigen_write_create_byte_field(ARG1_OP,
83 offsetof(struct atif_brightness_input, requested_display), "DISP");
84 /* ToInteger (DISP, Local1) */
85 acpigen_write_to_integer_from_namestring("DISP", LOCAL1_OP);
86 /* If ((Local1 == Zero)) */
87 acpigen_write_if_lequal_op_int(LOCAL1_OP, ATIF_QBTC_REQUEST_LCD1);
88 /* Return (Buffer (0x0A) { ... } */
89 acpigen_write_return_byte_buffer((uint8_t *)(void *)&brightness_out,
90 sizeof(brightness_out));
91 acpigen_pop_len(); /* if (LEqual(Local2, ATIF_QBTC_REQUEST_LCD1) */
92 /* Else */
93 acpigen_write_else();
94 /* Return (Buffer (0x0A) */
95 acpigen_write_return_byte_buffer((uint8_t *)(void *)&brightness_error,
96 sizeof(brightness_error));
97 acpigen_pop_len(); /* else */
98
99 acpigen_pop_len(); /* if (LEqual(Local0, 0x10) */
100 acpigen_pop_len(); /* else */
101
102 acpigen_pop_len(); /* Method */
103 acpigen_pop_len(); /* Scope */
104}
105
Raul E Rangelda5e07e2020-04-29 15:55:33 -0600106static void graphics_fill_ssdt(const struct device *dev)
Furquan Shaikhf939df72020-04-23 14:13:02 -0700107{
108 acpi_device_write_pci_dev(dev);
109 pci_rom_ssdt(dev);
Aaron Durbin77a062e2020-08-20 10:15:06 -0600110 if (CONFIG(SOC_AMD_COMMON_BLOCK_GRAPHICS_ATIF))
111 generate_atif(dev);
Furquan Shaikhf939df72020-04-23 14:13:02 -0700112}
113
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700114static const char *graphics_acpi_name(const struct device *dev)
115{
116 return "IGFX";
117}
118
119static const struct device_operations graphics_ops = {
120 .read_resources = pci_dev_read_resources,
121 .set_resources = pci_dev_set_resources,
122 .enable_resources = pci_dev_enable_resources,
123 .init = pci_dev_init,
124 .ops_pci = &pci_dev_ops_pci,
125 .write_acpi_tables = pci_rom_write_acpi_tables,
Furquan Shaikhf939df72020-04-23 14:13:02 -0700126 .acpi_fill_ssdt = graphics_fill_ssdt,
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700127 .acpi_name = graphics_acpi_name,
128};
129
130static const unsigned short pci_device_ids[] = {
Furquan Shaikh9e1a49c2020-04-23 14:01:12 -0700131 PCI_DEVICE_ID_AMD_FAM17H_GPU,
Furquan Shaikhc82aabc2020-04-23 13:59:00 -0700132 0,
133};
134
135static const struct pci_driver graphics_driver __pci_driver = {
136 .ops = &graphics_ops,
137 .vendor = PCI_VENDOR_ID_ATI,
138 .devices = pci_device_ids,
139};