blob: f32f744f8f3561c186ea8f0b5f177bb95ce74a6f [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
Sugnan Prabhu Sb087a942020-05-21 20:41:03 +053020#define POWER_RESOURCE_NAME "PRIC"
Matt Delco879b3c12020-06-17 13:10:22 +053021
22/*
23 * This implementation assumes there is only 1 endpoint at each end of every data port. It also
24 * assumes there are no clock lanes. It also assumes that any VCM or NVM for a CAM is on the
25 * same I2C bus as the CAM.
26 */
27
28/*
29 * Adds settings for a CIO2 device (typically at "\_SB.PCI0.CIO2"). A _DSD is added that
30 * specifies a child table for each port (e.g., PRT0 for "port0" and PRT1 for "port1"). Each
31 * PRTx table specifies a table for each endpoint (though only 1 endpoint is supported by this
32 * implementation so the table only has an "endpoint0" that points to a EPx0 table). The EPx0
33 * table primarily describes the # of lanes in "data-lines" and specifies the name of the other
34 * side in "remote-endpoint" (the name is usually of the form "\_SB.PCI0.I2Cx.CAM0" for the
35 * first port/cam and "\_SB.PCI0.I2Cx.CAM1" if there's a second port/cam).
36 */
37static void camera_fill_cio2(const struct device *dev)
38{
39 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
40 struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
41 char *ep_table_name[MAX_PORT_ENTRIES] = {NULL};
42 char *port_table_name[MAX_PORT_ENTRIES] = {NULL};
43 char *port_name[MAX_PORT_ENTRIES] = {NULL};
44 unsigned int i, j;
45 char name[BUS_PATH_MAX];
46 struct acpi_dp *ep_table = NULL;
47 struct acpi_dp *port_table = NULL;
48 struct acpi_dp *remote = NULL;
49 struct acpi_dp *lanes = NULL;
50
51 for (i = 0; i < config->cio2_num_ports && i < MAX_PORT_ENTRIES; ++i) {
52 snprintf(name, sizeof(name), "EP%u0", i);
53 ep_table_name[i] = strdup(name);
54 ep_table = acpi_dp_new_table(ep_table_name[i]);
55 acpi_dp_add_integer(ep_table, "endpoint", 0);
56 acpi_dp_add_integer(ep_table, "clock-lanes", 0);
57
58 if (config->cio2_lanes_used[i] > 0) {
59 lanes = acpi_dp_new_table("data-lanes");
60
61 for (j = 1; j <= config->cio2_lanes_used[i] &&
62 j <= MAX_PORT_ENTRIES; ++j)
63 acpi_dp_add_integer(lanes, NULL, j);
64 acpi_dp_add_array(ep_table, lanes);
65 }
66
67 if (config->cio2_lane_endpoint[i]) {
68 remote = acpi_dp_new_table("remote-endpoint");
69 acpi_dp_add_reference(remote, NULL, config->cio2_lane_endpoint[i]);
70 acpi_dp_add_integer(remote, NULL, 0);
71 acpi_dp_add_integer(remote, NULL, 0);
72 acpi_dp_add_array(ep_table, remote);
73 }
74
75 snprintf(name, sizeof(name), "PRT%u", i);
76 port_table_name[i] = strdup(name);
77 port_table = acpi_dp_new_table(port_table_name[i]);
78 acpi_dp_add_integer(port_table, "port", config->cio2_prt[i]);
79 acpi_dp_add_child(port_table, "endpoint0", ep_table);
80
81 snprintf(name, sizeof(name), "port%u", i);
82 port_name[i] = strdup(name);
83 acpi_dp_add_child(dsd, port_name[i], port_table);
84 }
85
86 acpi_dp_write(dsd);
87
88 for (i = 0; i < config->cio2_num_ports; ++i) {
89 free(ep_table_name[i]);
90 free(port_table_name[i]);
91 free(port_name[i]);
92 }
93}
Matt Delco1245b1e2020-06-17 07:26:55 +053094
Matt Delco1ffee9d2020-06-17 12:55:35 +053095static void apply_pld_defaults(struct drivers_intel_mipi_camera_config *config)
96{
97 if (!config->pld.ignore_color)
98 config->pld.ignore_color = 1;
99
100 if (!config->pld.visible)
101 config->pld.visible = 1;
102
103 if (!config->pld.vertical_offset)
104 config->pld.vertical_offset = 0xffff;
105
106 if (!config->pld.horizontal_offset)
107 config->pld.horizontal_offset = 0xffff;
108
109 /*
110 * PLD_PANEL_TOP has a value of zero, so the following will change any instance of
111 * PLD_PANEL_TOP to PLD_PANEL_FRONT unless disable_pld_defaults is set.
112 */
113 if (!config->pld.panel)
114 config->pld.panel = PLD_PANEL_FRONT;
115
116 /*
117 * PLD_HORIZONTAL_POSITION_LEFT has a value of zero, so the following will change any
118 * instance of that value to PLD_HORIZONTAL_POSITION_CENTER unless disable_pld_defaults
119 * is set.
120 */
121 if (!config->pld.horizontal_position)
122 config->pld.horizontal_position = PLD_HORIZONTAL_POSITION_CENTER;
123
124 /*
125 * The desired default for |vertical_position| is PLD_VERTICAL_POSITION_UPPER, which
126 * has a value of zero so no work is needed to set a default. The same applies for
127 * setting |shape| to PLD_SHAPE_ROUND.
128 */
129}
130
131static void camera_generate_pld(const struct device *dev)
132{
133 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
134
135 if (config->use_pld) {
136 if (!config->disable_pld_defaults)
137 apply_pld_defaults(config);
138
139 acpigen_write_pld(&config->pld);
140 }
141}
142
Matt Delco964033f2020-06-17 12:49:43 +0530143static uint32_t address_for_dev_type(const struct device *dev, uint8_t dev_type)
144{
145 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
146 uint16_t i2c_bus = dev->bus ? dev->bus->secondary : 0xFFFF;
147 uint16_t i2c_addr;
148
149 switch (dev_type) {
150 case DEV_TYPE_SENSOR:
151 i2c_addr = dev->path.i2c.device;
152 break;
153 case DEV_TYPE_VCM:
154 i2c_addr = config->vcm_address;
155 break;
156 case DEV_TYPE_ROM:
157 i2c_addr = config->rom_address;
158 break;
159 default:
160 return 0;
161 }
162
163 return (((uint32_t)i2c_bus) << 24 | ((uint32_t)i2c_addr) << 8 | dev_type);
164}
165
166static void camera_generate_dsm(const struct device *dev)
167{
168 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
169 int local1_ret = 1 + (config->ssdb.vcm_type ? 1 : 0) + (config->ssdb.rom_type ? 1 : 0);
170 int next_local1 = 1;
171 /* Method (_DSM, 4, NotSerialized) */
172 acpigen_write_method("_DSM", 4);
173
174 /* ToBuffer (Arg0, Local0) */
175 acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP);
176
177 /* If (LEqual (Local0, ToUUID(uuid))) */
178 acpigen_write_if();
179 acpigen_emit_byte(LEQUAL_OP);
180 acpigen_emit_byte(LOCAL0_OP);
181 acpigen_write_uuid(SENSOR_NAME_UUID);
182 acpigen_write_return_string(config->sensor_name ? config->sensor_name : "UNKNOWN");
183 acpigen_pop_len(); /* If */
184
185 /* If (LEqual (Local0, ToUUID(uuid))) */
186 acpigen_write_if();
187 acpigen_emit_byte(LEQUAL_OP);
188 acpigen_emit_byte(LOCAL0_OP);
189 acpigen_write_uuid(SENSOR_TYPE_UUID);
190 /* ToInteger (Arg2, Local1) */
191 acpigen_write_to_integer(ARG2_OP, LOCAL1_OP);
192
193 /* If (LEqual (Local1, 1)) */
194 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
195 acpigen_write_return_integer(local1_ret);
196 acpigen_pop_len(); /* If Arg2=1 */
197
198 /* If (LEqual (Local1, 2)) */
199 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
200 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_SENSOR));
201 acpigen_pop_len(); /* If Arg2=2 */
202
203 if (config->ssdb.vcm_type) {
204 /* If (LEqual (Local1, 3)) */
205 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1++);
206 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_VCM));
207 acpigen_pop_len(); /* If Arg2=3 */
208 }
209
210 if (config->ssdb.rom_type) {
211 /* If (LEqual (Local1, 3 or 4)) */
212 acpigen_write_if_lequal_op_int(LOCAL1_OP, next_local1);
213 acpigen_write_return_integer(address_for_dev_type(dev, DEV_TYPE_ROM));
214 acpigen_pop_len(); /* If Arg2=3 or 4 */
215 }
216
217 acpigen_pop_len(); /* If uuid */
218
219 /* Return (Buffer (One) { 0x0 }) */
220 acpigen_write_return_singleton_buffer(0x0);
221
222 acpigen_pop_len(); /* Method _DSM */
223}
224
Matt Delco879b3c12020-06-17 13:10:22 +0530225static void camera_fill_ssdb_defaults(struct drivers_intel_mipi_camera_config *config)
Matt Delco1245b1e2020-06-17 07:26:55 +0530226{
Matt Delco879b3c12020-06-17 13:10:22 +0530227 struct device *cio2 = pcidev_on_root(CIO2_PCI_DEV, CIO2_PCI_FN);
228 struct drivers_intel_mipi_camera_config *cio2_config;
229
Matt Delco1245b1e2020-06-17 07:26:55 +0530230 if (config->disable_ssdb_defaults)
231 return;
232
Matt Delco879b3c12020-06-17 13:10:22 +0530233 if (!config->ssdb.bdf_value)
234 config->ssdb.bdf_value = PCI_DEVFN(CIO2_PCI_DEV, CIO2_PCI_FN);
235
Matt Delco1245b1e2020-06-17 07:26:55 +0530236 if (!config->ssdb.platform)
237 config->ssdb.platform = PLATFORM_SKC;
238
239 if (!config->ssdb.flash_support)
240 config->ssdb.flash_support = FLASH_DISABLE;
241
242 if (!config->ssdb.privacy_led)
243 config->ssdb.privacy_led = PRIVACY_LED_A_16mA;
244
245 if (!config->ssdb.mipi_define)
246 config->ssdb.mipi_define = MIPI_INFO_ACPI_DEFINED;
247
248 if (!config->ssdb.mclk_speed)
249 config->ssdb.mclk_speed = CLK_FREQ_19_2MHZ;
Matt Delco879b3c12020-06-17 13:10:22 +0530250
251 if (!config->ssdb.lanes_used) {
252 cio2_config = cio2 ? cio2->chip_info : NULL;
253
254 if (!cio2_config) {
255 printk(BIOS_ERR, "Failed to get CIO2 config\n");
256 } else if (cio2_config->device_type != INTEL_ACPI_CAMERA_CIO2) {
257 printk(BIOS_ERR, "Device type isn't CIO2: %u\n",
258 (u32)cio2_config->device_type);
259 } else if (config->ssdb.link_used >= cio2_config->cio2_num_ports) {
260 printk(BIOS_ERR, "%u exceeds CIO2's %u links\n",
261 (u32)config->ssdb.link_used,
262 (u32)cio2_config->cio2_num_ports);
263 } else {
264 config->ssdb.lanes_used =
265 cio2_config->cio2_lanes_used[config->ssdb.link_used];
266 }
267 }
Matt Delco1245b1e2020-06-17 07:26:55 +0530268}
269
270/*
271 * Adds settings for a camera sensor device (typically at "\_SB.PCI0.I2Cx.CAMy"). The drivers
272 * for Linux tends to expect the camera sensor device and any related nvram / vcm devices to be
273 * separate ACPI devices, while the drivers for Windows want all of these to be grouped
274 * together in the camera sensor ACPI device. This implementation tries to satisfy both,
275 * though the unfortunate tradeoff is that the same I2C address for nvram and vcm is advertised
276 * by multiple devices in ACPI (via "_CRS"). The Windows driver can use the "_DSM" method to
277 * disambiguate the I2C resources in the camera sensor ACPI device. Drivers for Windows
278 * typically query "SSDB" for configuration information (represented as a binary blob dump of
279 * struct), while Linux drivers typically consult individual parameters in "_DSD".
280 *
281 * The tree of tables in "_DSD" is analogous to what's used for the "CIO2" device. The _DSD
282 * specifies a child table for the sensor's port (e.g., PRT0 for "port0"--this implementation
283 * assumes a camera only has 1 port). The PRT0 table specifies a table for each endpoint
284 * (though only 1 endpoint is supported by this implementation so the table only has an
285 * "endpoint0" that points to a EP00 table). The EP00 table primarily describes the # of lanes
286 * in "data-lines", a list of frequencies in "list-frequencies", and specifies the name of the
287 * other side in "remote-endpoint" (typically "\_SB.PCI0.CIO2").
288 */
289static void camera_fill_sensor(const struct device *dev)
290{
291 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
292 struct acpi_dp *ep00 = NULL;
293 struct acpi_dp *prt0 = NULL;
294 struct acpi_dp *dsd = NULL;
295 struct acpi_dp *remote = NULL;
296 const char *vcm_name = NULL;
297 struct acpi_dp *lens_focus = NULL;
Matt Delco879b3c12020-06-17 13:10:22 +0530298 const char *remote_name;
299 struct device *cio2 = pcidev_on_root(CIO2_PCI_DEV, CIO2_PCI_FN);
Matt Delco1245b1e2020-06-17 07:26:55 +0530300
Matt Delco1ffee9d2020-06-17 12:55:35 +0530301 camera_generate_pld(dev);
302
Matt Delco879b3c12020-06-17 13:10:22 +0530303 camera_fill_ssdb_defaults(config);
Matt Delco1245b1e2020-06-17 07:26:55 +0530304
Matt Delco964033f2020-06-17 12:49:43 +0530305 /* _DSM */
306 camera_generate_dsm(dev);
307
Matt Delco1245b1e2020-06-17 07:26:55 +0530308 ep00 = acpi_dp_new_table("EP00");
309 acpi_dp_add_integer(ep00, "endpoint", DEFAULT_ENDPOINT);
310 acpi_dp_add_integer(ep00, "clock-lanes", 0);
311
312 if (config->ssdb.lanes_used > 0) {
313 struct acpi_dp *lanes = acpi_dp_new_table("data-lanes");
314 uint32_t i;
315 for (i = 1; i <= config->ssdb.lanes_used; ++i)
316 acpi_dp_add_integer(lanes, NULL, i);
317 acpi_dp_add_array(ep00, lanes);
318 }
319
320 if (config->num_freq_entries) {
321 struct acpi_dp *freq = acpi_dp_new_table("link-frequencies");
322 uint32_t i;
323 for (i = 0; i < config->num_freq_entries && i < MAX_LINK_FREQ_ENTRIES; ++i)
324 acpi_dp_add_integer(freq, NULL, config->link_freq[i]);
325 acpi_dp_add_array(ep00, freq);
326 }
327
328 remote = acpi_dp_new_table("remote-endpoint");
329
Matt Delco879b3c12020-06-17 13:10:22 +0530330 if (config->remote_name) {
331 remote_name = config->remote_name;
332 } else {
333 if (cio2)
334 remote_name = acpi_device_path(cio2);
335 else
336 remote_name = DEFAULT_REMOTE_NAME;
337 }
338
339 acpi_dp_add_reference(remote, NULL, remote_name);
Matt Delco1245b1e2020-06-17 07:26:55 +0530340 acpi_dp_add_integer(remote, NULL, config->ssdb.link_used);
341 acpi_dp_add_integer(remote, NULL, DEFAULT_ENDPOINT);
342 acpi_dp_add_array(ep00, remote);
343
344 prt0 = acpi_dp_new_table("PRT0");
345
346 acpi_dp_add_integer(prt0, "port", 0);
347 acpi_dp_add_child(prt0, "endpoint0", ep00);
348 dsd = acpi_dp_new_table("_DSD");
349
350 acpi_dp_add_integer(dsd, "clock-frequency", config->ssdb.mclk_speed);
351
352 if (config->ssdb.degree)
353 acpi_dp_add_integer(dsd, "rotation", 180);
354
355 if (config->ssdb.vcm_type) {
356 if (config->vcm_name) {
357 vcm_name = config->vcm_name;
358 } else {
359 const struct device_path path = {
360 .type = DEVICE_PATH_I2C,
361 .i2c.device = config->vcm_address,
362 };
363 struct device *vcm_dev = find_dev_path(dev->bus, &path);
364 struct drivers_intel_mipi_camera_config *vcm_config;
365 vcm_config = vcm_dev ? vcm_dev->chip_info : NULL;
366
367 if (!vcm_config)
368 printk(BIOS_ERR, "Failed to get VCM\n");
369 else if (vcm_config->device_type != INTEL_ACPI_CAMERA_VCM)
370 printk(BIOS_ERR, "Device isn't VCM\n");
371 else
372 vcm_name = acpi_device_path(vcm_dev);
373 }
374 }
375
376 if (vcm_name) {
377 lens_focus = acpi_dp_new_table("lens-focus");
378 acpi_dp_add_reference(lens_focus, NULL, vcm_name);
379 acpi_dp_add_array(dsd, lens_focus);
380 }
381
382 acpi_dp_add_child(dsd, "port0", prt0);
383 acpi_dp_write(dsd);
384
385 acpigen_write_method_serialized("SSDB", 0);
386 acpigen_write_return_byte_buffer((uint8_t *)&config->ssdb, sizeof(config->ssdb));
387 acpigen_pop_len(); /* Method */
388
389 /* Fill Power Sequencing Data */
390 if (config->num_pwdb_entries > 0) {
391 acpigen_write_method_serialized("PWDB", 0);
392 acpigen_write_return_byte_buffer((uint8_t *)&config->pwdb,
393 sizeof(struct intel_pwdb) *
394 config->num_pwdb_entries);
395 acpigen_pop_len(); /* Method */
396 }
397}
398
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530399static void camera_fill_nvm(const struct device *dev)
400{
401 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
402 struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
403
404 /* It might be possible to default size or width based on type. */
405 if (!config->disable_nvm_defaults && !config->nvm_pagesize)
406 config->nvm_pagesize = 1;
407
408 if (!config->disable_nvm_defaults && !config->nvm_readonly)
409 config->nvm_readonly = 1;
410
411 if (config->nvm_size)
412 acpi_dp_add_integer(dsd, "size", config->nvm_size);
413
414 if (config->nvm_pagesize)
415 acpi_dp_add_integer(dsd, "pagesize", config->nvm_pagesize);
416
417 if (config->nvm_readonly)
418 acpi_dp_add_integer(dsd, "read-only", config->nvm_readonly);
419
420 if (config->nvm_width)
421 acpi_dp_add_integer(dsd, "address-width", config->nvm_width);
422
423 acpi_dp_write(dsd);
424}
425
426static void camera_fill_vcm(const struct device *dev)
427{
428 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
429 struct acpi_dp *dsd;
430
431 if (!config->vcm_compat)
432 return;
433
434 dsd = acpi_dp_new_table("_DSD");
435 acpi_dp_add_string(dsd, "compatible", config->vcm_compat);
436 acpi_dp_write(dsd);
437}
438
Sugnan Prabhu Sb087a942020-05-21 20:41:03 +0530439static void fill_power_res_sequence(struct drivers_intel_mipi_camera_config *config,
440 struct operation_seq *seq)
441{
442 unsigned int i;
443 uint8_t index;
444 uint8_t gpio_num;
445
446 for (i = 0; i < seq->ops_cnt; i++) {
447 switch (seq->ops[i].type) {
448 case IMGCLK:
449 index = seq->ops[i].index;
450 if (seq->ops[i].action == ENABLE) {
451 acpigen_emit_namestring("MCON");
452 acpigen_write_byte(config->clk_panel.clks[index].clknum);
453 acpigen_write_byte(config->clk_panel.clks[index].freq);
454 } else if (seq->ops[i].action == DISABLE) {
455 acpigen_emit_namestring("MCOF");
456 acpigen_write_byte(config->clk_panel.clks[index].clknum);
457 } else {
458 acpigen_write_debug_string("Unsupported clock action");
459 printk(BIOS_ERR, "Unsupported clock action: %x\n",
460 seq->ops[i].action);
461 printk(BIOS_ERR, "OS camera driver will likely not work");
462 }
463
464 break;
465 case GPIO:
466 index = seq->ops[i].index;
467 gpio_num = config->gpio_panel.gpio[index].gpio_num;
468 if (seq->ops[i].action == ENABLE) {
469 acpigen_soc_set_tx_gpio(gpio_num);
470 } else if (seq->ops[i].action == DISABLE) {
471 acpigen_soc_clear_tx_gpio(gpio_num);
472 } else {
473 acpigen_write_debug_string("Unsupported GPIO action");
474 printk(BIOS_ERR, "Unsupported GPIO action: %x\n",
475 seq->ops[i].action);
476 printk(BIOS_ERR, "OS camera driver will likely not work");
477 }
478
479 break;
480 default:
481 printk(BIOS_ERR, "Unsupported power operation: %x\n", seq->ops[i].type);
482 printk(BIOS_ERR, "OS camera driver will likely not work");
483 break;
484 }
485
486 if (seq->ops[i].delay_ms)
487 acpigen_write_sleep(seq->ops[i].delay_ms);
488 }
489}
490
Matt Delco7d002932020-06-16 11:39:52 +0530491static void write_pci_camera_device(const struct device *dev)
V Sowmya9f8023a2017-02-28 17:52:05 +0530492{
493 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
Matt Delco7d002932020-06-16 11:39:52 +0530494
495 if (dev->path.type != DEVICE_PATH_PCI) {
496 printk(BIOS_ERR, "CIO2/IMGU devices require PCI\n");
497 return;
498 }
499
500 acpigen_write_device(acpi_device_name(dev));
501 acpigen_write_ADR_pci_device(dev);
502 acpigen_write_name_string("_DDN", config->device_type == INTEL_ACPI_CAMERA_CIO2 ?
503 "Camera and Imaging Subsystem" : "Imaging Unit");
504}
505
506static void write_i2c_camera_device(const struct device *dev, const char *scope)
507{
508 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
V Sowmya9f8023a2017-02-28 17:52:05 +0530509 struct acpi_i2c i2c = {
510 .address = dev->path.i2c.device,
511 .mode_10bit = dev->path.i2c.mode_10bit,
512 .speed = I2C_SPEED_FAST,
513 .resource = scope,
514 };
515
Matt Delco7d002932020-06-16 11:39:52 +0530516 if (dev->path.type != DEVICE_PATH_I2C) {
517 printk(BIOS_ERR, "Non-CIO2/IMGU devices require I2C\n");
V Sowmya9f8023a2017-02-28 17:52:05 +0530518 return;
Matt Delco7d002932020-06-16 11:39:52 +0530519 }
V Sowmya9f8023a2017-02-28 17:52:05 +0530520
V Sowmya9f8023a2017-02-28 17:52:05 +0530521 acpigen_write_device(acpi_device_name(dev));
Matt Delco7d002932020-06-16 11:39:52 +0530522
Sugnan Prabhu Sb087a942020-05-21 20:41:03 +0530523 /* add power resource */
524 if (config->has_power_resource) {
525 acpigen_write_power_res(POWER_RESOURCE_NAME, 0, 0, NULL, 0);
526 acpigen_write_name_integer("STA", 0);
527 acpigen_write_STA_ext("STA");
528
529 acpigen_write_method_serialized("_ON", 0);
530 acpigen_write_if();
531 acpigen_emit_byte(LEQUAL_OP);
532 acpigen_emit_namestring("STA");
533 acpigen_write_integer(0);
534
535 fill_power_res_sequence(config, &config->on_seq);
536
537 acpigen_write_store_op_to_namestr(1, "STA");
538 acpigen_pop_len(); /* if */
539 acpigen_pop_len(); /* _ON */
540
541 /* _OFF operations */
542 acpigen_write_method_serialized("_OFF", 0);
543 acpigen_write_if();
544 acpigen_emit_byte(LEQUAL_OP);
545 acpigen_emit_namestring("STA");
546 acpigen_write_integer(1);
547
548 fill_power_res_sequence(config, &config->off_seq);
549
550 acpigen_write_store_op_to_namestr(0, "STA");
551 acpigen_pop_len(); /* if */
552 acpigen_pop_len(); /* _ON */
553
554 acpigen_pop_len(); /* Power Resource */
555 }
556
Matt Delco7d002932020-06-16 11:39:52 +0530557 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR)
558 acpigen_write_name_integer("_ADR", 0);
559
560 if (config->acpi_hid)
561 acpigen_write_name_string("_HID", config->acpi_hid);
562 else if (config->device_type == INTEL_ACPI_CAMERA_VCM)
563 acpigen_write_name_string("_HID", ACPI_DT_NAMESPACE_HID);
564 else if (config->device_type == INTEL_ACPI_CAMERA_NVM)
565 acpigen_write_name_string("_HID", "INT3499");
566
V Sowmya9f8023a2017-02-28 17:52:05 +0530567 acpigen_write_name_integer("_UID", config->acpi_uid);
568 acpigen_write_name_string("_DDN", config->chip_name);
Hung-Te Linb4be50c2018-09-10 10:55:49 +0800569 acpigen_write_STA(acpi_device_status(dev));
V Sowmya9f8023a2017-02-28 17:52:05 +0530570
571 /* Resources */
572 acpigen_write_name("_CRS");
573 acpigen_write_resourcetemplate_header();
574 acpi_device_write_i2c(&i2c);
V Sowmya9f8023a2017-02-28 17:52:05 +0530575
Matt Delco7d002932020-06-16 11:39:52 +0530576 /*
577 * The optional vcm/nvram devices are presumed to be on the same I2C bus as the camera
578 * sensor.
579 */
580 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR &&
581 config->ssdb.vcm_type && config->vcm_address) {
582 struct acpi_i2c i2c_vcm = i2c;
583 i2c_vcm.address = config->vcm_address;
584 acpi_device_write_i2c(&i2c_vcm);
V Sowmya9f8023a2017-02-28 17:52:05 +0530585 }
586
Matt Delco7d002932020-06-16 11:39:52 +0530587 if (config->device_type == INTEL_ACPI_CAMERA_SENSOR &&
588 config->ssdb.rom_type && config->rom_address) {
589 struct acpi_i2c i2c_rom = i2c;
590 i2c_rom.address = config->rom_address;
591 acpi_device_write_i2c(&i2c_rom);
592 }
593
594 acpigen_write_resourcetemplate_footer();
595}
596
597static void write_camera_device_common(const struct device *dev)
598{
599 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
600
601 /* Mark it as Camera related device */
602 if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
603 config->device_type == INTEL_ACPI_CAMERA_IMGU ||
604 config->device_type == INTEL_ACPI_CAMERA_SENSOR ||
605 config->device_type == INTEL_ACPI_CAMERA_VCM) {
606 acpigen_write_name_integer("CAMD", config->device_type);
607 }
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530608
Sugnan Prabhu Sb087a942020-05-21 20:41:03 +0530609 if (config->pr0 || config->has_power_resource) {
610 acpigen_write_name("_PR0");
611 acpigen_write_package(1);
612 if (config->pr0)
613 acpigen_emit_namestring(config->pr0); /* External power resource */
614 else
615 acpigen_emit_namestring(POWER_RESOURCE_NAME);
616
617 acpigen_pop_len(); /* _PR0 */
618 }
619
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530620 switch (config->device_type) {
Matt Delco879b3c12020-06-17 13:10:22 +0530621 case INTEL_ACPI_CAMERA_CIO2:
622 camera_fill_cio2(dev);
623 break;
Matt Delco1245b1e2020-06-17 07:26:55 +0530624 case INTEL_ACPI_CAMERA_SENSOR:
625 camera_fill_sensor(dev);
626 break;
Matt Delcoc3a83bf2020-06-16 12:02:34 +0530627 case INTEL_ACPI_CAMERA_VCM:
628 camera_fill_vcm(dev);
629 break;
630 case INTEL_ACPI_CAMERA_NVM:
631 camera_fill_nvm(dev);
632 break;
633 default:
634 break;
635 }
Matt Delco7d002932020-06-16 11:39:52 +0530636}
637
638static void camera_fill_ssdt(const struct device *dev)
639{
640 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
641 const char *scope = acpi_device_scope(dev);
642
643 if (!dev->enabled || !scope)
644 return;
645
646 /* Device */
647 acpigen_write_scope(scope);
648
649 if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
650 config->device_type == INTEL_ACPI_CAMERA_IMGU)
651 write_pci_camera_device(dev);
652 else
653 write_i2c_camera_device(dev, scope);
654
655 write_camera_device_common(dev);
V Sowmya9f8023a2017-02-28 17:52:05 +0530656
657 acpigen_pop_len(); /* Device */
658 acpigen_pop_len(); /* Scope */
Matt Delco7d002932020-06-16 11:39:52 +0530659
660 if (dev->path.type == DEVICE_PATH_PCI) {
661 printk(BIOS_INFO, "%s: %s PCI address 0%x\n", acpi_device_path(dev),
662 dev->chip_ops->name, dev->path.pci.devfn);
663 } else {
664 printk(BIOS_INFO, "%s: %s I2C address 0%xh\n", acpi_device_path(dev),
665 dev->chip_ops->name, dev->path.i2c.device);
666 }
V Sowmya9f8023a2017-02-28 17:52:05 +0530667}
668
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600669static const char *camera_acpi_name(const struct device *dev)
V Sowmya9f8023a2017-02-28 17:52:05 +0530670{
Matt Delco7d002932020-06-16 11:39:52 +0530671 const char *prefix = NULL;
672 static char name[5];
V Sowmya9f8023a2017-02-28 17:52:05 +0530673 struct drivers_intel_mipi_camera_config *config = dev->chip_info;
Matt Delco7d002932020-06-16 11:39:52 +0530674
675 if (config->acpi_name)
676 return config->acpi_name;
677
678 switch (config->device_type) {
679 case INTEL_ACPI_CAMERA_CIO2:
680 return "CIO2";
681 case INTEL_ACPI_CAMERA_IMGU:
682 return "IMGU";
683 case INTEL_ACPI_CAMERA_PMIC:
684 return "PMIC";
685 case INTEL_ACPI_CAMERA_SENSOR:
686 prefix = "CAM";
687 break;
688 case INTEL_ACPI_CAMERA_VCM:
689 prefix = "VCM";
690 break;
691 case INTEL_ACPI_CAMERA_NVM:
692 prefix = "NVM";
693 break;
694 default:
695 printk(BIOS_ERR, "Invalid device type: %x\n", config->device_type);
696 return NULL;
697 }
698
699 /*
700 * The camera # knows which link # they use, so that's used as the basis for the
701 * instance #. The VCM and NVM don't have this information, so the best we can go on is
702 * the _UID.
703 */
704 snprintf(name, sizeof(name), "%s%1u", prefix,
705 config->device_type == INTEL_ACPI_CAMERA_SENSOR ?
706 config->ssdb.link_used : config->acpi_uid);
707 return name;
V Sowmya9f8023a2017-02-28 17:52:05 +0530708}
709
710static struct device_operations camera_ops = {
Nico Huber2f8ba692020-04-05 14:05:24 +0200711 .read_resources = noop_read_resources,
712 .set_resources = noop_set_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200713 .acpi_name = camera_acpi_name,
714 .acpi_fill_ssdt = camera_fill_ssdt,
V Sowmya9f8023a2017-02-28 17:52:05 +0530715};
716
717static void camera_enable(struct device *dev)
718{
719 dev->ops = &camera_ops;
720}
721
722struct chip_operations drivers_intel_mipi_camera_ops = {
723 CHIP_NAME("Intel MIPI Camera Device")
Elyes HAOUAS2aa3b162018-11-27 17:02:10 +0100724 .enable_dev = camera_enable
V Sowmya9f8023a2017-02-28 17:52:05 +0530725};