v4l2-fwnode.c 24 KB

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