blob: 03e5ab65db90068b43b137147a4700f0f1254321 [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
Matt Delco879b3c12020-06-17 13:10:22 +05303#include <stdlib.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07004#include <acpi/acpi.h>
5#include <acpi/acpi_device.h>
6#include <acpi/acpigen.h>
V Sowmya9f8023a2017-02-28 17:52:05 +05307#include <console/console.h>
Nico Huber0f2dd1e2017-08-01 14:02:40 +02008#include <device/i2c_simple.h>
V Sowmya9f8023a2017-02-28 17:52:05 +05309#include <device/device.h>
10#include <device/path.h>
Matt Delco7d002932020-06-16 11:39:52 +053011#include <device/pci_def.h>
V Sowmya9f8023a2017-02-28 17:52:05 +053012#include "chip.h"
13
Matt Delco1245b1e2020-06-17 07:26:55 +053014#define SENSOR_NAME_UUID "822ace8f-2814-4174-a56b-5f029fe079ee"
15#define SENSOR_TYPE_UUID "26257549-9271-4ca4-bb43-c4899d5a4881"
16#define DEFAULT_ENDPOINT 0
Matt Delco879b3c12020-06-17 13:10:22 +053017#define DEFAULT_REMOTE_NAME "\\_SB.PCI0.CIO2"
18#define CIO2_PCI_DEV 0x14
19#define CIO2_PCI_FN 0x3
20
21/*
22 * This implementation assumes there is only 1 endpoint at each end of every data port. It also
23 * assumes there are no clock lanes. It also assumes that any VCM or NVM for a CAM is on the
24 * same I2C bus as the CAM.
25 */
26
27/*
28 * Adds settings for a CIO2 device (typically at "\_SB.PCI0.CIO2"). A _DSD is added that
29 * specifies a child table for each port (e.g., PRT0 for "port0" and PRT1 for "port1"). Each
30 * PRTx table specifies a table for each endpoint (though only 1 endpoint is supported by this
31 * implementation so the table only has an "endpoint0" that points to a EPx0 table). The EPx0
32 * table primarily describes the # of lanes in "data-lines" and specifies the name of the other
33 * side in "remote-endpoint" (the name is usually of the form "\_SB.PCI0.I2Cx.CAM0" for the
34 * first port/cam and "\_SB.PCI0.I2Cx.CAM1" if there's a second port/cam).
35 */
36static void camera_fill_cio2(const struct device *dev)
37{
38 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
39 struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
40 char *ep_table_name[MAX_PORT_ENTRIES] = {NULL};
41 char *port_table_name[MAX_PORT_ENTRIES] = {NULL};
42 char *port_name[MAX_PORT_ENTRIES] = {NULL};
43 unsigned int i, j;
44 char name[BUS_PATH_MAX];
45 struct acpi_dp *ep_table = NULL;
46 struct acpi_dp *port_table = NULL;
47 struct acpi_dp *remote = NULL;
48 struct acpi_dp *lanes = NULL;
49
50 for (i = 0; i < config->cio2_num_ports && i < MAX_PORT_ENTRIES; ++i) {
51 snprintf(name, sizeof(name), "EP%u0", i);
52 ep_table_name[i] = strdup(name);
53 ep_table = acpi_dp_new_table(ep_table_name[i]);
54 acpi_dp_add_integer(ep_table, "endpoint", 0);
55 acpi_dp_add_integer(ep_table, "clock-lanes", 0);
56
57 if (config->cio2_lanes_used[i] > 0) {
58 lanes = acpi_dp_new_table("data-lanes");
59
60 for (j = 1; j <= config->cio2_lanes_used[i] &&
61 j <= MAX_PORT_ENTRIES; ++j)
62 acpi_dp_add_integer(lanes, NULL, j);
63 acpi_dp_add_array(ep_table, lanes);
64 }
65
66 if (config->cio2_lane_endpoint[i]) {
67 remote = acpi_dp_new_table("remote-endpoint");
68 acpi_dp_add_reference(remote, NULL, config->cio2_lane_endpoint[i]);
69 acpi_dp_add_integer(remote, NULL, 0);
70 acpi_dp_add_integer(remote, NULL, 0);
71 acpi_dp_add_array(ep_table, remote);
72 }
73
74 snprintf(name, sizeof(name), "PRT%u", i);
75 port_table_name[i] = strdup(name);
76 port_table = acpi_dp_new_table(port_table_name[i]);
77 acpi_dp_add_integer(port_table, "port", config->cio2_prt[i]);
78 acpi_dp_add_child(port_table, "endpoint0", ep_table);
79
80 snprintf(name, sizeof(name), "port%u", i);
81 port_name[i] = strdup(name);
82 acpi_dp_add_child(dsd, port_name[i], port_table);
83 }
84
85 acpi_dp_write(dsd);
86
87 for (i = 0; i < config->cio2_num_ports; ++i) {
88 free(ep_table_name[i]);
89 free(port_table_name[i]);
90 free(port_name[i]);
91 }
92}
Matt Delco1245b1e2020-06-17 07:26:55 +053093
Matt Delco1ffee9d2020-06-17 12:55:35 +053094static void apply_pld_defaults(struct drivers_intel_mipi_camera_config *config)
95{
96 if (!config->pld.ignore_color)
97 config->pld.ignore_color = 1;
98
99 if (!config->pld.visible)
100 config->pld.visible = 1;
101
102 if (!config->pld.vertical_offset)
103 config->pld.vertical_offset = 0xffff;
104
105 if (!config->pld.horizontal_offset)
106 config->pld.horizontal_offset = 0xffff;
107
108 /*
109 * PLD_PANEL_TOP has a value of zero, so the following will change any instance of
110 * PLD_PANEL_TOP to PLD_PANEL_FRONT unless disable_pld_defaults is set.
111 */
112 if (!config->pld.panel)
113 config->pld.panel = PLD_PANEL_FRONT;
114
115 /*
116 * PLD_HORIZONTAL_POSITION_LEFT has a value of zero, so the following will change any
117 * instance of that value to PLD_HORIZONTAL_POSITION_CENTER unless disable_pld_defaults
118 * is set.
119 */
120 if (!config->pld.horizontal_position)
121 config->pld.horizontal_position = PLD_HORIZONTAL_POSITION_CENTER;
122
123 /*
124 * The desired default for |vertical_position| is PLD_VERTICAL_POSITION_UPPER, which
125 * has a value of zero so no work is needed to set a default. The same applies for
126 * setting |shape| to PLD_SHAPE_ROUND.
127 */
128}
129
130static void camera_generate_pld(const struct device *dev)
131{
132 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
133
134 if (config->use_pld) {
135 if (!config->disable_pld_defaults)
136 apply_pld_defaults(config);
137
138 acpigen_write_pld(&config->pld);
139 }
140}
141
Matt Delco964033f2020-06-17 12:49:43 +0530142static uint32_t address_for_dev_type(const struct device *dev, uint8_t dev_type)
143{
144 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
145 uint16_t i2c_bus = dev->bus ? dev->bus->secondary : 0xFFFF;
146 uint16_t i2c_addr;
147
148 switch (dev_type) {
149 case DEV_TYPE_SENSOR:
150 i2c_addr = dev->path.i2c.device;
151 break;
152 case DEV_TYPE_VCM:
153 i2c_addr = config->vcm_address;
154 break;
155 case DEV_TYPE_ROM:
156 i2c_addr = config->rom_address;
157 break;
158 default:
159 return 0;
160 }
161
162 return (((uint32_t)i2c_bus) << 24 | ((uint32_t)i2c_addr) << 8 | dev_type);
163}
164
165static void camera_generate_dsm(const struct device *dev)
166{
167 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
168 int local1_ret = 1 + (config->ssdb.vcm_type ? 1 : 0) + (config->ssdb.rom_type ? 1 : 0);
169 int next_local1 = 1;
170 /* Method (_DSM, 4, NotSerialized) */
171 acpigen_write_method("_DSM", 4);
172
173 /* ToBuffer (Arg0, Local0) */
174 acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP);
175
176 /* If (LEqual (Local0, ToUUID(uuid))) */
177 acpigen_write_if();
178 acpigen_emit_byte(LEQUAL_OP);
179 acpigen_emit_byte(LOCAL0_OP);
180 acpigen_write_uuid(SENSOR_NAME_UUID);
181 acpigen_write_return_string(config->sensor_name ? config->sensor_name : "UNKNOWN");
182 acpigen_pop_len(); /* If */
183
184 /* If (LEqual (Local0, ToUUID(uuid))) */
185 acpigen_write_if();
186 acpigen_emit_byte(LEQUAL_OP);
187 acpigen_emit_byte(LOCAL0_OP);
188 acpigen_write_uuid(SENSOR_TYPE_UUID);
189 /* ToInteger (Arg2, Local1) */
190 acpigen_write_to_integer(ARG2_OP, LOCAL1_OP);
191
192 /* If (LEqual (Local1, 1)) */
193 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
194 acpigen_write_return_integer(local1_ret);
195 acpigen_pop_len(); /* If Arg2=1 */
196
197 /* If (LEqual (Local1, 2)) */
198 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
199 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_SENSOR));
200 acpigen_pop_len(); /* If Arg2=2 */
201
202 if (config->ssdb.vcm_type) {
203 /* If (LEqual (Local1, 3)) */
204 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
205 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_VCM));
206 acpigen_pop_len(); /* If Arg2=3 */
207 }
208
209 if (config->ssdb.rom_type) {
210 /* If (LEqual (Local1, 3 or 4)) */
211 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1);
212 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_ROM));
213 acpigen_pop_len(); /* If Arg2=3 or 4 */
214 }
215
216 acpigen_pop_len(); /* If uuid */
217
218 /* Return (Buffer (One) { 0x0 }) */
219 acpigen_write_return_singleton_buffer(0x0);
220
221 acpigen_pop_len(); /* Method _DSM */
222}
223
Matt Delco879b3c12020-06-17 13:10:22 +0530224static void camera_fill_ssdb_defaults(struct drivers_intel_mipi_camera_config *config)
Matt Delco1245b1e2020-06-17 07:26:55 +0530225{
Matt Delco879b3c12020-06-17 13:10:22 +0530226 struct device *cio2 = pcidev_on_root(CIO2_PCI_DEV, CIO2_PCI_FN);
227 struct drivers_intel_mipi_camera_config *cio2_config;
228
Matt Delco1245b1e2020-06-17 07:26:55 +0530229 if (config->disable_ssdb_defaults)
230 return;
231
Matt Delco879b3c12020-06-17 13:10:22 +0530232 if (!config->ssdb.bdf_value)
233 config->ssdb.bdf_value = PCI_DEVFN(CIO2_PCI_DEV, CIO2_PCI_FN);
234
Matt Delco1245b1e2020-06-17 07:26:55 +0530235 if (!config->ssdb.platform)
236 config->ssdb.platform = PLATFORM_SKC;
237
238 if (!config->ssdb.flash_support)
239 config->ssdb.flash_support = FLASH_DISABLE;
240
241 if (!config->ssdb.privacy_led)
242 config->ssdb.privacy_led = PRIVACY_LED_A_16mA;
243
244 if (!config->ssdb.mipi_define)
245 config->ssdb.mipi_define = MIPI_INFO_ACPI_DEFINED;
246
247 if (!config->ssdb.mclk_speed)
248 config->ssdb.mclk_speed = CLK_FREQ_19_2MHZ;
Matt Delco879b3c12020-06-17 13:10:22 +0530249
250 if (!config->ssdb.lanes_used) {
251 cio2_config = cio2 ? cio2->chip_info : NULL;
252
253 if (!cio2_config) {
254 printk(BIOS_ERR, "Failed to get CIO2 config\n");
255 } else if (cio2_config->device_type != INTEL_ACPI_CAMERA_CIO2) {
256 printk(BIOS_ERR, "Device type isn't CIO2: %u\n",
257 (u32)cio2_config->device_type);
258 } else if (config->ssdb.link_used >= cio2_config->cio2_num_ports) {
259 printk(BIOS_ERR, "%u exceeds CIO2's %u links\n",
260 (u32)config->ssdb.link_used,
261 (u32)cio2_config->cio2_num_ports);
262 } else {
263 config->ssdb.lanes_used =
264 cio2_config->cio2_lanes_used[config->ssdb.link_used];
265 }
266 }
Matt Delco1245b1e2020-06-17 07:26:55 +0530267}
268
269/*
270 * Adds settings for a camera sensor device (typically at "\_SB.PCI0.I2Cx.CAMy"). The drivers
271 * for Linux tends to expect the camera sensor device and any related nvram / vcm devices to be
272 * separate ACPI devices, while the drivers for Windows want all of these to be grouped
273 * together in the camera sensor ACPI device. This implementation tries to satisfy both,
274 * though the unfortunate tradeoff is that the same I2C address for nvram and vcm is advertised
275 * by multiple devices in ACPI (via "_CRS"). The Windows driver can use the "_DSM" method to
276 * disambiguate the I2C resources in the camera sensor ACPI device. Drivers for Windows
277 * typically query "SSDB" for configuration information (represented as a binary blob dump of
278 * struct), while Linux drivers typically consult individual parameters in "_DSD".
279 *
280 * The tree of tables in "_DSD" is analogous to what's used for the "CIO2" device. The _DSD
281 * specifies a child table for the sensor's port (e.g., PRT0 for "port0"--this implementation
282 * assumes a camera only has 1 port). The PRT0 table specifies a table for each endpoint
283 * (though only 1 endpoint is supported by this implementation so the table only has an
284 * "endpoint0" that points to a EP00 table). The EP00 table primarily describes the # of lanes
285 * in "data-lines", a list of frequencies in "list-frequencies", and specifies the name of the
286 * other side in "remote-endpoint" (typically "\_SB.PCI0.CIO2").
287 */
288static void camera_fill_sensor(const struct device *dev)
289{
290 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
291 struct acpi_dp *ep00 = NULL;
292 struct acpi_dp *prt0 = NULL;
293 struct acpi_dp *dsd = NULL;
294 struct acpi_dp *remote = NULL;
295 const char *vcm_name = NULL;
296 struct acpi_dp *lens_focus = NULL;
Matt Delco879b3c12020-06-17 13:10:22 +0530297 const char *remote_name;
298 struct device *cio2 = pcidev_on_root(CIO2_PCI_DEV, CIO2_PCI_FN);
Matt Delco1245b1e2020-06-17 07:26:55 +0530299
Matt Delco1ffee9d2020-06-17 12:55:35 +0530300 camera_generate_pld(dev);
301
Matt Delco879b3c12020-06-17 13:10:22 +0530302 camera_fill_ssdb_defaults(config);
Matt Delco1245b1e2020-06-17 07:26:55 +0530303
Matt Delco964033f2020-06-17 12:49:43 +0530304 /* _DSM */
305 camera_generate_dsm(dev);
306
Matt Delco1245b1e2020-06-17 07:26:55 +0530307 ep00 = acpi_dp_new_table("EP00");
308 acpi_dp_add_integer(ep00, "endpoint", DEFAULT_ENDPOINT);
309 acpi_dp_add_integer(ep00, "clock-lanes", 0);
310
311 if (config->ssdb.lanes_used > 0) {
312 struct acpi_dp *lanes = acpi_dp_new_table("data-lanes");
313 uint32_t i;
314 for (i = 1; i <= config->ssdb.lanes_used; ++i)
315 acpi_dp_add_integer(lanes, NULL, i);
316 acpi_dp_add_array(ep00, lanes);
317 }
318
319 if (config->num_freq_entries) {
320 struct acpi_dp *freq = acpi_dp_new_table("link-frequencies");
321 uint32_t i;
322 for (i = 0; i < config->num_freq_entries && i < MAX_LINK_FREQ_ENTRIES; ++i)
323 acpi_dp_add_integer(freq, NULL, config->link_freq[i]);
324 acpi_dp_add_array(ep00, freq);
325 }
326
327 remote = acpi_dp_new_table("remote-endpoint");
328
Matt Delco879b3c12020-06-17 13:10:22 +0530329 if (config->remote_name) {
330 remote_name = config->remote_name;
331 } else {
332 if (cio2)
333 remote_name = acpi_device_path(cio2);
334 else
335 remote_name = DEFAULT_REMOTE_NAME;
336 }
337
338 acpi_dp_add_reference(remote, NULL, remote_name);
Matt Delco1245b1e2020-06-17 07:26:55 +0530339 acpi_dp_add_integer(remote, NULL, config->ssdb.link_used);
340 acpi_dp_add_integer(remote, NULL, DEFAULT_ENDPOINT);
341 acpi_dp_add_array(ep00, remote);
342
343 prt0 = acpi_dp_new_table("PRT0");
344
345 acpi_dp_add_integer(prt0, "port", 0);
346 acpi_dp_add_child(prt0, "endpoint0", ep00);
347 dsd = acpi_dp_new_table("_DSD");
348
349 acpi_dp_add_integer(dsd, "clock-frequency", config->ssdb.mclk_speed);
350
351 if (config->ssdb.degree)
352 acpi_dp_add_integer(dsd, "rotation", 180);
353
354 if (config->ssdb.vcm_type) {
355 if (config->vcm_name) {
356 vcm_name = config->vcm_name;
357 } else {
358 const struct device_path path = {
359 .type = DEVICE_PATH_I2C,
360 .i2c.device = config->vcm_address,
361 };
362 struct device *vcm_dev = find_dev_path(dev->bus, &path);
363 struct drivers_intel_mipi_camera_config *vcm_config;
364 vcm_config = vcm_dev ? vcm_dev->chip_info : NULL;
365
366 if (!vcm_config)
367 printk(BIOS_ERR, "Failed to get VCM\n");
368 else if (vcm_config->device_type != INTEL_ACPI_CAMERA_VCM)
369 printk(BIOS_ERR, "Device isn't VCM\n");
370 else
371 vcm_name = acpi_device_path(vcm_dev);
372 }
373 }
374
375 if (vcm_name) {
376 lens_focus = acpi_dp_new_table("lens-focus");
377 acpi_dp_add_reference(lens_focus, NULL, vcm_name);
378 acpi_dp_add_array(dsd, lens_focus);
379 }
380
381 acpi_dp_add_child(dsd, "port0", prt0);
382 acpi_dp_write(dsd);
383
384 acpigen_write_method_serialized("SSDB", 0);
385 acpigen_write_return_byte_buffer((uint8_t *)&config->ssdb, sizeof(config->ssdb));
386 acpigen_pop_len(); /* Method */
387
388 /* Fill Power Sequencing Data */
389 if (config->num_pwdb_entries > 0) {
390 acpigen_write_method_serialized("PWDB", 0);
391 acpigen_write_return_byte_buffer((uint8_t *)&config->pwdb,
392 sizeof(struct intel_pwdb) *
393 config->num_pwdb_entries);
394 acpigen_pop_len(); /* Method */
395 }
396}
397
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530398static void camera_fill_nvm(const struct device *dev)
399{
400 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
401 struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
402
403 /* It might be possible to default size or width based on type. */
404 if (!config->disable_nvm_defaults && !config->nvm_pagesize)
405 config->nvm_pagesize = 1;
406
407 if (!config->disable_nvm_defaults && !config->nvm_readonly)
408 config->nvm_readonly = 1;
409
410 if (config->nvm_size)
411 acpi_dp_add_integer(dsd, "size", config->nvm_size);
412
413 if (config->nvm_pagesize)
414 acpi_dp_add_integer(dsd, "pagesize", config->nvm_pagesize);
415
416 if (config->nvm_readonly)
417 acpi_dp_add_integer(dsd, "read-only", config->nvm_readonly);
418
419 if (config->nvm_width)
420 acpi_dp_add_integer(dsd, "address-width", config->nvm_width);
421
422 acpi_dp_write(dsd);
423}
424
425static void camera_fill_vcm(const struct device *dev)
426{
427 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
428 struct acpi_dp *dsd;
429
430 if (!config->vcm_compat)
431 return;
432
433 dsd = acpi_dp_new_table("_DSD");
434 acpi_dp_add_string(dsd, "compatible", config->vcm_compat);
435 acpi_dp_write(dsd);
436}
437
Matt Delco7d002932020-06-16 11:39:52 +0530438static void write_pci_camera_device(const struct device *dev)
V Sowmya9f8023a2017-02-28 17:52:05 +0530439{
440 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
Matt Delco7d002932020-06-16 11:39:52 +0530441
442 if (dev->path.type != DEVICE_PATH_PCI) {
443 printk(BIOS_ERR, "CIO2/IMGU devices require PCI\n");
444 return;
445 }
446
447 acpigen_write_device(acpi_device_name(dev));
448 acpigen_write_ADR_pci_device(dev);
449 acpigen_write_name_string("_DDN", config->device_type == INTEL_ACPI_CAMERA_CIO2 ?
450 "Camera and Imaging Subsystem" : "Imaging Unit");
451}
452
453static void write_i2c_camera_device(const struct device *dev, const char *scope)
454{
455 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
V Sowmya9f8023a2017-02-28 17:52:05 +0530456 struct acpi_i2c i2c = {
457 .address = dev->path.i2c.device,
458 .mode_10bit = dev->path.i2c.mode_10bit,
459 .speed = I2C_SPEED_FAST,
460 .resource = scope,
461 };
462
Matt Delco7d002932020-06-16 11:39:52 +0530463 if (dev->path.type != DEVICE_PATH_I2C) {
464 printk(BIOS_ERR, "Non-CIO2/IMGU devices require I2C\n");
V Sowmya9f8023a2017-02-28 17:52:05 +0530465 return;
Matt Delco7d002932020-06-16 11:39:52 +0530466 }
V Sowmya9f8023a2017-02-28 17:52:05 +0530467
V Sowmya9f8023a2017-02-28 17:52:05 +0530468 acpigen_write_device(acpi_device_name(dev));
Matt Delco7d002932020-06-16 11:39:52 +0530469
470 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR)
471 acpigen_write_name_integer("_ADR", 0);
472
473 if (config->acpi_hid)
474 acpigen_write_name_string("_HID", config->acpi_hid);
475 else if (config->device_type == INTEL_ACPI_CAMERA_VCM)
476 acpigen_write_name_string("_HID", ACPI_DT_NAMESPACE_HID);
477 else if (config->device_type == INTEL_ACPI_CAMERA_NVM)
478 acpigen_write_name_string("_HID", "INT3499");
479
V Sowmya9f8023a2017-02-28 17:52:05 +0530480 acpigen_write_name_integer("_UID", config->acpi_uid);
481 acpigen_write_name_string("_DDN", config->chip_name);
Hung-Te Linb4be50c2018-09-10 10:55:49 +0800482 acpigen_write_STA(acpi_device_status(dev));
V Sowmya9f8023a2017-02-28 17:52:05 +0530483
484 /* Resources */
485 acpigen_write_name("_CRS");
486 acpigen_write_resourcetemplate_header();
487 acpi_device_write_i2c(&i2c);
V Sowmya9f8023a2017-02-28 17:52:05 +0530488
Matt Delco7d002932020-06-16 11:39:52 +0530489 /*
490 * The optional vcm/nvram devices are presumed to be on the same I2C bus as the camera
491 * sensor.
492 */
493 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR &&
494 config->ssdb.vcm_type && config->vcm_address) {
495 struct acpi_i2c i2c_vcm = i2c;
496 i2c_vcm.address = config->vcm_address;
497 acpi_device_write_i2c(&i2c_vcm);
V Sowmya9f8023a2017-02-28 17:52:05 +0530498 }
499
Matt Delco7d002932020-06-16 11:39:52 +0530500 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR &&
501 config->ssdb.rom_type && config->rom_address) {
502 struct acpi_i2c i2c_rom = i2c;
503 i2c_rom.address = config->rom_address;
504 acpi_device_write_i2c(&i2c_rom);
505 }
506
507 acpigen_write_resourcetemplate_footer();
508}
509
510static void write_camera_device_common(const struct device *dev)
511{
512 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
513
514 /* Mark it as Camera related device */
515 if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
516 config->device_type == INTEL_ACPI_CAMERA_IMGU ||
517 config->device_type == INTEL_ACPI_CAMERA_SENSOR ||
518 config->device_type == INTEL_ACPI_CAMERA_VCM) {
519 acpigen_write_name_integer("CAMD", config->device_type);
520 }
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530521
522 switch (config->device_type) {
Matt Delco879b3c12020-06-17 13:10:22 +0530523 case INTEL_ACPI_CAMERA_CIO2:
524 camera_fill_cio2(dev);
525 break;
Matt Delco1245b1e2020-06-17 07:26:55 +0530526 case INTEL_ACPI_CAMERA_SENSOR:
527 camera_fill_sensor(dev);
528 break;
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530529 case INTEL_ACPI_CAMERA_VCM:
530 camera_fill_vcm(dev);
531 break;
532 case INTEL_ACPI_CAMERA_NVM:
533 camera_fill_nvm(dev);
534 break;
535 default:
536 break;
537 }
Matt Delco7d002932020-06-16 11:39:52 +0530538}
539
540static void camera_fill_ssdt(const struct device *dev)
541{
542 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
543 const char *scope = acpi_device_scope(dev);
544
545 if (!dev->enabled || !scope)
546 return;
547
548 /* Device */
549 acpigen_write_scope(scope);
550
551 if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
552 config->device_type == INTEL_ACPI_CAMERA_IMGU)
553 write_pci_camera_device(dev);
554 else
555 write_i2c_camera_device(dev, scope);
556
557 write_camera_device_common(dev);
V Sowmya9f8023a2017-02-28 17:52:05 +0530558
559 acpigen_pop_len(); /* Device */
560 acpigen_pop_len(); /* Scope */
Matt Delco7d002932020-06-16 11:39:52 +0530561
562 if (dev->path.type == DEVICE_PATH_PCI) {
563 printk(BIOS_INFO, "%s: %s PCI address 0%x\n", acpi_device_path(dev),
564 dev->chip_ops->name, dev->path.pci.devfn);
565 } else {
566 printk(BIOS_INFO, "%s: %s I2C address 0%xh\n", acpi_device_path(dev),
567 dev->chip_ops->name, dev->path.i2c.device);
568 }
V Sowmya9f8023a2017-02-28 17:52:05 +0530569}
570
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600571static const char *camera_acpi_name(const struct device *dev)
V Sowmya9f8023a2017-02-28 17:52:05 +0530572{
Matt Delco7d002932020-06-16 11:39:52 +0530573 const char *prefix = NULL;
574 static char name[5];
V Sowmya9f8023a2017-02-28 17:52:05 +0530575 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
Matt Delco7d002932020-06-16 11:39:52 +0530576
577 if (config->acpi_name)
578 return config->acpi_name;
579
580 switch (config->device_type) {
581 case INTEL_ACPI_CAMERA_CIO2:
582 return "CIO2";
583 case INTEL_ACPI_CAMERA_IMGU:
584 return "IMGU";
585 case INTEL_ACPI_CAMERA_PMIC:
586 return "PMIC";
587 case INTEL_ACPI_CAMERA_SENSOR:
588 prefix = "CAM";
589 break;
590 case INTEL_ACPI_CAMERA_VCM:
591 prefix = "VCM";
592 break;
593 case INTEL_ACPI_CAMERA_NVM:
594 prefix = "NVM";
595 break;
596 default:
597 printk(BIOS_ERR, "Invalid device type: %x\n", config->device_type);
598 return NULL;
599 }
600
601 /*
602 * The camera # knows which link # they use, so that's used as the basis for the
603 * instance #. The VCM and NVM don't have this information, so the best we can go on is
604 * the _UID.
605 */
606 snprintf(name, sizeof(name), "%s%1u", prefix,
607 config->device_type == INTEL_ACPI_CAMERA_SENSOR ?
608 config->ssdb.link_used : config->acpi_uid);
609 return name;
V Sowmya9f8023a2017-02-28 17:52:05 +0530610}
611
612static struct device_operations camera_ops = {
Nico Huber2f8ba692020-04-05 14:05:24 +0200613 .read_resources = noop_read_resources,
614 .set_resources = noop_set_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200615 .acpi_name = camera_acpi_name,
616 .acpi_fill_ssdt = camera_fill_ssdt,
V Sowmya9f8023a2017-02-28 17:52:05 +0530617};
618
619static void camera_enable(struct device *dev)
620{
621 dev->ops = &camera_ops;
622}
623
624struct chip_operations drivers_intel_mipi_camera_ops = {
625 CHIP_NAME("Intel MIPI Camera Device")
Elyes HAOUAS2aa3b162018-11-27 17:02:10 +0100626 .enable_dev = camera_enable
V Sowmya9f8023a2017-02-28 17:52:05 +0530627};