v4l2-fwnode.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. /*
  2. * V4L2 fwnode binding parsing library
  3. *
  4. * The origins of the V4L2 fwnode library are in V4L2 OF library that
  5. * formerly was located in v4l2-of.c.
  6. *
  7. * Copyright (c) 2016 Intel Corporation.
  8. * Author: Sakari Ailus <sakari.ailus@linux.intel.com>
  9. *
  10. * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
  11. * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
  12. *
  13. * Copyright (C) 2012 Renesas Electronics Corp.
  14. * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  15. *
  16. * This program is free software; you can redistribute it and/or modify
  17. * it under the terms of version 2 of the GNU General Public License as
  18. * published by the Free Software Foundation.
  19. */
  20. #include <linux/acpi.h>
  21. #include <linux/kernel.h>
  22. #include <linux/mm.h>
  23. #include <linux/module.h>
  24. #include <linux/of.h>
  25. #include <linux/property.h>
  26. #include <linux/slab.h>
  27. #include <linux/string.h>
  28. #include <linux/types.h>
  29. #include <media/v4l2-async.h>
  30. #include <media/v4l2-fwnode.h>
  31. #include <media/v4l2-subdev.h>
  32. enum v4l2_fwnode_bus_type {
  33. V4L2_FWNODE_BUS_TYPE_GUESS = 0,
  34. V4L2_FWNODE_BUS_TYPE_CSI2_CPHY,
  35. V4L2_FWNODE_BUS_TYPE_CSI1,
  36. V4L2_FWNODE_BUS_TYPE_CCP2,
  37. NR_OF_V4L2_FWNODE_BUS_TYPE,
  38. };
  39. static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode,
  40. struct v4l2_fwnode_endpoint *vep)
  41. {
  42. struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2;
  43. bool have_clk_lane = false;
  44. unsigned int flags = 0, lanes_used = 0;
  45. unsigned int i;
  46. u32 v;
  47. int rval;
  48. rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0);
  49. if (rval > 0) {
  50. u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES];
  51. bus->num_data_lanes =
  52. min_t(int, V4L2_FWNODE_CSI2_MAX_DATA_LANES, rval);
  53. fwnode_property_read_u32_array(fwnode, "data-lanes", array,
  54. bus->num_data_lanes);
  55. for (i = 0; i < bus->num_data_lanes; i++) {
  56. if (lanes_used & BIT(array[i]))
  57. pr_warn("duplicated lane %u in data-lanes\n",
  58. array[i]);
  59. lanes_used |= BIT(array[i]);
  60. bus->data_lanes[i] = array[i];
  61. }
  62. rval = fwnode_property_read_u32_array(fwnode,
  63. "lane-polarities", NULL,
  64. 0);
  65. if (rval > 0) {
  66. if (rval != 1 + bus->num_data_lanes /* clock+data */) {
  67. pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n",
  68. 1 + bus->num_data_lanes, rval);
  69. return -EINVAL;
  70. }
  71. fwnode_property_read_u32_array(fwnode,
  72. "lane-polarities", array,
  73. 1 + bus->num_data_lanes);
  74. for (i = 0; i < 1 + bus->num_data_lanes; i++)
  75. bus->lane_polarities[i] = array[i];
  76. }
  77. }
  78. if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
  79. if (lanes_used & BIT(v))
  80. pr_warn("duplicated lane %u in clock-lanes\n", v);
  81. lanes_used |= BIT(v);
  82. bus->clock_lane = v;
  83. have_clk_lane = true;
  84. }
  85. if (fwnode_property_present(fwnode, "clock-noncontinuous"))
  86. flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
  87. else if (have_clk_lane || bus->num_data_lanes > 0)
  88. flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
  89. bus->flags = flags;
  90. vep->bus_type = V4L2_MBUS_CSI2;
  91. return 0;
  92. }
  93. static void v4l2_fwnode_endpoint_parse_parallel_bus(
  94. struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep)
  95. {
  96. struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel;
  97. unsigned int flags = 0;
  98. u32 v;
  99. if (!fwnode_property_read_u32(fwnode, "hsync-active", &v))
  100. flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH :
  101. V4L2_MBUS_HSYNC_ACTIVE_LOW;
  102. if (!fwnode_property_read_u32(fwnode, "vsync-active", &v))
  103. flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH :
  104. V4L2_MBUS_VSYNC_ACTIVE_LOW;
  105. if (!fwnode_property_read_u32(fwnode, "field-even-active", &v))
  106. flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH :
  107. V4L2_MBUS_FIELD_EVEN_LOW;
  108. if (flags)
  109. vep->bus_type = V4L2_MBUS_PARALLEL;
  110. else
  111. vep->bus_type = V4L2_MBUS_BT656;
  112. if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v))
  113. flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING :
  114. V4L2_MBUS_PCLK_SAMPLE_FALLING;
  115. if (!fwnode_property_read_u32(fwnode, "data-active", &v))
  116. flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH :
  117. V4L2_MBUS_DATA_ACTIVE_LOW;
  118. if (fwnode_property_present(fwnode, "slave-mode"))
  119. flags |= V4L2_MBUS_SLAVE;
  120. else
  121. flags |= V4L2_MBUS_MASTER;
  122. if (!fwnode_property_read_u32(fwnode, "bus-width", &v))
  123. bus->bus_width = v;
  124. if (!fwnode_property_read_u32(fwnode, "data-shift", &v))
  125. bus->data_shift = v;
  126. if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v))
  127. flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH :
  128. V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW;
  129. if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v))
  130. flags |= v ? V4L2_MBUS_DATA_ENABLE_HIGH :
  131. V4L2_MBUS_DATA_ENABLE_LOW;
  132. bus->flags = flags;
  133. }
  134. static void
  135. v4l2_fwnode_endpoint_parse_csi1_bus(struct fwnode_handle *fwnode,
  136. struct v4l2_fwnode_endpoint *vep,
  137. u32 bus_type)
  138. {
  139. struct v4l2_fwnode_bus_mipi_csi1 *bus = &vep->bus.mipi_csi1;
  140. u32 v;
  141. if (!fwnode_property_read_u32(fwnode, "clock-inv", &v))
  142. bus->clock_inv = v;
  143. if (!fwnode_property_read_u32(fwnode, "strobe", &v))
  144. bus->strobe = v;
  145. if (!fwnode_property_read_u32(fwnode, "data-lanes", &v))
  146. bus->data_lane = v;
  147. if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v))
  148. bus->clock_lane = v;
  149. if (bus_type == V4L2_FWNODE_BUS_TYPE_CCP2)
  150. vep->bus_type = V4L2_MBUS_CCP2;
  151. else
  152. vep->bus_type = V4L2_MBUS_CSI1;
  153. }
  154. int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
  155. struct v4l2_fwnode_endpoint *vep)
  156. {
  157. u32 bus_type = 0;
  158. int rval;
  159. fwnode_graph_parse_endpoint(fwnode, &vep->base);
  160. /* Zero fields from bus_type to until the end */
  161. memset(&vep->bus_type, 0, sizeof(*vep) -
  162. offsetof(typeof(*vep), bus_type));
  163. fwnode_property_read_u32(fwnode, "bus-type", &bus_type);
  164. switch (bus_type) {
  165. case V4L2_FWNODE_BUS_TYPE_GUESS:
  166. rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep);
  167. if (rval)
  168. return rval;
  169. /*
  170. * Parse the parallel video bus properties only if none
  171. * of the MIPI CSI-2 specific properties were found.
  172. */
  173. if (vep->bus.mipi_csi2.flags == 0)
  174. v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep);
  175. return 0;
  176. case V4L2_FWNODE_BUS_TYPE_CCP2:
  177. case V4L2_FWNODE_BUS_TYPE_CSI1:
  178. v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, bus_type);
  179. return 0;
  180. default:
  181. pr_warn("unsupported bus type %u\n", bus_type);
  182. return -EINVAL;
  183. }
  184. }
  185. EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse);
  186. void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep)
  187. {
  188. if (IS_ERR_OR_NULL(vep))
  189. return;
  190. kfree(vep->link_frequencies);
  191. kfree(vep);
  192. }
  193. EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free);
  194. struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse(
  195. struct fwnode_handle *fwnode)
  196. {
  197. struct v4l2_fwnode_endpoint *vep;
  198. int rval;
  199. vep = kzalloc(sizeof(*vep), GFP_KERNEL);
  200. if (!vep)
  201. return ERR_PTR(-ENOMEM);
  202. rval = v4l2_fwnode_endpoint_parse(fwnode, vep);
  203. if (rval < 0)
  204. goto out_err;
  205. rval = fwnode_property_read_u64_array(fwnode, "link-frequencies",
  206. NULL, 0);
  207. if (rval > 0) {
  208. vep->link_frequencies =
  209. kmalloc_array(rval, sizeof(*vep->link_frequencies),
  210. GFP_KERNEL);
  211. if (!vep->link_frequencies) {
  212. rval = -ENOMEM;
  213. goto out_err;
  214. }
  215. vep->nr_of_link_frequencies = rval;
  216. rval = fwnode_property_read_u64_array(
  217. fwnode, "link-frequencies", vep->link_frequencies,
  218. vep->nr_of_link_frequencies);
  219. if (rval < 0)
  220. goto out_err;
  221. }
  222. return vep;
  223. out_err:
  224. v4l2_fwnode_endpoint_free(vep);
  225. return ERR_PTR(rval);
  226. }
  227. EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse);
  228. int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode,
  229. struct v4l2_fwnode_link *link)
  230. {
  231. const char *port_prop = is_of_node(__fwnode) ? "reg" : "port";
  232. struct fwnode_handle *fwnode;
  233. memset(link, 0, sizeof(*link));
  234. fwnode = fwnode_get_parent(__fwnode);
  235. fwnode_property_read_u32(fwnode, port_prop, &link->local_port);
  236. fwnode = fwnode_get_next_parent(fwnode);
  237. if (is_of_node(fwnode) &&
  238. of_node_cmp(to_of_node(fwnode)->name, "ports") == 0)
  239. fwnode = fwnode_get_next_parent(fwnode);
  240. link->local_node = fwnode;
  241. fwnode = fwnode_graph_get_remote_endpoint(__fwnode);
  242. if (!fwnode) {
  243. fwnode_handle_put(fwnode);
  244. return -ENOLINK;
  245. }
  246. fwnode = fwnode_get_parent(fwnode);
  247. fwnode_property_read_u32(fwnode, port_prop, &link->remote_port);
  248. fwnode = fwnode_get_next_parent(fwnode);
  249. if (is_of_node(fwnode) &&
  250. of_node_cmp(to_of_node(fwnode)->name, "ports") == 0)
  251. fwnode = fwnode_get_next_parent(fwnode);
  252. link->remote_node = fwnode;
  253. return 0;
  254. }
  255. EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link);
  256. void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link)
  257. {
  258. fwnode_handle_put(link->local_node);
  259. fwnode_handle_put(link->remote_node);
  260. }
  261. EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
  262. static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier,
  263. unsigned int max_subdevs)
  264. {
  265. struct v4l2_async_subdev **subdevs;
  266. if (max_subdevs <= notifier->max_subdevs)
  267. return 0;
  268. subdevs = kvmalloc_array(
  269. max_subdevs, sizeof(*notifier->subdevs),
  270. GFP_KERNEL | __GFP_ZERO);
  271. if (!subdevs)
  272. return -ENOMEM;
  273. if (notifier->subdevs) {
  274. memcpy(subdevs, notifier->subdevs,
  275. sizeof(*subdevs) * notifier->num_subdevs);
  276. kvfree(notifier->subdevs);
  277. }
  278. notifier->subdevs = subdevs;
  279. notifier->max_subdevs = max_subdevs;
  280. return 0;
  281. }
  282. static int v4l2_async_notifier_fwnode_parse_endpoint(
  283. struct device *dev, struct v4l2_async_notifier *notifier,
  284. struct fwnode_handle *endpoint, unsigned int asd_struct_size,
  285. int (*parse_endpoint)(struct device *dev,
  286. struct v4l2_fwnode_endpoint *vep,
  287. struct v4l2_async_subdev *asd))
  288. {
  289. struct v4l2_async_subdev *asd;
  290. struct v4l2_fwnode_endpoint *vep;
  291. int ret = 0;
  292. asd = kzalloc(asd_struct_size, GFP_KERNEL);
  293. if (!asd)
  294. return -ENOMEM;
  295. asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
  296. asd->match.fwnode =
  297. fwnode_graph_get_remote_port_parent(endpoint);
  298. if (!asd->match.fwnode) {
  299. dev_warn(dev, "bad remote port parent\n");
  300. ret = -EINVAL;
  301. goto out_err;
  302. }
  303. vep = v4l2_fwnode_endpoint_alloc_parse(endpoint);
  304. if (IS_ERR(vep)) {
  305. ret = PTR_ERR(vep);
  306. dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n",
  307. ret);
  308. goto out_err;
  309. }
  310. ret = parse_endpoint ? parse_endpoint(dev, vep, asd) : 0;
  311. if (ret == -ENOTCONN)
  312. dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep->base.port,
  313. vep->base.id);
  314. else if (ret < 0)
  315. dev_warn(dev,
  316. "driver could not parse port@%u/endpoint@%u (%d)\n",
  317. vep->base.port, vep->base.id, ret);
  318. v4l2_fwnode_endpoint_free(vep);
  319. if (ret < 0)
  320. goto out_err;
  321. notifier->subdevs[notifier->num_subdevs] = asd;
  322. notifier->num_subdevs++;
  323. return 0;
  324. out_err:
  325. fwnode_handle_put(asd->match.fwnode);
  326. kfree(asd);
  327. return ret == -ENOTCONN ? 0 : ret;
  328. }
  329. static int __v4l2_async_notifier_parse_fwnode_endpoints(
  330. struct device *dev, struct v4l2_async_notifier *notifier,
  331. size_t asd_struct_size, unsigned int port, bool has_port,
  332. int (*parse_endpoint)(struct device *dev,
  333. struct v4l2_fwnode_endpoint *vep,
  334. struct v4l2_async_subdev *asd))
  335. {
  336. struct fwnode_handle *fwnode;
  337. unsigned int max_subdevs = notifier->max_subdevs;
  338. int ret;
  339. if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
  340. return -EINVAL;
  341. for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
  342. dev_fwnode(dev), fwnode)); ) {
  343. struct fwnode_handle *dev_fwnode;
  344. bool is_available;
  345. dev_fwnode = fwnode_graph_get_port_parent(fwnode);
  346. is_available = fwnode_device_is_available(dev_fwnode);
  347. fwnode_handle_put(dev_fwnode);
  348. if (!is_available)
  349. continue;
  350. if (has_port) {
  351. struct fwnode_endpoint ep;
  352. ret = fwnode_graph_parse_endpoint(fwnode, &ep);
  353. if (ret) {
  354. fwnode_handle_put(fwnode);
  355. return ret;
  356. }
  357. if (ep.port != port)
  358. continue;
  359. }
  360. max_subdevs++;
  361. }
  362. /* No subdevs to add? Return here. */
  363. if (max_subdevs == notifier->max_subdevs)
  364. return 0;
  365. ret = v4l2_async_notifier_realloc(notifier, max_subdevs);
  366. if (ret)
  367. return ret;
  368. for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
  369. dev_fwnode(dev), fwnode)); ) {
  370. struct fwnode_handle *dev_fwnode;
  371. bool is_available;
  372. dev_fwnode = fwnode_graph_get_port_parent(fwnode);
  373. is_available = fwnode_device_is_available(dev_fwnode);
  374. fwnode_handle_put(dev_fwnode);
  375. if (!is_available)
  376. continue;
  377. if (has_port) {
  378. struct fwnode_endpoint ep;
  379. ret = fwnode_graph_parse_endpoint(fwnode, &ep);
  380. if (ret)
  381. break;
  382. if (ep.port != port)
  383. continue;
  384. }
  385. if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
  386. ret = -EINVAL;
  387. break;
  388. }
  389. ret = v4l2_async_notifier_fwnode_parse_endpoint(
  390. dev, notifier, fwnode, asd_struct_size, parse_endpoint);
  391. if (ret < 0)
  392. break;
  393. }
  394. fwnode_handle_put(fwnode);
  395. return ret;
  396. }
  397. int v4l2_async_notifier_parse_fwnode_endpoints(
  398. struct device *dev, struct v4l2_async_notifier *notifier,
  399. size_t asd_struct_size,
  400. int (*parse_endpoint)(struct device *dev,
  401. struct v4l2_fwnode_endpoint *vep,
  402. struct v4l2_async_subdev *asd))
  403. {
  404. return __v4l2_async_notifier_parse_fwnode_endpoints(
  405. dev, notifier, asd_struct_size, 0, false, parse_endpoint);
  406. }
  407. EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints);
  408. int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
  409. struct device *dev, struct v4l2_async_notifier *notifier,
  410. size_t asd_struct_size, unsigned int port,
  411. int (*parse_endpoint)(struct device *dev,
  412. struct v4l2_fwnode_endpoint *vep,
  413. struct v4l2_async_subdev *asd))
  414. {
  415. return __v4l2_async_notifier_parse_fwnode_endpoints(
  416. dev, notifier, asd_struct_size, port, true, parse_endpoint);
  417. }
  418. EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port);
  419. /*
  420. * v4l2_fwnode_reference_parse - parse references for async sub-devices
  421. * @dev: the device node the properties of which are parsed for references
  422. * @notifier: the async notifier where the async subdevs will be added
  423. * @prop: the name of the property
  424. *
  425. * Return: 0 on success
  426. * -ENOENT if no entries were found
  427. * -ENOMEM if memory allocation failed
  428. * -EINVAL if property parsing failed
  429. */
  430. static int v4l2_fwnode_reference_parse(
  431. struct device *dev, struct v4l2_async_notifier *notifier,
  432. const char *prop)
  433. {
  434. struct fwnode_reference_args args;
  435. unsigned int index;
  436. int ret;
  437. for (index = 0;
  438. !(ret = fwnode_property_get_reference_args(
  439. dev_fwnode(dev), prop, NULL, 0, index, &args));
  440. index++)
  441. fwnode_handle_put(args.fwnode);
  442. if (!index)
  443. return -ENOENT;
  444. /*
  445. * Note that right now both -ENODATA and -ENOENT may signal
  446. * out-of-bounds access. Return the error in cases other than that.
  447. */
  448. if (ret != -ENOENT && ret != -ENODATA)
  449. return ret;
  450. ret = v4l2_async_notifier_realloc(notifier,
  451. notifier->num_subdevs + index);
  452. if (ret)
  453. return ret;
  454. for (index = 0; !fwnode_property_get_reference_args(
  455. dev_fwnode(dev), prop, NULL, 0, index, &args);
  456. index++) {
  457. struct v4l2_async_subdev *asd;
  458. if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
  459. ret = -EINVAL;
  460. goto error;
  461. }
  462. asd = kzalloc(sizeof(*asd), GFP_KERNEL);
  463. if (!asd) {
  464. ret = -ENOMEM;
  465. goto error;
  466. }
  467. notifier->subdevs[notifier->num_subdevs] = asd;
  468. asd->match.fwnode = args.fwnode;
  469. asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
  470. notifier->num_subdevs++;
  471. }
  472. return 0;
  473. error:
  474. fwnode_handle_put(args.fwnode);
  475. return ret;
  476. }
  477. /*
  478. * v4l2_fwnode_reference_get_int_prop - parse a reference with integer
  479. * arguments
  480. * @fwnode: fwnode to read @prop from
  481. * @notifier: notifier for @dev
  482. * @prop: the name of the property
  483. * @index: the index of the reference to get
  484. * @props: the array of integer property names
  485. * @nprops: the number of integer property names in @nprops
  486. *
  487. * First find an fwnode referred to by the reference at @index in @prop.
  488. *
  489. * Then under that fwnode, @nprops times, for each property in @props,
  490. * iteratively follow child nodes starting from fwnode such that they have the
  491. * property in @props array at the index of the child node distance from the
  492. * root node and the value of that property matching with the integer argument
  493. * of the reference, at the same index.
  494. *
  495. * The child fwnode reched at the end of the iteration is then returned to the
  496. * caller.
  497. *
  498. * The core reason for this is that you cannot refer to just any node in ACPI.
  499. * So to refer to an endpoint (easy in DT) you need to refer to a device, then
  500. * provide a list of (property name, property value) tuples where each tuple
  501. * uniquely identifies a child node. The first tuple identifies a child directly
  502. * underneath the device fwnode, the next tuple identifies a child node
  503. * underneath the fwnode identified by the previous tuple, etc. until you
  504. * reached the fwnode you need.
  505. *
  506. * An example with a graph, as defined in Documentation/acpi/dsd/graph.txt:
  507. *
  508. * Scope (\_SB.PCI0.I2C2)
  509. * {
  510. * Device (CAM0)
  511. * {
  512. * Name (_DSD, Package () {
  513. * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
  514. * Package () {
  515. * Package () {
  516. * "compatible",
  517. * Package () { "nokia,smia" }
  518. * },
  519. * },
  520. * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
  521. * Package () {
  522. * Package () { "port0", "PRT0" },
  523. * }
  524. * })
  525. * Name (PRT0, Package() {
  526. * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
  527. * Package () {
  528. * Package () { "port", 0 },
  529. * },
  530. * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
  531. * Package () {
  532. * Package () { "endpoint0", "EP00" },
  533. * }
  534. * })
  535. * Name (EP00, Package() {
  536. * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
  537. * Package () {
  538. * Package () { "endpoint", 0 },
  539. * Package () {
  540. * "remote-endpoint",
  541. * Package() {
  542. * \_SB.PCI0.ISP, 4, 0
  543. * }
  544. * },
  545. * }
  546. * })
  547. * }
  548. * }
  549. *
  550. * Scope (\_SB.PCI0)
  551. * {
  552. * Device (ISP)
  553. * {
  554. * Name (_DSD, Package () {
  555. * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
  556. * Package () {
  557. * Package () { "port4", "PRT4" },
  558. * }
  559. * })
  560. *
  561. * Name (PRT4, Package() {
  562. * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
  563. * Package () {
  564. * Package () { "port", 4 },
  565. * },
  566. * ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
  567. * Package () {
  568. * Package () { "endpoint0", "EP40" },
  569. * }
  570. * })
  571. *
  572. * Name (EP40, Package() {
  573. * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
  574. * Package () {
  575. * Package () { "endpoint", 0 },
  576. * Package () {
  577. * "remote-endpoint",
  578. * Package () {
  579. * \_SB.PCI0.I2C2.CAM0,
  580. * 0, 0
  581. * }
  582. * },
  583. * }
  584. * })
  585. * }
  586. * }
  587. *
  588. * From the EP40 node under ISP device, you could parse the graph remote
  589. * endpoint using v4l2_fwnode_reference_get_int_prop with these arguments:
  590. *
  591. * @fwnode: fwnode referring to EP40 under ISP.
  592. * @prop: "remote-endpoint"
  593. * @index: 0
  594. * @props: "port", "endpoint"
  595. * @nprops: 2
  596. *
  597. * And you'd get back fwnode referring to EP00 under CAM0.
  598. *
  599. * The same works the other way around: if you use EP00 under CAM0 as the
  600. * fwnode, you'll get fwnode referring to EP40 under ISP.
  601. *
  602. * The same example in DT syntax would look like this:
  603. *
  604. * cam: cam0 {
  605. * compatible = "nokia,smia";
  606. *
  607. * port {
  608. * port = <0>;
  609. * endpoint {
  610. * endpoint = <0>;
  611. * remote-endpoint = <&isp 4 0>;
  612. * };
  613. * };
  614. * };
  615. *
  616. * isp: isp {
  617. * ports {
  618. * port@4 {
  619. * port = <4>;
  620. * endpoint {
  621. * endpoint = <0>;
  622. * remote-endpoint = <&cam 0 0>;
  623. * };
  624. * };
  625. * };
  626. * };
  627. *
  628. * Return: 0 on success
  629. * -ENOENT if no entries (or the property itself) were found
  630. * -EINVAL if property parsing otherwise failed
  631. * -ENOMEM if memory allocation failed
  632. */
  633. static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop(
  634. struct fwnode_handle *fwnode, const char *prop, unsigned int index,
  635. const char * const *props, unsigned int nprops)
  636. {
  637. struct fwnode_reference_args fwnode_args;
  638. u64 *args = fwnode_args.args;
  639. struct fwnode_handle *child;
  640. int ret;
  641. /*
  642. * Obtain remote fwnode as well as the integer arguments.
  643. *
  644. * Note that right now both -ENODATA and -ENOENT may signal
  645. * out-of-bounds access. Return -ENOENT in that case.
  646. */
  647. ret = fwnode_property_get_reference_args(fwnode, prop, NULL, nprops,
  648. index, &fwnode_args);
  649. if (ret)
  650. return ERR_PTR(ret == -ENODATA ? -ENOENT : ret);
  651. /*
  652. * Find a node in the tree under the referred fwnode corresponding to
  653. * the integer arguments.
  654. */
  655. fwnode = fwnode_args.fwnode;
  656. while (nprops--) {
  657. u32 val;
  658. /* Loop over all child nodes under fwnode. */
  659. fwnode_for_each_child_node(fwnode, child) {
  660. if (fwnode_property_read_u32(child, *props, &val))
  661. continue;
  662. /* Found property, see if its value matches. */
  663. if (val == *args)
  664. break;
  665. }
  666. fwnode_handle_put(fwnode);
  667. /* No property found; return an error here. */
  668. if (!child) {
  669. fwnode = ERR_PTR(-ENOENT);
  670. break;
  671. }
  672. props++;
  673. args++;
  674. fwnode = child;
  675. }
  676. return fwnode;
  677. }
  678. /*
  679. * v4l2_fwnode_reference_parse_int_props - parse references for async
  680. * sub-devices
  681. * @dev: struct device pointer
  682. * @notifier: notifier for @dev
  683. * @prop: the name of the property
  684. * @props: the array of integer property names
  685. * @nprops: the number of integer properties
  686. *
  687. * Use v4l2_fwnode_reference_get_int_prop to find fwnodes through reference in
  688. * property @prop with integer arguments with child nodes matching in properties
  689. * @props. Then, set up V4L2 async sub-devices for those fwnodes in the notifier
  690. * accordingly.
  691. *
  692. * While it is technically possible to use this function on DT, it is only
  693. * meaningful on ACPI. On Device tree you can refer to any node in the tree but
  694. * on ACPI the references are limited to devices.
  695. *
  696. * Return: 0 on success
  697. * -ENOENT if no entries (or the property itself) were found
  698. * -EINVAL if property parsing otherwisefailed
  699. * -ENOMEM if memory allocation failed
  700. */
  701. static int v4l2_fwnode_reference_parse_int_props(
  702. struct device *dev, struct v4l2_async_notifier *notifier,
  703. const char *prop, const char * const *props, unsigned int nprops)
  704. {
  705. struct fwnode_handle *fwnode;
  706. unsigned int index;
  707. int ret;
  708. index = 0;
  709. do {
  710. fwnode = v4l2_fwnode_reference_get_int_prop(dev_fwnode(dev),
  711. prop, index,
  712. props, nprops);
  713. if (IS_ERR(fwnode)) {
  714. /*
  715. * Note that right now both -ENODATA and -ENOENT may
  716. * signal out-of-bounds access. Return the error in
  717. * cases other than that.
  718. */
  719. if (PTR_ERR(fwnode) != -ENOENT &&
  720. PTR_ERR(fwnode) != -ENODATA)
  721. return PTR_ERR(fwnode);
  722. break;
  723. }
  724. fwnode_handle_put(fwnode);
  725. index++;
  726. } while (1);
  727. ret = v4l2_async_notifier_realloc(notifier,
  728. notifier->num_subdevs + index);
  729. if (ret)
  730. return -ENOMEM;
  731. for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(
  732. dev_fwnode(dev), prop, index, props,
  733. nprops))); index++) {
  734. struct v4l2_async_subdev *asd;
  735. if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
  736. ret = -EINVAL;
  737. goto error;
  738. }
  739. asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL);
  740. if (!asd) {
  741. ret = -ENOMEM;
  742. goto error;
  743. }
  744. notifier->subdevs[notifier->num_subdevs] = asd;
  745. asd->match.fwnode = fwnode;
  746. asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
  747. notifier->num_subdevs++;
  748. }
  749. return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
  750. error:
  751. fwnode_handle_put(fwnode);
  752. return ret;
  753. }
  754. int v4l2_async_notifier_parse_fwnode_sensor_common(
  755. struct device *dev, struct v4l2_async_notifier *notifier)
  756. {
  757. static const char * const led_props[] = { "led" };
  758. static const struct {
  759. const char *name;
  760. const char * const *props;
  761. unsigned int nprops;
  762. } props[] = {
  763. { "flash-leds", led_props, ARRAY_SIZE(led_props) },
  764. { "lens-focus", NULL, 0 },
  765. };
  766. unsigned int i;
  767. for (i = 0; i < ARRAY_SIZE(props); i++) {
  768. int ret;
  769. if (props[i].props && is_acpi_node(dev_fwnode(dev)))
  770. ret = v4l2_fwnode_reference_parse_int_props(
  771. dev, notifier, props[i].name,
  772. props[i].props, props[i].nprops);
  773. else
  774. ret = v4l2_fwnode_reference_parse(
  775. dev, notifier, props[i].name);
  776. if (ret && ret != -ENOENT) {
  777. dev_warn(dev, "parsing property \"%s\" failed (%d)\n",
  778. props[i].name, ret);
  779. return ret;
  780. }
  781. }
  782. return 0;
  783. }
  784. EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_sensor_common);
  785. int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
  786. {
  787. struct v4l2_async_notifier *notifier;
  788. int ret;
  789. if (WARN_ON(!sd->dev))
  790. return -ENODEV;
  791. notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
  792. if (!notifier)
  793. return -ENOMEM;
  794. ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev,
  795. notifier);
  796. if (ret < 0)
  797. goto out_cleanup;
  798. ret = v4l2_async_subdev_notifier_register(sd, notifier);
  799. if (ret < 0)
  800. goto out_cleanup;
  801. ret = v4l2_async_register_subdev(sd);
  802. if (ret < 0)
  803. goto out_unregister;
  804. sd->subdev_notifier = notifier;
  805. return 0;
  806. out_unregister:
  807. v4l2_async_notifier_unregister(notifier);
  808. out_cleanup:
  809. v4l2_async_notifier_cleanup(notifier);
  810. kfree(notifier);
  811. return ret;
  812. }
  813. EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
  814. MODULE_LICENSE("GPL");
  815. MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
  816. MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
  817. MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");