Commit | Line | Data |
---|---|---|
02283b98 EG |
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 | void v4l2_i2c_subdev_set_name(struct v4l2_subdev *sd, struct i2c_client *client, | |
12 | const char *devname, const char *postfix) | |
13 | { | |
14 | if (!devname) | |
15 | devname = client->dev.driver->name; | |
16 | if (!postfix) | |
17 | postfix = ""; | |
18 | ||
19 | snprintf(sd->name, sizeof(sd->name), "%s%s %d-%04x", devname, postfix, | |
20 | i2c_adapter_id(client->adapter), client->addr); | |
21 | } | |
22 | EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_set_name); | |
23 | ||
24 | void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, | |
25 | const struct v4l2_subdev_ops *ops) | |
26 | { | |
27 | v4l2_subdev_init(sd, ops); | |
28 | sd->flags |= V4L2_SUBDEV_FL_IS_I2C; | |
29 | /* the owner is the same as the i2c_client's driver owner */ | |
30 | sd->owner = client->dev.driver->owner; | |
31 | sd->dev = &client->dev; | |
32 | /* i2c_client and v4l2_subdev point to one another */ | |
33 | v4l2_set_subdevdata(sd, client); | |
34 | i2c_set_clientdata(client, sd); | |
35 | v4l2_i2c_subdev_set_name(sd, client, NULL, NULL); | |
36 | } | |
37 | EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); | |
38 | ||
39 | /* Load an i2c sub-device. */ | |
40 | struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, | |
41 | struct i2c_adapter *adapter, struct i2c_board_info *info, | |
42 | const unsigned short *probe_addrs) | |
43 | { | |
44 | struct v4l2_subdev *sd = NULL; | |
45 | struct i2c_client *client; | |
46 | ||
47 | BUG_ON(!v4l2_dev); | |
48 | ||
49 | request_module(I2C_MODULE_PREFIX "%s", info->type); | |
50 | ||
51 | /* Create the i2c client */ | |
52 | if (info->addr == 0 && probe_addrs) | |
53 | client = i2c_new_probed_device(adapter, info, probe_addrs, | |
54 | NULL); | |
55 | else | |
56 | client = i2c_new_device(adapter, info); | |
57 | ||
58 | /* Note: by loading the module first we are certain that c->driver | |
59 | will be set if the driver was found. If the module was not loaded | |
60 | first, then the i2c core tries to delay-load the module for us, | |
61 | and then c->driver is still NULL until the module is finally | |
62 | loaded. This delay-load mechanism doesn't work if other drivers | |
63 | want to use the i2c device, so explicitly loading the module | |
64 | is the best alternative. */ | |
65 | if (client == NULL || client->dev.driver == NULL) | |
66 | goto error; | |
67 | ||
68 | /* Lock the module so we can safely get the v4l2_subdev pointer */ | |
69 | if (!try_module_get(client->dev.driver->owner)) | |
70 | goto error; | |
71 | sd = i2c_get_clientdata(client); | |
72 | ||
73 | /* Register with the v4l2_device which increases the module's | |
74 | use count as well. */ | |
75 | if (v4l2_device_register_subdev(v4l2_dev, sd)) | |
76 | sd = NULL; | |
77 | /* Decrease the module use count to match the first try_module_get. */ | |
78 | module_put(client->dev.driver->owner); | |
79 | ||
80 | error: | |
81 | /* If we have a client but no subdev, then something went wrong and | |
82 | we must unregister the client. */ | |
83 | if (client && sd == NULL) | |
84 | i2c_unregister_device(client); | |
85 | return sd; | |
86 | } | |
87 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board); | |
88 | ||
89 | struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, | |
90 | struct i2c_adapter *adapter, const char *client_type, | |
91 | u8 addr, const unsigned short *probe_addrs) | |
92 | { | |
93 | struct i2c_board_info info; | |
94 | ||
95 | /* Setup the i2c board info with the device type and | |
96 | the device address. */ | |
97 | memset(&info, 0, sizeof(info)); | |
98 | strscpy(info.type, client_type, sizeof(info.type)); | |
99 | info.addr = addr; | |
100 | ||
101 | return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs); | |
102 | } | |
103 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); | |
104 | ||
105 | /* Return i2c client address of v4l2_subdev. */ | |
106 | unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) | |
107 | { | |
108 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
109 | ||
110 | return client ? client->addr : I2C_CLIENT_END; | |
111 | } | |
112 | EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr); | |
113 | ||
114 | /* Return a list of I2C tuner addresses to probe. Use only if the tuner | |
115 | addresses are unknown. */ | |
116 | const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) | |
117 | { | |
118 | static const unsigned short radio_addrs[] = { | |
119 | #if IS_ENABLED(CONFIG_MEDIA_TUNER_TEA5761) | |
120 | 0x10, | |
121 | #endif | |
122 | 0x60, | |
123 | I2C_CLIENT_END | |
124 | }; | |
125 | static const unsigned short demod_addrs[] = { | |
126 | 0x42, 0x43, 0x4a, 0x4b, | |
127 | I2C_CLIENT_END | |
128 | }; | |
129 | static const unsigned short tv_addrs[] = { | |
130 | 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ | |
131 | 0x60, 0x61, 0x62, 0x63, 0x64, | |
132 | I2C_CLIENT_END | |
133 | }; | |
134 | ||
135 | switch (type) { | |
136 | case ADDRS_RADIO: | |
137 | return radio_addrs; | |
138 | case ADDRS_DEMOD: | |
139 | return demod_addrs; | |
140 | case ADDRS_TV: | |
141 | return tv_addrs; | |
142 | case ADDRS_TV_WITH_DEMOD: | |
143 | return tv_addrs + 4; | |
144 | } | |
145 | return NULL; | |
146 | } | |
147 | EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); |