Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * v4l2-i2c - I2C helpers for Video4Linux2
4 : : */
5 : :
6 : : #include <linux/i2c.h>
7 : : #include <linux/module.h>
8 : : #include <media/v4l2-common.h>
9 : : #include <media/v4l2-device.h>
10 : :
11 : 0 : void v4l2_i2c_subdev_unregister(struct v4l2_subdev *sd)
12 : : {
13 : : struct i2c_client *client = v4l2_get_subdevdata(sd);
14 : :
15 : : /*
16 : : * We need to unregister the i2c client
17 : : * explicitly. We cannot rely on
18 : : * i2c_del_adapter to always unregister
19 : : * clients for us, since if the i2c bus is a
20 : : * platform bus, then it is never deleted.
21 : : *
22 : : * Device tree or ACPI based devices must not
23 : : * be unregistered as they have not been
24 : : * registered by us, and would not be
25 : : * re-created by just probing the V4L2 driver.
26 : : */
27 [ # # # # : 0 : if (client && !client->dev.of_node && !client->dev.fwnode)
# # ]
28 : 0 : i2c_unregister_device(client);
29 : 0 : }
30 : :
31 : 0 : void v4l2_i2c_subdev_set_name(struct v4l2_subdev *sd,
32 : : struct i2c_client *client,
33 : : const char *devname, const char *postfix)
34 : : {
35 [ # # ]: 0 : if (!devname)
36 : 0 : devname = client->dev.driver->name;
37 [ # # ]: 0 : if (!postfix)
38 : : postfix = "";
39 : :
40 : 0 : snprintf(sd->name, sizeof(sd->name), "%s%s %d-%04x", devname, postfix,
41 : 0 : i2c_adapter_id(client->adapter), client->addr);
42 : 0 : }
43 : : EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_set_name);
44 : :
45 : 0 : void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
46 : : const struct v4l2_subdev_ops *ops)
47 : : {
48 : 0 : v4l2_subdev_init(sd, ops);
49 : 0 : sd->flags |= V4L2_SUBDEV_FL_IS_I2C;
50 : : /* the owner is the same as the i2c_client's driver owner */
51 : 0 : sd->owner = client->dev.driver->owner;
52 : 0 : sd->dev = &client->dev;
53 : : /* i2c_client and v4l2_subdev point to one another */
54 : : v4l2_set_subdevdata(sd, client);
55 : : i2c_set_clientdata(client, sd);
56 : 0 : v4l2_i2c_subdev_set_name(sd, client, NULL, NULL);
57 : 0 : }
58 : : EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
59 : :
60 : : /* Load an i2c sub-device. */
61 : : struct v4l2_subdev
62 : 0 : *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
63 : : struct i2c_adapter *adapter,
64 : : struct i2c_board_info *info,
65 : : const unsigned short *probe_addrs)
66 : : {
67 : : struct v4l2_subdev *sd = NULL;
68 : : struct i2c_client *client;
69 : :
70 [ # # ]: 0 : if (!v4l2_dev)
71 : : return NULL;
72 : :
73 : 0 : request_module(I2C_MODULE_PREFIX "%s", info->type);
74 : :
75 : : /* Create the i2c client */
76 [ # # # # ]: 0 : if (info->addr == 0 && probe_addrs)
77 : 0 : client = i2c_new_probed_device(adapter, info, probe_addrs,
78 : : NULL);
79 : : else
80 : 0 : client = i2c_new_device(adapter, info);
81 : :
82 : : /*
83 : : * Note: by loading the module first we are certain that c->driver
84 : : * will be set if the driver was found. If the module was not loaded
85 : : * first, then the i2c core tries to delay-load the module for us,
86 : : * and then c->driver is still NULL until the module is finally
87 : : * loaded. This delay-load mechanism doesn't work if other drivers
88 : : * want to use the i2c device, so explicitly loading the module
89 : : * is the best alternative.
90 : : */
91 [ # # # # ]: 0 : if (!client || !client->dev.driver)
92 : : goto error;
93 : :
94 : : /* Lock the module so we can safely get the v4l2_subdev pointer */
95 [ # # ]: 0 : if (!try_module_get(client->dev.driver->owner))
96 : : goto error;
97 : : sd = i2c_get_clientdata(client);
98 : :
99 : : /*
100 : : * Register with the v4l2_device which increases the module's
101 : : * use count as well.
102 : : */
103 [ # # ]: 0 : if (v4l2_device_register_subdev(v4l2_dev, sd))
104 : : sd = NULL;
105 : : /* Decrease the module use count to match the first try_module_get. */
106 : 0 : module_put(client->dev.driver->owner);
107 : :
108 : : error:
109 : : /*
110 : : * If we have a client but no subdev, then something went wrong and
111 : : * we must unregister the client.
112 : : */
113 [ # # ]: 0 : if (client && !sd)
114 : 0 : i2c_unregister_device(client);
115 : 0 : return sd;
116 : : }
117 : : EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board);
118 : :
119 : 0 : struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
120 : : struct i2c_adapter *adapter,
121 : : const char *client_type,
122 : : u8 addr,
123 : : const unsigned short *probe_addrs)
124 : : {
125 : : struct i2c_board_info info;
126 : :
127 : : /*
128 : : * Setup the i2c board info with the device type and
129 : : * the device address.
130 : : */
131 : 0 : memset(&info, 0, sizeof(info));
132 : 0 : strscpy(info.type, client_type, sizeof(info.type));
133 : 0 : info.addr = addr;
134 : :
135 : 0 : return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info,
136 : : probe_addrs);
137 : : }
138 : : EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
139 : :
140 : : /* Return i2c client address of v4l2_subdev. */
141 : 0 : unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
142 : : {
143 : : struct i2c_client *client = v4l2_get_subdevdata(sd);
144 : :
145 [ # # ]: 0 : return client ? client->addr : I2C_CLIENT_END;
146 : : }
147 : : EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr);
148 : :
149 : : /*
150 : : * Return a list of I2C tuner addresses to probe. Use only if the tuner
151 : : * addresses are unknown.
152 : : */
153 : 0 : const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
154 : : {
155 : : static const unsigned short radio_addrs[] = {
156 : : #if IS_ENABLED(CONFIG_MEDIA_TUNER_TEA5761)
157 : : 0x10,
158 : : #endif
159 : : 0x60,
160 : : I2C_CLIENT_END
161 : : };
162 : : static const unsigned short demod_addrs[] = {
163 : : 0x42, 0x43, 0x4a, 0x4b,
164 : : I2C_CLIENT_END
165 : : };
166 : : static const unsigned short tv_addrs[] = {
167 : : 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
168 : : 0x60, 0x61, 0x62, 0x63, 0x64,
169 : : I2C_CLIENT_END
170 : : };
171 : :
172 [ # # # # : 0 : switch (type) {
# ]
173 : : case ADDRS_RADIO:
174 : : return radio_addrs;
175 : : case ADDRS_DEMOD:
176 : 0 : return demod_addrs;
177 : : case ADDRS_TV:
178 : 0 : return tv_addrs;
179 : : case ADDRS_TV_WITH_DEMOD:
180 : 0 : return tv_addrs + 4;
181 : : }
182 : 0 : return NULL;
183 : : }
184 : : EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
|