1 // SPDX-License-Identifier: GPL-2.0
3 * Device physical location support
5 * Author: Won Chung <wonchung@google.com>
8 #include <linux/acpi.h>
9 #include <linux/sysfs.h>
11 #include "physical_location.h"
13 bool dev_add_physical_location(struct device *dev)
15 struct acpi_pld_info *pld;
18 if (!has_acpi_companion(dev))
21 status = acpi_get_physical_device_location(ACPI_HANDLE(dev), &pld);
22 if (ACPI_FAILURE(status))
25 dev->physical_location =
26 kzalloc(sizeof(*dev->physical_location), GFP_KERNEL);
27 if (!dev->physical_location) {
32 dev->physical_location->panel = pld->panel;
33 dev->physical_location->vertical_position = pld->vertical_position;
34 dev->physical_location->horizontal_position = pld->horizontal_position;
35 dev->physical_location->dock = pld->dock;
36 dev->physical_location->lid = pld->lid;
42 static ssize_t panel_show(struct device *dev, struct device_attribute *attr,
47 switch (dev->physical_location->panel) {
48 case DEVICE_PANEL_TOP:
51 case DEVICE_PANEL_BOTTOM:
54 case DEVICE_PANEL_LEFT:
57 case DEVICE_PANEL_RIGHT:
60 case DEVICE_PANEL_FRONT:
63 case DEVICE_PANEL_BACK:
69 return sysfs_emit(buf, "%s\n", panel);
71 static DEVICE_ATTR_RO(panel);
73 static ssize_t vertical_position_show(struct device *dev,
74 struct device_attribute *attr, char *buf)
76 const char *vertical_position;
78 switch (dev->physical_location->vertical_position) {
79 case DEVICE_VERT_POS_UPPER:
80 vertical_position = "upper";
82 case DEVICE_VERT_POS_CENTER:
83 vertical_position = "center";
85 case DEVICE_VERT_POS_LOWER:
86 vertical_position = "lower";
89 vertical_position = "unknown";
91 return sysfs_emit(buf, "%s\n", vertical_position);
93 static DEVICE_ATTR_RO(vertical_position);
95 static ssize_t horizontal_position_show(struct device *dev,
96 struct device_attribute *attr, char *buf)
98 const char *horizontal_position;
100 switch (dev->physical_location->horizontal_position) {
101 case DEVICE_HORI_POS_LEFT:
102 horizontal_position = "left";
104 case DEVICE_HORI_POS_CENTER:
105 horizontal_position = "center";
107 case DEVICE_HORI_POS_RIGHT:
108 horizontal_position = "right";
111 horizontal_position = "unknown";
113 return sysfs_emit(buf, "%s\n", horizontal_position);
115 static DEVICE_ATTR_RO(horizontal_position);
117 static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
120 return sysfs_emit(buf, "%s\n",
121 dev->physical_location->dock ? "yes" : "no");
123 static DEVICE_ATTR_RO(dock);
125 static ssize_t lid_show(struct device *dev, struct device_attribute *attr,
128 return sysfs_emit(buf, "%s\n",
129 dev->physical_location->lid ? "yes" : "no");
131 static DEVICE_ATTR_RO(lid);
133 static struct attribute *dev_attr_physical_location[] = {
134 &dev_attr_panel.attr,
135 &dev_attr_vertical_position.attr,
136 &dev_attr_horizontal_position.attr,
142 const struct attribute_group dev_attr_physical_location_group = {
143 .name = "physical_location",
144 .attrs = dev_attr_physical_location,