Skip to content

Commit 68b9bcc

Browse files
jwrdegoedemchehab
authored andcommitted
media: ipu3-cio2: Add support for instantiating i2c-clients for VCMs
Some sensors come with a variable-focus lens where the lens focus is controller by a VCM (Voice Coil Motor). If there is a VCM for the lens-focus, and if so which one, is described on the vcm_type field of the ACPI SSDB table. These VCMs are a second I2C device listed as an extra I2cSerialBusV2 resource in the same ACPI device as the sensor. The i2c-core-acpi.c code only instantiates an i2c-client for the first I2cSerialBusV2 resource. Add support for instantiating an i2c-client for the VCM with the type of the i2c-client set based on the SSDB vcm_type field. Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Sakari Ailus <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent fc2c204 commit 68b9bcc

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

drivers/media/pci/intel/ipu3/cio2-bridge.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <linux/acpi.h>
55
#include <linux/device.h>
6+
#include <linux/i2c.h>
67
#include <linux/pci.h>
78
#include <linux/property.h>
89
#include <media/v4l2-fwnode.h>
@@ -38,6 +39,18 @@ static const struct cio2_property_names prop_names = {
3839
.link_frequencies = "link-frequencies",
3940
};
4041

42+
static const char * const cio2_vcm_types[] = {
43+
"ad5823",
44+
"dw9714",
45+
"ad5816",
46+
"dw9719",
47+
"dw9718",
48+
"dw9806b",
49+
"wv517s",
50+
"lc898122xa",
51+
"lc898212axb",
52+
};
53+
4154
static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
4255
void *data, u32 size)
4356
{
@@ -134,6 +147,12 @@ static void cio2_bridge_create_fwnode_properties(
134147
sensor->dev_properties[2] = PROPERTY_ENTRY_U32(
135148
sensor->prop_names.orientation,
136149
orientation);
150+
if (sensor->ssdb.vcmtype) {
151+
sensor->vcm_ref[0] =
152+
SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]);
153+
sensor->dev_properties[3] =
154+
PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref);
155+
}
137156

138157
sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
139158
sensor->prop_names.bus_type,
@@ -195,6 +214,33 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
195214
sensor->node_names.endpoint,
196215
&nodes[SWNODE_CIO2_PORT],
197216
sensor->cio2_properties);
217+
if (sensor->ssdb.vcmtype)
218+
nodes[SWNODE_VCM] =
219+
NODE_VCM(cio2_vcm_types[sensor->ssdb.vcmtype - 1]);
220+
}
221+
222+
static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor)
223+
{
224+
struct i2c_board_info board_info = { };
225+
char name[16];
226+
227+
if (!sensor->ssdb.vcmtype)
228+
return;
229+
230+
snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev));
231+
board_info.dev_name = name;
232+
strscpy(board_info.type, cio2_vcm_types[sensor->ssdb.vcmtype - 1],
233+
ARRAY_SIZE(board_info.type));
234+
board_info.swnode = &sensor->swnodes[SWNODE_VCM];
235+
236+
sensor->vcm_i2c_client =
237+
i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(sensor->adev),
238+
1, &board_info);
239+
if (IS_ERR(sensor->vcm_i2c_client)) {
240+
dev_warn(&sensor->adev->dev, "Error instantiation VCM i2c-client: %ld\n",
241+
PTR_ERR(sensor->vcm_i2c_client));
242+
sensor->vcm_i2c_client = NULL;
243+
}
198244
}
199245

200246
static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
@@ -207,6 +253,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
207253
software_node_unregister_nodes(sensor->swnodes);
208254
ACPI_FREE(sensor->pld);
209255
acpi_dev_put(sensor->adev);
256+
i2c_unregister_device(sensor->vcm_i2c_client);
210257
}
211258
}
212259

@@ -239,6 +286,12 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
239286
if (ret)
240287
goto err_put_adev;
241288

289+
if (sensor->ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) {
290+
dev_warn(&adev->dev, "Unknown VCM type %d\n",
291+
sensor->ssdb.vcmtype);
292+
sensor->ssdb.vcmtype = 0;
293+
}
294+
242295
status = acpi_get_physical_device_location(adev->handle, &sensor->pld);
243296
if (ACPI_FAILURE(status)) {
244297
ret = -ENODEV;
@@ -269,6 +322,8 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
269322
sensor->adev = acpi_dev_get(adev);
270323
adev->fwnode.secondary = fwnode;
271324

325+
cio2_bridge_instantiate_vcm_i2c_client(sensor);
326+
272327
dev_info(&cio2->dev, "Found supported sensor %s\n",
273328
acpi_dev_name(adev));
274329

drivers/media/pci/intel/ipu3/cio2-bridge.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "ipu3-cio2.h"
1010

11+
struct i2c_client;
12+
1113
#define CIO2_HID "INT343E"
1214
#define CIO2_MAX_LANES 4
1315
#define MAX_NUM_LINK_FREQS 3
@@ -42,12 +44,19 @@
4244
.properties = _PROPS, \
4345
}
4446

47+
#define NODE_VCM(_TYPE) \
48+
(const struct software_node) { \
49+
.name = _TYPE, \
50+
}
51+
4552
enum cio2_sensor_swnodes {
4653
SWNODE_SENSOR_HID,
4754
SWNODE_SENSOR_PORT,
4855
SWNODE_SENSOR_ENDPOINT,
4956
SWNODE_CIO2_PORT,
5057
SWNODE_CIO2_ENDPOINT,
58+
/* Must be last because it is optional / maybe empty */
59+
SWNODE_VCM,
5160
SWNODE_COUNT
5261
};
5362

@@ -106,19 +115,22 @@ struct cio2_sensor_config {
106115
struct cio2_sensor {
107116
char name[ACPI_ID_LEN];
108117
struct acpi_device *adev;
118+
struct i2c_client *vcm_i2c_client;
109119

110-
struct software_node swnodes[6];
120+
/* SWNODE_COUNT + 1 for terminating empty node */
121+
struct software_node swnodes[SWNODE_COUNT + 1];
111122
struct cio2_node_names node_names;
112123

113124
struct cio2_sensor_ssdb ssdb;
114125
struct acpi_pld_info *pld;
115126

116127
struct cio2_property_names prop_names;
117128
struct property_entry ep_properties[5];
118-
struct property_entry dev_properties[4];
129+
struct property_entry dev_properties[5];
119130
struct property_entry cio2_properties[3];
120131
struct software_node_ref_args local_ref[1];
121132
struct software_node_ref_args remote_ref[1];
133+
struct software_node_ref_args vcm_ref[1];
122134
};
123135

124136
struct cio2_bridge {

0 commit comments

Comments
 (0)