185-media-atmel-atmel-isc-add-microchip-xisc-driver.patch 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. From 74fd7ea680cb1a3a43b51a7279aea45efdf9ec42 Mon Sep 17 00:00:00 2001
  2. From: Eugen Hristev <[email protected]>
  3. Date: Tue, 13 Apr 2021 12:57:29 +0200
  4. Subject: [PATCH 185/247] media: atmel: atmel-isc: add microchip-xisc driver
  5. Add driver for the extended variant of the isc, the microchip XISC
  6. present on sama7g5 product.
  7. [hverkuil: drop MODULE_SUPPORTED_DEVICE, no longer exists]
  8. [hverkuil: made isc_sama7g5_config_csc et al static]
  9. [hverkuil: made sama7g5_controller_formats et al static]
  10. Signed-off-by: Eugen Hristev <[email protected]>
  11. Signed-off-by: Hans Verkuil <[email protected]>
  12. Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  13. ---
  14. drivers/media/platform/Makefile | 1 +
  15. drivers/media/platform/atmel/Kconfig | 11 +
  16. drivers/media/platform/atmel/Makefile | 2 +
  17. drivers/media/platform/atmel/atmel-isc-base.c | 2 +-
  18. drivers/media/platform/atmel/atmel-isc-regs.h | 26 +
  19. .../media/platform/atmel/atmel-sama7g5-isc.c | 630 ++++++++++++++++++
  20. 6 files changed, 671 insertions(+), 1 deletion(-)
  21. create mode 100644 drivers/media/platform/atmel/atmel-sama7g5-isc.c
  22. --- a/drivers/media/platform/Makefile
  23. +++ b/drivers/media/platform/Makefile
  24. @@ -64,6 +64,7 @@ obj-$(CONFIG_VIDEO_RCAR_VIN) += rcar-vi
  25. obj-$(CONFIG_VIDEO_ATMEL_ISC) += atmel/
  26. obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel/
  27. +obj-$(CONFIG_VIDEO_ATMEL_XISC) += atmel/
  28. obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32/
  29. --- a/drivers/media/platform/atmel/Kconfig
  30. +++ b/drivers/media/platform/atmel/Kconfig
  31. @@ -12,6 +12,17 @@ config VIDEO_ATMEL_ISC
  32. This module makes the ATMEL Image Sensor Controller available
  33. as a v4l2 device.
  34. +config VIDEO_ATMEL_XISC
  35. + tristate "ATMEL eXtended Image Sensor Controller (XISC) support"
  36. + depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API
  37. + depends on ARCH_AT91 || COMPILE_TEST
  38. + select VIDEOBUF2_DMA_CONTIG
  39. + select REGMAP_MMIO
  40. + select V4L2_FWNODE
  41. + help
  42. + This module makes the ATMEL eXtended Image Sensor Controller
  43. + available as a v4l2 device.
  44. +
  45. config VIDEO_ATMEL_ISI
  46. tristate "ATMEL Image Sensor Interface (ISI) support"
  47. depends on VIDEO_V4L2 && OF
  48. --- a/drivers/media/platform/atmel/Makefile
  49. +++ b/drivers/media/platform/atmel/Makefile
  50. @@ -1,5 +1,7 @@
  51. # SPDX-License-Identifier: GPL-2.0-only
  52. atmel-isc-objs = atmel-sama5d2-isc.o atmel-isc-base.o
  53. +atmel-xisc-objs = atmel-sama7g5-isc.o atmel-isc-base.o
  54. obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o
  55. obj-$(CONFIG_VIDEO_ATMEL_ISC) += atmel-isc.o
  56. +obj-$(CONFIG_VIDEO_ATMEL_XISC) += atmel-xisc.o
  57. --- a/drivers/media/platform/atmel/atmel-isc-base.c
  58. +++ b/drivers/media/platform/atmel/atmel-isc-base.c
  59. @@ -600,7 +600,7 @@ static int isc_configure(struct isc_devi
  60. mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_LOW |
  61. ISC_PFE_CFG0_VPOL_LOW | ISC_PFE_CFG0_PPOL_LOW |
  62. ISC_PFE_CFG0_MODE_MASK | ISC_PFE_CFG0_CCIR_CRC |
  63. - ISC_PFE_CFG0_CCIR656;
  64. + ISC_PFE_CFG0_CCIR656 | ISC_PFE_CFG0_MIPI;
  65. regmap_update_bits(regmap, ISC_PFE_CFG0, mask, pfe_cfg0);
  66. --- a/drivers/media/platform/atmel/atmel-isc-regs.h
  67. +++ b/drivers/media/platform/atmel/atmel-isc-regs.h
  68. @@ -26,6 +26,7 @@
  69. #define ISC_PFE_CFG0_PPOL_LOW BIT(2)
  70. #define ISC_PFE_CFG0_CCIR656 BIT(9)
  71. #define ISC_PFE_CFG0_CCIR_CRC BIT(10)
  72. +#define ISC_PFE_CFG0_MIPI BIT(14)
  73. #define ISC_PFE_CFG0_MODE_PROGRESSIVE (0x0 << 4)
  74. #define ISC_PFE_CFG0_MODE_MASK GENMASK(6, 4)
  75. @@ -184,6 +185,8 @@
  76. /* ISC Gamma Correction Control Register */
  77. #define ISC_GAM_CTRL 0x00000094
  78. +#define ISC_GAM_CTRL_BIPART BIT(4)
  79. +
  80. /* ISC_Gamma Correction Blue Entry Register */
  81. #define ISC_GAM_BENTRY 0x00000098
  82. @@ -222,6 +225,8 @@
  83. /* Offset for CSC register specific to sama5d2 product */
  84. #define ISC_SAMA5D2_CSC_OFFSET 0
  85. +/* Offset for CSC register specific to sama7g5 product */
  86. +#define ISC_SAMA7G5_CSC_OFFSET 0x11c
  87. /* Color Space Conversion Control Register */
  88. #define ISC_CSC_CTRL 0x00000398
  89. @@ -246,6 +251,8 @@
  90. /* Offset for CBC register specific to sama5d2 product */
  91. #define ISC_SAMA5D2_CBC_OFFSET 0
  92. +/* Offset for CBC register specific to sama7g5 product */
  93. +#define ISC_SAMA7G5_CBC_OFFSET 0x11c
  94. /* Contrast And Brightness Control Register */
  95. #define ISC_CBC_CTRL 0x000003b4
  96. @@ -261,18 +268,30 @@
  97. #define ISC_CBC_CONTRAST 0x000003c0
  98. #define ISC_CBC_CONTRAST_MASK GENMASK(11, 0)
  99. +/* Hue Register */
  100. +#define ISC_CBCHS_HUE 0x4e0
  101. +/* Saturation Register */
  102. +#define ISC_CBCHS_SAT 0x4e4
  103. +
  104. /* Offset for SUB422 register specific to sama5d2 product */
  105. #define ISC_SAMA5D2_SUB422_OFFSET 0
  106. +/* Offset for SUB422 register specific to sama7g5 product */
  107. +#define ISC_SAMA7G5_SUB422_OFFSET 0x124
  108. +
  109. /* Subsampling 4:4:4 to 4:2:2 Control Register */
  110. #define ISC_SUB422_CTRL 0x000003c4
  111. /* Offset for SUB420 register specific to sama5d2 product */
  112. #define ISC_SAMA5D2_SUB420_OFFSET 0
  113. +/* Offset for SUB420 register specific to sama7g5 product */
  114. +#define ISC_SAMA7G5_SUB420_OFFSET 0x124
  115. /* Subsampling 4:2:2 to 4:2:0 Control Register */
  116. #define ISC_SUB420_CTRL 0x000003cc
  117. /* Offset for RLP register specific to sama5d2 product */
  118. #define ISC_SAMA5D2_RLP_OFFSET 0
  119. +/* Offset for RLP register specific to sama7g5 product */
  120. +#define ISC_SAMA7G5_RLP_OFFSET 0x124
  121. /* Rounding, Limiting and Packing Configuration Register */
  122. #define ISC_RLP_CFG 0x000003d0
  123. @@ -303,6 +322,8 @@
  124. /* Offset for HIS register specific to sama5d2 product */
  125. #define ISC_SAMA5D2_HIS_OFFSET 0
  126. +/* Offset for HIS register specific to sama7g5 product */
  127. +#define ISC_SAMA7G5_HIS_OFFSET 0x124
  128. /* Histogram Control Register */
  129. #define ISC_HIS_CTRL 0x000003d4
  130. @@ -326,6 +347,8 @@
  131. /* Offset for DMA register specific to sama5d2 product */
  132. #define ISC_SAMA5D2_DMA_OFFSET 0
  133. +/* Offset for DMA register specific to sama7g5 product */
  134. +#define ISC_SAMA7G5_DMA_OFFSET 0x13c
  135. /* DMA Configuration Register */
  136. #define ISC_DCFG 0x000003e0
  137. @@ -376,11 +399,14 @@
  138. /* Offset for version register specific to sama5d2 product */
  139. #define ISC_SAMA5D2_VERSION_OFFSET 0
  140. +#define ISC_SAMA7G5_VERSION_OFFSET 0x13c
  141. /* Version Register */
  142. #define ISC_VERSION 0x0000040c
  143. /* Offset for version register specific to sama5d2 product */
  144. #define ISC_SAMA5D2_HIS_ENTRY_OFFSET 0
  145. +/* Offset for version register specific to sama7g5 product */
  146. +#define ISC_SAMA7G5_HIS_ENTRY_OFFSET 0x14c
  147. /* Histogram Entry */
  148. #define ISC_HIS_ENTRY 0x00000410
  149. --- /dev/null
  150. +++ b/drivers/media/platform/atmel/atmel-sama7g5-isc.c
  151. @@ -0,0 +1,630 @@
  152. +// SPDX-License-Identifier: GPL-2.0
  153. +/*
  154. + * Microchip eXtended Image Sensor Controller (XISC) driver
  155. + *
  156. + * Copyright (C) 2019-2021 Microchip Technology, Inc. and its subsidiaries
  157. + *
  158. + * Author: Eugen Hristev <[email protected]>
  159. + *
  160. + * Sensor-->PFE-->DPC-->WB-->CFA-->CC-->GAM-->VHXS-->CSC-->CBHS-->SUB-->RLP-->DMA-->HIS
  161. + *
  162. + * ISC video pipeline integrates the following submodules:
  163. + * PFE: Parallel Front End to sample the camera sensor input stream
  164. + * DPC: Defective Pixel Correction with black offset correction, green disparity
  165. + * correction and defective pixel correction (3 modules total)
  166. + * WB: Programmable white balance in the Bayer domain
  167. + * CFA: Color filter array interpolation module
  168. + * CC: Programmable color correction
  169. + * GAM: Gamma correction
  170. + *VHXS: Vertical and Horizontal Scaler
  171. + * CSC: Programmable color space conversion
  172. + *CBHS: Contrast Brightness Hue and Saturation control
  173. + * SUB: This module performs YCbCr444 to YCbCr420 chrominance subsampling
  174. + * RLP: This module performs rounding, range limiting
  175. + * and packing of the incoming data
  176. + * DMA: This module performs DMA master accesses to write frames to external RAM
  177. + * HIS: Histogram module performs statistic counters on the frames
  178. + */
  179. +
  180. +#include <linux/clk.h>
  181. +#include <linux/clkdev.h>
  182. +#include <linux/clk-provider.h>
  183. +#include <linux/delay.h>
  184. +#include <linux/interrupt.h>
  185. +#include <linux/math64.h>
  186. +#include <linux/module.h>
  187. +#include <linux/of.h>
  188. +#include <linux/of_graph.h>
  189. +#include <linux/platform_device.h>
  190. +#include <linux/pm_runtime.h>
  191. +#include <linux/regmap.h>
  192. +#include <linux/videodev2.h>
  193. +
  194. +#include <media/v4l2-ctrls.h>
  195. +#include <media/v4l2-device.h>
  196. +#include <media/v4l2-event.h>
  197. +#include <media/v4l2-image-sizes.h>
  198. +#include <media/v4l2-ioctl.h>
  199. +#include <media/v4l2-fwnode.h>
  200. +#include <media/v4l2-subdev.h>
  201. +#include <media/videobuf2-dma-contig.h>
  202. +
  203. +#include "atmel-isc-regs.h"
  204. +#include "atmel-isc.h"
  205. +
  206. +#define ISC_SAMA7G5_MAX_SUPPORT_WIDTH 3264
  207. +#define ISC_SAMA7G5_MAX_SUPPORT_HEIGHT 2464
  208. +
  209. +#define ISC_SAMA7G5_PIPELINE \
  210. + (WB_ENABLE | CFA_ENABLE | CC_ENABLE | GAM_ENABLES | CSC_ENABLE | \
  211. + CBC_ENABLE | SUB422_ENABLE | SUB420_ENABLE)
  212. +
  213. +/* This is a list of the formats that the ISC can *output* */
  214. +static const struct isc_format sama7g5_controller_formats[] = {
  215. + {
  216. + .fourcc = V4L2_PIX_FMT_ARGB444,
  217. + },
  218. + {
  219. + .fourcc = V4L2_PIX_FMT_ARGB555,
  220. + },
  221. + {
  222. + .fourcc = V4L2_PIX_FMT_RGB565,
  223. + },
  224. + {
  225. + .fourcc = V4L2_PIX_FMT_ABGR32,
  226. + },
  227. + {
  228. + .fourcc = V4L2_PIX_FMT_XBGR32,
  229. + },
  230. + {
  231. + .fourcc = V4L2_PIX_FMT_YUV420,
  232. + },
  233. + {
  234. + .fourcc = V4L2_PIX_FMT_UYVY,
  235. + },
  236. + {
  237. + .fourcc = V4L2_PIX_FMT_VYUY,
  238. + },
  239. + {
  240. + .fourcc = V4L2_PIX_FMT_YUYV,
  241. + },
  242. + {
  243. + .fourcc = V4L2_PIX_FMT_YUV422P,
  244. + },
  245. + {
  246. + .fourcc = V4L2_PIX_FMT_GREY,
  247. + },
  248. + {
  249. + .fourcc = V4L2_PIX_FMT_Y10,
  250. + },
  251. + {
  252. + .fourcc = V4L2_PIX_FMT_Y16,
  253. + },
  254. +};
  255. +
  256. +/* This is a list of formats that the ISC can receive as *input* */
  257. +static struct isc_format sama7g5_formats_list[] = {
  258. + {
  259. + .fourcc = V4L2_PIX_FMT_SBGGR8,
  260. + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
  261. + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
  262. + .cfa_baycfg = ISC_BAY_CFG_BGBG,
  263. + },
  264. + {
  265. + .fourcc = V4L2_PIX_FMT_SGBRG8,
  266. + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
  267. + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
  268. + .cfa_baycfg = ISC_BAY_CFG_GBGB,
  269. + },
  270. + {
  271. + .fourcc = V4L2_PIX_FMT_SGRBG8,
  272. + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
  273. + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
  274. + .cfa_baycfg = ISC_BAY_CFG_GRGR,
  275. + },
  276. + {
  277. + .fourcc = V4L2_PIX_FMT_SRGGB8,
  278. + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
  279. + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
  280. + .cfa_baycfg = ISC_BAY_CFG_RGRG,
  281. + },
  282. + {
  283. + .fourcc = V4L2_PIX_FMT_SBGGR10,
  284. + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
  285. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
  286. + .cfa_baycfg = ISC_BAY_CFG_RGRG,
  287. + },
  288. + {
  289. + .fourcc = V4L2_PIX_FMT_SGBRG10,
  290. + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
  291. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
  292. + .cfa_baycfg = ISC_BAY_CFG_GBGB,
  293. + },
  294. + {
  295. + .fourcc = V4L2_PIX_FMT_SGRBG10,
  296. + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
  297. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
  298. + .cfa_baycfg = ISC_BAY_CFG_GRGR,
  299. + },
  300. + {
  301. + .fourcc = V4L2_PIX_FMT_SRGGB10,
  302. + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
  303. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
  304. + .cfa_baycfg = ISC_BAY_CFG_RGRG,
  305. + },
  306. + {
  307. + .fourcc = V4L2_PIX_FMT_SBGGR12,
  308. + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
  309. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE,
  310. + .cfa_baycfg = ISC_BAY_CFG_BGBG,
  311. + },
  312. + {
  313. + .fourcc = V4L2_PIX_FMT_SGBRG12,
  314. + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
  315. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE,
  316. + .cfa_baycfg = ISC_BAY_CFG_GBGB,
  317. + },
  318. + {
  319. + .fourcc = V4L2_PIX_FMT_SGRBG12,
  320. + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
  321. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE,
  322. + .cfa_baycfg = ISC_BAY_CFG_GRGR,
  323. + },
  324. + {
  325. + .fourcc = V4L2_PIX_FMT_SRGGB12,
  326. + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
  327. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE,
  328. + .cfa_baycfg = ISC_BAY_CFG_RGRG,
  329. + },
  330. + {
  331. + .fourcc = V4L2_PIX_FMT_GREY,
  332. + .mbus_code = MEDIA_BUS_FMT_Y8_1X8,
  333. + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
  334. + },
  335. + {
  336. + .fourcc = V4L2_PIX_FMT_YUYV,
  337. + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
  338. + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
  339. + },
  340. + {
  341. + .fourcc = V4L2_PIX_FMT_UYVY,
  342. + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
  343. + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
  344. + },
  345. + {
  346. + .fourcc = V4L2_PIX_FMT_RGB565,
  347. + .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
  348. + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT,
  349. + },
  350. + {
  351. + .fourcc = V4L2_PIX_FMT_Y10,
  352. + .mbus_code = MEDIA_BUS_FMT_Y10_1X10,
  353. + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
  354. + },
  355. +
  356. +};
  357. +
  358. +static void isc_sama7g5_config_csc(struct isc_device *isc)
  359. +{
  360. + struct regmap *regmap = isc->regmap;
  361. +
  362. + /* Convert RGB to YUV */
  363. + regmap_write(regmap, ISC_CSC_YR_YG + isc->offsets.csc,
  364. + 0x42 | (0x81 << 16));
  365. + regmap_write(regmap, ISC_CSC_YB_OY + isc->offsets.csc,
  366. + 0x19 | (0x10 << 16));
  367. + regmap_write(regmap, ISC_CSC_CBR_CBG + isc->offsets.csc,
  368. + 0xFDA | (0xFB6 << 16));
  369. + regmap_write(regmap, ISC_CSC_CBB_OCB + isc->offsets.csc,
  370. + 0x70 | (0x80 << 16));
  371. + regmap_write(regmap, ISC_CSC_CRR_CRG + isc->offsets.csc,
  372. + 0x70 | (0xFA2 << 16));
  373. + regmap_write(regmap, ISC_CSC_CRB_OCR + isc->offsets.csc,
  374. + 0xFEE | (0x80 << 16));
  375. +}
  376. +
  377. +static void isc_sama7g5_config_cbc(struct isc_device *isc)
  378. +{
  379. + struct regmap *regmap = isc->regmap;
  380. +
  381. + /* Configure what is set via v4l2 ctrls */
  382. + regmap_write(regmap, ISC_CBC_BRIGHT + isc->offsets.cbc, isc->ctrls.brightness);
  383. + regmap_write(regmap, ISC_CBC_CONTRAST + isc->offsets.cbc, isc->ctrls.contrast);
  384. + /* Configure Hue and Saturation as neutral midpoint */
  385. + regmap_write(regmap, ISC_CBCHS_HUE, 0);
  386. + regmap_write(regmap, ISC_CBCHS_SAT, (1 << 4));
  387. +}
  388. +
  389. +static void isc_sama7g5_config_cc(struct isc_device *isc)
  390. +{
  391. + struct regmap *regmap = isc->regmap;
  392. +
  393. + /* Configure each register at the neutral fixed point 1.0 or 0.0 */
  394. + regmap_write(regmap, ISC_CC_RR_RG, (1 << 8));
  395. + regmap_write(regmap, ISC_CC_RB_OR, 0);
  396. + regmap_write(regmap, ISC_CC_GR_GG, (1 << 8) << 16);
  397. + regmap_write(regmap, ISC_CC_GB_OG, 0);
  398. + regmap_write(regmap, ISC_CC_BR_BG, 0);
  399. + regmap_write(regmap, ISC_CC_BB_OB, (1 << 8));
  400. +}
  401. +
  402. +static void isc_sama7g5_config_ctrls(struct isc_device *isc,
  403. + const struct v4l2_ctrl_ops *ops)
  404. +{
  405. + struct isc_ctrls *ctrls = &isc->ctrls;
  406. + struct v4l2_ctrl_handler *hdl = &ctrls->handler;
  407. +
  408. + ctrls->contrast = 16;
  409. +
  410. + v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 16);
  411. +}
  412. +
  413. +static void isc_sama7g5_config_dpc(struct isc_device *isc)
  414. +{
  415. + u32 bay_cfg = isc->config.sd_format->cfa_baycfg;
  416. + struct regmap *regmap = isc->regmap;
  417. +
  418. + regmap_update_bits(regmap, ISC_DPC_CFG, ISC_DPC_CFG_BLOFF_MASK,
  419. + (64 << ISC_DPC_CFG_BLOFF_SHIFT));
  420. + regmap_update_bits(regmap, ISC_DPC_CFG, ISC_DPC_CFG_BAYCFG_MASK,
  421. + (bay_cfg << ISC_DPC_CFG_BAYCFG_SHIFT));
  422. +}
  423. +
  424. +static void isc_sama7g5_config_gam(struct isc_device *isc)
  425. +{
  426. + struct regmap *regmap = isc->regmap;
  427. +
  428. + regmap_update_bits(regmap, ISC_GAM_CTRL, ISC_GAM_CTRL_BIPART,
  429. + ISC_GAM_CTRL_BIPART);
  430. +}
  431. +
  432. +static void isc_sama7g5_config_rlp(struct isc_device *isc)
  433. +{
  434. + struct regmap *regmap = isc->regmap;
  435. + u32 rlp_mode = isc->config.rlp_cfg_mode;
  436. +
  437. + regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp,
  438. + ISC_RLP_CFG_MODE_MASK | ISC_RLP_CFG_LSH |
  439. + ISC_RLP_CFG_YMODE_MASK, rlp_mode);
  440. +}
  441. +
  442. +static void isc_sama7g5_adapt_pipeline(struct isc_device *isc)
  443. +{
  444. + isc->try_config.bits_pipeline &= ISC_SAMA7G5_PIPELINE;
  445. +}
  446. +
  447. +/* Gamma table with gamma 1/2.2 */
  448. +static const u32 isc_sama7g5_gamma_table[][GAMMA_ENTRIES] = {
  449. + /* index 0 --> gamma bipartite */
  450. + {
  451. + 0x980, 0x4c0320, 0x650260, 0x7801e0, 0x8701a0, 0x940180,
  452. + 0xa00160, 0xab0120, 0xb40120, 0xbd0120, 0xc60100, 0xce0100,
  453. + 0xd600e0, 0xdd00e0, 0xe400e0, 0xeb00c0, 0xf100c0, 0xf700c0,
  454. + 0xfd00c0, 0x10300a0, 0x10800c0, 0x10e00a0, 0x11300a0, 0x11800a0,
  455. + 0x11d00a0, 0x12200a0, 0x12700a0, 0x12c0080, 0x13000a0, 0x1350080,
  456. + 0x13900a0, 0x13e0080, 0x1420076, 0x17d0062, 0x1ae0054, 0x1d8004a,
  457. + 0x1fd0044, 0x21f003e, 0x23e003a, 0x25b0036, 0x2760032, 0x28f0030,
  458. + 0x2a7002e, 0x2be002c, 0x2d4002c, 0x2ea0028, 0x2fe0028, 0x3120026,
  459. + 0x3250024, 0x3370024, 0x3490022, 0x35a0022, 0x36b0020, 0x37b0020,
  460. + 0x38b0020, 0x39b001e, 0x3aa001e, 0x3b9001c, 0x3c7001c, 0x3d5001c,
  461. + 0x3e3001c, 0x3f1001c, 0x3ff001a, 0x40c001a },
  462. +};
  463. +
  464. +static int xisc_parse_dt(struct device *dev, struct isc_device *isc)
  465. +{
  466. + struct device_node *np = dev->of_node;
  467. + struct device_node *epn = NULL;
  468. + struct isc_subdev_entity *subdev_entity;
  469. + unsigned int flags;
  470. + int ret;
  471. + bool mipi_mode;
  472. +
  473. + INIT_LIST_HEAD(&isc->subdev_entities);
  474. +
  475. + mipi_mode = of_property_read_bool(np, "microchip,mipi-mode");
  476. +
  477. + while (1) {
  478. + struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 };
  479. +
  480. + epn = of_graph_get_next_endpoint(np, epn);
  481. + if (!epn)
  482. + return 0;
  483. +
  484. + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn),
  485. + &v4l2_epn);
  486. + if (ret) {
  487. + ret = -EINVAL;
  488. + dev_err(dev, "Could not parse the endpoint\n");
  489. + break;
  490. + }
  491. +
  492. + subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity),
  493. + GFP_KERNEL);
  494. + if (!subdev_entity) {
  495. + ret = -ENOMEM;
  496. + break;
  497. + }
  498. + subdev_entity->epn = epn;
  499. +
  500. + flags = v4l2_epn.bus.parallel.flags;
  501. +
  502. + if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
  503. + subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW;
  504. +
  505. + if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
  506. + subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW;
  507. +
  508. + if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
  509. + subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
  510. +
  511. + if (v4l2_epn.bus_type == V4L2_MBUS_BT656)
  512. + subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_CCIR_CRC |
  513. + ISC_PFE_CFG0_CCIR656;
  514. +
  515. + if (mipi_mode)
  516. + subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_MIPI;
  517. +
  518. + list_add_tail(&subdev_entity->list, &isc->subdev_entities);
  519. + }
  520. + of_node_put(epn);
  521. +
  522. + return ret;
  523. +}
  524. +
  525. +static int microchip_xisc_probe(struct platform_device *pdev)
  526. +{
  527. + struct device *dev = &pdev->dev;
  528. + struct isc_device *isc;
  529. + struct resource *res;
  530. + void __iomem *io_base;
  531. + struct isc_subdev_entity *subdev_entity;
  532. + int irq;
  533. + int ret;
  534. + u32 ver;
  535. +
  536. + isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
  537. + if (!isc)
  538. + return -ENOMEM;
  539. +
  540. + platform_set_drvdata(pdev, isc);
  541. + isc->dev = dev;
  542. +
  543. + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  544. + io_base = devm_ioremap_resource(dev, res);
  545. + if (IS_ERR(io_base))
  546. + return PTR_ERR(io_base);
  547. +
  548. + isc->regmap = devm_regmap_init_mmio(dev, io_base, &isc_regmap_config);
  549. + if (IS_ERR(isc->regmap)) {
  550. + ret = PTR_ERR(isc->regmap);
  551. + dev_err(dev, "failed to init register map: %d\n", ret);
  552. + return ret;
  553. + }
  554. +
  555. + irq = platform_get_irq(pdev, 0);
  556. + if (irq < 0)
  557. + return irq;
  558. +
  559. + ret = devm_request_irq(dev, irq, isc_interrupt, 0,
  560. + "microchip-sama7g5-xisc", isc);
  561. + if (ret < 0) {
  562. + dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
  563. + irq, ret);
  564. + return ret;
  565. + }
  566. +
  567. + isc->gamma_table = isc_sama7g5_gamma_table;
  568. + isc->gamma_max = 0;
  569. +
  570. + isc->max_width = ISC_SAMA7G5_MAX_SUPPORT_WIDTH;
  571. + isc->max_height = ISC_SAMA7G5_MAX_SUPPORT_HEIGHT;
  572. +
  573. + isc->config_dpc = isc_sama7g5_config_dpc;
  574. + isc->config_csc = isc_sama7g5_config_csc;
  575. + isc->config_cbc = isc_sama7g5_config_cbc;
  576. + isc->config_cc = isc_sama7g5_config_cc;
  577. + isc->config_gam = isc_sama7g5_config_gam;
  578. + isc->config_rlp = isc_sama7g5_config_rlp;
  579. + isc->config_ctrls = isc_sama7g5_config_ctrls;
  580. +
  581. + isc->adapt_pipeline = isc_sama7g5_adapt_pipeline;
  582. +
  583. + isc->offsets.csc = ISC_SAMA7G5_CSC_OFFSET;
  584. + isc->offsets.cbc = ISC_SAMA7G5_CBC_OFFSET;
  585. + isc->offsets.sub422 = ISC_SAMA7G5_SUB422_OFFSET;
  586. + isc->offsets.sub420 = ISC_SAMA7G5_SUB420_OFFSET;
  587. + isc->offsets.rlp = ISC_SAMA7G5_RLP_OFFSET;
  588. + isc->offsets.his = ISC_SAMA7G5_HIS_OFFSET;
  589. + isc->offsets.dma = ISC_SAMA7G5_DMA_OFFSET;
  590. + isc->offsets.version = ISC_SAMA7G5_VERSION_OFFSET;
  591. + isc->offsets.his_entry = ISC_SAMA7G5_HIS_ENTRY_OFFSET;
  592. +
  593. + isc->controller_formats = sama7g5_controller_formats;
  594. + isc->controller_formats_size = ARRAY_SIZE(sama7g5_controller_formats);
  595. + isc->formats_list = sama7g5_formats_list;
  596. + isc->formats_list_size = ARRAY_SIZE(sama7g5_formats_list);
  597. +
  598. + /* sama7g5-isc RAM access port is full AXI4 - 32 bits per beat */
  599. + isc->dcfg = ISC_DCFG_YMBSIZE_BEATS32 | ISC_DCFG_CMBSIZE_BEATS32;
  600. +
  601. + ret = isc_pipeline_init(isc);
  602. + if (ret)
  603. + return ret;
  604. +
  605. + isc->hclock = devm_clk_get(dev, "hclock");
  606. + if (IS_ERR(isc->hclock)) {
  607. + ret = PTR_ERR(isc->hclock);
  608. + dev_err(dev, "failed to get hclock: %d\n", ret);
  609. + return ret;
  610. + }
  611. +
  612. + ret = clk_prepare_enable(isc->hclock);
  613. + if (ret) {
  614. + dev_err(dev, "failed to enable hclock: %d\n", ret);
  615. + return ret;
  616. + }
  617. +
  618. + ret = isc_clk_init(isc);
  619. + if (ret) {
  620. + dev_err(dev, "failed to init isc clock: %d\n", ret);
  621. + goto unprepare_hclk;
  622. + }
  623. +
  624. + isc->ispck = isc->isc_clks[ISC_ISPCK].clk;
  625. +
  626. + ret = clk_prepare_enable(isc->ispck);
  627. + if (ret) {
  628. + dev_err(dev, "failed to enable ispck: %d\n", ret);
  629. + goto unprepare_hclk;
  630. + }
  631. +
  632. + /* ispck should be greater or equal to hclock */
  633. + ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
  634. + if (ret) {
  635. + dev_err(dev, "failed to set ispck rate: %d\n", ret);
  636. + goto unprepare_clk;
  637. + }
  638. +
  639. + ret = v4l2_device_register(dev, &isc->v4l2_dev);
  640. + if (ret) {
  641. + dev_err(dev, "unable to register v4l2 device.\n");
  642. + goto unprepare_clk;
  643. + }
  644. +
  645. + ret = xisc_parse_dt(dev, isc);
  646. + if (ret) {
  647. + dev_err(dev, "fail to parse device tree\n");
  648. + goto unregister_v4l2_device;
  649. + }
  650. +
  651. + if (list_empty(&isc->subdev_entities)) {
  652. + dev_err(dev, "no subdev found\n");
  653. + ret = -ENODEV;
  654. + goto unregister_v4l2_device;
  655. + }
  656. +
  657. + list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
  658. + struct v4l2_async_subdev *asd;
  659. +
  660. + v4l2_async_notifier_init(&subdev_entity->notifier);
  661. +
  662. + asd = v4l2_async_notifier_add_fwnode_remote_subdev(
  663. + &subdev_entity->notifier,
  664. + of_fwnode_handle(subdev_entity->epn),
  665. + struct v4l2_async_subdev);
  666. +
  667. + of_node_put(subdev_entity->epn);
  668. + subdev_entity->epn = NULL;
  669. +
  670. + if (IS_ERR(asd)) {
  671. + ret = PTR_ERR(asd);
  672. + goto cleanup_subdev;
  673. + }
  674. +
  675. + subdev_entity->notifier.ops = &isc_async_ops;
  676. +
  677. + ret = v4l2_async_notifier_register(&isc->v4l2_dev,
  678. + &subdev_entity->notifier);
  679. + if (ret) {
  680. + dev_err(dev, "fail to register async notifier\n");
  681. + goto cleanup_subdev;
  682. + }
  683. +
  684. + if (video_is_registered(&isc->video_dev))
  685. + break;
  686. + }
  687. +
  688. + pm_runtime_set_active(dev);
  689. + pm_runtime_enable(dev);
  690. + pm_request_idle(dev);
  691. +
  692. + regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver);
  693. + dev_info(dev, "Microchip XISC version %x\n", ver);
  694. +
  695. + return 0;
  696. +
  697. +cleanup_subdev:
  698. + isc_subdev_cleanup(isc);
  699. +
  700. +unregister_v4l2_device:
  701. + v4l2_device_unregister(&isc->v4l2_dev);
  702. +
  703. +unprepare_clk:
  704. + clk_disable_unprepare(isc->ispck);
  705. +unprepare_hclk:
  706. + clk_disable_unprepare(isc->hclock);
  707. +
  708. + isc_clk_cleanup(isc);
  709. +
  710. + return ret;
  711. +}
  712. +
  713. +static int microchip_xisc_remove(struct platform_device *pdev)
  714. +{
  715. + struct isc_device *isc = platform_get_drvdata(pdev);
  716. +
  717. + pm_runtime_disable(&pdev->dev);
  718. +
  719. + isc_subdev_cleanup(isc);
  720. +
  721. + v4l2_device_unregister(&isc->v4l2_dev);
  722. +
  723. + clk_disable_unprepare(isc->ispck);
  724. + clk_disable_unprepare(isc->hclock);
  725. +
  726. + isc_clk_cleanup(isc);
  727. +
  728. + return 0;
  729. +}
  730. +
  731. +static int __maybe_unused xisc_runtime_suspend(struct device *dev)
  732. +{
  733. + struct isc_device *isc = dev_get_drvdata(dev);
  734. +
  735. + clk_disable_unprepare(isc->ispck);
  736. + clk_disable_unprepare(isc->hclock);
  737. +
  738. + return 0;
  739. +}
  740. +
  741. +static int __maybe_unused xisc_runtime_resume(struct device *dev)
  742. +{
  743. + struct isc_device *isc = dev_get_drvdata(dev);
  744. + int ret;
  745. +
  746. + ret = clk_prepare_enable(isc->hclock);
  747. + if (ret)
  748. + return ret;
  749. +
  750. + ret = clk_prepare_enable(isc->ispck);
  751. + if (ret)
  752. + clk_disable_unprepare(isc->hclock);
  753. +
  754. + return ret;
  755. +}
  756. +
  757. +static const struct dev_pm_ops microchip_xisc_dev_pm_ops = {
  758. + SET_RUNTIME_PM_OPS(xisc_runtime_suspend, xisc_runtime_resume, NULL)
  759. +};
  760. +
  761. +static const struct of_device_id microchip_xisc_of_match[] = {
  762. + { .compatible = "microchip,sama7g5-isc" },
  763. + { }
  764. +};
  765. +MODULE_DEVICE_TABLE(of, microchip_xisc_of_match);
  766. +
  767. +static struct platform_driver microchip_xisc_driver = {
  768. + .probe = microchip_xisc_probe,
  769. + .remove = microchip_xisc_remove,
  770. + .driver = {
  771. + .name = "microchip-sama7g5-xisc",
  772. + .pm = &microchip_xisc_dev_pm_ops,
  773. + .of_match_table = of_match_ptr(microchip_xisc_of_match),
  774. + },
  775. +};
  776. +
  777. +module_platform_driver(microchip_xisc_driver);
  778. +
  779. +MODULE_AUTHOR("Eugen Hristev <[email protected]>");
  780. +MODULE_DESCRIPTION("The V4L2 driver for Microchip-XISC");
  781. +MODULE_LICENSE("GPL v2");