blob: c4caccec5b98ae2ec69c3acc5220d2644935cc27 [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 Delco1245b1e2020-06-17 07:26:55 +053013#define SENSOR_NAME_UUID "822ace8f-2814-4174-a56b-5f029fe079ee"
14#define SENSOR_TYPE_UUID "26257549-9271-4ca4-bb43-c4899d5a4881"
15#define DEFAULT_ENDPOINT 0
16
Matt Delco964033f2020-06-17 12:49:43 +053017static uint32_t address_for_dev_type(const struct device *dev, uint8_t dev_type)
18{
19 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
20 uint16_t i2c_bus = dev->bus ? dev->bus->secondary : 0xFFFF;
21 uint16_t i2c_addr;
22
23 switch (dev_type) {
24 case DEV_TYPE_SENSOR:
25 i2c_addr = dev->path.i2c.device;
26 break;
27 case DEV_TYPE_VCM:
28 i2c_addr = config->vcm_address;
29 break;
30 case DEV_TYPE_ROM:
31 i2c_addr = config->rom_address;
32 break;
33 default:
34 return 0;
35 }
36
37 return (((uint32_t)i2c_bus) << 24 | ((uint32_t)i2c_addr) << 8 | dev_type);
38}
39
40static void camera_generate_dsm(const struct device *dev)
41{
42 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
43 int local1_ret = 1 + (config->ssdb.vcm_type ? 1 : 0) + (config->ssdb.rom_type ? 1 : 0);
44 int next_local1 = 1;
45 /* Method (_DSM, 4, NotSerialized) */
46 acpigen_write_method("_DSM", 4);
47
48 /* ToBuffer (Arg0, Local0) */
49 acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP);
50
51 /* If (LEqual (Local0, ToUUID(uuid))) */
52 acpigen_write_if();
53 acpigen_emit_byte(LEQUAL_OP);
54 acpigen_emit_byte(LOCAL0_OP);
55 acpigen_write_uuid(SENSOR_NAME_UUID);
56 acpigen_write_return_string(config->sensor_name ? config->sensor_name : "UNKNOWN");
57 acpigen_pop_len(); /* If */
58
59 /* If (LEqual (Local0, ToUUID(uuid))) */
60 acpigen_write_if();
61 acpigen_emit_byte(LEQUAL_OP);
62 acpigen_emit_byte(LOCAL0_OP);
63 acpigen_write_uuid(SENSOR_TYPE_UUID);
64 /* ToInteger (Arg2, Local1) */
65 acpigen_write_to_integer(ARG2_OP, LOCAL1_OP);
66
67 /* If (LEqual (Local1, 1)) */
68 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
69 acpigen_write_return_integer(local1_ret);
70 acpigen_pop_len(); /* If Arg2=1 */
71
72 /* If (LEqual (Local1, 2)) */
73 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
74 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_SENSOR));
75 acpigen_pop_len(); /* If Arg2=2 */
76
77 if (config->ssdb.vcm_type) {
78 /* If (LEqual (Local1, 3)) */
79 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
80 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_VCM));
81 acpigen_pop_len(); /* If Arg2=3 */
82 }
83
84 if (config->ssdb.rom_type) {
85 /* If (LEqual (Local1, 3 or 4)) */
86 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1);
87 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_ROM));
88 acpigen_pop_len(); /* If Arg2=3 or 4 */
89 }
90
91 acpigen_pop_len(); /* If uuid */
92
93 /* Return (Buffer (One) { 0x0 }) */
94 acpigen_write_return_singleton_buffer(0x0);
95
96 acpigen_pop_len(); /* Method _DSM */
97}
98
Matt Delco1245b1e2020-06-17 07:26:55 +053099static void camera_fill_sensor_defaults(struct drivers_intel_mipi_camera_config *config)
100{
101 if (config->disable_ssdb_defaults)
102 return;
103
104 if (!config->ssdb.platform)
105 config->ssdb.platform = PLATFORM_SKC;
106
107 if (!config->ssdb.flash_support)
108 config->ssdb.flash_support = FLASH_DISABLE;
109
110 if (!config->ssdb.privacy_led)
111 config->ssdb.privacy_led = PRIVACY_LED_A_16mA;
112
113 if (!config->ssdb.mipi_define)
114 config->ssdb.mipi_define = MIPI_INFO_ACPI_DEFINED;
115
116 if (!config->ssdb.mclk_speed)
117 config->ssdb.mclk_speed = CLK_FREQ_19_2MHZ;
118}
119
120/*
121 * Adds settings for a camera sensor device (typically at "\_SB.PCI0.I2Cx.CAMy"). The drivers
122 * for Linux tends to expect the camera sensor device and any related nvram / vcm devices to be
123 * separate ACPI devices, while the drivers for Windows want all of these to be grouped
124 * together in the camera sensor ACPI device. This implementation tries to satisfy both,
125 * though the unfortunate tradeoff is that the same I2C address for nvram and vcm is advertised
126 * by multiple devices in ACPI (via "_CRS"). The Windows driver can use the "_DSM" method to
127 * disambiguate the I2C resources in the camera sensor ACPI device. Drivers for Windows
128 * typically query "SSDB" for configuration information (represented as a binary blob dump of
129 * struct), while Linux drivers typically consult individual parameters in "_DSD".
130 *
131 * The tree of tables in "_DSD" is analogous to what's used for the "CIO2" device. The _DSD
132 * specifies a child table for the sensor's port (e.g., PRT0 for "port0"--this implementation
133 * assumes a camera only has 1 port). The PRT0 table specifies a table for each endpoint
134 * (though only 1 endpoint is supported by this implementation so the table only has an
135 * "endpoint0" that points to a EP00 table). The EP00 table primarily describes the # of lanes
136 * in "data-lines", a list of frequencies in "list-frequencies", and specifies the name of the
137 * other side in "remote-endpoint" (typically "\_SB.PCI0.CIO2").
138 */
139static void camera_fill_sensor(const struct device *dev)
140{
141 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
142 struct acpi_dp *ep00 = NULL;
143 struct acpi_dp *prt0 = NULL;
144 struct acpi_dp *dsd = NULL;
145 struct acpi_dp *remote = NULL;
146 const char *vcm_name = NULL;
147 struct acpi_dp *lens_focus = NULL;
148
149 camera_fill_sensor_defaults(config);
150
Matt Delco964033f2020-06-17 12:49:43 +0530151 /* _DSM */
152 camera_generate_dsm(dev);
153
Matt Delco1245b1e2020-06-17 07:26:55 +0530154 ep00 = acpi_dp_new_table("EP00");
155 acpi_dp_add_integer(ep00, "endpoint", DEFAULT_ENDPOINT);
156 acpi_dp_add_integer(ep00, "clock-lanes", 0);
157
158 if (config->ssdb.lanes_used > 0) {
159 struct acpi_dp *lanes = acpi_dp_new_table("data-lanes");
160 uint32_t i;
161 for (i = 1; i <= config->ssdb.lanes_used; ++i)
162 acpi_dp_add_integer(lanes, NULL, i);
163 acpi_dp_add_array(ep00, lanes);
164 }
165
166 if (config->num_freq_entries) {
167 struct acpi_dp *freq = acpi_dp_new_table("link-frequencies");
168 uint32_t i;
169 for (i = 0; i < config->num_freq_entries && i < MAX_LINK_FREQ_ENTRIES; ++i)
170 acpi_dp_add_integer(freq, NULL, config->link_freq[i]);
171 acpi_dp_add_array(ep00, freq);
172 }
173
174 remote = acpi_dp_new_table("remote-endpoint");
175
176 acpi_dp_add_reference(remote, NULL, config->remote_name);
177 acpi_dp_add_integer(remote, NULL, config->ssdb.link_used);
178 acpi_dp_add_integer(remote, NULL, DEFAULT_ENDPOINT);
179 acpi_dp_add_array(ep00, remote);
180
181 prt0 = acpi_dp_new_table("PRT0");
182
183 acpi_dp_add_integer(prt0, "port", 0);
184 acpi_dp_add_child(prt0, "endpoint0", ep00);
185 dsd = acpi_dp_new_table("_DSD");
186
187 acpi_dp_add_integer(dsd, "clock-frequency", config->ssdb.mclk_speed);
188
189 if (config->ssdb.degree)
190 acpi_dp_add_integer(dsd, "rotation", 180);
191
192 if (config->ssdb.vcm_type) {
193 if (config->vcm_name) {
194 vcm_name = config->vcm_name;
195 } else {
196 const struct device_path path = {
197 .type = DEVICE_PATH_I2C,
198 .i2c.device = config->vcm_address,
199 };
200 struct device *vcm_dev = find_dev_path(dev->bus, &path);
201 struct drivers_intel_mipi_camera_config *vcm_config;
202 vcm_config = vcm_dev ? vcm_dev->chip_info : NULL;
203
204 if (!vcm_config)
205 printk(BIOS_ERR, "Failed to get VCM\n");
206 else if (vcm_config->device_type != INTEL_ACPI_CAMERA_VCM)
207 printk(BIOS_ERR, "Device isn't VCM\n");
208 else
209 vcm_name = acpi_device_path(vcm_dev);
210 }
211 }
212
213 if (vcm_name) {
214 lens_focus = acpi_dp_new_table("lens-focus");
215 acpi_dp_add_reference(lens_focus, NULL, vcm_name);
216 acpi_dp_add_array(dsd, lens_focus);
217 }
218
219 acpi_dp_add_child(dsd, "port0", prt0);
220 acpi_dp_write(dsd);
221
222 acpigen_write_method_serialized("SSDB", 0);
223 acpigen_write_return_byte_buffer((uint8_t *)&config->ssdb, sizeof(config->ssdb));
224 acpigen_pop_len(); /* Method */
225
226 /* Fill Power Sequencing Data */
227 if (config->num_pwdb_entries > 0) {
228 acpigen_write_method_serialized("PWDB", 0);
229 acpigen_write_return_byte_buffer((uint8_t *)&config->pwdb,
230 sizeof(struct intel_pwdb) *
231 config->num_pwdb_entries);
232 acpigen_pop_len(); /* Method */
233 }
234}
235
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530236static void camera_fill_nvm(const struct device *dev)
237{
238 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
239 struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
240
241 /* It might be possible to default size or width based on type. */
242 if (!config->disable_nvm_defaults && !config->nvm_pagesize)
243 config->nvm_pagesize = 1;
244
245 if (!config->disable_nvm_defaults && !config->nvm_readonly)
246 config->nvm_readonly = 1;
247
248 if (config->nvm_size)
249 acpi_dp_add_integer(dsd, "size", config->nvm_size);
250
251 if (config->nvm_pagesize)
252 acpi_dp_add_integer(dsd, "pagesize", config->nvm_pagesize);
253
254 if (config->nvm_readonly)
255 acpi_dp_add_integer(dsd, "read-only", config->nvm_readonly);
256
257 if (config->nvm_width)
258 acpi_dp_add_integer(dsd, "address-width", config->nvm_width);
259
260 acpi_dp_write(dsd);
261}
262
263static void camera_fill_vcm(const struct device *dev)
264{
265 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
266 struct acpi_dp *dsd;
267
268 if (!config->vcm_compat)
269 return;
270
271 dsd = acpi_dp_new_table("_DSD");
272 acpi_dp_add_string(dsd, "compatible", config->vcm_compat);
273 acpi_dp_write(dsd);
274}
275
Matt Delco7d002932020-06-16 11:39:52 +0530276static void write_pci_camera_device(const struct device *dev)
V Sowmya9f8023a2017-02-28 17:52:05 +0530277{
278 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
Matt Delco7d002932020-06-16 11:39:52 +0530279
280 if (dev->path.type != DEVICE_PATH_PCI) {
281 printk(BIOS_ERR, "CIO2/IMGU devices require PCI\n");
282 return;
283 }
284
285 acpigen_write_device(acpi_device_name(dev));
286 acpigen_write_ADR_pci_device(dev);
287 acpigen_write_name_string("_DDN", config->device_type == INTEL_ACPI_CAMERA_CIO2 ?
288 "Camera and Imaging Subsystem" : "Imaging Unit");
289}
290
291static void write_i2c_camera_device(const struct device *dev, const char *scope)
292{
293 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
V Sowmya9f8023a2017-02-28 17:52:05 +0530294 struct acpi_i2c i2c = {
295 .address = dev->path.i2c.device,
296 .mode_10bit = dev->path.i2c.mode_10bit,
297 .speed = I2C_SPEED_FAST,
298 .resource = scope,
299 };
300
Matt Delco7d002932020-06-16 11:39:52 +0530301 if (dev->path.type != DEVICE_PATH_I2C) {
302 printk(BIOS_ERR, "Non-CIO2/IMGU devices require I2C\n");
V Sowmya9f8023a2017-02-28 17:52:05 +0530303 return;
Matt Delco7d002932020-06-16 11:39:52 +0530304 }
V Sowmya9f8023a2017-02-28 17:52:05 +0530305
V Sowmya9f8023a2017-02-28 17:52:05 +0530306 acpigen_write_device(acpi_device_name(dev));
Matt Delco7d002932020-06-16 11:39:52 +0530307
308 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR)
309 acpigen_write_name_integer("_ADR", 0);
310
311 if (config->acpi_hid)
312 acpigen_write_name_string("_HID", config->acpi_hid);
313 else if (config->device_type == INTEL_ACPI_CAMERA_VCM)
314 acpigen_write_name_string("_HID", ACPI_DT_NAMESPACE_HID);
315 else if (config->device_type == INTEL_ACPI_CAMERA_NVM)
316 acpigen_write_name_string("_HID", "INT3499");
317
V Sowmya9f8023a2017-02-28 17:52:05 +0530318 acpigen_write_name_integer("_UID", config->acpi_uid);
319 acpigen_write_name_string("_DDN", config->chip_name);
Hung-Te Linb4be50c2018-09-10 10:55:49 +0800320 acpigen_write_STA(acpi_device_status(dev));
V Sowmya9f8023a2017-02-28 17:52:05 +0530321
322 /* Resources */
323 acpigen_write_name("_CRS");
324 acpigen_write_resourcetemplate_header();
325 acpi_device_write_i2c(&i2c);
V Sowmya9f8023a2017-02-28 17:52:05 +0530326
Matt Delco7d002932020-06-16 11:39:52 +0530327 /*
328 * The optional vcm/nvram devices are presumed to be on the same I2C bus as the camera
329 * sensor.
330 */
331 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR &&
332 config->ssdb.vcm_type && config->vcm_address) {
333 struct acpi_i2c i2c_vcm = i2c;
334 i2c_vcm.address = config->vcm_address;
335 acpi_device_write_i2c(&i2c_vcm);
V Sowmya9f8023a2017-02-28 17:52:05 +0530336 }
337
Matt Delco7d002932020-06-16 11:39:52 +0530338 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR &&
339 config->ssdb.rom_type && config->rom_address) {
340 struct acpi_i2c i2c_rom = i2c;
341 i2c_rom.address = config->rom_address;
342 acpi_device_write_i2c(&i2c_rom);
343 }
344
345 acpigen_write_resourcetemplate_footer();
346}
347
348static void write_camera_device_common(const struct device *dev)
349{
350 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
351
352 /* Mark it as Camera related device */
353 if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
354 config->device_type == INTEL_ACPI_CAMERA_IMGU ||
355 config->device_type == INTEL_ACPI_CAMERA_SENSOR ||
356 config->device_type == INTEL_ACPI_CAMERA_VCM) {
357 acpigen_write_name_integer("CAMD", config->device_type);
358 }
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530359
360 switch (config->device_type) {
Matt Delco1245b1e2020-06-17 07:26:55 +0530361 case INTEL_ACPI_CAMERA_SENSOR:
362 camera_fill_sensor(dev);
363 break;
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530364 case INTEL_ACPI_CAMERA_VCM:
365 camera_fill_vcm(dev);
366 break;
367 case INTEL_ACPI_CAMERA_NVM:
368 camera_fill_nvm(dev);
369 break;
370 default:
371 break;
372 }
Matt Delco7d002932020-06-16 11:39:52 +0530373}
374
375static void camera_fill_ssdt(const struct device *dev)
376{
377 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
378 const char *scope = acpi_device_scope(dev);
379
380 if (!dev->enabled || !scope)
381 return;
382
383 /* Device */
384 acpigen_write_scope(scope);
385
386 if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
387 config->device_type == INTEL_ACPI_CAMERA_IMGU)
388 write_pci_camera_device(dev);
389 else
390 write_i2c_camera_device(dev, scope);
391
392 write_camera_device_common(dev);
V Sowmya9f8023a2017-02-28 17:52:05 +0530393
394 acpigen_pop_len(); /* Device */
395 acpigen_pop_len(); /* Scope */
Matt Delco7d002932020-06-16 11:39:52 +0530396
397 if (dev->path.type == DEVICE_PATH_PCI) {
398 printk(BIOS_INFO, "%s: %s PCI address 0%x\n", acpi_device_path(dev),
399 dev->chip_ops->name, dev->path.pci.devfn);
400 } else {
401 printk(BIOS_INFO, "%s: %s I2C address 0%xh\n", acpi_device_path(dev),
402 dev->chip_ops->name, dev->path.i2c.device);
403 }
V Sowmya9f8023a2017-02-28 17:52:05 +0530404}
405
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600406static const char *camera_acpi_name(const struct device *dev)
V Sowmya9f8023a2017-02-28 17:52:05 +0530407{
Matt Delco7d002932020-06-16 11:39:52 +0530408 const char *prefix = NULL;
409 static char name[5];
V Sowmya9f8023a2017-02-28 17:52:05 +0530410 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
Matt Delco7d002932020-06-16 11:39:52 +0530411
412 if (config->acpi_name)
413 return config->acpi_name;
414
415 switch (config->device_type) {
416 case INTEL_ACPI_CAMERA_CIO2:
417 return "CIO2";
418 case INTEL_ACPI_CAMERA_IMGU:
419 return "IMGU";
420 case INTEL_ACPI_CAMERA_PMIC:
421 return "PMIC";
422 case INTEL_ACPI_CAMERA_SENSOR:
423 prefix = "CAM";
424 break;
425 case INTEL_ACPI_CAMERA_VCM:
426 prefix = "VCM";
427 break;
428 case INTEL_ACPI_CAMERA_NVM:
429 prefix = "NVM";
430 break;
431 default:
432 printk(BIOS_ERR, "Invalid device type: %x\n", config->device_type);
433 return NULL;
434 }
435
436 /*
437 * The camera # knows which link # they use, so that's used as the basis for the
438 * instance #. The VCM and NVM don't have this information, so the best we can go on is
439 * the _UID.
440 */
441 snprintf(name, sizeof(name), "%s%1u", prefix,
442 config->device_type == INTEL_ACPI_CAMERA_SENSOR ?
443 config->ssdb.link_used : config->acpi_uid);
444 return name;
V Sowmya9f8023a2017-02-28 17:52:05 +0530445}
446
447static struct device_operations camera_ops = {
Nico Huber2f8ba692020-04-05 14:05:24 +0200448 .read_resources = noop_read_resources,
449 .set_resources = noop_set_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200450 .acpi_name = camera_acpi_name,
451 .acpi_fill_ssdt = camera_fill_ssdt,
V Sowmya9f8023a2017-02-28 17:52:05 +0530452};
453
454static void camera_enable(struct device *dev)
455{
456 dev->ops = &camera_ops;
457}
458
459struct chip_operations drivers_intel_mipi_camera_ops = {
460 CHIP_NAME("Intel MIPI Camera Device")
Elyes HAOUAS2aa3b162018-11-27 17:02:10 +0100461 .enable_dev = camera_enable
V Sowmya9f8023a2017-02-28 17:52:05 +0530462};