/ src / drivers / amd / i2s_machine_dev / i2s_machine_dev.c
i2s_machine_dev.c
  1  /* SPDX-License-Identifier: GPL-2.0-or-later */
  2  
  3  #include <acpi/acpi_device.h>
  4  #include <acpi/acpigen.h>
  5  #include <device/device.h>
  6  #include <stdio.h>
  7  
  8  #include "chip.h"
  9  #include <console/console.h>
 10  
 11  #define AMD_I2S_ACPI_DESC	"I2S machine driver"
 12  
 13  static void i2s_machine_dev_fill_crs_dsd(const char *path,
 14  					const struct acpi_gpio *dmic_select_gpio)
 15  {
 16  	struct acpi_dp *dsd;
 17  
 18  	/* Resources */
 19  	acpigen_write_name("_CRS");
 20  	acpigen_write_resourcetemplate_header();
 21  	acpi_device_write_gpio(dmic_select_gpio);
 22  	acpigen_write_resourcetemplate_footer();
 23  
 24  	dsd = acpi_dp_new_table("_DSD");
 25  	/*
 26  	 * This GPIO is used to select DMIC0 or DMIC1 by the kernel driver. It does not
 27  	 * really have a polarity since low and high control the selection of DMIC and
 28  	 * hence does not have an active polarity.
 29  	 * Kernel driver does not use the polarity field and instead treats the GPIO
 30  	 * selection as follows:
 31  	 * Set low (0) = Select DMIC0
 32  	 * Set high (1) = Select DMIC1
 33  	 */
 34  	acpi_dp_add_gpio(dsd, "dmic-gpios", path,
 35  			 0,  /* Index = 0 (There is a single GPIO entry in _CRS). */
 36  			 0,  /* Pin = 0 (There is a single pin in the GPIO resource). */
 37  			 0); /* Active low = 0 (Kernel driver does not use active polarity). */
 38  	acpi_dp_write(dsd);
 39  }
 40  
 41  static void i2s_machine_dev_fill_ssdt(const struct device *dev)
 42  {
 43  	const char *scope = acpi_device_scope(dev);
 44  	const struct acpi_gpio *dmic_select_gpio;
 45  	const struct drivers_amd_i2s_machine_dev_config *cfg;
 46  	const char *path = acpi_device_path(dev);
 47  
 48  	cfg = config_of(dev);
 49  
 50  	dmic_select_gpio = &cfg->dmic_select_gpio;
 51  
 52  	if (scope == NULL) {
 53  		printk(BIOS_ERR, "%s: ERROR: ACPI I2S scope not found\n", dev_path(dev));
 54  		return;
 55  	}
 56  
 57  	if (cfg->hid == NULL) {
 58  		printk(BIOS_ERR, "%s: ERROR: HID required\n", dev_path(dev));
 59  		return;
 60  	}
 61  
 62  	acpigen_write_scope(scope); /* Scope */
 63  	acpigen_write_device(acpi_device_name(dev)); /* Device */
 64  	acpigen_write_name_string("_HID", cfg->hid);
 65  	acpigen_write_name_integer("_UID", cfg->uid);
 66  	acpigen_write_name_string("_DDN", AMD_I2S_ACPI_DESC);
 67  
 68  	acpigen_write_STA(acpi_device_status(dev));
 69  
 70  	if (dmic_select_gpio->pin_count)
 71  		i2s_machine_dev_fill_crs_dsd(path, dmic_select_gpio);
 72  
 73  	acpigen_pop_len(); /* Device */
 74  	acpigen_pop_len(); /* Scope */
 75  
 76  	printk(BIOS_INFO, "%s: %s at %s\n", path, AMD_I2S_ACPI_DESC, dev_path(dev));
 77  }
 78  
 79  static const char *i2s_machine_dev_acpi_name(const struct device *dev)
 80  {
 81  	static char name[5];
 82  	snprintf(name, sizeof(name), "I2S%X", dev->path.generic.id);
 83  	return name;
 84  }
 85  
 86  static struct device_operations i2s_machine_dev_ops = {
 87  	.read_resources		= noop_read_resources,
 88  	.set_resources		= noop_set_resources,
 89  	.acpi_name		= i2s_machine_dev_acpi_name,
 90  	.acpi_fill_ssdt		= i2s_machine_dev_fill_ssdt,
 91  };
 92  
 93  static void i2s_machine_dev_enable(struct device *dev)
 94  {
 95  	dev->ops = &i2s_machine_dev_ops;
 96  }
 97  
 98  struct chip_operations drivers_amd_i2s_machine_dev_ops = {
 99  	.name = "AMD I2S Machine Device",
100  	.enable_dev = i2s_machine_dev_enable
101  };