summaryrefslogtreecommitdiff
path: root/src/drivers/i2c/max98390/max98390.c
blob: 08ed6251632ad9b7b006e7daea59851c28a97aa1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <acpi/acpi.h>
#include <acpi/acpi_device.h>
#include <acpi/acpigen.h>
#include <console/console.h>
#include <device/i2c.h>
#include <device/device.h>
#include <device/path.h>
#include <stdint.h>
#include <vendorcode/google/chromeos/chromeos.h>
#include "chip.h"

#define MAX98390_ACPI_HID "MX98390"

#define MAX98390_DP_INT(key, val) acpi_dp_add_integer(dp, "maxim," key, (val))

static void max98390_fill_ssdt(const struct device *dev)
{
	struct drivers_i2c_max98390_config *config = dev->chip_info;
	const char *scope = acpi_device_scope(dev);
	struct acpi_i2c i2c = {
		.address = dev->path.i2c.device,
		.mode_10bit = dev->path.i2c.mode_10bit,
		.speed = I2C_SPEED_FAST,
		.resource = scope,
	};
	struct acpi_dp *dp = NULL;
	uint64_t r0_value, temp_value;
	char dsm_name[80] = {};

	if (!scope)
		return;

	/* Device */
	acpigen_write_scope(scope);
	acpigen_write_device(acpi_device_name(dev));
	acpigen_write_name_string("_HID", MAX98390_ACPI_HID);
	acpigen_write_name_integer("_UID", config->uid);
	acpigen_write_name_string("_DDN", config->desc);
	acpigen_write_STA(acpi_device_status(dev));

	/* Resources */
	acpigen_write_name("_CRS");
	acpigen_write_resourcetemplate_header();
	acpi_device_write_i2c(&i2c);
	acpigen_write_resourcetemplate_footer();

	/* Device Properties */
	if (CONFIG(CHROMEOS_DSM_CALIB)) {
		if (get_dsm_calibration_from_key(config->r0_calib_key, &r0_value)
		    || get_dsm_calibration_from_key(config->temperature_calib_key,
						    &temp_value)) {
			printk(BIOS_ERR,
			       "Failed to get dsm_calib parameters from VPD"
			       " with key %s and %s\n",
			       config->r0_calib_key, config->temperature_calib_key);
		} else {
			dp = acpi_dp_new_table("_DSD");
			MAX98390_DP_INT("r0_calib", r0_value);
			MAX98390_DP_INT("temperature_calib", temp_value);
			printk(BIOS_INFO, "set dsm_calib properties\n");
		}
	}

	if (CONFIG(CHROMEOS_DSM_PARAM_FILE_NAME)) {
		if (config->dsm_param_file_name) {
			if (!dp)
				dp = acpi_dp_new_table("_DSD");

			size_t chars = snprintf(dsm_name, sizeof(dsm_name), "%s_%s_%s.bin",
					config->dsm_param_file_name, CONFIG_MAINBOARD_VENDOR,
					CONFIG_MAINBOARD_PART_NUMBER);

			if (chars >= sizeof(dsm_name))
				printk(BIOS_ERR, "ERROR: String too long in %s\n", __func__);

			acpi_dp_add_string(dp, "maxim,dsm_param_name", dsm_name);
		}
	}

	if (!dp)
		dp = acpi_dp_new_table("_DSD");

	acpi_dp_add_integer(dp, "maxim,vmon-slot-no", config->vmon_slot_no);
	acpi_dp_add_integer(dp, "maxim,imon-slot-no", config->imon_slot_no);

	if (dp)
		acpi_dp_write(dp);

	acpigen_pop_len(); /* Device */
	acpigen_pop_len(); /* Scope */

	printk(BIOS_INFO, "%s: %s address 0%xh\n", acpi_device_path(dev), dev->chip_ops->name,
	       dev->path.i2c.device);
}

static const char *max98390_acpi_name(const struct device *dev)
{
	struct drivers_i2c_max98390_config *config = dev->chip_info;
	static char name[5];

	if (config->name)
		return config->name;

	snprintf(name, sizeof(name), "D%03.3X", dev->path.i2c.device);
	return name;
}

static struct device_operations max98390_ops = {
	.read_resources = noop_read_resources,
	.set_resources = noop_set_resources,
	.acpi_name = max98390_acpi_name,
	.acpi_fill_ssdt = max98390_fill_ssdt,
};

static void max98390_enable(struct device *dev)
{
	struct drivers_i2c_max98390_config *config = dev->chip_info;

	if (!config)
		return;

	dev->ops = &max98390_ops;

	/* Name the device as per description provided in devicetree */
	if (config->desc)
		dev->name = config->desc;
}

struct chip_operations drivers_i2c_max98390_ops = {
	CHIP_NAME("Maxim MAX98390 Codec")
	.enable_dev = max98390_enable
};