rcar-isp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2021 Renesas Electronics Corp.
  4. *
  5. * Driver for Renesas R-Car ISP Channel Selector
  6. *
  7. * The ISP hardware is capable of more than just channel selection, features
  8. * such as demosaicing, white balance control and color space conversion are
  9. * also possible. These more advanced features are not supported by the driver
  10. * due to lack of documentation.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/mutex.h>
  14. #include <linux/of_device.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/pm_runtime.h>
  17. #include <linux/reset.h>
  18. #include <media/mipi-csi2.h>
  19. #include <media/v4l2-subdev.h>
  20. #define ISPINPUTSEL0_REG 0x0008
  21. #define ISPINPUTSEL0_SEL_CSI0 BIT(31)
  22. #define ISPSTART_REG 0x0014
  23. #define ISPSTART_START 0xffff
  24. #define ISPSTART_STOP 0x0000
  25. #define ISPPROCMODE_DT_REG(n) (0x1100 + (0x4 * (n)))
  26. #define ISPPROCMODE_DT_PROC_MODE_VC3(pm) (((pm) & 0x3f) << 24)
  27. #define ISPPROCMODE_DT_PROC_MODE_VC2(pm) (((pm) & 0x3f) << 16)
  28. #define ISPPROCMODE_DT_PROC_MODE_VC1(pm) (((pm) & 0x3f) << 8)
  29. #define ISPPROCMODE_DT_PROC_MODE_VC0(pm) ((pm) & 0x3f)
  30. #define ISPCS_FILTER_ID_CH_REG(n) (0x3000 + (0x0100 * (n)))
  31. #define ISPCS_DT_CODE03_CH_REG(n) (0x3008 + (0x100 * (n)))
  32. #define ISPCS_DT_CODE03_EN3 BIT(31)
  33. #define ISPCS_DT_CODE03_DT3(dt) (((dt) & 0x3f) << 24)
  34. #define ISPCS_DT_CODE03_EN2 BIT(23)
  35. #define ISPCS_DT_CODE03_DT2(dt) (((dt) & 0x3f) << 16)
  36. #define ISPCS_DT_CODE03_EN1 BIT(15)
  37. #define ISPCS_DT_CODE03_DT1(dt) (((dt) & 0x3f) << 8)
  38. #define ISPCS_DT_CODE03_EN0 BIT(7)
  39. #define ISPCS_DT_CODE03_DT0(dt) ((dt) & 0x3f)
  40. struct rcar_isp_format {
  41. u32 code;
  42. unsigned int datatype;
  43. unsigned int procmode;
  44. };
  45. static const struct rcar_isp_format rcar_isp_formats[] = {
  46. {
  47. .code = MEDIA_BUS_FMT_RGB888_1X24,
  48. .datatype = MIPI_CSI2_DT_RGB888,
  49. .procmode = 0x15
  50. }, {
  51. .code = MEDIA_BUS_FMT_Y10_1X10,
  52. .datatype = MIPI_CSI2_DT_RAW10,
  53. .procmode = 0x10,
  54. }, {
  55. .code = MEDIA_BUS_FMT_UYVY8_1X16,
  56. .datatype = MIPI_CSI2_DT_YUV422_8B,
  57. .procmode = 0x0c,
  58. }, {
  59. .code = MEDIA_BUS_FMT_YUYV8_1X16,
  60. .datatype = MIPI_CSI2_DT_YUV422_8B,
  61. .procmode = 0x0c,
  62. }, {
  63. .code = MEDIA_BUS_FMT_UYVY8_2X8,
  64. .datatype = MIPI_CSI2_DT_YUV422_8B,
  65. .procmode = 0x0c,
  66. }, {
  67. .code = MEDIA_BUS_FMT_YUYV10_2X10,
  68. .datatype = MIPI_CSI2_DT_YUV422_8B,
  69. .procmode = 0x0c,
  70. },
  71. };
  72. static const struct rcar_isp_format *risp_code_to_fmt(unsigned int code)
  73. {
  74. unsigned int i;
  75. for (i = 0; i < ARRAY_SIZE(rcar_isp_formats); i++) {
  76. if (rcar_isp_formats[i].code == code)
  77. return &rcar_isp_formats[i];
  78. }
  79. return NULL;
  80. }
  81. enum rcar_isp_input {
  82. RISP_CSI_INPUT0,
  83. RISP_CSI_INPUT1,
  84. };
  85. enum rcar_isp_pads {
  86. RCAR_ISP_SINK,
  87. RCAR_ISP_PORT0,
  88. RCAR_ISP_PORT1,
  89. RCAR_ISP_PORT2,
  90. RCAR_ISP_PORT3,
  91. RCAR_ISP_PORT4,
  92. RCAR_ISP_PORT5,
  93. RCAR_ISP_PORT6,
  94. RCAR_ISP_PORT7,
  95. RCAR_ISP_NUM_PADS,
  96. };
  97. struct rcar_isp {
  98. struct device *dev;
  99. void __iomem *base;
  100. struct reset_control *rstc;
  101. enum rcar_isp_input csi_input;
  102. struct v4l2_subdev subdev;
  103. struct media_pad pads[RCAR_ISP_NUM_PADS];
  104. struct v4l2_async_notifier notifier;
  105. struct v4l2_subdev *remote;
  106. struct mutex lock; /* Protects mf and stream_count. */
  107. struct v4l2_mbus_framefmt mf;
  108. int stream_count;
  109. };
  110. static inline struct rcar_isp *sd_to_isp(struct v4l2_subdev *sd)
  111. {
  112. return container_of(sd, struct rcar_isp, subdev);
  113. }
  114. static inline struct rcar_isp *notifier_to_isp(struct v4l2_async_notifier *n)
  115. {
  116. return container_of(n, struct rcar_isp, notifier);
  117. }
  118. static void risp_write(struct rcar_isp *isp, u32 offset, u32 value)
  119. {
  120. iowrite32(value, isp->base + offset);
  121. }
  122. static u32 risp_read(struct rcar_isp *isp, u32 offset)
  123. {
  124. return ioread32(isp->base + offset);
  125. }
  126. static int risp_power_on(struct rcar_isp *isp)
  127. {
  128. int ret;
  129. ret = pm_runtime_resume_and_get(isp->dev);
  130. if (ret < 0)
  131. return ret;
  132. ret = reset_control_deassert(isp->rstc);
  133. if (ret < 0) {
  134. pm_runtime_put(isp->dev);
  135. return ret;
  136. }
  137. return 0;
  138. }
  139. static void risp_power_off(struct rcar_isp *isp)
  140. {
  141. reset_control_assert(isp->rstc);
  142. pm_runtime_put(isp->dev);
  143. }
  144. static int risp_start(struct rcar_isp *isp)
  145. {
  146. const struct rcar_isp_format *format;
  147. unsigned int vc;
  148. u32 sel_csi = 0;
  149. int ret;
  150. format = risp_code_to_fmt(isp->mf.code);
  151. if (!format) {
  152. dev_err(isp->dev, "Unsupported bus format\n");
  153. return -EINVAL;
  154. }
  155. ret = risp_power_on(isp);
  156. if (ret) {
  157. dev_err(isp->dev, "Failed to power on ISP\n");
  158. return ret;
  159. }
  160. /* Select CSI-2 input source. */
  161. if (isp->csi_input == RISP_CSI_INPUT1)
  162. sel_csi = ISPINPUTSEL0_SEL_CSI0;
  163. risp_write(isp, ISPINPUTSEL0_REG,
  164. risp_read(isp, ISPINPUTSEL0_REG) | sel_csi);
  165. /* Configure Channel Selector. */
  166. for (vc = 0; vc < 4; vc++) {
  167. u8 ch = vc + 4;
  168. u8 dt = format->datatype;
  169. risp_write(isp, ISPCS_FILTER_ID_CH_REG(ch), BIT(vc));
  170. risp_write(isp, ISPCS_DT_CODE03_CH_REG(ch),
  171. ISPCS_DT_CODE03_EN3 | ISPCS_DT_CODE03_DT3(dt) |
  172. ISPCS_DT_CODE03_EN2 | ISPCS_DT_CODE03_DT2(dt) |
  173. ISPCS_DT_CODE03_EN1 | ISPCS_DT_CODE03_DT1(dt) |
  174. ISPCS_DT_CODE03_EN0 | ISPCS_DT_CODE03_DT0(dt));
  175. }
  176. /* Setup processing method. */
  177. risp_write(isp, ISPPROCMODE_DT_REG(format->datatype),
  178. ISPPROCMODE_DT_PROC_MODE_VC3(format->procmode) |
  179. ISPPROCMODE_DT_PROC_MODE_VC2(format->procmode) |
  180. ISPPROCMODE_DT_PROC_MODE_VC1(format->procmode) |
  181. ISPPROCMODE_DT_PROC_MODE_VC0(format->procmode));
  182. /* Start ISP. */
  183. risp_write(isp, ISPSTART_REG, ISPSTART_START);
  184. ret = v4l2_subdev_call(isp->remote, video, s_stream, 1);
  185. if (ret)
  186. risp_power_off(isp);
  187. return ret;
  188. }
  189. static void risp_stop(struct rcar_isp *isp)
  190. {
  191. v4l2_subdev_call(isp->remote, video, s_stream, 0);
  192. /* Stop ISP. */
  193. risp_write(isp, ISPSTART_REG, ISPSTART_STOP);
  194. risp_power_off(isp);
  195. }
  196. static int risp_s_stream(struct v4l2_subdev *sd, int enable)
  197. {
  198. struct rcar_isp *isp = sd_to_isp(sd);
  199. int ret = 0;
  200. mutex_lock(&isp->lock);
  201. if (!isp->remote) {
  202. ret = -ENODEV;
  203. goto out;
  204. }
  205. if (enable && isp->stream_count == 0) {
  206. ret = risp_start(isp);
  207. if (ret)
  208. goto out;
  209. } else if (!enable && isp->stream_count == 1) {
  210. risp_stop(isp);
  211. }
  212. isp->stream_count += enable ? 1 : -1;
  213. out:
  214. mutex_unlock(&isp->lock);
  215. return ret;
  216. }
  217. static const struct v4l2_subdev_video_ops risp_video_ops = {
  218. .s_stream = risp_s_stream,
  219. };
  220. static int risp_set_pad_format(struct v4l2_subdev *sd,
  221. struct v4l2_subdev_state *sd_state,
  222. struct v4l2_subdev_format *format)
  223. {
  224. struct rcar_isp *isp = sd_to_isp(sd);
  225. struct v4l2_mbus_framefmt *framefmt;
  226. mutex_lock(&isp->lock);
  227. if (!risp_code_to_fmt(format->format.code))
  228. format->format.code = rcar_isp_formats[0].code;
  229. if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
  230. isp->mf = format->format;
  231. } else {
  232. framefmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
  233. *framefmt = format->format;
  234. }
  235. mutex_unlock(&isp->lock);
  236. return 0;
  237. }
  238. static int risp_get_pad_format(struct v4l2_subdev *sd,
  239. struct v4l2_subdev_state *sd_state,
  240. struct v4l2_subdev_format *format)
  241. {
  242. struct rcar_isp *isp = sd_to_isp(sd);
  243. mutex_lock(&isp->lock);
  244. if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
  245. format->format = isp->mf;
  246. else
  247. format->format = *v4l2_subdev_get_try_format(sd, sd_state, 0);
  248. mutex_unlock(&isp->lock);
  249. return 0;
  250. }
  251. static const struct v4l2_subdev_pad_ops risp_pad_ops = {
  252. .set_fmt = risp_set_pad_format,
  253. .get_fmt = risp_get_pad_format,
  254. .link_validate = v4l2_subdev_link_validate_default,
  255. };
  256. static const struct v4l2_subdev_ops rcar_isp_subdev_ops = {
  257. .video = &risp_video_ops,
  258. .pad = &risp_pad_ops,
  259. };
  260. /* -----------------------------------------------------------------------------
  261. * Async handling and registration of subdevices and links
  262. */
  263. static int risp_notify_bound(struct v4l2_async_notifier *notifier,
  264. struct v4l2_subdev *subdev,
  265. struct v4l2_async_subdev *asd)
  266. {
  267. struct rcar_isp *isp = notifier_to_isp(notifier);
  268. int pad;
  269. pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode,
  270. MEDIA_PAD_FL_SOURCE);
  271. if (pad < 0) {
  272. dev_err(isp->dev, "Failed to find pad for %s\n", subdev->name);
  273. return pad;
  274. }
  275. isp->remote = subdev;
  276. dev_dbg(isp->dev, "Bound %s pad: %d\n", subdev->name, pad);
  277. return media_create_pad_link(&subdev->entity, pad,
  278. &isp->subdev.entity, 0,
  279. MEDIA_LNK_FL_ENABLED |
  280. MEDIA_LNK_FL_IMMUTABLE);
  281. }
  282. static void risp_notify_unbind(struct v4l2_async_notifier *notifier,
  283. struct v4l2_subdev *subdev,
  284. struct v4l2_async_subdev *asd)
  285. {
  286. struct rcar_isp *isp = notifier_to_isp(notifier);
  287. isp->remote = NULL;
  288. dev_dbg(isp->dev, "Unbind %s\n", subdev->name);
  289. }
  290. static const struct v4l2_async_notifier_operations risp_notify_ops = {
  291. .bound = risp_notify_bound,
  292. .unbind = risp_notify_unbind,
  293. };
  294. static int risp_parse_dt(struct rcar_isp *isp)
  295. {
  296. struct v4l2_async_subdev *asd;
  297. struct fwnode_handle *fwnode;
  298. struct fwnode_handle *ep;
  299. unsigned int id;
  300. int ret;
  301. for (id = 0; id < 2; id++) {
  302. ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(isp->dev),
  303. 0, id, 0);
  304. if (ep)
  305. break;
  306. }
  307. if (!ep) {
  308. dev_err(isp->dev, "Not connected to subdevice\n");
  309. return -EINVAL;
  310. }
  311. if (id == 1)
  312. isp->csi_input = RISP_CSI_INPUT1;
  313. fwnode = fwnode_graph_get_remote_endpoint(ep);
  314. fwnode_handle_put(ep);
  315. dev_dbg(isp->dev, "Found '%pOF'\n", to_of_node(fwnode));
  316. v4l2_async_nf_init(&isp->notifier);
  317. isp->notifier.ops = &risp_notify_ops;
  318. asd = v4l2_async_nf_add_fwnode(&isp->notifier, fwnode,
  319. struct v4l2_async_subdev);
  320. fwnode_handle_put(fwnode);
  321. if (IS_ERR(asd))
  322. return PTR_ERR(asd);
  323. ret = v4l2_async_subdev_nf_register(&isp->subdev, &isp->notifier);
  324. if (ret)
  325. v4l2_async_nf_cleanup(&isp->notifier);
  326. return ret;
  327. }
  328. /* -----------------------------------------------------------------------------
  329. * Platform Device Driver
  330. */
  331. static const struct media_entity_operations risp_entity_ops = {
  332. .link_validate = v4l2_subdev_link_validate,
  333. };
  334. static int risp_probe_resources(struct rcar_isp *isp,
  335. struct platform_device *pdev)
  336. {
  337. struct resource *res;
  338. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  339. isp->base = devm_ioremap_resource(&pdev->dev, res);
  340. if (IS_ERR(isp->base))
  341. return PTR_ERR(isp->base);
  342. isp->rstc = devm_reset_control_get(&pdev->dev, NULL);
  343. return PTR_ERR_OR_ZERO(isp->rstc);
  344. }
  345. static const struct of_device_id risp_of_id_table[] = {
  346. { .compatible = "renesas,r8a779a0-isp" },
  347. { /* sentinel */ },
  348. };
  349. MODULE_DEVICE_TABLE(of, risp_of_id_table);
  350. static int risp_probe(struct platform_device *pdev)
  351. {
  352. struct rcar_isp *isp;
  353. unsigned int i;
  354. int ret;
  355. isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
  356. if (!isp)
  357. return -ENOMEM;
  358. isp->dev = &pdev->dev;
  359. mutex_init(&isp->lock);
  360. ret = risp_probe_resources(isp, pdev);
  361. if (ret) {
  362. dev_err(isp->dev, "Failed to get resources\n");
  363. goto error_mutex;
  364. }
  365. platform_set_drvdata(pdev, isp);
  366. pm_runtime_enable(&pdev->dev);
  367. ret = risp_parse_dt(isp);
  368. if (ret)
  369. goto error_pm;
  370. isp->subdev.owner = THIS_MODULE;
  371. isp->subdev.dev = &pdev->dev;
  372. v4l2_subdev_init(&isp->subdev, &rcar_isp_subdev_ops);
  373. v4l2_set_subdevdata(&isp->subdev, &pdev->dev);
  374. snprintf(isp->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s %s",
  375. KBUILD_MODNAME, dev_name(&pdev->dev));
  376. isp->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
  377. isp->subdev.entity.function = MEDIA_ENT_F_VID_MUX;
  378. isp->subdev.entity.ops = &risp_entity_ops;
  379. isp->pads[RCAR_ISP_SINK].flags = MEDIA_PAD_FL_SINK;
  380. for (i = RCAR_ISP_PORT0; i < RCAR_ISP_NUM_PADS; i++)
  381. isp->pads[i].flags = MEDIA_PAD_FL_SOURCE;
  382. ret = media_entity_pads_init(&isp->subdev.entity, RCAR_ISP_NUM_PADS,
  383. isp->pads);
  384. if (ret)
  385. goto error_notifier;
  386. ret = v4l2_async_register_subdev(&isp->subdev);
  387. if (ret < 0)
  388. goto error_notifier;
  389. dev_info(isp->dev, "Using CSI-2 input: %u\n", isp->csi_input);
  390. return 0;
  391. error_notifier:
  392. v4l2_async_nf_unregister(&isp->notifier);
  393. v4l2_async_nf_cleanup(&isp->notifier);
  394. error_pm:
  395. pm_runtime_disable(&pdev->dev);
  396. error_mutex:
  397. mutex_destroy(&isp->lock);
  398. return ret;
  399. }
  400. static int risp_remove(struct platform_device *pdev)
  401. {
  402. struct rcar_isp *isp = platform_get_drvdata(pdev);
  403. v4l2_async_nf_unregister(&isp->notifier);
  404. v4l2_async_nf_cleanup(&isp->notifier);
  405. v4l2_async_unregister_subdev(&isp->subdev);
  406. pm_runtime_disable(&pdev->dev);
  407. mutex_destroy(&isp->lock);
  408. return 0;
  409. }
  410. static struct platform_driver rcar_isp_driver = {
  411. .driver = {
  412. .name = "rcar-isp",
  413. .of_match_table = risp_of_id_table,
  414. },
  415. .probe = risp_probe,
  416. .remove = risp_remove,
  417. };
  418. module_platform_driver(rcar_isp_driver);
  419. MODULE_AUTHOR("Niklas Söderlund <[email protected]>");
  420. MODULE_DESCRIPTION("Renesas R-Car ISP Channel Selector driver");
  421. MODULE_LICENSE("GPL");