blob: 4356b0a602abcf3c00120002dfc2955a2beb6599 [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
V Sowmya9f8023a2017-02-28 17:52:05 +05302
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
4#include <acpi/acpi_device.h>
5#include <acpi/acpigen.h>
V Sowmya9f8023a2017-02-28 17:52:05 +05306#include <console/console.h>
Nico Huber0f2dd1e2017-08-01 14:02:40 +02007#include <device/i2c_simple.h>
V Sowmya9f8023a2017-02-28 17:52:05 +05308#include <device/device.h>
9#include <device/path.h>
Matt Delco7d002932020-06-16 11:39:52 +053010#include <device/pci_def.h>
V Sowmya9f8023a2017-02-28 17:52:05 +053011#include "chip.h"
12
Matt Delco7d002932020-06-16 11:39:52 +053013static void write_pci_camera_device(const struct device *dev)
V Sowmya9f8023a2017-02-28 17:52:05 +053014{
15 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
Matt Delco7d002932020-06-16 11:39:52 +053016
17 if (dev->path.type != DEVICE_PATH_PCI) {
18 printk(BIOS_ERR, "CIO2/IMGU devices require PCI\n");
19 return;
20 }
21
22 acpigen_write_device(acpi_device_name(dev));
23 acpigen_write_ADR_pci_device(dev);
24 acpigen_write_name_string("_DDN", config->device_type == INTEL_ACPI_CAMERA_CIO2 ?
25 "Camera and Imaging Subsystem" : "Imaging Unit");
26}
27
28static void write_i2c_camera_device(const struct device *dev, const char *scope)
29{
30 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
V Sowmya9f8023a2017-02-28 17:52:05 +053031 struct acpi_i2c i2c = {
32 .address = dev->path.i2c.device,
33 .mode_10bit = dev->path.i2c.mode_10bit,
34 .speed = I2C_SPEED_FAST,
35 .resource = scope,
36 };
37
Matt Delco7d002932020-06-16 11:39:52 +053038 if (dev->path.type != DEVICE_PATH_I2C) {
39 printk(BIOS_ERR, "Non-CIO2/IMGU devices require I2C\n");
V Sowmya9f8023a2017-02-28 17:52:05 +053040 return;
Matt Delco7d002932020-06-16 11:39:52 +053041 }
V Sowmya9f8023a2017-02-28 17:52:05 +053042
V Sowmya9f8023a2017-02-28 17:52:05 +053043 acpigen_write_device(acpi_device_name(dev));
Matt Delco7d002932020-06-16 11:39:52 +053044
45 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR)
46 acpigen_write_name_integer("_ADR", 0);
47
48 if (config->acpi_hid)
49 acpigen_write_name_string("_HID", config->acpi_hid);
50 else if (config->device_type == INTEL_ACPI_CAMERA_VCM)
51 acpigen_write_name_string("_HID", ACPI_DT_NAMESPACE_HID);
52 else if (config->device_type == INTEL_ACPI_CAMERA_NVM)
53 acpigen_write_name_string("_HID", "INT3499");
54
V Sowmya9f8023a2017-02-28 17:52:05 +053055 acpigen_write_name_integer("_UID", config->acpi_uid);
56 acpigen_write_name_string("_DDN", config->chip_name);
Hung-Te Linb4be50c2018-09-10 10:55:49 +080057 acpigen_write_STA(acpi_device_status(dev));
V Sowmya9f8023a2017-02-28 17:52:05 +053058
59 /* Resources */
60 acpigen_write_name("_CRS");
61 acpigen_write_resourcetemplate_header();
62 acpi_device_write_i2c(&i2c);
V Sowmya9f8023a2017-02-28 17:52:05 +053063
Matt Delco7d002932020-06-16 11:39:52 +053064 /*
65 * The optional vcm/nvram devices are presumed to be on the same I2C bus as the camera
66 * sensor.
67 */
68 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR &&
69 config->ssdb.vcm_type && config->vcm_address) {
70 struct acpi_i2c i2c_vcm = i2c;
71 i2c_vcm.address = config->vcm_address;
72 acpi_device_write_i2c(&i2c_vcm);
V Sowmya9f8023a2017-02-28 17:52:05 +053073 }
74
Matt Delco7d002932020-06-16 11:39:52 +053075 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR &&
76 config->ssdb.rom_type && config->rom_address) {
77 struct acpi_i2c i2c_rom = i2c;
78 i2c_rom.address = config->rom_address;
79 acpi_device_write_i2c(&i2c_rom);
80 }
81
82 acpigen_write_resourcetemplate_footer();
83}
84
85static void write_camera_device_common(const struct device *dev)
86{
87 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
88
89 /* Mark it as Camera related device */
90 if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
91 config->device_type == INTEL_ACPI_CAMERA_IMGU ||
92 config->device_type == INTEL_ACPI_CAMERA_SENSOR ||
93 config->device_type == INTEL_ACPI_CAMERA_VCM) {
94 acpigen_write_name_integer("CAMD", config->device_type);
95 }
96}
97
98static void camera_fill_ssdt(const struct device *dev)
99{
100 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
101 const char *scope = acpi_device_scope(dev);
102
103 if (!dev->enabled || !scope)
104 return;
105
106 /* Device */
107 acpigen_write_scope(scope);
108
109 if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
110 config->device_type == INTEL_ACPI_CAMERA_IMGU)
111 write_pci_camera_device(dev);
112 else
113 write_i2c_camera_device(dev, scope);
114
115 write_camera_device_common(dev);
V Sowmya9f8023a2017-02-28 17:52:05 +0530116
117 acpigen_pop_len(); /* Device */
118 acpigen_pop_len(); /* Scope */
Matt Delco7d002932020-06-16 11:39:52 +0530119
120 if (dev->path.type == DEVICE_PATH_PCI) {
121 printk(BIOS_INFO, "%s: %s PCI address 0%x\n", acpi_device_path(dev),
122 dev->chip_ops->name, dev->path.pci.devfn);
123 } else {
124 printk(BIOS_INFO, "%s: %s I2C address 0%xh\n", acpi_device_path(dev),
125 dev->chip_ops->name, dev->path.i2c.device);
126 }
V Sowmya9f8023a2017-02-28 17:52:05 +0530127}
128
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600129static const char *camera_acpi_name(const struct device *dev)
V Sowmya9f8023a2017-02-28 17:52:05 +0530130{
Matt Delco7d002932020-06-16 11:39:52 +0530131 const char *prefix = NULL;
132 static char name[5];
V Sowmya9f8023a2017-02-28 17:52:05 +0530133 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
Matt Delco7d002932020-06-16 11:39:52 +0530134
135 if (config->acpi_name)
136 return config->acpi_name;
137
138 switch (config->device_type) {
139 case INTEL_ACPI_CAMERA_CIO2:
140 return "CIO2";
141 case INTEL_ACPI_CAMERA_IMGU:
142 return "IMGU";
143 case INTEL_ACPI_CAMERA_PMIC:
144 return "PMIC";
145 case INTEL_ACPI_CAMERA_SENSOR:
146 prefix = "CAM";
147 break;
148 case INTEL_ACPI_CAMERA_VCM:
149 prefix = "VCM";
150 break;
151 case INTEL_ACPI_CAMERA_NVM:
152 prefix = "NVM";
153 break;
154 default:
155 printk(BIOS_ERR, "Invalid device type: %x\n", config->device_type);
156 return NULL;
157 }
158
159 /*
160 * The camera # knows which link # they use, so that's used as the basis for the
161 * instance #. The VCM and NVM don't have this information, so the best we can go on is
162 * the _UID.
163 */
164 snprintf(name, sizeof(name), "%s%1u", prefix,
165 config->device_type == INTEL_ACPI_CAMERA_SENSOR ?
166 config->ssdb.link_used : config->acpi_uid);
167 return name;
V Sowmya9f8023a2017-02-28 17:52:05 +0530168}
169
170static struct device_operations camera_ops = {
Nico Huber2f8ba692020-04-05 14:05:24 +0200171 .read_resources = noop_read_resources,
172 .set_resources = noop_set_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200173 .acpi_name = camera_acpi_name,
174 .acpi_fill_ssdt = camera_fill_ssdt,
V Sowmya9f8023a2017-02-28 17:52:05 +0530175};
176
177static void camera_enable(struct device *dev)
178{
179 dev->ops = &camera_ops;
180}
181
182struct chip_operations drivers_intel_mipi_camera_ops = {
183 CHIP_NAME("Intel MIPI Camera Device")
Elyes HAOUAS2aa3b162018-11-27 17:02:10 +0100184 .enable_dev = camera_enable
V Sowmya9f8023a2017-02-28 17:52:05 +0530185};