blob: 2cbb17a06c7ff9b73bc0b0908e02bf3ef74bd2d7 [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Mathew Kingc135b822019-10-14 10:19:15 -06003
Furquan Shaikh76cedd22020-05-02 10:24:23 -07004#include <acpi/acpigen.h>
Mathew Kingc135b822019-10-14 10:19:15 -06005#include <console/console.h>
6#include <device/device.h>
7#include <device/pci.h>
8#include <device/pci_ids.h>
9#include <stdint.h>
Mathew Kingc135b822019-10-14 10:19:15 -060010
11#include "chip.h"
12
13#define ACPI_DSM_PRIVACY_SCREEN_UUID "C7033113-8720-4CEB-9090-9D52B3E52D73"
14
Rajat Jain7ef06b02020-02-26 23:28:02 -080015#define ACPI_METHOD_EPS_PRESENT "EPSP"
16#define ACPI_METHOD_EPS_STATE "EPSS"
17#define ACPI_METHOD_EPS_ENABLE "EPSE"
18#define ACPI_METHOD_EPS_DISABLE "EPSD"
19
Mathew Kingc135b822019-10-14 10:19:15 -060020static void privacy_screen_detect_cb(void *arg)
21{
Furquan Shaikha0b0d422020-02-21 09:57:54 -080022 struct drivers_gfx_generic_privacy_screen_config *config = arg;
Mathew Kingc135b822019-10-14 10:19:15 -060023
24 acpigen_write_store();
25 acpigen_emit_namestring(config->detect_function);
26 acpigen_emit_byte(LOCAL2_OP);
27 acpigen_write_if_lequal_op_int(LOCAL2_OP, 1);
28 acpigen_write_return_singleton_buffer(0xF);
29 acpigen_pop_len();
30}
31static void privacy_screen_get_status_cb(void *arg)
32{
Furquan Shaikha0b0d422020-02-21 09:57:54 -080033 struct drivers_gfx_generic_privacy_screen_config *config = arg;
Mathew Kingc135b822019-10-14 10:19:15 -060034
35 acpigen_emit_byte(RETURN_OP);
36 acpigen_emit_namestring(config->status_function);
37}
38static void privacy_screen_enable_cb(void *arg)
39{
Furquan Shaikha0b0d422020-02-21 09:57:54 -080040 struct drivers_gfx_generic_privacy_screen_config *config = arg;
Mathew Kingc135b822019-10-14 10:19:15 -060041
42 acpigen_emit_namestring(config->enable_function);
43}
44static void privacy_screen_disable_cb(void *arg)
45{
Furquan Shaikha0b0d422020-02-21 09:57:54 -080046 struct drivers_gfx_generic_privacy_screen_config *config = arg;
Mathew Kingc135b822019-10-14 10:19:15 -060047
48 acpigen_emit_namestring(config->disable_function);
49}
50
51static void (*privacy_screen_callbacks[])(void *) = {
52 privacy_screen_detect_cb,
53 privacy_screen_get_status_cb,
54 privacy_screen_enable_cb,
55 privacy_screen_disable_cb,
56};
57
Rajat Jain7ef06b02020-02-26 23:28:02 -080058static void privacy_gpio_acpigen(struct acpi_gpio *gpio)
59{
60 /* EPS Present */
61 acpigen_write_method(ACPI_METHOD_EPS_PRESENT, 0);
62 acpigen_write_return_byte(1);
63 acpigen_pop_len();
64
65 /* EPS State */
66 acpigen_write_method(ACPI_METHOD_EPS_STATE, 0);
67 acpigen_get_rx_gpio(gpio);
68 acpigen_emit_byte(RETURN_OP);
69 acpigen_emit_byte(LOCAL0_OP);
70 acpigen_pop_len();
71
72 /* EPS Enable */
73 acpigen_write_method(ACPI_METHOD_EPS_ENABLE, 0);
74 acpigen_enable_tx_gpio(gpio);
75 acpigen_pop_len();
76
77 /* EPS Disable */
78 acpigen_write_method(ACPI_METHOD_EPS_DISABLE, 0);
79 acpigen_disable_tx_gpio(gpio);
80 acpigen_pop_len();
81}
82
83static void gfx_fill_privacy_screen_dsm(
84 struct drivers_gfx_generic_privacy_screen_config *privacy)
85{
86 if (!privacy->enabled)
87 return;
88
89 /* Populate ACPI methods, if EPS controlled via gpio */
90 if (privacy->gpio.pin_count == 1) {
91 privacy_gpio_acpigen(&privacy->gpio);
92 privacy->detect_function = ACPI_METHOD_EPS_PRESENT;
93 privacy->status_function = ACPI_METHOD_EPS_STATE;
94 privacy->enable_function = ACPI_METHOD_EPS_ENABLE;
95 privacy->disable_function = ACPI_METHOD_EPS_DISABLE;
96 }
97
98 acpigen_write_dsm(ACPI_DSM_PRIVACY_SCREEN_UUID,
99 privacy_screen_callbacks,
100 ARRAY_SIZE(privacy_screen_callbacks),
101 privacy);
102}
103
Furquan Shaikh7536a392020-04-24 21:59:21 -0700104static void gfx_fill_ssdt_generator(const struct device *dev)
Mathew Kingc135b822019-10-14 10:19:15 -0600105{
106 size_t i;
Furquan Shaikha0b0d422020-02-21 09:57:54 -0800107 struct drivers_gfx_generic_config *config = dev->chip_info;
Mathew Kingc135b822019-10-14 10:19:15 -0600108
109 const char *scope = acpi_device_scope(dev);
110
Rajat Jain7ef06b02020-02-26 23:28:02 -0800111 if (!scope || !dev->enabled)
Jacob Garber45192772020-02-01 13:04:11 -0700112 return;
113
Mathew Kingc135b822019-10-14 10:19:15 -0600114 acpigen_write_scope(scope);
115
116 /* Method (_DOD, 0) */
117 acpigen_write_method("_DOD", 0);
118 acpigen_emit_byte(RETURN_OP);
119 acpigen_write_package(config->device_count);
120 for (i = 0; i < config->device_count; i++)
121 acpigen_write_dword(config->device[i].addr);
122 acpigen_pop_len(); /* End Package. */
123 acpigen_pop_len(); /* End Method. */
124
125 for (i = 0; i < config->device_count; i++) {
126 acpigen_write_device(config->device[i].name);
Mathew Kingc135b822019-10-14 10:19:15 -0600127 acpigen_write_name_integer("_ADR", config->device[i].addr);
128 acpigen_write_name_integer("_STA", 0xF);
Rajat Jain7ef06b02020-02-26 23:28:02 -0800129 gfx_fill_privacy_screen_dsm(&config->device[i].privacy);
Mathew Kingc135b822019-10-14 10:19:15 -0600130 acpigen_pop_len(); /* Device */
131 }
132 acpigen_pop_len(); /* Scope */
133}
134
135static const char *gfx_acpi_name(const struct device *dev)
136{
Furquan Shaikha0b0d422020-02-21 09:57:54 -0800137 struct drivers_gfx_generic_config *config = dev->chip_info;
Mathew Kingc135b822019-10-14 10:19:15 -0600138
139 return config->name ? : "GFX0";
140}
141
142static struct device_operations gfx_ops = {
Nico Huber68680dd2020-03-31 17:34:52 +0200143 .acpi_name = gfx_acpi_name,
144 .acpi_fill_ssdt = gfx_fill_ssdt_generator,
Mathew Kingc135b822019-10-14 10:19:15 -0600145};
146
147static void gfx_enable(struct device *dev)
148{
Furquan Shaikha0b0d422020-02-21 09:57:54 -0800149 struct drivers_gfx_generic_config *config = dev->chip_info;
Mathew Kingc135b822019-10-14 10:19:15 -0600150
Rajat Jain7ef06b02020-02-26 23:28:02 -0800151 if (!config || !dev->enabled)
Mathew Kingc135b822019-10-14 10:19:15 -0600152 return;
153
154 dev->ops = &gfx_ops;
155}
156
Furquan Shaikha0b0d422020-02-21 09:57:54 -0800157struct chip_operations drivers_gfx_generic_ops = {
158 CHIP_NAME("Generic Graphics Device")
Mathew Kingc135b822019-10-14 10:19:15 -0600159 .enable_dev = gfx_enable
160};
Rajat Jain7ef06b02020-02-26 23:28:02 -0800161
162struct device *find_gfx_dev(void)
163{
164 struct device *dev;
165
166 for (dev = all_devices; dev; dev = dev->next) {
167 if (dev->chip_ops && dev->chip_ops == &drivers_gfx_generic_ops)
168 return dev;
169 }
170 return NULL;
171}