v4l2-fwnode.c 25 KB

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