|
34 | 34 | #include <drm/drm_utils.h> |
35 | 35 |
|
36 | 36 | #include <linux/export.h> |
| 37 | +#include <linux/of.h> |
37 | 38 | #include <linux/platform_device.h> |
38 | 39 | #include <linux/property.h> |
39 | 40 | #include <linux/uaccess.h> |
@@ -85,6 +86,7 @@ struct drm_conn_prop_enum_list { |
85 | 86 | int type; |
86 | 87 | const char *name; |
87 | 88 | struct ida ida; |
| 89 | + int first_dyn_num; |
88 | 90 | }; |
89 | 91 |
|
90 | 92 | /* |
@@ -114,12 +116,41 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { |
114 | 116 | { DRM_MODE_CONNECTOR_USB, "USB" }, |
115 | 117 | }; |
116 | 118 |
|
| 119 | +#define MAX_DT_NODE_NAME_LEN 20 |
| 120 | +#define DT_DRM_NODE_PREFIX "drm-" |
| 121 | + |
| 122 | +static void drm_connector_get_of_name(int type, char *node_name, int length) |
| 123 | +{ |
| 124 | + int i = 0; |
| 125 | + |
| 126 | + strscpy(node_name, DT_DRM_NODE_PREFIX, length); |
| 127 | + |
| 128 | + do { |
| 129 | + node_name[i + strlen(DT_DRM_NODE_PREFIX)] = |
| 130 | + tolower(drm_connector_enum_list[type].name[i]); |
| 131 | + |
| 132 | + } while (drm_connector_enum_list[type].name[i++] && |
| 133 | + i < length); |
| 134 | + |
| 135 | + node_name[length - 1] = '\0'; |
| 136 | +} |
| 137 | + |
117 | 138 | void drm_connector_ida_init(void) |
118 | 139 | { |
119 | | - int i; |
| 140 | + int i, id; |
| 141 | + char node_name[MAX_DT_NODE_NAME_LEN]; |
120 | 142 |
|
121 | | - for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) |
| 143 | + for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) { |
122 | 144 | ida_init(&drm_connector_enum_list[i].ida); |
| 145 | + |
| 146 | + drm_connector_get_of_name(i, node_name, MAX_DT_NODE_NAME_LEN); |
| 147 | + |
| 148 | + id = of_alias_get_highest_id(node_name); |
| 149 | + if (id > 0) |
| 150 | + drm_connector_enum_list[i].first_dyn_num = id + 1; |
| 151 | + else |
| 152 | + drm_connector_enum_list[i].first_dyn_num = 1; |
| 153 | + } |
123 | 154 | } |
124 | 155 |
|
125 | 156 | void drm_connector_ida_destroy(void) |
@@ -227,7 +258,9 @@ static int drm_connector_init_only(struct drm_device *dev, |
227 | 258 | struct i2c_adapter *ddc) |
228 | 259 | { |
229 | 260 | struct drm_mode_config *config = &dev->mode_config; |
| 261 | + char node_name[MAX_DT_NODE_NAME_LEN]; |
230 | 262 | int ret; |
| 263 | + int id; |
231 | 264 | struct ida *connector_ida = |
232 | 265 | &drm_connector_enum_list[connector_type].ida; |
233 | 266 |
|
@@ -257,8 +290,28 @@ static int drm_connector_init_only(struct drm_device *dev, |
257 | 290 | ret = 0; |
258 | 291 |
|
259 | 292 | connector->connector_type = connector_type; |
260 | | - connector->connector_type_id = |
261 | | - ida_alloc_min(connector_ida, 1, GFP_KERNEL); |
| 293 | + connector->connector_type_id = 0; |
| 294 | + |
| 295 | + drm_connector_get_of_name(connector_type, node_name, MAX_DT_NODE_NAME_LEN); |
| 296 | + id = of_alias_get_id(dev->dev->of_node, node_name); |
| 297 | + if (id > 0) { |
| 298 | + /* Try and allocate the requested ID |
| 299 | + * Valid range is 1 to 31, hence ignoring 0 as an error |
| 300 | + */ |
| 301 | + int type_id = ida_alloc_range(connector_ida, id, id, GFP_KERNEL); |
| 302 | + |
| 303 | + if (type_id > 0) |
| 304 | + connector->connector_type_id = type_id; |
| 305 | + else |
| 306 | + drm_err(dev, "Failed to acquire type ID %d for interface type %s, ret %d\n", |
| 307 | + id, drm_connector_enum_list[connector_type].name, |
| 308 | + type_id); |
| 309 | + } |
| 310 | + if (!connector->connector_type_id) |
| 311 | + connector->connector_type_id = |
| 312 | + ida_alloc_min(connector_ida, |
| 313 | + drm_connector_enum_list[connector_type].first_dyn_num, |
| 314 | + GFP_KERNEL); |
262 | 315 | if (connector->connector_type_id < 0) { |
263 | 316 | ret = connector->connector_type_id; |
264 | 317 | goto out_put_id; |
|
0 commit comments