History

Merge tag 'media/v6.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab: - New sensor drivers: gc05a2, gc08a3 and imx283 - New serializer/deserializer drivers: max96714 and max96717 - New JPEG encoder driver: e5010 - Support for Raspberry Pi PiSP Backend (BE) ISP driver - Old documentation for av7110 driver removed, as a new version was added as Documentation/userspace-api/media/dvb/legacy*.rst - atompisp: Linux firmwares are now available, so drop firmware-related task from TODO and update firmware logic - The imx258 driver has gained several improvements - wave5 driver has gained support for HEVC decoding - em28xx gained support for MyGica UTV3 - av7110 budget-patch driver removed - Lots of other cleanups, improvements and fixes * tag 'media/v6.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (301 commits) media: raspberrypi: Switch to remove_new media: uapi: pisp_be_config: Add extra config fields media: uapi: pisp_be_config: Re-sort pisp_be_tiles_config media: uapi: pisp_common: Capitalize all macros media: uapi: pisp_common: Add 32 bpp format test media: uapi: pisp_be_config: Drop BIT() from uAPI media: stm32: dcmipp: correct error handling in dcmipp_create_subdevs media: atomisp: Fix spelling mistakes in sh_css_sp.c media: atomisp: Fix spelling mistake in ia_css_debug.c media: atomisp: Fix spelling mistake in hmm_bo.c media: atomisp: Fix spelling mistake in ia_css_eed1_8.host.c media: atomisp: Fix spelling mistake in sh_css_internal.h media: atomisp: Fix spelling mistake "pipline" -> "pipeline" media: atomisp: Remove unused GPIO related defines and APIs media: atomisp: Replace COMPILATION_ERROR_IF() by static_assert() media: atomisp: Clean up unused macros from math_support.h media: atomisp: csi2-bridge: Add DMI quirk for OV5693 on Xiaomi Mipad2 media: atomisp: Update TODO media: atomisp: Prefix firmware paths with "intel/ipu/" media: atomisp: Remove firmware_name module parameter ...

Linus Torvalds committed 2 years ago

Commit b1bc5542 parents 0ffb8a4 68a7210405 files · +21983 −10210Browse files

Unified · Split

405 files
  1. Documentation/admin-guide/media/em28xx-cardlist.rst +8 −0
  2. Documentation/admin-guide/media/ipu6-isys.rst +7 −7
  3. Documentation/admin-guide/media/raspberrypi-pisp-be.dot +20 −0
  4. Documentation/admin-guide/media/raspberrypi-pisp-be.rst +109 −0
  5. Documentation/admin-guide/media/tuner-cardlist.rst +2 −0
  6. Documentation/admin-guide/media/v4l-drivers.rst +1 −0
  7. Documentation/admin-guide/media/vivid.rst +65 −120
  8. Documentation/devicetree/bindings/media/i2c/galaxycore,gc05a2.yaml +112 −0
  9. Documentation/devicetree/bindings/media/i2c/galaxycore,gc08a3.yaml +112 −0
  10. Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +174 −0
  11. Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml +157 −0
  12. Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml +8 −3
  13. Documentation/devicetree/bindings/media/i2c/sony,imx283.yaml +107 −0
  14. Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml +75 −0
  15. Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml +1 −0
  16. Documentation/devicetree/bindings/media/mediatek,mt7622-cir.yaml +55 −0
  17. Documentation/devicetree/bindings/media/mtk-cir.txt +0 −28
  18. Documentation/devicetree/bindings/media/qcom,msm8996-venus.yaml +3 −1
  19. Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml +63 −0
  20. Documentation/devicetree/bindings/media/rc.yaml +1 −0
  21. Documentation/devicetree/bindings/media/rockchip-rga.yaml +1 −0
  22. Documentation/driver-api/media/v4l2-core.rst +1 −0
  23. Documentation/driver-api/media/v4l2-jpeg.rst +10 −0
  24. Documentation/userspace-api/media/drivers/index.rst +1 −1
  25. Documentation/userspace-api/media/drivers/vgxy61.rst +0 −0
  26. Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst +2 −2
  27. Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +14 −0
  28. Documentation/userspace-api/media/v4l/meta-formats.rst +1 −0
  29. Documentation/userspace-api/media/v4l/metafmt-pisp-be.rst +56 −0
  30. Documentation/userspace-api/media/v4l/pixfmt-bayer.rst +1 −0
  31. Documentation/userspace-api/media/v4l/pixfmt-rgb.rst +54 −0
  32. Documentation/userspace-api/media/v4l/pixfmt-srggb8-pisp-comp.rst +74 −0
  33. Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst +4 −0
  34. MAINTAINERS +57 −6
  35. drivers/media/common/siano/smscoreapi.c +5 −5
  36. drivers/media/common/siano/smscoreapi.h +2 −16
  37. drivers/media/common/siano/smsdvb-main.c +2 −2
  38. drivers/media/common/siano/smsendian.c +5 −3
  39. drivers/media/common/uvc.c +1 −0
  40. drivers/media/common/videobuf2/videobuf2-core.c +0 −1
  41. drivers/media/common/videobuf2/videobuf2-dvb.c +1 −0
  42. drivers/media/dvb-frontends/au8522_decoder.c +1 −0
  43. drivers/media/dvb-frontends/dib7000p.c +0 −5
  44. drivers/media/dvb-frontends/drx39xyj/drxj.c +0 −7
  45. drivers/media/dvb-frontends/mb86a16.c +1 −0
  46. drivers/media/dvb-frontends/mxl5xx_defs.h +2 −2
  47. drivers/media/dvb-frontends/stv090x.c +21 −16
  48. drivers/media/dvb-frontends/stv0910.c +0 −5
  49. drivers/media/i2c/Kconfig +67 −1
  50. drivers/media/i2c/Makefile +6 −1
  51. drivers/media/i2c/adv748x/adv748x-afe.c +2 −2
  52. drivers/media/i2c/adv748x/adv748x-csi2.c +95 −50
  53. drivers/media/i2c/adv748x/adv748x.h +0 −1
  54. drivers/media/i2c/adv7511-v4l2.c +0 −5
  55. drivers/media/i2c/alvium-csi2.c +51 −14
  56. drivers/media/i2c/alvium-csi2.h +11 −5
  57. drivers/media/i2c/dw9768.c +0 −5
  58. drivers/media/i2c/gc05a2.c +1359 −0
  59. drivers/media/i2c/gc08a3.c +1339 −0
  60. drivers/media/i2c/gc2145.c +72 −18
  61. drivers/media/i2c/hi846.c +1 −1
  62. drivers/media/i2c/imx219.c +1 −1
  63. drivers/media/i2c/imx258.c +810 −614
  64. drivers/media/i2c/imx283.c +1612 −0
  65. drivers/media/i2c/imx412.c +4 −5
  66. drivers/media/i2c/ks0127.c +0 −8
  67. drivers/media/i2c/max9286.c +68 −113
  68. drivers/media/i2c/max96714.c +1024 −0
  69. drivers/media/i2c/max96717.c +927 −0
  70. drivers/media/i2c/ov2680.c +1 −1
  71. drivers/media/i2c/ov5647.c +4 −7
  72. drivers/media/i2c/ov5693.c +0 −10
  73. drivers/media/i2c/tw9910.c +0 −5
  74. drivers/media/i2c/uda1342.c +1 −0
  75. drivers/media/i2c/vgxy61.c +1 −1
  76. drivers/media/pci/bt8xx/bt878.c +5 −4
  77. drivers/media/pci/bt8xx/bt878.h +2 −1
  78. drivers/media/pci/bt8xx/dvb-bt8xx.c +4 −4
  79. drivers/media/pci/cx18/cx18-scb.h +1 −1
  80. drivers/media/pci/ddbridge/ddbridge.h +1 −1
  81. drivers/media/pci/intel/ipu-bridge.c +29 −11
  82. drivers/media/pci/intel/ipu6/ipu6-buttress.c +2 −2
  83. drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +42 −56
  84. drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h +0 −2
  85. drivers/media/pci/intel/ipu6/ipu6-isys-queue.c +0 −3
  86. drivers/media/pci/intel/ipu6/ipu6-isys-video.c +7 −36
  87. drivers/media/pci/intel/ivsc/mei_csi.c +15 −9
  88. drivers/media/pci/ivtv/ivtv-driver.c +24 −69
  89. drivers/media/pci/ivtv/ivtv-fileops.c +39 −27
  90. drivers/media/pci/ivtv/ivtv-udma.c +8 −0
  91. drivers/media/pci/ivtv/ivtv-yuv.c +6 −0
  92. drivers/media/pci/ivtv/ivtvfb.c +4 −3
  93. drivers/media/pci/mantis/hopper_cards.c +1 −1
  94. drivers/media/pci/mantis/mantis_cards.c +1 −1
  95. drivers/media/pci/mantis/mantis_common.h +1 −1
  96. drivers/media/pci/mantis/mantis_dma.c +2 −2
  97. drivers/media/pci/mantis/mantis_dma.h +1 −1
  98. drivers/media/pci/mantis/mantis_dvb.c +6 −6
  99. drivers/media/pci/ngene/ngene-core.c +11 −11
  100. drivers/media/pci/ngene/ngene.h +3 −2
  101. drivers/media/pci/saa7134/saa7134-alsa.c +1 −0
  102. drivers/media/pci/saa7134/saa7134-dvb.c +7 −2
  103. drivers/media/pci/saa7134/saa7134-empress.c +1 −0
  104. drivers/media/pci/saa7134/saa7134-go7007.c +1 −0
  105. drivers/media/pci/smipcie/smipcie-main.c +9 −9
  106. drivers/media/pci/smipcie/smipcie.h +2 −1
  107. drivers/media/pci/ttpci/budget-av.c +2 −1
  108. drivers/media/pci/ttpci/budget-ci.c +14 −13
  109. drivers/media/pci/ttpci/budget-core.c +6 −5
  110. drivers/media/pci/ttpci/budget.h +3 −2
  111. drivers/media/pci/tw5864/tw5864-core.c +1 −1
  112. drivers/media/pci/tw5864/tw5864-video.c +7 −6
  113. drivers/media/pci/tw5864/tw5864.h +4 −3
  114. drivers/media/platform/Kconfig +2 −0
  115. drivers/media/platform/Makefile +2 −0
  116. drivers/media/platform/allegro-dvt/nal-hevc.h +4 −3
  117. drivers/media/platform/amphion/vdec.c +0 −2
  118. drivers/media/platform/amphion/venc.c +4 −2
  119. drivers/media/platform/amphion/vpu.h +1 −0
  120. drivers/media/platform/amphion/vpu_defs.h +1 −0
  121. drivers/media/platform/amphion/vpu_malone.c +0 −5
  122. drivers/media/platform/amphion/vpu_v4l2.c +16 −0
  123. drivers/media/platform/amphion/vpu_v4l2.h +1 −0
  124. drivers/media/platform/amphion/vpu_windsor.c +2 −0
  125. drivers/media/platform/chips-media/wave5/wave5-helper.c +7 −1
  126. drivers/media/platform/chips-media/wave5/wave5-hw.c +295 −100
  127. drivers/media/platform/chips-media/wave5/wave5-regdefine.h +5 −0
  128. drivers/media/platform/chips-media/wave5/wave5-vdi.c +16 −11
  129. drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +37 −14
  130. drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c +1 −1
  131. drivers/media/platform/chips-media/wave5/wave5-vpu.c +26 −9
  132. drivers/media/platform/chips-media/wave5/wave5-vpuapi.h +3 −0
  133. drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h +11 −5
  134. drivers/media/platform/chips-media/wave5/wave5.h +6 −0
  135. drivers/media/platform/imagination/Kconfig +13 −0
  136. drivers/media/platform/imagination/Makefile +3 −0
  137. drivers/media/platform/imagination/e5010-core-regs.h +585 −0
  138. drivers/media/platform/imagination/e5010-jpeg-enc-hw.c +267 −0
  139. drivers/media/platform/imagination/e5010-jpeg-enc-hw.h +42 −0
  140. drivers/media/platform/imagination/e5010-jpeg-enc.c +1632 −0
  141. drivers/media/platform/imagination/e5010-jpeg-enc.h +168 −0
  142. drivers/media/platform/imagination/e5010-mmu-regs.h +311 −0
  143. drivers/media/platform/intel/pxa_camera.c +8 −7
  144. drivers/media/platform/m2m-deinterlace.c +0 −4
  145. drivers/media/platform/marvell/mcam-core.c +5 −4
  146. drivers/media/platform/marvell/mcam-core.h +2 −1
  147. drivers/media/platform/marvell/mmp-driver.c +1 −0
  148. drivers/media/platform/mediatek/mdp3/mdp_cfg_data.c +280 −0
  149. drivers/media/platform/mediatek/mdp3/mtk-img-ipi.h +1 −0
  150. drivers/media/platform/mediatek/mdp3/mtk-mdp3-cfg.h +1 −0
  151. drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c +3 −0
  152. drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c +2 −1
  153. drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c +54 −6
  154. drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c +1 −1
  155. drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c +6 −0
  156. drivers/media/platform/nvidia/tegra-vde/h264.c +0 −5
  157. drivers/media/platform/nvidia/tegra-vde/vde.h +0 −1
  158. drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c +3 −11
  159. drivers/media/platform/nxp/imx-mipi-csis.c +15 −7
  160. drivers/media/platform/nxp/imx-pxp.c +3 −0
  161. drivers/media/platform/qcom/camss/Makefile +1 −0
  162. drivers/media/platform/qcom/camss/camss-csid-4-1.c +5 −127
  163. drivers/media/platform/qcom/camss/camss-csid-4-7.c +5 −155
  164. drivers/media/platform/qcom/camss/camss-csid-gen2.c +135 −272
  165. drivers/media/platform/qcom/camss/camss-csid.c +481 −31
  166. drivers/media/platform/qcom/camss/camss-csid.h +23 −9
  167. drivers/media/platform/qcom/camss/camss-csiphy.c +33 −41
  168. drivers/media/platform/qcom/camss/camss-csiphy.h +20 −3
  169. drivers/media/platform/qcom/camss/camss-format.c +91 −0
  170. drivers/media/platform/qcom/camss/camss-format.h +62 −0
  171. drivers/media/platform/qcom/camss/camss-vfe-17x.c +5 −5
  172. drivers/media/platform/qcom/camss/camss-vfe-4-1.c +2 −2
  173. drivers/media/platform/qcom/camss/camss-vfe-4-7.c +3 −3
  174. drivers/media/platform/qcom/camss/camss-vfe-4-8.c +3 −3
  175. drivers/media/platform/qcom/camss/camss-vfe-gen1.c +4 −4
  176. drivers/media/platform/qcom/camss/camss-vfe.c +288 −195
  177. drivers/media/platform/qcom/camss/camss-vfe.h +19 −3
  178. drivers/media/platform/qcom/camss/camss-video.c +3 −291
  179. drivers/media/platform/qcom/camss/camss-video.h +1 −3
  180. drivers/media/platform/qcom/camss/camss.c +497 −186
  181. drivers/media/platform/qcom/camss/camss.h +15 −5
  182. drivers/media/platform/qcom/venus/core.c +44 −1
  183. drivers/media/platform/qcom/venus/core.h +2 −0
  184. drivers/media/platform/qcom/venus/vdec.c +2 −1
  185. drivers/media/platform/raspberrypi/Kconfig +5 −0
  186. drivers/media/platform/raspberrypi/Makefile +3 −0
  187. drivers/media/platform/raspberrypi/pisp_be/Kconfig +12 −0
  188. drivers/media/platform/raspberrypi/pisp_be/Makefile +6 −0
  189. drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +1797 −0
  190. drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h +519 −0
  191. drivers/media/platform/renesas/rcar-csi2.c +93 −62
  192. drivers/media/platform/renesas/rcar-vin/rcar-dma.c +13 −3
  193. drivers/media/platform/renesas/vsp1/vsp1_brx.c +11 −20
  194. drivers/media/platform/renesas/vsp1/vsp1_clu.c +2 −2
  195. drivers/media/platform/renesas/vsp1/vsp1_drm.c +22 −5
  196. drivers/media/platform/renesas/vsp1/vsp1_drm.h +2 −0
  197. drivers/media/platform/renesas/vsp1/vsp1_entity.c +12 −54
  198. drivers/media/platform/renesas/vsp1/vsp1_entity.h +26 −22
  199. drivers/media/platform/renesas/vsp1/vsp1_hgo.c +13 −15
  200. drivers/media/platform/renesas/vsp1/vsp1_hgt.c +9 −11
  201. drivers/media/platform/renesas/vsp1/vsp1_histo.c +24 −52
  202. drivers/media/platform/renesas/vsp1/vsp1_hsit.c +3 −3
  203. drivers/media/platform/renesas/vsp1/vsp1_lif.c +2 −2
  204. drivers/media/platform/renesas/vsp1/vsp1_lut.c +1 −0
  205. drivers/media/platform/renesas/vsp1/vsp1_pipe.c +97 −6
  206. drivers/media/platform/renesas/vsp1/vsp1_pipe.h +27 −21
  207. drivers/media/platform/renesas/vsp1/vsp1_rpf.c +27 −29
  208. drivers/media/platform/renesas/vsp1/vsp1_rwpf.c +8 −18
  209. drivers/media/platform/renesas/vsp1/vsp1_rwpf.h +0 −3
  210. drivers/media/platform/renesas/vsp1/vsp1_sru.c +16 −21
  211. drivers/media/platform/renesas/vsp1/vsp1_uds.c +20 −31
  212. drivers/media/platform/renesas/vsp1/vsp1_uif.c +6 −9
  213. drivers/media/platform/renesas/vsp1/vsp1_video.c +68 −132
  214. drivers/media/platform/renesas/vsp1/vsp1_wpf.c +16 −27
  215. drivers/media/platform/rockchip/rga/rga-buf.c +5 −0
  216. drivers/media/platform/rockchip/rga/rga.c +4 −0
  217. drivers/media/platform/rockchip/rga/rga.h +3 −0
  218. drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c +4 −4
  219. drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c +4 −4
  220. drivers/media/platform/samsung/exynos4-is/common.c +1 −0
  221. drivers/media/platform/samsung/exynos4-is/fimc-is.c +1 −0
  222. drivers/media/platform/samsung/exynos4-is/fimc-lite.c +1 −0
  223. drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +7 −7
  224. drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h +1 −1
  225. drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-debugfs.h +2 −2
  226. drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c +2 −2
  227. drivers/media/platform/ti/vpe/vpdma.c +1 −0
  228. drivers/media/platform/verisilicon/Kconfig +1 −0
  229. drivers/media/platform/verisilicon/hantro_jpeg.c +13 −116
  230. drivers/media/platform/xilinx/xilinx-dma.c +2 −2
  231. drivers/media/platform/xilinx/xilinx-dma.h +1 −1
  232. drivers/media/radio/si470x/radio-si470x-common.c +1 −0
  233. drivers/media/radio/wl128x/fmdrv.h +3 −2
  234. drivers/media/radio/wl128x/fmdrv_common.c +20 −20
  235. drivers/media/rc/imon.c +1 −4
  236. drivers/media/rc/keymaps/Makefile +1 −0
  237. drivers/media/rc/keymaps/rc-mygica-utv3.c +69 −0
  238. drivers/media/rc/mceusb.c +3 −10
  239. drivers/media/rc/rc-main.c +1 −0
  240. drivers/media/spi/gs1662.c +0 −8
  241. drivers/media/test-drivers/vimc/vimc-capture.c +1 −1
  242. drivers/media/test-drivers/vimc/vimc-common.c +24 −1
  243. drivers/media/test-drivers/vimc/vimc-common.h +8 −6
  244. drivers/media/test-drivers/vimc/vimc-core.c +1 −1
  245. drivers/media/test-drivers/vimc/vimc-debayer.c +91 −110
  246. drivers/media/test-drivers/vimc/vimc-lens.c +3 −2
  247. drivers/media/test-drivers/vimc/vimc-scaler.c +54 −80
  248. drivers/media/test-drivers/vimc/vimc-sensor.c +56 −69
  249. drivers/media/test-drivers/vivid/vivid-cec.c +69 −19
  250. drivers/media/test-drivers/vivid/vivid-core.c +215 −35
  251. drivers/media/test-drivers/vivid/vivid-core.h +114 −11
  252. drivers/media/test-drivers/vivid/vivid-ctrls.c +152 −110
  253. drivers/media/test-drivers/vivid/vivid-kthread-cap.c +55 −31
  254. drivers/media/test-drivers/vivid/vivid-sdr-cap.c +6 −1
  255. drivers/media/test-drivers/vivid/vivid-touch-cap.c +3 −3
  256. drivers/media/test-drivers/vivid/vivid-vbi-cap.c +5 −2
  257. drivers/media/test-drivers/vivid/vivid-vbi-out.c +2 −0
  258. drivers/media/test-drivers/vivid/vivid-vid-cap.c +76 −44
  259. drivers/media/test-drivers/vivid/vivid-vid-cap.h +2 −0
  260. drivers/media/test-drivers/vivid/vivid-vid-common.c +98 −36
  261. drivers/media/test-drivers/vivid/vivid-vid-common.h +4 −1
  262. drivers/media/test-drivers/vivid/vivid-vid-out.c +18 −23
  263. drivers/media/tuners/tda9887.c +1 −0
  264. drivers/media/tuners/tuner-types.c +21 −0
  265. drivers/media/tuners/xc2028.c +8 −1
  266. drivers/media/usb/b2c2/flexcop-usb.c +4 −3
  267. drivers/media/usb/cx231xx/cx231xx-417.c +1 −1
  268. drivers/media/usb/cx231xx/cx231xx-video.c +1 −1
  269. drivers/media/usb/dvb-usb/dibusb-common.c +1 −0
  270. drivers/media/usb/dvb-usb/dibusb-mc-common.c +1 −0
  271. drivers/media/usb/dvb-usb/dvb-usb-init.c +31 −4
  272. drivers/media/usb/dvb-usb/opera1.c +0 −4
  273. drivers/media/usb/em28xx/em28xx-cards.c +52 −0
  274. drivers/media/usb/em28xx/em28xx-core.c +2 −1
  275. drivers/media/usb/em28xx/em28xx.h +1 −0
  276. drivers/media/usb/go7007/go7007-driver.c +1 −0
  277. drivers/media/usb/go7007/go7007-i2c.c +19 −11
  278. drivers/media/usb/go7007/go7007-usb.c +1 −0
  279. drivers/media/usb/pvrusb2/pvrusb2-debugifc.c +0 −5
  280. drivers/media/usb/ttusb-dec/ttusb_dec.c +11 −10
  281. drivers/media/usb/uvc/uvc_ctrl.c +108 −85
  282. drivers/media/usb/uvc/uvc_driver.c +30 −130
  283. drivers/media/usb/uvc/uvc_video.c +116 −53
  284. drivers/media/usb/uvc/uvcvideo.h +7 −3
  285. drivers/media/v4l2-core/v4l2-async.c +8 −0
  286. drivers/media/v4l2-core/v4l2-cci.c +9 −0
  287. drivers/media/v4l2-core/v4l2-common.c +2 −0
  288. drivers/media/v4l2-core/v4l2-ctrls-defs.c +5 −0
  289. drivers/media/v4l2-core/v4l2-fwnode.c +1 −0
  290. drivers/media/v4l2-core/v4l2-ioctl.c +13 −0
  291. drivers/media/v4l2-core/v4l2-jpeg.c +116 −0
  292. drivers/media/v4l2-core/v4l2-subdev.c +232 −161
  293. drivers/staging/media/atomisp/TODO +2 −29
  294. drivers/staging/media/atomisp/i2c/atomisp-libmsrlisthelper.c +1 −0
  295. drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c +1 −0
  296. drivers/staging/media/atomisp/include/linux/atomisp_platform.h +11 −16
  297. drivers/staging/media/atomisp/pci/atomisp_common.h +0 −1
  298. drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +14 −0
  299. drivers/staging/media/atomisp/pci/atomisp_ioctl.c +1 −1
  300. drivers/staging/media/atomisp/pci/atomisp_v4l2.c +16 −25
  301. drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_comm.h +6 −0
  302. drivers/staging/media/atomisp/pci/camera/util/interface/ia_css_util.h +0 −11
  303. drivers/staging/media/atomisp/pci/camera/util/src/util.c +11 −14
  304. drivers/staging/media/atomisp/pci/gpio_block_defs.h +0 −17
  305. drivers/staging/media/atomisp/pci/hive_isp_css_common/gpio_global.h +0 −23
  306. drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gpio_local.h +0 −21
  307. drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gpio_private.h +3 −6
  308. drivers/staging/media/atomisp/pci/hive_isp_css_include/assert_support.h +0 −23
  309. drivers/staging/media/atomisp/pci/hive_isp_css_include/gpio.h +0 −46
  310. drivers/staging/media/atomisp/pci/hive_isp_css_include/host/gpio_public.h +0 −46
  311. drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h +2 −108
  312. drivers/staging/media/atomisp/pci/hive_isp_css_include/type_support.h +3 −2
  313. drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +2 −2
  314. drivers/staging/media/atomisp/pci/ia_css_3a.h +5 −0
  315. drivers/staging/media/atomisp/pci/ia_css_dvs.h +4 −0
  316. drivers/staging/media/atomisp/pci/ia_css_metadata.h +4 −0
  317. drivers/staging/media/atomisp/pci/ia_css_types.h +2 −0
  318. drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8.host.c +1 −1
  319. drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.c +3 −3
  320. drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c +0 −2
  321. drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c +2 −2
  322. drivers/staging/media/atomisp/pci/runtime/spctrl/interface/ia_css_spctrl_comm.h +4 −0
  323. drivers/staging/media/atomisp/pci/sh_css.c +4 −44
  324. drivers/staging/media/atomisp/pci/sh_css_frac.h +3 −1
  325. drivers/staging/media/atomisp/pci/sh_css_internal.h +15 −4
  326. drivers/staging/media/atomisp/pci/sh_css_sp.c +13 −11
  327. drivers/staging/media/av7110/Kconfig +0 −22
  328. drivers/staging/media/av7110/Makefile +0 −2
  329. drivers/staging/media/av7110/TODO +0 −3
  330. drivers/staging/media/av7110/audio-bilingual-channel-select.rst +0 −58
  331. drivers/staging/media/av7110/audio-channel-select.rst +0 −57
  332. drivers/staging/media/av7110/audio-clear-buffer.rst +0 −48
  333. drivers/staging/media/av7110/audio-continue.rst +0 −48
  334. drivers/staging/media/av7110/audio-fclose.rst +0 −51
  335. drivers/staging/media/av7110/audio-fopen.rst +0 −103
  336. drivers/staging/media/av7110/audio-fwrite.rst +0 −79
  337. drivers/staging/media/av7110/audio-get-capabilities.rst +0 −54
  338. drivers/staging/media/av7110/audio-get-status.rst +0 −54
  339. drivers/staging/media/av7110/audio-pause.rst +0 −49
  340. drivers/staging/media/av7110/audio-play.rst +0 −48
  341. drivers/staging/media/av7110/audio-select-source.rst +0 −56
  342. drivers/staging/media/av7110/audio-set-av-sync.rst +0 −58
  343. drivers/staging/media/av7110/audio-set-bypass-mode.rst +0 −62
  344. drivers/staging/media/av7110/audio-set-id.rst +0 −59
  345. drivers/staging/media/av7110/audio-set-mixer.rst +0 −53
  346. drivers/staging/media/av7110/audio-set-mute.rst +0 −62
  347. drivers/staging/media/av7110/audio-set-streamtype.rst +0 −66
  348. drivers/staging/media/av7110/audio-stop.rst +0 −48
  349. drivers/staging/media/av7110/audio.rst +0 −27
  350. drivers/staging/media/av7110/audio_data_types.rst +0 −116
  351. drivers/staging/media/av7110/audio_function_calls.rst +0 −30
  352. drivers/staging/media/av7110/av7110.c +235 −261
  353. drivers/staging/media/av7110/av7110.h +22 −28
  354. drivers/staging/media/av7110/av7110_av.c +121 −113
  355. drivers/staging/media/av7110/av7110_av.h +18 −19
  356. drivers/staging/media/av7110/av7110_ca.c +20 −23
  357. drivers/staging/media/av7110/av7110_ca.h +6 −6
  358. drivers/staging/media/av7110/av7110_hw.c +108 −122
  359. drivers/staging/media/av7110/av7110_hw.h +33 −46
  360. drivers/staging/media/av7110/av7110_ipack.c +136 −146
  361. drivers/staging/media/av7110/av7110_ipack.h +6 −6
  362. drivers/staging/media/av7110/av7110_ir.c +1 −2
  363. drivers/staging/media/av7110/av7110_v4l.c +52 −50
  364. drivers/staging/media/av7110/budget-patch.c +0 −665
  365. drivers/staging/media/av7110/dvb_filter.c +58 −58
  366. drivers/staging/media/av7110/dvb_filter.h +9 −13
  367. drivers/staging/media/av7110/sp8870.c +108 −92
  368. drivers/staging/media/av7110/sp8870.h +10 −14
  369. drivers/staging/media/av7110/video-clear-buffer.rst +0 −54
  370. drivers/staging/media/av7110/video-command.rst +0 −96
  371. drivers/staging/media/av7110/video-continue.rst +0 −57
  372. drivers/staging/media/av7110/video-fast-forward.rst +0 −72
  373. drivers/staging/media/av7110/video-fclose.rst +0 −51
  374. drivers/staging/media/av7110/video-fopen.rst +0 −111
  375. drivers/staging/media/av7110/video-freeze.rst +0 −61
  376. drivers/staging/media/av7110/video-fwrite.rst +0 −79
  377. drivers/staging/media/av7110/video-get-capabilities.rst +0 −61
  378. drivers/staging/media/av7110/video-get-event.rst +0 −105
  379. drivers/staging/media/av7110/video-get-frame-count.rst +0 −65
  380. drivers/staging/media/av7110/video-get-pts.rst +0 −69
  381. drivers/staging/media/av7110/video-get-size.rst +0 −69
  382. drivers/staging/media/av7110/video-get-status.rst +0 −72
  383. drivers/staging/media/av7110/video-play.rst +0 −57
  384. drivers/staging/media/av7110/video-select-source.rst +0 −76
  385. drivers/staging/media/av7110/video-set-blank.rst +0 −64
  386. drivers/staging/media/av7110/video-set-display-format.rst +0 −60
  387. drivers/staging/media/av7110/video-set-format.rst +0 −82
  388. drivers/staging/media/av7110/video-set-streamtype.rst +0 −61
  389. drivers/staging/media/av7110/video-slowmotion.rst +0 −72
  390. drivers/staging/media/av7110/video-stillpicture.rst +0 −61
  391. drivers/staging/media/av7110/video-stop.rst +0 −74
  392. drivers/staging/media/av7110/video-try-command.rst +0 −66
  393. drivers/staging/media/av7110/video.rst +0 −36
  394. drivers/staging/media/av7110/video_function_calls.rst +0 −35
  395. drivers/staging/media/av7110/video_types.rst +0 −248
  396. drivers/staging/media/max96712/max96712.c +28 −9
  397. include/media/ipu-bridge.h +1 −0
  398. include/media/rc-map.h +1 −0
  399. include/media/tuner.h +1 −0
  400. include/media/v4l2-jpeg.h +32 −0
  401. include/media/v4l2-subdev.h +67 −25
  402. include/uapi/linux/media/raspberrypi/pisp_be_config.h +968 −0
  403. include/uapi/linux/media/raspberrypi/pisp_common.h +202 −0
  404. include/uapi/linux/v4l2-controls.h +2 −0
  405. include/uapi/linux/videodev2.h +17 −0
Documentation/admin-guide/media/em28xx-cardlist.rst+8−0
@@ -438,3 +438,11 @@ EM28xx cards list · 437 unmodified lines
438438 - MyGica iGrabber
439439 - em2860
440440 - 1f4d:1abe
441+ * - 106
442+ - Hauppauge USB QuadHD ATSC
443+ - em28274
444+ - 2040:846d
445+ * - 107
446+ - MyGica UTV3 Analog USB2.0 TV Box
447+ - em2860
448+ - eb1a:2860
Documentation/admin-guide/media/ipu6-isys.rst+7−7
@@ -135,16 +135,16 @@ sensor ov2740 on Lenovo X1 Yoga laptop. · 134 unmodified lines
135135 .. code-block:: none
136136
137137 media-ctl -l "\"ov2740 14-0036\":0 -> \"Intel IPU6 CSI2 1\":0[1]"
138− media-ctl -l "\"Intel IPU6 CSI2 1\":1 -> \"Intel IPU6 ISYS Capture 0\":0[5]"
139− media-ctl -l "\"Intel IPU6 CSI2 1\":2 -> \"Intel IPU6 ISYS Capture 1\":0[5]"
138+ media-ctl -l "\"Intel IPU6 CSI2 1\":1 -> \"Intel IPU6 ISYS Capture 0\":0[1]"
139+ media-ctl -l "\"Intel IPU6 CSI2 1\":2 -> \"Intel IPU6 ISYS Capture 1\":0[1]"
140140
141141 # set routing
142− media-ctl -v -R "\"Intel IPU6 CSI2 1\" [0/0->1/0[1],0/1->2/1[1]]"
142+ media-ctl -R "\"Intel IPU6 CSI2 1\" [0/0->1/0[1],0/1->2/1[1]]"
143143
144− media-ctl -v "\"Intel IPU6 CSI2 1\":0/0 [fmt:SGRBG10/1932x1092]"
145− media-ctl -v "\"Intel IPU6 CSI2 1\":0/1 [fmt:GENERIC_8/97x1]"
146− media-ctl -v "\"Intel IPU6 CSI2 1\":1/0 [fmt:SGRBG10/1932x1092]"
147− media-ctl -v "\"Intel IPU6 CSI2 1\":2/1 [fmt:GENERIC_8/97x1]"
144+ media-ctl -V "\"Intel IPU6 CSI2 1\":0/0 [fmt:SGRBG10/1932x1092]"
145+ media-ctl -V "\"Intel IPU6 CSI2 1\":0/1 [fmt:GENERIC_8/97x1]"
146+ media-ctl -V "\"Intel IPU6 CSI2 1\":1/0 [fmt:SGRBG10/1932x1092]"
147+ media-ctl -V "\"Intel IPU6 CSI2 1\":2/1 [fmt:GENERIC_8/97x1]"
148148
149149 CAPTURE_DEV=$(media-ctl -e "Intel IPU6 ISYS Capture 0")
150150 ./yavta --data-prefix -c100 -n5 -I -s1932x1092 --file=/tmp/frame-#.bin \
Documentation/admin-guide/media/raspberrypi-pisp-be.dot+20−0
@@ -0,0 +1,20 @@
1+digraph board {
2+ rankdir=TB
3+ n00000001 [label="{{<port0> 0 | <port1> 1 | <port2> 2 | <port7> 7} | pispbe\n | {<port3> 3 | <port4> 4 | <port5> 5 | <port6> 6}}", shape=Mrecord, style=filled, fillcolor=green]
4+ n00000001:port3 -> n0000001c [style=bold]
5+ n00000001:port4 -> n00000022 [style=bold]
6+ n00000001:port5 -> n00000028 [style=bold]
7+ n00000001:port6 -> n0000002e [style=bold]
8+ n0000000a [label="pispbe-input\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
9+ n0000000a -> n00000001:port0 [style=bold]
10+ n00000010 [label="pispbe-tdn_input\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
11+ n00000010 -> n00000001:port1 [style=bold]
12+ n00000016 [label="pispbe-stitch_input\n/dev/video2", shape=box, style=filled, fillcolor=yellow]
13+ n00000016 -> n00000001:port2 [style=bold]
14+ n0000001c [label="pispbe-output0\n/dev/video3", shape=box, style=filled, fillcolor=yellow]
15+ n00000022 [label="pispbe-output1\n/dev/video4", shape=box, style=filled, fillcolor=yellow]
16+ n00000028 [label="pispbe-tdn_output\n/dev/video5", shape=box, style=filled, fillcolor=yellow]
17+ n0000002e [label="pispbe-stitch_output\n/dev/video6", shape=box, style=filled, fillcolor=yellow]
18+ n00000034 [label="pispbe-config\n/dev/video7", shape=box, style=filled, fillcolor=yellow]
19+ n00000034 -> n00000001:port7 [style=bold]
20+}
Documentation/admin-guide/media/raspberrypi-pisp-be.rst+109−0
@@ -0,0 +1,109 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+=========================================================
4+Raspberry Pi PiSP Back End Memory-to-Memory ISP (pisp-be)
5+=========================================================
6+
7+The PiSP Back End
8+=================
9+
10+The PiSP Back End is a memory-to-memory Image Signal Processor (ISP) which reads
11+image data from DRAM memory and performs image processing as specified by the
12+application through the parameters in a configuration buffer, before writing
13+pixel data back to memory through two distinct output channels.
14+
15+The ISP registers and programming model are documented in the `Raspberry Pi
16+Image Signal Processor (PiSP) Specification document`_
17+
18+The PiSP Back End ISP processes images in tiles. The handling of image
19+tessellation and the computation of low-level configuration parameters is
20+realized by a free software library called `libpisp
21+<https://github.com/raspberrypi/libpisp>`_.
22+
23+The full image processing pipeline, which involves capturing RAW Bayer data from
24+an image sensor through a MIPI CSI-2 compatible capture interface, storing them
25+in DRAM memory and processing them in the PiSP Back End to obtain images usable
26+by an application is implemented in `libcamera <https://libcamera.org>`_ as
27+part of the Raspberry Pi platform support.
28+
29+The pisp-be driver
30+==================
31+
32+The Raspberry Pi PiSP Back End (pisp-be) driver is located under
33+drivers/media/platform/raspberrypi/pisp-be. It uses the `V4L2 API` to register
34+a number of video capture and output devices, the `V4L2 subdev API` to register
35+a subdevice for the ISP that connects the video devices in a single media graph
36+realized using the `Media Controller (MC) API`.
37+
38+The media topology registered by the `pisp-be` driver is represented below:
39+
40+.. _pips-be-topology:
41+
42+.. kernel-figure:: raspberrypi-pisp-be.dot
43+ :alt: Diagram of the default media pipeline topology
44+ :align: center
45+
46+
47+The media graph registers the following video device nodes:
48+
49+- pispbe-input: output device for images to be submitted to the ISP for
50+ processing.
51+- pispbe-tdn_input: output device for temporal denoise.
52+- pispbe-stitch_input: output device for image stitching (HDR).
53+- pispbe-output0: first capture device for processed images.
54+- pispbe-output1: second capture device for processed images.
55+- pispbe-tdn_output: capture device for temporal denoise.
56+- pispbe-stitch_output: capture device for image stitching (HDR).
57+- pispbe-config: output device for ISP configuration parameters.
58+
59+pispbe-input
60+------------
61+
62+Images to be processed by the ISP are queued to the `pispbe-input` output device
63+node. For a list of image formats supported as input to the ISP refer to the
64+`Raspberry Pi Image Signal Processor (PiSP) Specification document`_.
65+
66+pispbe-tdn_input, pispbe-tdn_output
67+-----------------------------------
68+
69+The `pispbe-tdn_input` output video device receives images to be processed by
70+the temporal denoise block which are captured from the `pispbe-tdn_output`
71+capture video device. Userspace is responsible for maintaining queues on both
72+devices, and ensuring that buffers completed on the output are queued to the
73+input.
74+
75+pispbe-stitch_input, pispbe-stitch_output
76+-----------------------------------------
77+
78+To realize HDR (high dynamic range) image processing the image stitching and
79+tonemapping blocks are used. The `pispbe-stitch_output` writes images to memory
80+and the `pispbe-stitch_input` receives the previously written frame to process
81+it along with the current input image. Userspace is responsible for maintaining
82+queues on both devices, and ensuring that buffers completed on the output are
83+queued to the input.
84+
85+pispbe-output0, pispbe-output1
86+------------------------------
87+
88+The two capture devices write to memory the pixel data as processed by the ISP.
89+
90+pispbe-config
91+-------------
92+
93+The `pispbe-config` output video devices receives a buffer of configuration
94+parameters that define the desired image processing to be performed by the ISP.
95+
96+The format of the ISP configuration parameter is defined by
97+:c:type:`pisp_be_tiles_config` C structure and the meaning of each parameter is
98+described in the `Raspberry Pi Image Signal Processor (PiSP) Specification
99+document`_.
100+
101+ISP configuration
102+=================
103+
104+The ISP configuration is described solely by the content of the parameters
105+buffer. The only parameter that userspace needs to configure using the V4L2 API
106+is the image format on the output and capture video devices for validation of
107+the content of the parameters buffer.
108+
109+.. _Raspberry Pi Image Signal Processor (PiSP) Specification document: https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf
Documentation/admin-guide/media/tuner-cardlist.rst+2−0
@@ -97,4 +97,6 @@ Tuner number Card name · 96 unmodified lines
9797 89 Sony BTF-PG472Z PAL/SECAM
9898 90 Sony BTF-PK467Z NTSC-M-JP
9999 91 Sony BTF-PB463Z NTSC-M
100+92 Silicon Labs Si2157 tuner
101+93 Tena TNF931D-DFDR1
100102 ============ =====================================================
Documentation/admin-guide/media/v4l-drivers.rst+1−0
@@ -23,6 +23,7 @@ Video4Linux (V4L) driver-specific documentation · 22 unmodified lines
2323 omap4_camera
2424 philips
2525 qcom_camss
26+ raspberrypi-pisp-be
2627 rcar-fdp1
2728 rkisp1
2829 saa7134
Documentation/admin-guide/media/vivid.rst+65−120
@@ -302,6 +302,15 @@ all configurable using the following module options: · 301 unmodified lines
302302 - 0: forbid hints
303303 - 1: allow hints
304304
305+- supports_requests:
306+
307+ specifies if the device should support the Request API. There are
308+ three possible values, default is 1:
309+
310+ - 0: no request
311+ - 1: supports requests
312+ - 2: requires requests
313+
305314 Taken together, all these module options allow you to precisely customize
306315 the driver behavior and test your application with all sorts of permutations.
307316 It is also very suitable to emulate hardware that is not yet available, e.g.
@@ -313,10 +322,10 @@ Video Capture · 5 unmodified lines
313322
314323 This is probably the most frequently used feature. The video capture device
315324 can be configured by using the module options num_inputs, input_types and
316−ccs_cap_mode (see section 1 for more detailed information), but by default
317−four inputs are configured: a webcam, a TV tuner, an S-Video and an HDMI
318−input, one input for each input type. Those are described in more detail
319−below.
325+ccs_cap_mode (see "Configuring the driver" for more detailed information),
326+but by default four inputs are configured: a webcam, a TV tuner, an S-Video
327+and an HDMI input, one input for each input type. Those are described in more
328+detail below.
320329
321330 Special attention has been given to the rate at which new frames become
322331 available. The jitter will be around 1 jiffie (that depends on the HZ
@@ -434,10 +443,10 @@ Video Output · 111 unmodified lines
434443 ------------
435444
436445 The video output device can be configured by using the module options
437−num_outputs, output_types and ccs_out_mode (see section 1 for more detailed
438−information), but by default two outputs are configured: an S-Video and an
439−HDMI input, one output for each output type. Those are described in more detail
440−below.
446+num_outputs, output_types and ccs_out_mode (see "Configuring the driver"
447+for more detailed information), but by default two outputs are configured:
448+an S-Video and an HDMI input, one output for each output type. Those are
449+described in more detail below.
441450
442451 Like with video capture the framerate is also exact in the long term.
443452
@@ -1011,11 +1020,6 @@ Digital Video Controls · 567 unmodified lines
10111020 affects the reported colorspace since DVI_D outputs will always use
10121021 sRGB.
10131022
1014−- Display Present:
1015−
1016− sets the presence of a "display" on the HDMI output. This affects
1017− the tx_edid_present, tx_hotplug and tx_rxsense controls.
1018−
10191023
10201024 FM Radio Receiver Controls
10211025 ~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1130,35 +1134,34 @@ Metadata Capture Controls · 108 unmodified lines
11301134
11311135 if set, then the generated metadata stream contains Source Clock information.
11321136
1133−Video, VBI and RDS Looping
1134−--------------------------
11351137
1136−The vivid driver supports looping of video output to video input, VBI output
1137−to VBI input and RDS output to RDS input. For video/VBI looping this emulates
1138−as if a cable was hooked up between the output and input connector. So video
1139−and VBI looping is only supported between S-Video and HDMI inputs and outputs.
1140−VBI is only valid for S-Video as it makes no sense for HDMI.
1138+Video, Sliced VBI and HDMI CEC Looping
1139+--------------------------------------
11411140
1142−Since radio is wireless this looping always happens if the radio receiver
1143−frequency is close to the radio transmitter frequency. In that case the radio
1144−transmitter will 'override' the emulated radio stations.
1145−
1146−Looping is currently supported only between devices created by the same
1147−vivid driver instance.
1141+Video Looping functionality is supported for devices created by the same
1142+vivid driver instance, as well as across multiple instances of the vivid driver.
1143+The vivid driver supports looping of video and Sliced VBI data between an S-Video output
1144+and an S-Video input. It also supports looping of video and HDMI CEC data between an
1145+HDMI output and an HDMI input.
11481146
1147+To enable looping, set the 'HDMI/S-Video XXX-N Is Connected To' control(s) to select
1148+whether an input uses the Test Pattern Generator, or is disconnected, or is connected
1149+to an output. An input can be connected to an output from any vivid instance.
1150+The inputs and outputs are numbered XXX-N where XXX is the vivid instance number
1151+(see module option n_devs). If there is only one vivid instance (the default), then
1152+XXX will be 000. And N is the Nth S-Video/HDMI input or output of that instance.
1153+If vivid is loaded without module options, then you can connect the S-Video 000-0 input
1154+to the S-Video 000-0 output, or the HDMI 000-0 input to the HDMI 000-0 output.
1155+This is the equivalent of connecting or disconnecting a cable between an input and an
1156+output in a physical device.
11491157
1150−Video and Sliced VBI looping
1151−~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1158+If an 'HDMI/S-Video XXX-N Is Connected To' control selected an output, then the video
1159+output will be looped to the video input provided that:
11521160
1153−The way to enable video/VBI looping is currently fairly crude. A 'Loop Video'
1154−control is available in the "Vivid" control class of the video
1155−capture and VBI capture devices. When checked the video looping will be enabled.
1156−Once enabled any video S-Video or HDMI input will show a static test pattern
1157−until the video output has started. At that time the video output will be
1158−looped to the video input provided that:
1161+- the currently selected input matches the input indicated by the control name.
11591162
1160−- the input type matches the output type. So the HDMI input cannot receive
1161− video from the S-Video output.
1163+- in the vivid instance of the output connector, the currently selected output matches
1164+ the output indicated by the control's value.
11621165
11631166 - the video resolution of the video input must match that of the video output.
11641167 So it is not possible to loop a 50 Hz (720x576) S-Video output to a 60 Hz
@@ -1185,6 +1188,8 @@ looped to the video input provided that: · 20 unmodified lines
11851188 "DV Timings Signal Mode" for the HDMI input should be configured so that a
11861189 valid signal is passed to the video input.
11871190
1191+If any condition is not valid, then the 'Noise' test pattern is shown.
1192+
11881193 The framerates do not have to match, although this might change in the future.
11891194
11901195 By default you will see the OSD text superimposed on top of the looped video.
@@ -1198,17 +1203,26 @@ and WSS (50 Hz formats) VBI data is looped. Teletext VBI data is not looped. · 7 unmodified lines
11981203
11991204
12001205 Radio & RDS Looping
1201−~~~~~~~~~~~~~~~~~~~
1202−
1203−As mentioned in section 6 the radio receiver emulates stations are regular
1204−frequency intervals. Depending on the frequency of the radio receiver a
1205−signal strength value is calculated (this is returned by VIDIOC_G_TUNER).
1206−However, it will also look at the frequency set by the radio transmitter and
1207−if that results in a higher signal strength than the settings of the radio
1208−transmitter will be used as if it was a valid station. This also includes
1209−the RDS data (if any) that the transmitter 'transmits'. This is received
1210−faithfully on the receiver side. Note that when the driver is loaded the
1211−frequencies of the radio receiver and transmitter are not identical, so
1206+-------------------
1207+
1208+The vivid driver supports looping of RDS output to RDS input.
1209+
1210+Since radio is wireless this looping always happens if the radio receiver
1211+frequency is close to the radio transmitter frequency. In that case the radio
1212+transmitter will 'override' the emulated radio stations.
1213+
1214+RDS looping is currently supported only between devices created by the same
1215+vivid driver instance.
1216+
1217+As mentioned in the "Radio Receiver" section, the radio receiver emulates
1218+stations at regular frequency intervals. Depending on the frequency of the
1219+radio receiver a signal strength value is calculated (this is returned by
1220+VIDIOC_G_TUNER). However, it will also look at the frequency set by the radio
1221+transmitter and if that results in a higher signal strength than the settings
1222+of the radio transmitter will be used as if it was a valid station. This also
1223+includes the RDS data (if any) that the transmitter 'transmits'. This is
1224+received faithfully on the receiver side. Note that when the driver is loaded
1225+the frequencies of the radio receiver and transmitter are not identical, so
12121226 initially no looping takes place.
12131227
12141228
@@ -1218,8 +1232,8 @@ Cropping, Composing, Scaling · 3 unmodified lines
12181232 This driver supports cropping, composing and scaling in any combination. Normally
12191233 which features are supported can be selected through the Vivid controls,
12201234 but it is also possible to hardcode it when the module is loaded through the
1221−ccs_cap_mode and ccs_out_mode module options. See section 1 on the details of
1222−these module options.
1235+ccs_cap_mode and ccs_out_mode module options. See "Configuring the driver" on
1236+the details of these module options.
12231237
12241238 This allows you to test your application for all these variations.
12251239
@@ -1260,7 +1274,8 @@ is set, then the alpha component is only used for the color red and set to · 34 unmodified lines
12601274
12611275 The driver has to be configured to support the multiplanar formats. By default
12621276 the driver instances are single-planar. This can be changed by setting the
1263−multiplanar module option, see section 1 for more details on that option.
1277+multiplanar module option, see "Configuring the driver" for more details on that
1278+option.
12641279
12651280 If the driver instance is using the multiplanar formats/API, then the first
12661281 single planar format (YUYV) and the multiplanar NV16M and NV61M formats the
@@ -1270,74 +1285,6 @@ data_offset to be non-zero, so this is a useful feature for testing applications · 3 unmodified lines
12701285 Video output will also honor any data_offset that the application set.
12711286
12721287
1273−Capture Overlay
1274−---------------
1275−
1276−Note: capture overlay support is implemented primarily to test the existing
1277−V4L2 capture overlay API. In practice few if any GPUs support such overlays
1278−anymore, and neither are they generally needed anymore since modern hardware
1279−is so much more capable. By setting flag 0x10000 in the node_types module
1280−option the vivid driver will create a simple framebuffer device that can be
1281−used for testing this API. Whether this API should be used for new drivers is
1282−questionable.
1283−
1284−This driver has support for a destructive capture overlay with bitmap clipping
1285−and list clipping (up to 16 rectangles) capabilities. Overlays are not
1286−supported for multiplanar formats. It also honors the struct v4l2_window field
1287−setting: if it is set to FIELD_TOP or FIELD_BOTTOM and the capture setting is
1288−FIELD_ALTERNATE, then only the top or bottom fields will be copied to the overlay.
1289−
1290−The overlay only works if you are also capturing at that same time. This is a
1291−vivid limitation since it copies from a buffer to the overlay instead of
1292−filling the overlay directly. And if you are not capturing, then no buffers
1293−are available to fill.
1294−
1295−In addition, the pixelformat of the capture format and that of the framebuffer
1296−must be the same for the overlay to work. Otherwise VIDIOC_OVERLAY will return
1297−an error.
1298−
1299−In order to really see what it going on you will need to create two vivid
1300−instances: the first with a framebuffer enabled. You configure the capture
1301−overlay of the second instance to use the framebuffer of the first, then
1302−you start capturing in the second instance. For the first instance you setup
1303−the output overlay for the video output, turn on video looping and capture
1304−to see the blended framebuffer overlay that's being written to by the second
1305−instance. This setup would require the following commands:
1306−
1307−.. code-block:: none
1308−
1309− $ sudo modprobe vivid n_devs=2 node_types=0x10101,0x1
1310− $ v4l2-ctl -d1 --find-fb
1311− /dev/fb1 is the framebuffer associated with base address 0x12800000
1312− $ sudo v4l2-ctl -d2 --set-fbuf fb=1
1313− $ v4l2-ctl -d1 --set-fbuf fb=1
1314− $ v4l2-ctl -d0 --set-fmt-video=pixelformat='AR15'
1315− $ v4l2-ctl -d1 --set-fmt-video-out=pixelformat='AR15'
1316− $ v4l2-ctl -d2 --set-fmt-video=pixelformat='AR15'
1317− $ v4l2-ctl -d0 -i2
1318− $ v4l2-ctl -d2 -i2
1319− $ v4l2-ctl -d2 -c horizontal_movement=4
1320− $ v4l2-ctl -d1 --overlay=1
1321− $ v4l2-ctl -d0 -c loop_video=1
1322− $ v4l2-ctl -d2 --stream-mmap --overlay=1
1323−
1324−And from another console:
1325−
1326−.. code-block:: none
1327−
1328− $ v4l2-ctl -d1 --stream-out-mmap
1329−
1330−And yet another console:
1331−
1332−.. code-block:: none
1333−
1334− $ qv4l2
1335−
1336−and start streaming.
1337−
1338−As you can see, this is not for the faint of heart...
1339−
1340−
13411288 Output Overlay
13421289 --------------
13431290
@@ -1405,8 +1352,6 @@ Just as a reminder and in no particular order: · 61 unmodified lines
14051352 - Add ARGB888 overlay support: better testing of the alpha channel
14061353 - Improve pixel aspect support in the tpg code by passing a real v4l2_fract
14071354 - Use per-queue locks and/or per-device locks to improve throughput
1408−- Add support to loop from a specific output to a specific input across
1409− vivid instances
14101355 - The SDR radio should use the same 'frequencies' for stations as the normal
14111356 radio receiver, and give back noise if the frequency doesn't match up with
14121357 a station frequency
Documentation/devicetree/bindings/media/i2c/galaxycore,gc05a2.yaml+112−0
@@ -0,0 +1,112 @@
1+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+# Copyright (c) 2023 MediaTek Inc.
3+%YAML 1.2
4+---
5+$id: http://devicetree.org/schemas/media/i2c/galaxycore,gc05a2.yaml#
6+$schema: http://devicetree.org/meta-schemas/core.yaml#
7+
8+title: GalaxyCore gc05a2 1/5" 5M Pixel MIPI CSI-2 sensor
9+
10+maintainers:
11+ - Zhi Mao <zhi.mao@mediatek.com>
12+
13+description:
14+ The gc05a2 is a raw image sensor with an MIPI CSI-2 image data
15+ interface and CCI (I2C compatible) control bus. The output format
16+ is raw Bayer.
17+
18+properties:
19+ compatible:
20+ const: galaxycore,gc05a2
21+
22+ reg:
23+ maxItems: 1
24+
25+ clocks:
26+ maxItems: 1
27+
28+ dovdd-supply: true
29+
30+ avdd-supply: true
31+
32+ dvdd-supply: true
33+
34+ reset-gpios:
35+ description: Reference to the GPIO connected to the RESETB pin.
36+ maxItems: 1
37+
38+ port:
39+ $ref: /schemas/graph.yaml#/$defs/port-base
40+ additionalProperties: false
41+ description:
42+ Output port node, single endpoint describing the CSI-2 transmitter.
43+
44+ properties:
45+ endpoint:
46+ $ref: /schemas/media/video-interfaces.yaml#
47+ unevaluatedProperties: false
48+
49+ properties:
50+ data-lanes:
51+ oneOf:
52+ - items:
53+ - const: 1
54+ - const: 2
55+ - const: 3
56+ - const: 4
57+ - items:
58+ - const: 1
59+ - const: 2
60+
61+ link-frequencies: true
62+
63+ required:
64+ - data-lanes
65+ - link-frequencies
66+
67+ required:
68+ - endpoint
69+
70+required:
71+ - compatible
72+ - reg
73+ - clocks
74+ - dovdd-supply
75+ - avdd-supply
76+ - dvdd-supply
77+ - reset-gpios
78+ - port
79+
80+additionalProperties: false
81+
82+examples:
83+ - |
84+ #include <dt-bindings/gpio/gpio.h>
85+
86+ i2c {
87+ #address-cells = <1>;
88+ #size-cells = <0>;
89+
90+ sensor@37 {
91+ compatible = "galaxycore,gc05a2";
92+ reg = <0x37>;
93+
94+ clocks = <&gc05a2_clk>;
95+
96+ reset-gpios = <&pio 21 GPIO_ACTIVE_LOW>;
97+
98+ avdd-supply = <&gc05a2_avdd>;
99+ dovdd-supply = <&gc05a2_dovdd>;
100+ dvdd-supply = <&gc05a2_dvdd>;
101+
102+ port {
103+ sensor_out: endpoint {
104+ data-lanes = <1 2>;
105+ link-frequencies = /bits/ 64 <448000000 224000000>;
106+ remote-endpoint = <&seninf_csi_port_1_in>;
107+ };
108+ };
109+ };
110+ };
111+
112+...
Documentation/devicetree/bindings/media/i2c/galaxycore,gc08a3.yaml+112−0
@@ -0,0 +1,112 @@
1+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+# Copyright (c) 2023 MediaTek Inc.
3+%YAML 1.2
4+---
5+$id: http://devicetree.org/schemas/media/i2c/galaxycore,gc08a3.yaml#
6+$schema: http://devicetree.org/meta-schemas/core.yaml#
7+
8+title: GalaxyCore gc08a3 1/4" 8M Pixel MIPI CSI-2 sensor
9+
10+maintainers:
11+ - Zhi Mao <zhi.mao@mediatek.com>
12+
13+description:
14+ The gc08a3 is a raw image sensor with an MIPI CSI-2 image data
15+ interface and CCI (I2C compatible) control bus. The output format
16+ is raw Bayer.
17+
18+properties:
19+ compatible:
20+ const: galaxycore,gc08a3
21+
22+ reg:
23+ maxItems: 1
24+
25+ clocks:
26+ maxItems: 1
27+
28+ dovdd-supply: true
29+
30+ avdd-supply: true
31+
32+ dvdd-supply: true
33+
34+ reset-gpios:
35+ description: Reference to the GPIO connected to the RESETB pin.
36+ maxItems: 1
37+
38+ port:
39+ $ref: /schemas/graph.yaml#/$defs/port-base
40+ additionalProperties: false
41+ description:
42+ Output port node, single endpoint describing the CSI-2 transmitter.
43+
44+ properties:
45+ endpoint:
46+ $ref: /schemas/media/video-interfaces.yaml#
47+ unevaluatedProperties: false
48+
49+ properties:
50+ data-lanes:
51+ oneOf:
52+ - items:
53+ - const: 1
54+ - const: 2
55+ - const: 3
56+ - const: 4
57+ - items:
58+ - const: 1
59+ - const: 2
60+
61+ link-frequencies: true
62+
63+ required:
64+ - data-lanes
65+ - link-frequencies
66+
67+ required:
68+ - endpoint
69+
70+required:
71+ - compatible
72+ - reg
73+ - clocks
74+ - dovdd-supply
75+ - avdd-supply
76+ - dvdd-supply
77+ - reset-gpios
78+ - port
79+
80+additionalProperties: false
81+
82+examples:
83+ - |
84+ #include <dt-bindings/gpio/gpio.h>
85+
86+ i2c {
87+ #address-cells = <1>;
88+ #size-cells = <0>;
89+
90+ sensor@31 {
91+ compatible = "galaxycore,gc08a3";
92+ reg = <0x31>;
93+
94+ clocks = <&gc08a3_clk>;
95+
96+ reset-gpios = <&pio 19 GPIO_ACTIVE_LOW>;
97+
98+ avdd-supply = <&gc08a3_avdd>;
99+ dovdd-supply = <&gc08a3_dovdd>;
100+ dvdd-supply = <&gc08a3_dvdd>;
101+
102+ port {
103+ sensor_out: endpoint {
104+ data-lanes = <1 2 3 4>;
105+ link-frequencies = /bits/ 64 <336000000 207000000>;
106+ remote-endpoint = <&seninf_csi_port_0_in>;
107+ };
108+ };
109+ };
110+ };
111+
112+...
Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml+174−0
@@ -0,0 +1,174 @@
1+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+# Copyright (C) 2024 Collabora Ltd.
3+%YAML 1.2
4+---
5+$id: http://devicetree.org/schemas/media/i2c/maxim,max96714.yaml#
6+$schema: http://devicetree.org/meta-schemas/core.yaml#
7+
8+title: Maxim MAX96714 GMSL2 to CSI-2 Deserializer
9+
10+maintainers:
11+ - Julien Massot <julien.massot@collabora.com>
12+
13+description:
14+ The MAX96714 deserializer converts GMSL2 serial inputs into MIPI
15+ CSI-2 D-PHY formatted output. The device allows the GMSL2 link to
16+ simultaneously transmit bidirectional control-channel data while forward
17+ video transmissions are in progress. The MAX96714 can connect to one
18+ remotely located serializer using industry-standard coax or STP
19+ interconnects. The device cans operate in pixel or tunnel mode. In pixel mode
20+ the MAX96714 can select individual video stream, while the tunnel mode forward all
21+ the MIPI data received by the serializer.
22+
23+ The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
24+ forward direction and 187.5Mbps in the reverse direction.
25+ MAX96714F only supports a fixed rate of 3Gbps in the forward direction.
26+
27+properties:
28+ compatible:
29+ oneOf:
30+ - const: maxim,max96714f
31+ - items:
32+ - enum:
33+ - maxim,max96714
34+ - const: maxim,max96714f
35+
36+ reg:
37+ maxItems: 1
38+
39+ powerdown-gpios:
40+ maxItems: 1
41+ description:
42+ Specifier for the GPIO connected to the PWDNB pin.
43+
44+ ports:
45+ $ref: /schemas/graph.yaml#/properties/ports
46+
47+ properties:
48+ port@0:
49+ $ref: /schemas/graph.yaml#/properties/port
50+ unevaluatedProperties: false
51+ description: GMSL Input
52+ properties:
53+ endpoint:
54+ $ref: /schemas/media/video-interfaces.yaml#
55+ unevaluatedProperties: false
56+ description:
57+ Endpoint for GMSL2-Link port.
58+
59+ port@1:
60+ $ref: /schemas/graph.yaml#/$defs/port-base
61+ unevaluatedProperties: false
62+ description: CSI-2 Output port
63+
64+ properties:
65+ endpoint:
66+ $ref: /schemas/media/video-interfaces.yaml#
67+ unevaluatedProperties: false
68+
69+ properties:
70+ data-lanes:
71+ minItems: 1
72+ maxItems: 4
73+
74+ lane-polarities:
75+ minItems: 1
76+ maxItems: 5
77+
78+ link-frequencies:
79+ maxItems: 1
80+
81+ required:
82+ - data-lanes
83+
84+ required:
85+ - port@1
86+
87+ i2c-gate:
88+ $ref: /schemas/i2c/i2c-gate.yaml
89+ unevaluatedProperties: false
90+ description:
91+ The MAX96714 will pass through and forward the I2C requests from the
92+ incoming I2C bus over the GMSL2 link. Therefore it supports an i2c-gate
93+ subnode to configure a serializer.
94+
95+ port0-poc-supply:
96+ description: Regulator providing Power over Coax for the GMSL port
97+
98+required:
99+ - compatible
100+ - reg
101+ - ports
102+
103+additionalProperties: false
104+
105+examples:
106+ - |
107+ #include <dt-bindings/gpio/gpio.h>
108+ #include <dt-bindings/media/video-interfaces.h>
109+
110+ i2c {
111+ #address-cells = <1>;
112+ #size-cells = <0>;
113+
114+ deserializer@28 {
115+ compatible = "maxim,max96714f";
116+ reg = <0x28>;
117+ powerdown-gpios = <&main_gpio0 37 GPIO_ACTIVE_LOW>;
118+
119+ ports {
120+ #address-cells = <1>;
121+ #size-cells = <0>;
122+ port@0 {
123+ reg = <0>;
124+ max96714_gmsl_in: endpoint {
125+ remote-endpoint = <&max96917f_gmsl_out>;
126+ };
127+ };
128+
129+ port@1 {
130+ reg = <1>;
131+ max96714_csi_out: endpoint {
132+ data-lanes = <1 2 3 4>;
133+ link-frequencies = /bits/ 64 <400000000>;
134+ remote-endpoint = <&csi_in>;
135+ };
136+ };
137+ };
138+
139+ i2c-gate {
140+ #address-cells = <1>;
141+ #size-cells = <0>;
142+
143+ serializer@40 {
144+ compatible = "maxim,max96717f";
145+ reg = <0x40>;
146+ gpio-controller;
147+ #gpio-cells = <2>;
148+ #clock-cells = <0>;
149+
150+ ports {
151+ #address-cells = <1>;
152+ #size-cells = <0>;
153+
154+ port@0 {
155+ reg = <0>;
156+ max96717f_csi_in: endpoint {
157+ data-lanes = <1 2>;
158+ lane-polarities = <1 0 1>;
159+ remote-endpoint = <&sensor_out>;
160+ };
161+ };
162+
163+ port@1 {
164+ reg = <1>;
165+ max96917f_gmsl_out: endpoint {
166+ remote-endpoint = <&max96714_gmsl_in>;
167+ };
168+ };
169+ };
170+ };
171+ };
172+ };
173+ };
174+...
Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml+157−0
@@ -0,0 +1,157 @@
1+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+# Copyright (C) 2024 Collabora Ltd.
3+%YAML 1.2
4+---
5+$id: http://devicetree.org/schemas/media/i2c/maxim,max96717.yaml#
6+$schema: http://devicetree.org/meta-schemas/core.yaml#
7+
8+title: MAX96717 CSI-2 to GMSL2 Serializer
9+
10+maintainers:
11+ - Julien Massot <julien.massot@collabora.com>
12+
13+description:
14+ The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input
15+ into GMSL2 serial outputs. The device allows the GMSL2 link to
16+ simultaneously transmit bidirectional control-channel data while forward
17+ video transmissions are in progress. The MAX96717 can connect to one
18+ remotely located deserializer using industry-standard coax or STP
19+ interconnects. The device cans operate in pixel or tunnel mode. In pixel mode
20+ the MAX96717 can select the MIPI datatype, while the tunnel mode forward all the MIPI
21+ data received by the serializer.
22+ The MAX96717 supports Reference Over Reverse (channel),
23+ to generate a clock output for the sensor from the GMSL reverse channel.
24+
25+ The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the
26+ forward direction and 187.5Mbps in the reverse direction.
27+ MAX96717F only supports a fixed rate of 3Gbps in the forward direction.
28+
29+properties:
30+ compatible:
31+ oneOf:
32+ - const: maxim,max96717f
33+ - items:
34+ - enum:
35+ - maxim,max96717
36+ - const: maxim,max96717f
37+
38+ '#gpio-cells':
39+ const: 2
40+ description:
41+ First cell is the GPIO pin number, second cell is the flags. The GPIO pin
42+ number must be in range of [0, 10].
43+
44+ gpio-controller: true
45+
46+ '#clock-cells':
47+ const: 0
48+
49+ reg:
50+ maxItems: 1
51+
52+ ports:
53+ $ref: /schemas/graph.yaml#/properties/ports
54+
55+ properties:
56+ port@0:
57+ $ref: /schemas/graph.yaml#/$defs/port-base
58+ unevaluatedProperties: false
59+ description: CSI-2 Input port
60+
61+ properties:
62+ endpoint:
63+ $ref: /schemas/media/video-interfaces.yaml#
64+ unevaluatedProperties: false
65+
66+ properties:
67+ data-lanes:
68+ minItems: 1
69+ maxItems: 4
70+
71+ lane-polarities:
72+ minItems: 1
73+ maxItems: 5
74+
75+ required:
76+ - data-lanes
77+
78+ port@1:
79+ $ref: /schemas/graph.yaml#/properties/port
80+ unevaluatedProperties: false
81+ description: GMSL Output port
82+
83+ required:
84+ - port@1
85+
86+ i2c-gate:
87+ $ref: /schemas/i2c/i2c-gate.yaml
88+ unevaluatedProperties: false
89+ description:
90+ The MAX96717 will forward the I2C requests from the
91+ incoming GMSL2 link. Therefore, it supports an i2c-gate
92+ subnode to configure a sensor.
93+
94+required:
95+ - compatible
96+ - reg
97+ - ports
98+
99+additionalProperties: false
100+
101+examples:
102+ - |
103+ #include <dt-bindings/gpio/gpio.h>
104+ #include <dt-bindings/media/video-interfaces.h>
105+
106+ i2c {
107+ #address-cells = <1>;
108+ #size-cells = <0>;
109+ serializer: serializer@40 {
110+ compatible = "maxim,max96717f";
111+ reg = <0x40>;
112+ gpio-controller;
113+ #gpio-cells = <2>;
114+ #clock-cells = <0>;
115+
116+ ports {
117+ #address-cells = <1>;
118+ #size-cells = <0>;
119+
120+ port@0 {
121+ reg = <0>;
122+ max96717f_csi_in: endpoint {
123+ data-lanes = <1 2 3 4>;
124+ remote-endpoint = <&sensor_out>;
125+ };
126+ };
127+
128+ port@1 {
129+ reg = <1>;
130+ max96917f_gmsl_out: endpoint {
131+ remote-endpoint = <&deser_gmsl_in>;
132+ };
133+ };
134+ };
135+
136+ i2c-gate {
137+ #address-cells = <1>;
138+ #size-cells = <0>;
139+ sensor@10 {
140+ compatible = "st,st-vgxy61";
141+ reg = <0x10>;
142+ reset-gpios = <&serializer 0 GPIO_ACTIVE_LOW>;
143+ clocks = <&serializer>;
144+ VCORE-supply = <&v1v2>;
145+ VDDIO-supply = <&v1v8>;
146+ VANA-supply = <&v2v8>;
147+ port {
148+ sensor_out: endpoint {
149+ data-lanes = <1 2 3 4>;
150+ remote-endpoint = <&max96717f_csi_in>;
151+ };
152+ };
153+ };
154+ };
155+ };
156+ };
157+...
Documentation/devicetree/bindings/media/i2c/sony,imx258.yamlrenamed from Documentation/devicetree/bindings/media/i2c/imx258.yaml+8−3
@@ -1,7 +1,7 @@
11 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
22 %YAML 1.2
33 ---
4−$id: http://devicetree.org/schemas/media/i2c/imx258.yaml#
4+$id: http://devicetree.org/schemas/media/i2c/sony,imx258.yaml#
55 $schema: http://devicetree.org/meta-schemas/core.yaml#
66
77 title: Sony IMX258 13 Mpixel CMOS Digital Image Sensor
@@ -13,11 +13,16 @@ description: |- · 5 unmodified lines
1313 IMX258 is a diagonal 5.867mm (Type 1/3.06) 13 Mega-pixel CMOS active pixel
1414 type stacked image sensor with a square pixel array of size 4208 x 3120. It
1515 is programmable through I2C interface. Image data is sent through MIPI
16− CSI-2.
16+ CSI-2. The sensor exists in two different models, a standard variant
17+ (IMX258) and a variant with phase detection autofocus (IMX258-PDAF).
18+ The camera module does not expose the model through registers, so the
19+ exact model needs to be specified.
1720
1821 properties:
1922 compatible:
20− const: sony,imx258
23+ enum:
24+ - sony,imx258
25+ - sony,imx258-pdaf
2126
2227 assigned-clocks: true
2328 assigned-clock-parents: true
Documentation/devicetree/bindings/media/i2c/sony,imx283.yaml+107−0
@@ -0,0 +1,107 @@
1+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+# Copyright (C) 2024 Ideas on Board Oy
3+%YAML 1.2
4+---
5+$id: http://devicetree.org/schemas/media/i2c/sony,imx283.yaml#
6+$schema: http://devicetree.org/meta-schemas/core.yaml#
7+
8+title: Sony IMX283 Sensor
9+
10+maintainers:
11+ - Kieran Bingham <kieran.bingham@ideasonboard.com>
12+ - Umang Jain <umang.jain@ideasonboard.com>
13+
14+description:
15+ IMX283 sensor is a Sony CMOS active pixel digital image sensor with an active
16+ array size of 5472H x 3648V. It is programmable through I2C interface. The
17+ I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
18+ sent through MIPI CSI-2.
19+
20+properties:
21+ compatible:
22+ const: sony,imx283
23+
24+ reg:
25+ maxItems: 1
26+
27+ clocks:
28+ description: Clock frequency from 6 to 24 MHz.
29+ maxItems: 1
30+
31+ vadd-supply:
32+ description: Analog power supply (2.9V)
33+
34+ vdd1-supply:
35+ description: Interface power supply (1.8V)
36+
37+ vdd2-supply:
38+ description: Digital power supply (1.2V)
39+
40+ reset-gpios:
41+ description: Sensor reset (XCLR) GPIO
42+ maxItems: 1
43+
44+ port:
45+ $ref: /schemas/graph.yaml#/$defs/port-base
46+ additionalProperties: false
47+
48+ properties:
49+ endpoint:
50+ $ref: /schemas/media/video-interfaces.yaml#
51+ unevaluatedProperties: false
52+
53+ properties:
54+ data-lanes:
55+ anyOf:
56+ - items:
57+ - const: 1
58+ - const: 2
59+ - const: 3
60+ - const: 4
61+
62+ link-frequencies: true
63+
64+ required:
65+ - data-lanes
66+ - link-frequencies
67+
68+ required:
69+ - endpoint
70+
71+required:
72+ - compatible
73+ - reg
74+ - clocks
75+ - port
76+
77+additionalProperties: false
78+
79+examples:
80+ - |
81+ i2c {
82+ #address-cells = <1>;
83+ #size-cells = <0>;
84+
85+ camera@1a {
86+ compatible = "sony,imx283";
87+ reg = <0x1a>;
88+ clocks = <&imx283_clk>;
89+
90+ assigned-clocks = <&imx283_clk>;
91+ assigned-clock-parents = <&imx283_clk_parent>;
92+ assigned-clock-rates = <12000000>;
93+
94+ vadd-supply = <&camera_vadd_2v9>;
95+ vdd1-supply = <&camera_vdd1_1v8>;
96+ vdd2-supply = <&camera_vdd2_1v2>;
97+
98+ port {
99+ imx283: endpoint {
100+ remote-endpoint = <&cam>;
101+ data-lanes = <1 2 3 4>;
102+ link-frequencies = /bits/ 64 <360000000>;
103+ };
104+ };
105+ };
106+ };
107+...
Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml+75−0
@@ -0,0 +1,75 @@
1+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+%YAML 1.2
3+---
4+$id: http://devicetree.org/schemas/media/img,e5010-jpeg-enc.yaml#
5+$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+title: Imagination E5010 JPEG Encoder
8+
9+maintainers:
10+ - Devarsh Thakkar <devarsht@ti.com>
11+
12+description: |
13+ The E5010 is a JPEG encoder from Imagination Technologies implemented on
14+ TI's AM62A SoC. It is capable of real time encoding of YUV420 and YUV422
15+ inputs to JPEG and M-JPEG. It supports baseline JPEG Encoding up to
16+ 8Kx8K resolution.
17+
18+properties:
19+ compatible:
20+ oneOf:
21+ - items:
22+ - const: ti,am62a-jpeg-enc
23+ - const: img,e5010-jpeg-enc
24+ - const: img,e5010-jpeg-enc
25+
26+ reg:
27+ items:
28+ - description: The E5010 core register region
29+ - description: The E5010 mmu register region
30+
31+ reg-names:
32+ items:
33+ - const: core
34+ - const: mmu
35+
36+ power-domains:
37+ maxItems: 1
38+
39+ resets:
40+ maxItems: 1
41+
42+ clocks:
43+ maxItems: 1
44+
45+ interrupts:
46+ maxItems: 1
47+
48+required:
49+ - compatible
50+ - reg
51+ - reg-names
52+ - interrupts
53+ - clocks
54+
55+additionalProperties: false
56+
57+examples:
58+ - |
59+ #include <dt-bindings/soc/ti,sci_pm_domain.h>
60+ #include <dt-bindings/interrupt-controller/arm-gic.h>
61+ #include <dt-bindings/interrupt-controller/irq.h>
62+
63+ soc {
64+ #address-cells = <2>;
65+ #size-cells = <2>;
66+ jpeg-encoder@fd20000 {
67+ compatible = "img,e5010-jpeg-enc";
68+ reg = <0x00 0xfd20000 0x00 0x100>,
69+ <0x00 0xfd20200 0x00 0x200>;
70+ reg-names = "core", "mmu";
71+ clocks = <&k3_clks 201 0>;
72+ power-domains = <&k3_pds 201 TI_SCI_PD_EXCLUSIVE>;
73+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
74+ };
75+ };
Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml+1−0
@@ -23,6 +23,7 @@ properties: · 22 unmodified lines
2323 oneOf:
2424 - enum:
2525 - mediatek,mt8183-mdp3-rdma
26+ - mediatek,mt8188-mdp3-rdma
2627 - mediatek,mt8195-mdp3-rdma
2728 - mediatek,mt8195-vdo1-rdma
2829 - items:
Documentation/devicetree/bindings/media/mediatek,mt7622-cir.yaml+55−0
@@ -0,0 +1,55 @@
1+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2+%YAML 1.2
3+---
4+$id: http://devicetree.org/schemas/media/mediatek,mt7622-cir.yaml#
5+$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+title: MediaTek Consumer Infrared Receiver on-SoC Controller
8+
9+maintainers:
10+ - Sean Wang <sean.wang@mediatek.com>
11+
12+allOf:
13+ - $ref: rc.yaml#
14+
15+properties:
16+ compatible:
17+ enum:
18+ - mediatek,mt7622-cir
19+ - mediatek,mt7623-cir
20+
21+ reg:
22+ maxItems: 1
23+
24+ interrupts:
25+ maxItems: 1
26+
27+ clocks:
28+ maxItems: 2
29+
30+ clock-names:
31+ items:
32+ - const: clk
33+ - const: bus
34+
35+required:
36+ - reg
37+ - interrupts
38+ - clocks
39+ - clock-names
40+
41+unevaluatedProperties: false
42+
43+examples:
44+ - |
45+ #include <dt-bindings/clock/mt2701-clk.h>
46+ #include <dt-bindings/interrupt-controller/arm-gic.h>
47+
48+ ir@10013000 {
49+ compatible = "mediatek,mt7623-cir";
50+ reg = <0x10013000 0x1000>;
51+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_LOW>;
52+ clocks = <&infracfg CLK_INFRA_IRRX>, <&topckgen CLK_TOP_AXI_SEL>;
53+ clock-names = "clk", "bus";
54+ linux,rc-map-name = "rc-rc6-mce";
55+ };
Documentation/devicetree/bindings/media/mtk-cir.txt+0−28
@@ -1,28 +0,0 @@
1−Device-Tree bindings for Mediatek consumer IR controller
2−found in Mediatek SoC family
3−
4−Required properties:
5−- compatible : Should be
6− "mediatek,mt7623-cir": for MT7623 SoC
7− "mediatek,mt7622-cir": for MT7622 SoC
8−- clocks : list of clock specifiers, corresponding to
9− entries in clock-names property;
10−- clock-names : should contain
11− - "clk" entries: for MT7623 SoC
12− - "clk", "bus" entries: for MT7622 SoC
13−- interrupts : should contain IR IRQ number;
14−- reg : should contain IO map address for IR.
15−
16−Optional properties:
17−- linux,rc-map-name : see rc.txt file in the same directory.
18−
19−Example:
20−
21−cir: cir@10013000 {
22− compatible = "mediatek,mt7623-cir";
23− reg = <0 0x10013000 0 0x1000>;
24− interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_LOW>;
25− clocks = <&infracfg CLK_INFRA_IRRX>;
26− clock-names = "clk";
27− linux,rc-map-name = "rc-rc6-mce";
28−};
Documentation/devicetree/bindings/media/qcom,msm8996-venus.yaml+3−1
@@ -18,7 +18,9 @@ allOf: · 17 unmodified lines
1818
1919 properties:
2020 compatible:
21− const: qcom,msm8996-venus
21+ enum:
22+ - qcom,msm8996-venus
23+ - qcom,msm8998-venus
2224
2325 power-domains:
2426 maxItems: 1
Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml+63−0
@@ -0,0 +1,63 @@
1+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+%YAML 1.2
3+---
4+$id: http://devicetree.org/schemas/media/raspberrypi,pispbe.yaml#
5+$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+title: Raspberry Pi PiSP Image Signal Processor (ISP) Back End
8+
9+maintainers:
10+ - Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
11+ - Jacopo Mondi <jacopo.mondi@ideasonboard.com>
12+
13+description: |
14+ The Raspberry Pi PiSP Image Signal Processor (ISP) Back End is an image
15+ processor that fetches images in Bayer or Grayscale format from DRAM memory
16+ in tiles and produces images consumable by applications.
17+
18+ The full ISP documentation is available at
19+ https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf
20+
21+properties:
22+ compatible:
23+ items:
24+ - enum:
25+ - brcm,bcm2712-pispbe
26+ - const: raspberrypi,pispbe
27+
28+ reg:
29+ maxItems: 1
30+
31+ interrupts:
32+ maxItems: 1
33+
34+ clocks:
35+ maxItems: 1
36+
37+ iommus:
38+ maxItems: 1
39+
40+required:
41+ - compatible
42+ - reg
43+ - interrupts
44+ - clocks
45+
46+additionalProperties: false
47+
48+examples:
49+ - |
50+ #include <dt-bindings/interrupt-controller/arm-gic.h>
51+
52+ soc {
53+ #address-cells = <2>;
54+ #size-cells = <2>;
55+
56+ isp@880000 {
57+ compatible = "brcm,bcm2712-pispbe", "raspberrypi,pispbe";
58+ reg = <0x10 0x00880000 0x0 0x4000>;
59+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
60+ clocks = <&firmware_clocks 7>;
61+ iommus = <&iommu2>;
62+ };
63+ };
Documentation/devicetree/bindings/media/rc.yaml+1−0
@@ -103,6 +103,7 @@ properties: · 102 unmodified lines
103103 - rc-msi-digivox-iii
104104 - rc-msi-tvanywhere
105105 - rc-msi-tvanywhere-plus
106+ - rc-mygica-utv3
106107 - rc-nebula
107108 - rc-nec-terratec-cinergy-xs
108109 - rc-norwood
Documentation/devicetree/bindings/media/rockchip-rga.yaml+1−0
@@ -24,6 +24,7 @@ properties: · 23 unmodified lines
2424 - enum:
2525 - rockchip,rk3228-rga
2626 - rockchip,rk3568-rga
27+ - rockchip,rk3588-rga
2728 - const: rockchip,rk3288-rga
2829
2930 reg:
Documentation/driver-api/media/v4l2-core.rst+1−0
@@ -26,3 +26,4 @@ Video4Linux devices · 25 unmodified lines
2626 v4l2-tuner
2727 v4l2-common
2828 v4l2-tveeprom
29+ v4l2-jpeg
Documentation/driver-api/media/v4l2-jpeg.rst+10−0
@@ -0,0 +1,10 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+V4L2 JPEG header related functions and data structures
4+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
6+.. kernel-doc:: include/media/v4l2-jpeg.h
7+ :internal:
8+
9+.. kernel-doc:: drivers/media/v4l2-core/v4l2-jpeg.c
10+ :export:
Documentation/userspace-api/media/drivers/index.rst+1−1
@@ -35,6 +35,6 @@ For more details see the file COPYING in the source distribution of Linux. · 34 unmodified lines
3535 max2175
3636 npcm-video
3737 omap3isp-uapi
38− st-vgxy61
3938 thp7312
4039 uvcvideo
40+ vgxy61
Documentation/userspace-api/media/drivers/vgxy61.rstrenamed from Documentation/userspace-api/media/drivers/st-vgxy61.rst+0−0

File renamed without changes.

Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst+2−2
@@ -971,8 +971,8 @@ FWHT Flags · 970 unmodified lines
971971 - ``horizontal_scale``
972972 - Horizontal scaling factor.
973973 * - __u8
974− - ``vertical_scaling factor``
975− - Vertical scale.
974+ - ``vertical_scale``
975+ - Vertical scaling factor.
976976 * - __u8
977977 - ``version``
978978 - Bitstream version.
Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst+14−0
@@ -1653,6 +1653,20 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - · 1652 unmodified lines
16531653 Quantization parameter for a P frame for FWHT. Valid range: from 1
16541654 to 31.
16551655
1656+``V4L2_CID_MPEG_VIDEO_AVERAGE_QP (integer)``
1657+ This read-only control returns the average QP value of the currently
1658+ encoded frame. The value applies to the last dequeued capture buffer
1659+ (VIDIOC_DQBUF). Its valid range depends on the encoding format and parameters.
1660+ For H264, its valid range is from 0 to 51.
1661+ For HEVC, its valid range is from 0 to 51 for 8 bit and
1662+ from 0 to 63 for 10 bit.
1663+ For H263 and MPEG4, its valid range is from 1 to 31.
1664+ For VP8, its valid range is from 0 to 127.
1665+ For VP9, its valid range is from 0 to 255.
1666+ If the codec's MIN_QP and MAX_QP are set, then the QP will meet both requirements.
1667+ Codecs need to always use the specified range, rather then a HW custom range.
1668+ Applicable to encoders
1669+
16561670 .. raw:: latex
16571671
16581672 \normalsize
Documentation/userspace-api/media/v4l/meta-formats.rst+1−0
@@ -15,6 +15,7 @@ These formats are used for the :ref:`metadata` interface only. · 14 unmodified lines
1515 metafmt-d4xx
1616 metafmt-generic
1717 metafmt-intel-ipu3
18+ metafmt-pisp-be
1819 metafmt-rkisp1
1920 metafmt-uvc
2021 metafmt-vivid
Documentation/userspace-api/media/v4l/metafmt-pisp-be.rst+56−0
@@ -0,0 +1,56 @@
1+.. SPDX-License-Identifier: GPL-2.0
2+
3+.. _v4l2-meta-fmt-rpi-be-cfg:
4+
5+************************
6+V4L2_META_FMT_RPI_BE_CFG
7+************************
8+
9+Raspberry Pi PiSP Back End configuration format
10+===============================================
11+
12+The Raspberry Pi PiSP Back End memory-to-memory image signal processor is
13+configured by userspace by providing a buffer of configuration parameters
14+to the `pispbe-config` output video device node using the
15+:c:type:`v4l2_meta_format` interface.
16+
17+The PiSP Back End processes images in tiles, and its configuration requires
18+specifying two different sets of parameters by populating the members of
19+:c:type:`pisp_be_tiles_config` defined in the ``pisp_be_config.h`` header file.
20+
21+The `Raspberry Pi PiSP technical specification
22+<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_
23+provide detailed description of the ISP back end configuration and programming
24+model.
25+
26+Global configuration data
27+-------------------------
28+
29+The global configuration data describe how the pixels in a particular image are
30+to be processed and is therefore shared across all the tiles of the image. So
31+for example, LSC (Lens Shading Correction) or Denoise parameters would be common
32+across all tiles from the same frame.
33+
34+Global configuration data are passed to the ISP by populating the member of
35+:c:type:`pisp_be_config`.
36+
37+Tile parameters
38+---------------
39+
40+As the ISP processes images in tiles, each set of tiles parameters describe how
41+a single tile in an image is going to be processed. A single set of tile
42+parameters consist of 160 bytes of data and to process a batch of tiles several
43+sets of tiles parameters are required.
44+
45+Tiles parameters are passed to the ISP by populating the member of
46+``pisp_tile`` and the ``num_tiles`` fields of :c:type:`pisp_be_tiles_config`.
47+
48+Raspberry Pi PiSP Back End uAPI data types
49+==========================================
50+
51+This section describes the data types exposed to userspace by the Raspberry Pi
52+PiSP Back End. The section is informative only, for a detailed description of
53+each field refer to the `Raspberry Pi PiSP technical specification
54+<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_.
55+
56+.. kernel-doc:: include/uapi/linux/media/raspberrypi/pisp_be_config.h
Documentation/userspace-api/media/v4l/pixfmt-bayer.rst+1−0
@@ -20,6 +20,7 @@ orders. See also `the Wikipedia article on Bayer filter · 19 unmodified lines
2020 :maxdepth: 1
2121
2222 pixfmt-srggb8
23+ pixfmt-srggb8-pisp-comp
2324 pixfmt-srggb10
2425 pixfmt-srggb10p
2526 pixfmt-srggb10alaw8
Documentation/userspace-api/media/v4l/pixfmt-rgb.rst+54−0
@@ -996,6 +996,60 @@ arranged in little endian order. · 995 unmodified lines
996996
997997 \normalsize
998998
999+16 Bits Per Component
1000+=====================
1001+
1002+These formats store an RGB triplet in six bytes, with 16 bits per component
1003+stored in memory in little endian byte order. They are named based on the order
1004+of the RGB components as stored in memory. For instance, RGB48 stores R\
1005+:sub:`7:0` and R\ :sub:`15:8` in bytes 0 and 1 respectively. This differs from
1006+the DRM format nomenclature that instead uses the order of components as seen in
1007+the 48-bits little endian word.
1008+
1009+.. raw:: latex
1010+
1011+ \small
1012+
1013+.. flat-table:: RGB Formats With 16 Bits Per Component
1014+ :header-rows: 1
1015+
1016+ * - Identifier
1017+ - Code
1018+ - Byte 0
1019+ - Byte 1
1020+ - Byte 2
1021+ - Byte 3
1022+ - Byte 4
1023+ - Byte 5
1024+
1025+ * .. _V4L2-PIX-FMT-BGR48:
1026+
1027+ - ``V4L2_PIX_FMT_BGR48``
1028+ - 'BGR6'
1029+
1030+ - B\ :sub:`7-0`
1031+ - B\ :sub:`15-8`
1032+ - G\ :sub:`7-0`
1033+ - G\ :sub:`15-8`
1034+ - R\ :sub:`7-0`
1035+ - R\ :sub:`15-8`
1036+
1037+ * .. _V4L2-PIX-FMT-RGB48:
1038+
1039+ - ``V4L2_PIX_FMT_RGB48``
1040+ - 'RGB6'
1041+
1042+ - R\ :sub:`7-0`
1043+ - R\ :sub:`15-8`
1044+ - G\ :sub:`7-0`
1045+ - G\ :sub:`15-8`
1046+ - B\ :sub:`7-0`
1047+ - B\ :sub:`15-8`
1048+
1049+.. raw:: latex
1050+
1051+ \normalsize
1052+
9991053 Deprecated RGB Formats
10001054 ======================
10011055
Documentation/userspace-api/media/v4l/pixfmt-srggb8-pisp-comp.rst+74−0
@@ -0,0 +1,74 @@
1+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
2+
3+.. _v4l2-pix-fmt-pisp-comp1-rggb:
4+.. _v4l2-pix-fmt-pisp-comp1-grbg:
5+.. _v4l2-pix-fmt-pisp-comp1-gbrg:
6+.. _v4l2-pix-fmt-pisp-comp1-bggr:
7+.. _v4l2-pix-fmt-pisp-comp1-mono:
8+.. _v4l2-pix-fmt-pisp-comp2-rggb:
9+.. _v4l2-pix-fmt-pisp-comp2-grbg:
10+.. _v4l2-pix-fmt-pisp-comp2-gbrg:
11+.. _v4l2-pix-fmt-pisp-comp2-bggr:
12+.. _v4l2-pix-fmt-pisp-comp2-mono:
13+
14+**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
15+V4L2_PIX_FMT_PISP_COMP1_RGGB ('PC1R'), V4L2_PIX_FMT_PISP_COMP1_GRBG ('PC1G'), V4L2_PIX_FMT_PISP_COMP1_GBRG ('PC1g'), V4L2_PIX_FMT_PISP_COMP1_BGGR ('PC1B), V4L2_PIX_FMT_PISP_COMP1_MONO ('PC1M'), V4L2_PIX_FMT_PISP_COMP2_RGGB ('PC2R'), V4L2_PIX_FMT_PISP_COMP2_GRBG ('PC2G'), V4L2_PIX_FMT_PISP_COMP2_GBRG ('PC2g'), V4L2_PIX_FMT_PISP_COMP2_BGGR ('PC2B), V4L2_PIX_FMT_PISP_COMP2_MONO ('PC2M')
16+**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
17+
18+================================================
19+Raspberry Pi PiSP compressed 8-bit Bayer formats
20+================================================
21+
22+Description
23+===========
24+
25+The Raspberry Pi ISP (PiSP) uses a family of three fixed-rate compressed Bayer
26+formats. A black-level offset may be subtracted to improve compression
27+efficiency; the nominal black level and amount of offset must be signalled out
28+of band. Each scanline is padded to a multiple of 8 pixels wide, and each block
29+of 8 horizontally-contiguous pixels is coded using 8 bytes.
30+
31+Mode 1 uses a quantization and delta-based coding scheme which preserves up to
32+12 significant bits. Mode 2 is a simple sqrt-like companding scheme with 6 PWL
33+chords, preserving up to 12 significant bits. Mode 3 combines both companding
34+(with 4 chords) and the delta scheme, preserving up to 14 significant bits.
35+
36+The remainder of this description applies to Modes 1 and 3.
37+
38+Each block of 8 pixels is separated into even and odd phases of 4 pixels,
39+coded independently by 32-bit words at successive locations in memory.
40+The two LS bits of each 32-bit word give its "quantization mode".
41+
42+In quantization mode 0, the lowest 321 quantization levels are multiples of
43+FSD/4096 and the remaining levels are successive multiples of FSD/2048.
44+Quantization modes 1 and 2 use linear quantization with step sizes of
45+FSD/1024 and FSD/512 respectively. Each of the four pixels is quantized
46+independently, with rounding to the nearest level.
47+In quantization mode 2 where the middle two samples have quantized values
48+(q1,q2) both in the range [384..511], they are coded using 9 bits for q1
49+followed by 7 bits for (q2 & 127). Otherwise, for quantization modes
50+0, 1 and 2: a 9-bit field encodes MIN(q1,q2) which must be in the range
51+[0..511] and a 7-bit field encodes (q2-q1+64) which must be in [0..127].
52+
53+Each of the outer samples (q0,q3) is encoded using a 7-bit field based
54+on its inner neighbour q1 or q2. In quantization mode 2 where the inner
55+sample has a quantized value in the range [448..511], the field value is
56+(q0-384). Otherwise for quantization modes 0, 1 and 2: The outer sample
57+is encoded as (q0-MAX(0,q1-64)). q3 is likewise coded based on q2.
58+Each of these values must be in the range [0..127]. All these fields
59+of 2, 9, 7, 7, 7 bits respectively are packed in little-endian order
60+to give a 32-bit word with LE byte order.
61+
62+Quantization mode 3 has a "7.5-bit" escape, used when none of the above
63+encodings will fit. Each pixel value is quantized to the nearest of 176
64+levels, where the lowest 95 levels are multiples of FSD/256 and the
65+remaining levels are multiples of FSD/128 (level 175 represents values
66+very close to FSD and may require saturating arithmetic to decode).
67+
68+Each pair of quantized pixels (q0,q1) or (q2,q3) is jointly coded
69+by a 15-bit field: 2816*(q0>>4) + 16*q1 + (q0&15).
70+Three fields of 2, 15, 15 bits are packed in LE order {15,15,2}.
71+
72+An implementation of a software decoder of compressed formats is available
73+in `Raspberry Pi camera applications code base
74+<https://github.com/raspberrypi/rpicam-apps/blob/main/image/dng.cpp>`_.
Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst+4−0
@@ -209,3 +209,7 @@ are often referred to as greyscale formats. · 208 unmodified lines
209209 For Y012 and Y12 formats, Y012 places its data in the 12 high bits, with
210210 padding zeros in the 4 low bits, in contrast to the Y12 format, which has
211211 its padding located in the most significant bits of the 16 bit word.
212+
213+ The 'P' variations of the Y10, Y12 and Y14 formats are packed according to
214+ the RAW10, RAW12 and RAW14 packing scheme as defined by the MIPI CSI-2
215+ specification.
MAINTAINERS+57−6
@@ -9190,6 +9190,20 @@ S: Maintained · 9189 unmodified lines
91909190 F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc0308.yaml
91919191 F: drivers/media/i2c/gc0308.c
91929192
9193+GALAXYCORE GC05a2 CAMERA SENSOR DRIVER
9194+M: Zhi Mao <zhi.mao@mediatek.com>
9195+L: linux-media@vger.kernel.org
9196+S: Maintained
9197+F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc05a2.yaml
9198+F: drivers/media/i2c/gc05a2.c
9199+
9200+GALAXYCORE GC08A3 CAMERA SENSOR DRIVER
9201+M: Zhi Mao <zhi.mao@mediatek.com>
9202+L: linux-media@vger.kernel.org
9203+S: Maintained
9204+F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc08a3.yaml
9205+F: drivers/media/i2c/gc08a3.c
9206+
91939207 GALAXYCORE GC2145 SENSOR DRIVER
91949208 M: Alain Volmat <alain.volmat@foss.st.com>
91959209 L: linux-media@vger.kernel.org
@@ -10872,6 +10886,13 @@ S: Maintained · 1676 unmodified lines
1087210886 F: Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml
1087310887 F: drivers/auxdisplay/img-ascii-lcd.c
1087410888
10889+IMGTEC JPEG ENCODER DRIVER
10890+M: Devarsh Thakkar <devarsht@ti.com>
10891+L: linux-media@vger.kernel.org
10892+S: Supported
10893+F: Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml
10894+F: drivers/media/platform/imagination/e5010*
10895+
1087510896 IMGTEC IR DECODER DRIVER
1087610897 S: Orphan
1087710898 F: drivers/media/rc/img-ir/
@@ -13632,6 +13653,20 @@ S: Maintained · 2754 unmodified lines
1363213653 F: Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
1363313654 F: drivers/staging/media/max96712/max96712.c
1363413655
13656+MAX96714 GMSL2 DESERIALIZER DRIVER
13657+M: Julien Massot <julien.massot@collabora.com>
13658+L: linux-media@vger.kernel.org
13659+S: Maintained
13660+F: Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
13661+F: drivers/media/i2c/max96714.c
13662+
13663+MAX96717 GMSL2 SERIALIZER DRIVER
13664+M: Julien Massot <julien.massot@collabora.com>
13665+L: linux-media@vger.kernel.org
13666+S: Maintained
13667+F: Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
13668+F: drivers/media/i2c/max96717.c
13669+
1363513670 MAX9860 MONO AUDIO VOICE CODEC DRIVER
1363613671 M: Peter Rosin <peda@axentia.se>
1363713672 L: alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -18948,6 +18983,15 @@ L: linux-edac@vger.kernel.org · 5310 unmodified lines
1894818983 S: Maintained
1894918984 F: drivers/ras/amd/fmpm.c
1895018985
18986+RASPBERRY PI PISP BACK END
18987+M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
18988+L: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
18989+L: linux-media@vger.kernel.org
18990+S: Maintained
18991+F: Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml
18992+F: drivers/media/platform/raspberrypi/pisp_be/
18993+F: include/uapi/linux/media/raspberrypi/
18994+
1895118995 RC-CORE / LIRC FRAMEWORK
1895218996 M: Sean Young <sean@mess.org>
1895318997 L: linux-media@vger.kernel.org
@@ -20898,7 +20942,6 @@ F: include/uapi/rdma/rdma_user_rxe.h · 1944 unmodified lines
2089820942
2089920943 SOFTLOGIC 6x10 MPEG CODEC
2090020944 M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
20901−M: Anton Sviridenko <anton@corp.bluecherry.net>
2090220945 M: Andrey Utkin <andrey_utkin@fastmail.com>
2090320946 M: Ismael Luceno <ismael@iodev.co.uk>
2090420947 L: linux-media@vger.kernel.org
@@ -20994,7 +21037,7 @@ M: Sakari Ailus <sakari.ailus@linux.intel.com> · 89 unmodified lines
2099421037 L: linux-media@vger.kernel.org
2099521038 S: Maintained
2099621039 T: git git://linuxtv.org/media_tree.git
20997−F: Documentation/devicetree/bindings/media/i2c/imx258.yaml
21040+F: Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
2099821041 F: drivers/media/i2c/imx258.c
2099921042
2100021043 SONY IMX274 SENSOR DRIVER
@@ -21005,6 +21048,15 @@ T: git git://linuxtv.org/media_tree.git · 4 unmodified lines
2100521048 F: Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml
2100621049 F: drivers/media/i2c/imx274.c
2100721050
21051+SONY IMX283 SENSOR DRIVER
21052+M: Kieran Bingham <kieran.bingham@ideasonboard.com>
21053+M: Umang Jain <umang.jain@ideasonboard.com>
21054+L: linux-media@vger.kernel.org
21055+S: Maintained
21056+T: git git://linuxtv.org/media_tree.git
21057+F: Documentation/devicetree/bindings/media/i2c/sony,imx283.yaml
21058+F: drivers/media/i2c/imx283.c
21059+
2100821060 SONY IMX290 SENSOR DRIVER
2100921061 M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
2101021062 L: linux-media@vger.kernel.org
@@ -21381,8 +21433,8 @@ L: linux-media@vger.kernel.org · 370 unmodified lines
2138121433 S: Maintained
2138221434 T: git git://linuxtv.org/media_tree.git
2138321435 F: Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml
21384−F: Documentation/userspace-api/media/drivers/st-vgxy61.rst
21385−F: drivers/media/i2c/st-vgxy61.c
21436+F: Documentation/userspace-api/media/drivers/vgxy61.rst
21437+F: drivers/media/i2c/vgxy61.c
2138621438
2138721439 ST VL53L0X ToF RANGER(I2C) IIO DRIVER
2138821440 M: Song Qiang <songqiang1304521@gmail.com>
@@ -23108,7 +23160,6 @@ F: tools/testing/selftests/turbostat/ · 1719 unmodified lines
2310823160
2310923161 TW5864 VIDEO4LINUX DRIVER
2311023162 M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
23111−M: Anton Sviridenko <anton@corp.bluecherry.net>
2311223163 M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>
2311323164 M: Andrey Utkin <andrey_utkin@fastmail.com>
2311423165 L: linux-media@vger.kernel.org
@@ -23725,7 +23776,7 @@ F: drivers/media/i2c/mt* · 610 unmodified lines
2372523776 F: drivers/media/i2c/og*
2372623777 F: drivers/media/i2c/ov*
2372723778 F: drivers/media/i2c/s5*
23728−F: drivers/media/i2c/st-vgxy61.c
23779+F: drivers/media/i2c/vgxy61.c
2372923780
2373023781 VF610 NAND DRIVER
2373123782 M: Stefan Agner <stefan@agner.ch>
drivers/media/common/siano/smscoreapi.c+5−5
@@ -839,7 +839,7 @@ static int smscore_configure_board(struct smscore_device_t *coredev) · 838 unmodified lines
839839 mtu_msg.x_msg_header.msg_flags = 0;
840840 mtu_msg.x_msg_header.msg_type = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;
841841 mtu_msg.x_msg_header.msg_length = sizeof(mtu_msg);
842− mtu_msg.msg_data[0] = board->mtu;
842+ mtu_msg.msg_data = board->mtu;
843843
844844 coredev->sendrequest_handler(coredev->context, &mtu_msg,
845845 sizeof(mtu_msg));
@@ -852,7 +852,7 @@ static int smscore_configure_board(struct smscore_device_t *coredev) · 6 unmodified lines
852852 SMS_INIT_MSG(&crys_msg.x_msg_header,
853853 MSG_SMS_NEW_CRYSTAL_REQ,
854854 sizeof(crys_msg));
855− crys_msg.msg_data[0] = board->crystal;
855+ crys_msg.msg_data = board->crystal;
856856
857857 coredev->sendrequest_handler(coredev->context, &crys_msg,
858858 sizeof(crys_msg));
@@ -1306,7 +1306,7 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode) · 447 unmodified lines
13061306 msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);
13071307 SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
13081308 sizeof(struct sms_msg_data));
1309− msg->msg_data[0] = mode;
1309+ msg->msg_data = mode;
13101310
13111311 rc = smscore_sendrequest_and_wait(coredev, msg,
13121312 msg->x_msg_header. msg_length,
@@ -1394,7 +1394,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) · 81 unmodified lines
13941394
13951395 SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
13961396 sizeof(struct sms_msg_data));
1397− msg->msg_data[0] = mode;
1397+ msg->msg_data = mode;
13981398
13991399 rc = smscore_sendrequest_and_wait(
14001400 coredev, msg, msg->x_msg_header.msg_length,
@@ -1554,7 +1554,7 @@ void smscore_onresponse(struct smscore_device_t *coredev, · 153 unmodified lines
15541554 struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
15551555
15561556 pr_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x\n",
1557− validity->msg_data[0]);
1557+ validity->msg_data);
15581558 complete(&coredev->data_validity_done);
15591559 break;
15601560 }
drivers/media/common/siano/smscoreapi.h+2−16
@@ -616,7 +616,7 @@ struct sms_msg_hdr { · 615 unmodified lines
616616
617617 struct sms_msg_data {
618618 struct sms_msg_hdr x_msg_header;
619− u32 msg_data[1];
619+ u32 msg_data;
620620 };
621621
622622 struct sms_msg_data2 {
@@ -666,7 +666,7 @@ struct sms_firmware { · 43 unmodified lines
666666 u32 check_sum;
667667 u32 length;
668668 u32 start_address;
669− u8 payload[1];
669+ u8 payload[];
670670 };
671671
672672 /* statistics information returned as response for
@@ -1042,20 +1042,6 @@ struct sms_srvm_signal_status { · 369 unmodified lines
10421042 u32 request_id;
10431043 };
10441044
1045−struct sms_i2c_req {
1046− u32 device_address; /* I2c device address */
1047− u32 write_count; /* number of bytes to write */
1048− u32 read_count; /* number of bytes to read */
1049− u8 Data[1];
1050−};
1051−
1052−struct sms_i2c_res {
1053− u32 status; /* non-zero value in case of failure */
1054− u32 read_count; /* number of bytes read */
1055− u8 Data[1];
1056−};
1057−
1058−
10591045 struct smscore_config_gpio {
10601046 #define SMS_GPIO_DIRECTION_INPUT 0
10611047 #define SMS_GPIO_DIRECTION_OUTPUT 1
drivers/media/common/siano/smsdvb-main.c+2−2
@@ -689,7 +689,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed) · 688 unmodified lines
689689 pid_msg.x_msg_header.msg_flags = 0;
690690 pid_msg.x_msg_header.msg_type = MSG_SMS_ADD_PID_FILTER_REQ;
691691 pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
692− pid_msg.msg_data[0] = feed->pid;
692+ pid_msg.msg_data = feed->pid;
693693
694694 return smsclient_sendrequest(client->smsclient,
695695 &pid_msg, sizeof(pid_msg));
@@ -711,7 +711,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed) · 15 unmodified lines
711711 pid_msg.x_msg_header.msg_flags = 0;
712712 pid_msg.x_msg_header.msg_type = MSG_SMS_REMOVE_PID_FILTER_REQ;
713713 pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
714− pid_msg.msg_data[0] = feed->pid;
714+ pid_msg.msg_data = feed->pid;
715715
716716 return smsclient_sendrequest(client->smsclient,
717717 &pid_msg, sizeof(pid_msg));
drivers/media/common/siano/smsendian.c+5−3
@@ -20,11 +20,12 @@ void smsendian_handle_tx_message(void *buffer) · 19 unmodified lines
2020 struct sms_msg_data *msg = buffer;
2121 int i;
2222 int msg_words;
23+ u32 *msg_data = &msg->msg_data;
2324
2425 switch (msg->x_msg_header.msg_type) {
2526 case MSG_SMS_DATA_DOWNLOAD_REQ:
2627 {
27− msg->msg_data[0] = le32_to_cpu((__force __le32)(msg->msg_data[0]));
28+ msg->msg_data = le32_to_cpu((__force __le32)(msg->msg_data));
2829 break;
2930 }
3031
@@ -33,7 +34,7 @@ void smsendian_handle_tx_message(void *buffer) · 2 unmodified lines
3334 sizeof(struct sms_msg_hdr))/4;
3435
3536 for (i = 0; i < msg_words; i++)
36− msg->msg_data[i] = le32_to_cpu((__force __le32)msg->msg_data[i]);
37+ msg_data[i] = le32_to_cpu((__force __le32)msg_data[i]);
3738
3839 break;
3940 }
@@ -66,11 +67,12 @@ void smsendian_handle_rx_message(void *buffer) · 26 unmodified lines
6667
6768 default:
6869 {
70+ u32 *msg_data = &msg->msg_data;
6971 msg_words = (msg->x_msg_header.msg_length -
7072 sizeof(struct sms_msg_hdr))/4;
7173
7274 for (i = 0; i < msg_words; i++)
73− msg->msg_data[i] = le32_to_cpu((__force __le32)msg->msg_data[i]);
75+ msg_data[i] = le32_to_cpu((__force __le32)msg_data[i]);
7476
7577 break;
7678 }
drivers/media/common/uvc.c+1−0
@@ -180,4 +180,5 @@ const struct uvc_format_desc *uvc_format_by_guid(const u8 guid[16]) · 179 unmodified lines
180180 }
181181 EXPORT_SYMBOL_GPL(uvc_format_by_guid);
182182
183+MODULE_DESCRIPTION("USB Video Class common code");
183184 MODULE_LICENSE("GPL");
drivers/media/common/videobuf2/videobuf2-core.c+0−1
@@ -199,7 +199,6 @@ module_param(debug, int, 0644); · 198 unmodified lines
199199 })
200200
201201 static void __vb2_queue_cancel(struct vb2_queue *q);
202−static void __enqueue_in_driver(struct vb2_buffer *vb);
203202
204203 static const char *vb2_state_name(enum vb2_buffer_state s)
205204 {
drivers/media/common/videobuf2/videobuf2-dvb.c+1−0
@@ -19,6 +19,7 @@ · 18 unmodified lines
1919 /* ------------------------------------------------------------------ */
2020
2121 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
22+MODULE_DESCRIPTION("Videobuf2 helper library for simple DVB cards");
2223 MODULE_LICENSE("GPL");
2324
2425 /* ------------------------------------------------------------------ */
drivers/media/dvb-frontends/au8522_decoder.c+1−0
@@ -25,6 +25,7 @@ · 24 unmodified lines
2525 #include "au8522_priv.h"
2626
2727 MODULE_AUTHOR("Devin Heitmueller");
28+MODULE_DESCRIPTION("Auvitek AU8522 QAM/8VSB demodulator driver and video decoder");
2829 MODULE_LICENSE("GPL");
2930
3031 static int au8522_analog_debug;
drivers/media/dvb-frontends/dib7000p.c+0−5
@@ -32,11 +32,6 @@ MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (defau · 31 unmodified lines
3232 __func__, ##arg); \
3333 } while (0)
3434
35−struct i2c_device {
36− struct i2c_adapter *i2c_adap;
37− u8 i2c_addr;
38−};
39−
4035 struct dib7000p_state {
4136 struct dvb_frontend demod;
4237 struct dib7000p_config cfg;
drivers/media/dvb-frontends/drx39xyj/drxj.c+0−7
@@ -976,13 +976,6 @@ static struct drx_aud_data drxj_default_aud_data_g = { · 975 unmodified lines
976976 /*-----------------------------------------------------------------------------
977977 STRUCTURES
978978 ----------------------------------------------------------------------------*/
979−struct drxjeq_stat {
980− u16 eq_mse;
981− u8 eq_mode;
982− u8 eq_ctrl;
983− u8 eq_stat;
984−};
985−
986979 /* HI command */
987980 struct drxj_hi_cmd {
988981 u16 cmd;
drivers/media/dvb-frontends/mb86a16.c+1−0
@@ -1854,5 +1854,6 @@ error: · 1853 unmodified lines
18541854 return NULL;
18551855 }
18561856 EXPORT_SYMBOL_GPL(mb86a16_attach);
1857+MODULE_DESCRIPTION("Fujitsu MB86A16 DVB-S/DSS DC Receiver driver");
18571858 MODULE_LICENSE("GPL");
18581859 MODULE_AUTHOR("Manu Abraham");
drivers/media/dvb-frontends/mxl5xx_defs.h+2−2
@@ -168,7 +168,7 @@ struct MBIN_FILE_HEADER_T { · 167 unmodified lines
168168
169169 struct MBIN_FILE_T {
170170 struct MBIN_FILE_HEADER_T header;
171− u8 data[1];
171+ u8 data[];
172172 };
173173
174174 struct MBIN_SEGMENT_HEADER_T {
@@ -179,7 +179,7 @@ struct MBIN_SEGMENT_HEADER_T { · 4 unmodified lines
179179
180180 struct MBIN_SEGMENT_T {
181181 struct MBIN_SEGMENT_HEADER_T header;
182− u8 data[1];
182+ u8 data[];
183183 };
184184
185185 enum MXL_CMD_TYPE_E { MXL_CMD_WRITE = 0, MXL_CMD_READ };
drivers/media/dvb-frontends/stv090x.c+21−16
@@ -748,6 +748,22 @@ static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 d · 747 unmodified lines
748748 return stv090x_write_regs(state, reg, &tmp, 1);
749749 }
750750
751+static inline void stv090x_tuner_i2c_lock(struct stv090x_state *state)
752+{
753+ if (state->config->tuner_i2c_lock)
754+ state->config->tuner_i2c_lock(&state->frontend, 1);
755+ else
756+ mutex_lock(&state->internal->tuner_lock);
757+}
758+
759+static inline void stv090x_tuner_i2c_unlock(struct stv090x_state *state)
760+{
761+ if (state->config->tuner_i2c_lock)
762+ state->config->tuner_i2c_lock(&state->frontend, 0);
763+ else
764+ mutex_unlock(&state->internal->tuner_lock);
765+}
766+
751767 static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
752768 {
753769 u32 reg;
@@ -761,12 +777,8 @@ static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable) · 7 unmodified lines
761777 * In case of any error, the lock is unlocked and exit within the
762778 * relevant operations themselves.
763779 */
764− if (enable) {
765− if (state->config->tuner_i2c_lock)
766− state->config->tuner_i2c_lock(&state->frontend, 1);
767− else
768− mutex_lock(&state->internal->tuner_lock);
769− }
780+ if (enable)
781+ stv090x_tuner_i2c_lock(state);
770782
771783 reg = STV090x_READ_DEMOD(state, I2CRPT);
772784 if (enable) {
@@ -782,20 +794,13 @@ static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable) · 9 unmodified lines
782794 goto err;
783795 }
784796
785− if (!enable) {
786− if (state->config->tuner_i2c_lock)
787− state->config->tuner_i2c_lock(&state->frontend, 0);
788− else
789− mutex_unlock(&state->internal->tuner_lock);
790− }
797+ if (!enable)
798+ stv090x_tuner_i2c_unlock(state);
791799
792800 return 0;
793801 err:
794802 dprintk(FE_ERROR, 1, "I/O error");
795− if (state->config->tuner_i2c_lock)
796− state->config->tuner_i2c_lock(&state->frontend, 0);
797− else
798− mutex_unlock(&state->internal->tuner_lock);
803+ stv090x_tuner_i2c_unlock(state);
799804 return -1;
800805 }
801806
drivers/media/dvb-frontends/stv0910.c+0−5
@@ -119,11 +119,6 @@ struct stv { · 118 unmodified lines
119119 u8 vth[6];
120120 };
121121
122−struct sinit_table {
123− u16 address;
124− u8 data;
125−};
126−
127122 struct slookup {
128123 s16 value;
129124 u32 reg_value;
drivers/media/i2c/Kconfig+67−1
@@ -70,6 +70,26 @@ config VIDEO_GC0308 · 69 unmodified lines
7070 To compile this driver as a module, choose M here: the
7171 module will be called gc0308.
7272
73+config VIDEO_GC05A2
74+ tristate "GalaxyCore gc05a2 sensor support"
75+ select V4L2_CCI_I2C
76+ help
77+ This is a Video4Linux2 sensor driver for the GalaxyCore gc05a2
78+ camera.
79+
80+ To compile this driver as a module, choose M here: the
81+ module will be called gc05a2.
82+
83+config VIDEO_GC08A3
84+ tristate "GalaxyCore gc08a3 sensor support"
85+ select V4L2_CCI_I2C
86+ help
87+ This is a Video4Linux2 sensor driver for the GalaxyCore gc08a3
88+ camera.
89+
90+ To compile this driver as a module, choose M here: the
91+ module will be called gc08a3.
92+
7393 config VIDEO_GC2145
7494 select V4L2_CCI_I2C
7595 tristate "GalaxyCore GC2145 sensor support"
@@ -139,6 +159,7 @@ config VIDEO_IMX219 · 63 unmodified lines
139159
140160 config VIDEO_IMX258
141161 tristate "Sony IMX258 sensor support"
162+ select V4L2_CCI_I2C
142163 help
143164 This is a Video4Linux2 sensor driver for the Sony
144165 IMX258 camera.
@@ -153,6 +174,16 @@ config VIDEO_IMX274 · 8 unmodified lines
153174 This is a V4L2 sensor driver for the Sony IMX274
154175 CMOS image sensor.
155176
177+config VIDEO_IMX283
178+ tristate "Sony IMX283 sensor support"
179+ select V4L2_CCI_I2C
180+ help
181+ This is a V4L2 sensor driver for the Sony IMX283
182+ CMOS image sensor.
183+
184+ To compile this driver as a module, choose M here: the
185+ module will be called imx283.
186+
156187 config VIDEO_IMX290
157188 tristate "Sony IMX290 sensor support"
158189 select REGMAP_I2C
@@ -659,7 +690,7 @@ config VIDEO_S5K6A3 · 500 unmodified lines
659690 This is a V4L2 sensor driver for Samsung S5K6A3 raw
660691 camera sensor.
661692
662−config VIDEO_ST_VGXY61
693+config VIDEO_VGXY61
663694 tristate "ST VGXY61 sensor support"
664695 select V4L2_CCI_I2C
665696 depends on OF && GPIOLIB
@@ -679,6 +710,7 @@ config VIDEO_THP7312 · 13 unmodified lines
679710 tristate "THine THP7312 support"
680711 depends on I2C
681712 select FW_LOADER
713+ select FW_UPLOAD
682714 select MEDIA_CONTROLLER
683715 select V4L2_CCI_I2C
684716 select V4L2_FWNODE
@@ -1575,6 +1607,40 @@ config VIDEO_DS90UB960 · 890 unmodified lines
15751607 Device driver for the Texas Instruments DS90UB960
15761608 FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer.
15771609
1610+config VIDEO_MAX96714
1611+ tristate "Maxim MAX96714 GMSL2 deserializer"
1612+ depends on OF && I2C && VIDEO_DEV
1613+ select I2C_MUX
1614+ select MEDIA_CONTROLLER
1615+ select GPIOLIB
1616+ select V4L2_CCI_I2C
1617+ select V4L2_FWNODE
1618+ select VIDEO_V4L2_SUBDEV_API
1619+ help
1620+ Device driver for the Maxim MAX96714 GMSL2 Deserializer.
1621+ MAX96714 deserializers convert a GMSL2 input to MIPI CSI-2
1622+ output.
1623+
1624+ To compile this driver as a module, choose M here: the
1625+ module will be called max96714.
1626+
1627+config VIDEO_MAX96717
1628+ tristate "Maxim MAX96717 GMSL2 Serializer support"
1629+ depends on OF && I2C && VIDEO_DEV && COMMON_CLK
1630+ select I2C_MUX
1631+ select MEDIA_CONTROLLER
1632+ select GPIOLIB
1633+ select V4L2_CCI_I2C
1634+ select V4L2_FWNODE
1635+ select VIDEO_V4L2_SUBDEV_API
1636+ help
1637+ Device driver for the Maxim MAX96717 GMSL2 Serializer.
1638+ MAX96717 serializers convert video on a MIPI CSI-2
1639+ input to a GMSL2 output.
1640+
1641+ To compile this driver as a module, choose M here: the
1642+ module will be called max96717.
1643+
15781644 endmenu
15791645
15801646 endif # VIDEO_DEV
drivers/media/i2c/Makefile+6−1
@@ -38,6 +38,8 @@ obj-$(CONFIG_VIDEO_DW9768) += dw9768.o · 37 unmodified lines
3838 obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
3939 obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/
4040 obj-$(CONFIG_VIDEO_GC0308) += gc0308.o
41+obj-$(CONFIG_VIDEO_GC05A2) += gc05a2.o
42+obj-$(CONFIG_VIDEO_GC08A3) += gc08a3.o
4143 obj-$(CONFIG_VIDEO_GC2145) += gc2145.o
4244 obj-$(CONFIG_VIDEO_HI556) += hi556.o
4345 obj-$(CONFIG_VIDEO_HI846) += hi846.o
@@ -48,6 +50,7 @@ obj-$(CONFIG_VIDEO_IMX214) += imx214.o · 4 unmodified lines
4850 obj-$(CONFIG_VIDEO_IMX219) += imx219.o
4951 obj-$(CONFIG_VIDEO_IMX258) += imx258.o
5052 obj-$(CONFIG_VIDEO_IMX274) += imx274.o
53+obj-$(CONFIG_VIDEO_IMX283) += imx283.o
5154 obj-$(CONFIG_VIDEO_IMX290) += imx290.o
5255 obj-$(CONFIG_VIDEO_IMX296) += imx296.o
5356 obj-$(CONFIG_VIDEO_IMX319) += imx319.o
@@ -64,6 +67,8 @@ obj-$(CONFIG_VIDEO_LM3646) += lm3646.o · 10 unmodified lines
6467 obj-$(CONFIG_VIDEO_M52790) += m52790.o
6568 obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
6669 obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
70+obj-$(CONFIG_VIDEO_MAX96714) += max96714.o
71+obj-$(CONFIG_VIDEO_MAX96717) += max96717.o
6772 obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
6873 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
6974 obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
@@ -124,7 +129,6 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o · 54 unmodified lines
124129 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
125130 obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
126131 obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
127−obj-$(CONFIG_VIDEO_ST_VGXY61) += st-vgxy61.o
128132 obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
129133 obj-$(CONFIG_VIDEO_TC358746) += tc358746.o
130134 obj-$(CONFIG_VIDEO_TDA1997X) += tda1997x.o
@@ -148,6 +152,7 @@ obj-$(CONFIG_VIDEO_TW9910) += tw9910.o · 17 unmodified lines
148152 obj-$(CONFIG_VIDEO_UDA1342) += uda1342.o
149153 obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
150154 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
155+obj-$(CONFIG_VIDEO_VGXY61) += vgxy61.o
151156 obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
152157 obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
153158 obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
drivers/media/i2c/adv748x/adv748x-afe.c+2−2
@@ -114,7 +114,7 @@ static void adv748x_afe_fill_format(struct adv748x_afe *afe, · 113 unmodified lines
114114 {
115115 memset(fmt, 0, sizeof(*fmt));
116116
117− fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
117+ fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
118118 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
119119 fmt->field = V4L2_FIELD_ALTERNATE;
120120
@@ -337,7 +337,7 @@ static int adv748x_afe_enum_mbus_code(struct v4l2_subdev *sd, · 216 unmodified lines
337337 if (code->index != 0)
338338 return -EINVAL;
339339
340− code->code = MEDIA_BUS_FMT_UYVY8_2X8;
340+ code->code = MEDIA_BUS_FMT_UYVY8_1X16;
341341
342342 return 0;
343343 }
drivers/media/i2c/adv748x/adv748x-csi2.c+95−50
@@ -6,7 +6,6 @@ · 5 unmodified lines
66 */
77
88 #include <linux/module.h>
9−#include <linux/mutex.h>
109
1110 #include <media/v4l2-ctrls.h>
1211 #include <media/v4l2-device.h>
@@ -14,6 +13,15 @@ · 1 unmodified line
1413
1514 #include "adv748x.h"
1615
16+static const unsigned int adv748x_csi2_txa_fmts[] = {
17+ MEDIA_BUS_FMT_UYVY8_1X16,
18+ MEDIA_BUS_FMT_RGB888_1X24,
19+};
20+
21+static const unsigned int adv748x_csi2_txb_fmts[] = {
22+ MEDIA_BUS_FMT_UYVY8_1X16,
23+};
24+
1725 int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc)
1826 {
1927 return tx_write(tx, ADV748X_CSI_VC_REF, vc << ADV748X_CSI_VC_REF_SHIFT);
@@ -59,7 +67,33 @@ static int adv748x_csi2_register_link(struct adv748x_csi2 *tx, · 39 unmodified lines
5967
6068 /* -----------------------------------------------------------------------------
6169 * v4l2_subdev_internal_ops
62− *
70+ */
71+
72+static int adv748x_csi2_init_state(struct v4l2_subdev *sd,
73+ struct v4l2_subdev_state *state)
74+{
75+ static const struct v4l2_mbus_framefmt adv748x_csi2_default_fmt = {
76+ .width = 1280,
77+ .height = 720,
78+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
79+ .colorspace = V4L2_COLORSPACE_SRGB,
80+ .field = V4L2_FIELD_NONE,
81+ .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT,
82+ .quantization = V4L2_QUANTIZATION_DEFAULT,
83+ .xfer_func = V4L2_XFER_FUNC_DEFAULT,
84+ };
85+ struct v4l2_mbus_framefmt *fmt;
86+
87+ fmt = v4l2_subdev_state_get_format(state, ADV748X_CSI2_SINK);
88+ *fmt = adv748x_csi2_default_fmt;
89+
90+ fmt = v4l2_subdev_state_get_format(state, ADV748X_CSI2_SOURCE);
91+ *fmt = adv748x_csi2_default_fmt;
92+
93+ return 0;
94+}
95+
96+/*
6397 * We use the internal registered operation to be able to ensure that our
6498 * incremental subdevices (not connected in the forward path) can be registered
6599 * against the resulting video path and media device.
@@ -109,6 +143,7 @@ static int adv748x_csi2_registered(struct v4l2_subdev *sd) · 43 unmodified lines
109143 }
110144
111145 static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = {
146+ .init_state = adv748x_csi2_init_state,
112147 .registered = adv748x_csi2_registered,
113148 };
114149
@@ -139,39 +174,55 @@ static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = { · 24 unmodified lines
139174 * But we must support setting the pad formats for format propagation.
140175 */
141176
142−static struct v4l2_mbus_framefmt *
143−adv748x_csi2_get_pad_format(struct v4l2_subdev *sd,
144− struct v4l2_subdev_state *sd_state,
145− unsigned int pad, u32 which)
177+static int adv748x_csi2_enum_mbus_code(struct v4l2_subdev *sd,
178+ struct v4l2_subdev_state *sd_state,
179+ struct v4l2_subdev_mbus_code_enum *code)
146180 {
147181 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
182+ const unsigned int *codes = is_txa(tx) ?
183+ adv748x_csi2_txa_fmts :
184+ adv748x_csi2_txb_fmts;
185+ size_t num_fmts = is_txa(tx) ? ARRAY_SIZE(adv748x_csi2_txa_fmts)
186+ : ARRAY_SIZE(adv748x_csi2_txb_fmts);
148187
149− if (which == V4L2_SUBDEV_FORMAT_TRY)
150− return v4l2_subdev_state_get_format(sd_state, pad);
188+ /*
189+ * The format available on the source pad is the one applied on the sink
190+ * pad.
191+ */
192+ if (code->pad == ADV748X_CSI2_SOURCE) {
193+ struct v4l2_mbus_framefmt *fmt;
151194
152− return &tx->format;
153−}
195+ if (code->index)
196+ return -EINVAL;
154197
155−static int adv748x_csi2_get_format(struct v4l2_subdev *sd,
156− struct v4l2_subdev_state *sd_state,
157− struct v4l2_subdev_format *sdformat)
158−{
159− struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
160− struct adv748x_state *state = tx->state;
161− struct v4l2_mbus_framefmt *mbusformat;
198+ fmt = v4l2_subdev_state_get_format(sd_state, ADV748X_CSI2_SINK);
199+ code->code = fmt->code;
162200
163− mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad,
164− sdformat->which);
165− if (!mbusformat)
201+ return 0;
202+ }
203+
204+ if (code->index >= num_fmts)
166205 return -EINVAL;
167206
168− mutex_lock(&state->mutex);
207+ code->code = codes[code->index];
169208
170− sdformat->format = *mbusformat;
209+ return 0;
210+}
171211
172− mutex_unlock(&state->mutex);
212+static bool adv748x_csi2_is_fmt_supported(struct adv748x_csi2 *tx, u32 code)
213+{
214+ const unsigned int *codes = is_txa(tx) ?
215+ adv748x_csi2_txa_fmts :
216+ adv748x_csi2_txb_fmts;
217+ size_t num_fmts = is_txa(tx) ? ARRAY_SIZE(adv748x_csi2_txa_fmts)
218+ : ARRAY_SIZE(adv748x_csi2_txb_fmts);
219+
220+ for (unsigned int i = 0; i < num_fmts; i++) {
221+ if (codes[i] == code)
222+ return true;
223+ }
173224
174− return 0;
225+ return false;
175226 }
176227
177228 static int adv748x_csi2_set_format(struct v4l2_subdev *sd,
@@ -179,38 +230,26 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd, · 1 unmodified line
179230 struct v4l2_subdev_format *sdformat)
180231 {
181232 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
182− struct adv748x_state *state = tx->state;
183233 struct v4l2_mbus_framefmt *mbusformat;
184− int ret = 0;
185−
186− mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad,
187− sdformat->which);
188− if (!mbusformat)
189− return -EINVAL;
190−
191− mutex_lock(&state->mutex);
192234
193− if (sdformat->pad == ADV748X_CSI2_SOURCE) {
194− const struct v4l2_mbus_framefmt *sink_fmt;
235+ if (sdformat->pad == ADV748X_CSI2_SOURCE)
236+ return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
195237
196− sink_fmt = adv748x_csi2_get_pad_format(sd, sd_state,
197− ADV748X_CSI2_SINK,
198− sdformat->which);
199−
200− if (!sink_fmt) {
201− ret = -EINVAL;
202− goto unlock;
203− }
204−
205− sdformat->format = *sink_fmt;
206− }
238+ /*
239+ * Make sure the format is supported, if not default it to
240+ * UYVY8 as it's supported by both TXes.
241+ */
242+ if (!adv748x_csi2_is_fmt_supported(tx, sdformat->format.code))
243+ sdformat->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
207244
245+ mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
208246 *mbusformat = sdformat->format;
209247
210−unlock:
211− mutex_unlock(&state->mutex);
248+ /* Propagate format to the source pad. */
249+ mbusformat = v4l2_subdev_state_get_format(sd_state, ADV748X_CSI2_SOURCE);
250+ *mbusformat = sdformat->format;
212251
213− return ret;
252+ return 0;
214253 }
215254
216255 static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
@@ -228,7 +267,8 @@ static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad · 11 unmodified lines
228267 }
229268
230269 static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
231− .get_fmt = adv748x_csi2_get_format,
270+ .enum_mbus_code = adv748x_csi2_enum_mbus_code,
271+ .get_fmt = v4l2_subdev_get_fmt,
232272 .set_fmt = adv748x_csi2_set_format,
233273 .get_mbus_config = adv748x_csi2_get_mbus_config,
234274 };
@@ -320,6 +360,11 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) · 85 unmodified lines
320360 if (ret)
321361 goto err_cleanup_subdev;
322362
363+ tx->sd.state_lock = &state->mutex;
364+ ret = v4l2_subdev_init_finalize(&tx->sd);
365+ if (ret)
366+ goto err_free_ctrl;
367+
323368 ret = v4l2_async_register_subdev(&tx->sd);
324369 if (ret)
325370 goto err_free_ctrl;
drivers/media/i2c/adv748x/adv748x.h+0−1
@@ -75,7 +75,6 @@ enum adv748x_csi2_pads { · 74 unmodified lines
7575
7676 struct adv748x_csi2 {
7777 struct adv748x_state *state;
78− struct v4l2_mbus_framefmt format;
7978 unsigned int page;
8079 unsigned int port;
8180 unsigned int num_lanes;
drivers/media/i2c/adv7511-v4l2.c+0−5
@@ -62,11 +62,6 @@ MODULE_LICENSE("GPL v2"); · 61 unmodified lines
6262 **********************************************************************
6363 */
6464
65−struct i2c_reg_value {
66− unsigned char reg;
67− unsigned char value;
68−};
69−
7065 struct adv7511_state_edid {
7166 /* total number of blocks */
7267 u32 blocks;
drivers/media/i2c/alvium-csi2.c+51−14
@@ -403,21 +403,22 @@ static int alvium_get_bcrm_vers(struct alvium_dev *alvium) · 402 unmodified lines
403403 static int alvium_get_fw_version(struct alvium_dev *alvium)
404404 {
405405 struct device *dev = &alvium->i2c_client->dev;
406− u64 spec, maj, min, pat;
407− int ret = 0;
406+ u64 val;
407+ int ret;
408408
409− ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_SPEC_VERSION_R,
410− &spec, &ret);
411− ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_MAJOR_VERSION_R,
412− &maj, &ret);
413− ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_MINOR_VERSION_R,
414− &min, &ret);
415− ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_PATCH_VERSION_R,
416− &pat, &ret);
409+ ret = alvium_read(alvium, REG_BCRM_DEVICE_FW, &val, NULL);
417410 if (ret)
418411 return ret;
419412
420− dev_info(dev, "fw version: %llu.%llu.%llu.%llu\n", spec, maj, min, pat);
413+ dev_info(dev, "fw version: %02u.%02u.%04u.%08x\n",
414+ (u8)((val & BCRM_DEVICE_FW_SPEC_MASK) >>
415+ BCRM_DEVICE_FW_SPEC_SHIFT),
416+ (u8)((val & BCRM_DEVICE_FW_MAJOR_MASK) >>
417+ BCRM_DEVICE_FW_MAJOR_SHIFT),
418+ (u16)((val & BCRM_DEVICE_FW_MINOR_MASK) >>
419+ BCRM_DEVICE_FW_MINOR_SHIFT),
420+ (u32)((val & BCRM_DEVICE_FW_PATCH_MASK) >>
421+ BCRM_DEVICE_FW_PATCH_SHIFT));
421422
422423 return 0;
423424 }
@@ -1188,6 +1189,20 @@ static int alvium_set_frame_rate(struct alvium_dev *alvium, u64 fr) · 764 unmodified lines
11881189 struct device *dev = &alvium->i2c_client->dev;
11891190 int ret;
11901191
1192+ ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_EN_RW,
1193+ 1);
1194+ if (ret) {
1195+ dev_err(dev, "Fail to set acquisition frame rate enable reg\n");
1196+ return ret;
1197+ }
1198+
1199+ ret = alvium_write_hshake(alvium, REG_BCRM_FRAME_START_TRIGGER_MODE_RW,
1200+ 0);
1201+ if (ret) {
1202+ dev_err(dev, "Fail to set frame start trigger mode reg\n");
1203+ return ret;
1204+ }
1205+
11911206 ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW,
11921207 fr);
11931208 if (ret) {
@@ -1707,6 +1722,27 @@ alvium_code_to_pixfmt(struct alvium_dev *alvium, u32 code) · 513 unmodified lines
17071722 return &alvium->alvium_csi2_fmt[0];
17081723 }
17091724
1725+static int alvium_enum_frame_size(struct v4l2_subdev *sd,
1726+ struct v4l2_subdev_state *state,
1727+ struct v4l2_subdev_frame_size_enum *fse)
1728+{
1729+ struct alvium_dev *alvium = sd_to_alvium(sd);
1730+ const struct alvium_pixfmt *alvium_csi2_fmt;
1731+
1732+ if (fse->index)
1733+ return -EINVAL;
1734+
1735+ alvium_csi2_fmt = alvium_code_to_pixfmt(alvium, fse->code);
1736+ if (fse->code != alvium_csi2_fmt->code)
1737+ return -EINVAL;
1738+
1739+ fse->min_width = alvium->img_min_width;
1740+ fse->max_width = alvium->img_max_width;
1741+ fse->min_height = alvium->img_min_height;
1742+ fse->max_height = alvium->img_max_height;
1743+ return 0;
1744+}
1745+
17101746 static int alvium_set_mode(struct alvium_dev *alvium,
17111747 struct v4l2_subdev_state *state)
17121748 {
@@ -1962,7 +1998,7 @@ static int alvium_g_volatile_ctrl(struct v4l2_ctrl *ctrl) · 249 unmodified lines
19621998 int val;
19631999
19642000 switch (ctrl->id) {
1965− case V4L2_CID_GAIN:
2001+ case V4L2_CID_ANALOGUE_GAIN:
19662002 val = alvium_get_gain(alvium);
19672003 if (val < 0)
19682004 return val;
@@ -1994,7 +2030,7 @@ static int alvium_s_ctrl(struct v4l2_ctrl *ctrl) · 25 unmodified lines
19942030 return 0;
19952031
19962032 switch (ctrl->id) {
1997− case V4L2_CID_GAIN:
2033+ case V4L2_CID_ANALOGUE_GAIN:
19982034 ret = alvium_set_ctrl_gain(alvium, ctrl->val);
19992035 break;
20002036 case V4L2_CID_AUTOGAIN:
@@ -2123,7 +2159,7 @@ static int alvium_ctrl_init(struct alvium_dev *alvium) · 122 unmodified lines
21232159
21242160 if (alvium->avail_ft.gain) {
21252161 ctrls->gain = v4l2_ctrl_new_std(hdl, ops,
2126− V4L2_CID_GAIN,
2162+ V4L2_CID_ANALOGUE_GAIN,
21272163 alvium->min_gain,
21282164 alvium->max_gain,
21292165 alvium->inc_gain,
@@ -2214,6 +2250,7 @@ static const struct v4l2_subdev_video_ops alvium_video_ops = { · 84 unmodified lines
22142250
22152251 static const struct v4l2_subdev_pad_ops alvium_pad_ops = {
22162252 .enum_mbus_code = alvium_enum_mbus_code,
2253+ .enum_frame_size = alvium_enum_frame_size,
22172254 .get_fmt = v4l2_subdev_get_fmt,
22182255 .set_fmt = alvium_set_fmt,
22192256 .get_selection = alvium_get_selection,
drivers/media/i2c/alvium-csi2.h+11−5
@@ -31,10 +31,7 @@ · 30 unmodified lines
3131 #define REG_BCRM_REG_ADDR_R CCI_REG16(0x0014)
3232
3333 #define REG_BCRM_FEATURE_INQUIRY_R REG_BCRM_V4L2_64BIT(0x0008)
34−#define REG_BCRM_DEVICE_FW_SPEC_VERSION_R REG_BCRM_V4L2_8BIT(0x0010)
35−#define REG_BCRM_DEVICE_FW_MAJOR_VERSION_R REG_BCRM_V4L2_8BIT(0x0011)
36−#define REG_BCRM_DEVICE_FW_MINOR_VERSION_R REG_BCRM_V4L2_16BIT(0x0012)
37−#define REG_BCRM_DEVICE_FW_PATCH_VERSION_R REG_BCRM_V4L2_32BIT(0x0014)
34+#define REG_BCRM_DEVICE_FW REG_BCRM_V4L2_64BIT(0x0010)
3835 #define REG_BCRM_WRITE_HANDSHAKE_RW REG_BCRM_V4L2_8BIT(0x0018)
3936
4037 /* Streaming Control Registers */
@@ -66,7 +63,7 @@ · 25 unmodified lines
6663 #define REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R REG_BCRM_V4L2_64BIT(0x0098)
6764 #define REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R REG_BCRM_V4L2_64BIT(0x00a0)
6865 #define REG_BCRM_ACQUISITION_FRAME_RATE_INC_R REG_BCRM_V4L2_64BIT(0x00a8)
69−#define REG_BCRM_ACQUISITION_FRAME_RATE_ENABLE_RW REG_BCRM_V4L2_8BIT(0x00b0)
66+#define REG_BCRM_ACQUISITION_FRAME_RATE_EN_RW REG_BCRM_V4L2_8BIT(0x00b0)
7067
7168 #define REG_BCRM_FRAME_START_TRIGGER_MODE_RW REG_BCRM_V4L2_8BIT(0x00b4)
7269 #define REG_BCRM_FRAME_START_TRIGGER_SOURCE_RW REG_BCRM_V4L2_8BIT(0x00b8)
@@ -205,6 +202,15 @@ · 132 unmodified lines
205202
206203 #define ALVIUM_LP2HS_DELAY_MS 100
207204
205+#define BCRM_DEVICE_FW_MAJOR_MASK GENMASK_ULL(15, 8)
206+#define BCRM_DEVICE_FW_MAJOR_SHIFT 8
207+#define BCRM_DEVICE_FW_MINOR_MASK GENMASK_ULL(31, 16)
208+#define BCRM_DEVICE_FW_MINOR_SHIFT 16
209+#define BCRM_DEVICE_FW_PATCH_MASK GENMASK_ULL(63, 32)
210+#define BCRM_DEVICE_FW_PATCH_SHIFT 32
211+#define BCRM_DEVICE_FW_SPEC_MASK GENMASK_ULL(7, 0)
212+#define BCRM_DEVICE_FW_SPEC_SHIFT 0
213+
208214 enum alvium_bcrm_mode {
209215 ALVIUM_BCM_MODE,
210216 ALVIUM_GENCP_MODE,
drivers/media/i2c/dw9768.c+0−5
@@ -115,11 +115,6 @@ static inline struct dw9768 *sd_to_dw9768(struct v4l2_subdev *subdev) · 114 unmodified lines
115115 return container_of(subdev, struct dw9768, sd);
116116 }
117117
118−struct regval_list {
119− u8 reg_num;
120− u8 value;
121−};
122−
123118 struct dw9768_aac_mode_ot_multi {
124119 u32 aac_mode_enum;
125120 u32 ot_multi_base100;
drivers/media/i2c/gc05a2.c+1359−0
@@ -0,0 +1,1359 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Driver for GalaxyCore gc05a2 image sensor
4+ *
5+ * Copyright 2024 MediaTek
6+ *
7+ * Zhi Mao <zhi.mao@mediatek.com>
8+ */
9+#include <linux/array_size.h>
10+#include <linux/bits.h>
11+#include <linux/clk.h>
12+#include <linux/container_of.h>
13+#include <linux/delay.h>
14+#include <linux/device.h>
15+#include <linux/err.h>
16+#include <linux/gpio/consumer.h>
17+#include <linux/math64.h>
18+#include <linux/mod_devicetable.h>
19+#include <linux/pm_runtime.h>
20+#include <linux/property.h>
21+#include <linux/regulator/consumer.h>
22+#include <linux/types.h>
23+#include <linux/units.h>
24+
25+#include <media/v4l2-cci.h>
26+#include <media/v4l2-ctrls.h>
27+#include <media/v4l2-event.h>
28+#include <media/v4l2-fwnode.h>
29+#include <media/v4l2-subdev.h>
30+
31+#define GC05A2_REG_TEST_PATTERN_EN CCI_REG8(0x008c)
32+#define GC05A2_REG_TEST_PATTERN_IDX CCI_REG8(0x008d)
33+#define GC05A2_TEST_PATTERN_EN 0x01
34+
35+#define GC05A2_STREAMING_REG CCI_REG8(0x0100)
36+
37+#define GC05A2_FLIP_REG CCI_REG8(0x0101)
38+#define GC05A2_FLIP_H_MASK BIT(0)
39+#define GC05A2_FLIP_V_MASK BIT(1)
40+
41+#define GC05A2_EXP_REG CCI_REG16(0x0202)
42+#define GC05A2_EXP_MARGIN 16
43+#define GC05A2_EXP_MIN 4
44+#define GC05A2_EXP_STEP 1
45+
46+#define GC05A2_AGAIN_REG CCI_REG16(0x0204)
47+#define GC05A2_AGAIN_MIN 1024
48+#define GC05A2_AGAIN_MAX (1024 * 16)
49+#define GC05A2_AGAIN_STEP 1
50+
51+#define GC05A2_FRAME_LENGTH_REG CCI_REG16(0x0340)
52+#define GC05A2_VTS_MAX 0xffff
53+
54+#define GC05A2_REG_CHIP_ID CCI_REG16(0x03f0)
55+#define GC05A2_CHIP_ID 0x05a2
56+
57+#define GC05A2_NATIVE_WIDTH 2592
58+#define GC05A2_NATIVE_HEIGHT 1944
59+
60+#define GC05A2_DEFAULT_CLK_FREQ (24 * HZ_PER_MHZ)
61+#define GC05A2_MBUS_CODE MEDIA_BUS_FMT_SGRBG10_1X10
62+#define GC05A2_DATA_LANES 2
63+#define GC05A2_RGB_DEPTH 10
64+#define GC05A2_SLEEP_US (2 * USEC_PER_MSEC)
65+
66+static const char *const gc05a2_test_pattern_menu[] = {
67+ "No Pattern", "Fade_to_gray_Color Bar", "Color Bar",
68+ "PN9", "Horizental_gradient", "Checkboard Pattern",
69+ "Slant", "Resolution", "Solid Black",
70+ "Solid White",
71+};
72+
73+static const s64 gc05a2_link_freq_menu_items[] = {
74+ (448 * HZ_PER_MHZ),
75+ (224 * HZ_PER_MHZ),
76+};
77+
78+static const char *const gc05a2_supply_name[] = {
79+ "avdd",
80+ "dvdd",
81+ "dovdd",
82+};
83+
84+struct gc05a2 {
85+ struct device *dev;
86+ struct v4l2_subdev sd;
87+ struct media_pad pad;
88+
89+ struct clk *xclk;
90+ struct regulator_bulk_data supplies[ARRAY_SIZE(gc05a2_supply_name)];
91+ struct gpio_desc *reset_gpio;
92+
93+ struct v4l2_ctrl_handler ctrls;
94+ struct v4l2_ctrl *pixel_rate;
95+ struct v4l2_ctrl *link_freq;
96+ struct v4l2_ctrl *exposure;
97+ struct v4l2_ctrl *vblank;
98+ struct v4l2_ctrl *hblank;
99+ struct v4l2_ctrl *hflip;
100+ struct v4l2_ctrl *vflip;
101+
102+ struct regmap *regmap;
103+ unsigned long link_freq_bitmap;
104+
105+ /* True if the device has been identified */
106+ bool identified;
107+ const struct gc05a2_mode *cur_mode;
108+};
109+
110+struct gc05a2_reg_list {
111+ u32 num_of_regs;
112+ const struct cci_reg_sequence *regs;
113+};
114+
115+static const struct cci_reg_sequence mode_2592x1944[] = {
116+ /* system */
117+ { CCI_REG8(0x0135), 0x01 },
118+ { CCI_REG8(0x0084), 0x21 },
119+ { CCI_REG8(0x0d05), 0xcc },
120+ { CCI_REG8(0x0218), 0x00 },
121+ { CCI_REG8(0x005e), 0x48 },
122+ { CCI_REG8(0x0d06), 0x01 },
123+ { CCI_REG8(0x0007), 0x16 },
124+ { CCI_REG8(0x0101), 0x00 },
125+
126+ /* analog */
127+ { CCI_REG8(0x0342), 0x07 },
128+ { CCI_REG8(0x0343), 0x28 },
129+ { CCI_REG8(0x0220), 0x07 },
130+ { CCI_REG8(0x0221), 0xd0 },
131+ { CCI_REG8(0x0202), 0x07 },
132+ { CCI_REG8(0x0203), 0x32 },
133+ { CCI_REG8(0x0340), 0x07 },
134+ { CCI_REG8(0x0341), 0xf0 },
135+ { CCI_REG8(0x0219), 0x00 },
136+ { CCI_REG8(0x0346), 0x00 },
137+ { CCI_REG8(0x0347), 0x04 },
138+ { CCI_REG8(0x0d14), 0x00 },
139+ { CCI_REG8(0x0d13), 0x05 },
140+ { CCI_REG8(0x0d16), 0x05 },
141+ { CCI_REG8(0x0d15), 0x1d },
142+ { CCI_REG8(0x00c0), 0x0a },
143+ { CCI_REG8(0x00c1), 0x30 },
144+ { CCI_REG8(0x034a), 0x07 },
145+ { CCI_REG8(0x034b), 0xa8 },
146+ { CCI_REG8(0x0e0a), 0x00 },
147+ { CCI_REG8(0x0e0b), 0x00 },
148+ { CCI_REG8(0x0e0e), 0x03 },
149+ { CCI_REG8(0x0e0f), 0x00 },
150+ { CCI_REG8(0x0e06), 0x0a },
151+ { CCI_REG8(0x0e23), 0x15 },
152+ { CCI_REG8(0x0e24), 0x15 },
153+ { CCI_REG8(0x0e2a), 0x10 },
154+ { CCI_REG8(0x0e2b), 0x10 },
155+ { CCI_REG8(0x0e17), 0x49 },
156+ { CCI_REG8(0x0e1b), 0x1c },
157+ { CCI_REG8(0x0e3a), 0x36 },
158+ { CCI_REG8(0x0d11), 0x84 },
159+ { CCI_REG8(0x0e52), 0x14 },
160+ { CCI_REG8(0x000b), 0x10 },
161+ { CCI_REG8(0x0008), 0x08 },
162+ { CCI_REG8(0x0223), 0x17 },
163+ { CCI_REG8(0x0d27), 0x39 },
164+ { CCI_REG8(0x0d22), 0x00 },
165+ { CCI_REG8(0x03f6), 0x0d },
166+ { CCI_REG8(0x0d04), 0x07 },
167+ { CCI_REG8(0x03f3), 0x72 },
168+ { CCI_REG8(0x03f4), 0xb8 },
169+ { CCI_REG8(0x03f5), 0xbc },
170+ { CCI_REG8(0x0d02), 0x73 },
171+
172+ /* auto load start */
173+ { CCI_REG8(0x00cb), 0x00 },
174+
175+ /* OUT 2592*1944 */
176+ { CCI_REG8(0x0350), 0x01 },
177+ { CCI_REG8(0x0353), 0x00 },
178+ { CCI_REG8(0x0354), 0x08 },
179+ { CCI_REG16(0x034c), 2592 }, /* Width */
180+ { CCI_REG8(0x021f), 0x14 },
181+
182+ /* MIPI */
183+ { CCI_REG8(0x0107), 0x05 },
184+ { CCI_REG8(0x0117), 0x01 },
185+ { CCI_REG8(0x0d81), 0x00 },
186+ { CCI_REG8(0x0d84), 0x0c },
187+ { CCI_REG8(0x0d85), 0xa8 },
188+ { CCI_REG8(0x0d86), 0x06 },
189+ { CCI_REG8(0x0d87), 0x55 },
190+ { CCI_REG8(0x0db3), 0x06 },
191+ { CCI_REG8(0x0db4), 0x08 },
192+ { CCI_REG8(0x0db5), 0x1e },
193+ { CCI_REG8(0x0db6), 0x02 },
194+ { CCI_REG8(0x0db8), 0x12 },
195+ { CCI_REG8(0x0db9), 0x0a },
196+ { CCI_REG8(0x0d93), 0x06 },
197+ { CCI_REG8(0x0d94), 0x09 },
198+ { CCI_REG8(0x0d95), 0x0d },
199+ { CCI_REG8(0x0d99), 0x0b },
200+ { CCI_REG8(0x0084), 0x01 },
201+ { CCI_REG8(0x0110), 0x01 },
202+};
203+
204+static const struct cci_reg_sequence mode_1280x720[] = {
205+ /* system */
206+ { CCI_REG8(0x0135), 0x05 },
207+ { CCI_REG8(0x0084), 0x21 },
208+ { CCI_REG8(0x0d05), 0xcc },
209+ { CCI_REG8(0x0218), 0x80 },
210+ { CCI_REG8(0x005e), 0x49 },
211+ { CCI_REG8(0x0d06), 0x81 },
212+ { CCI_REG8(0x0007), 0x16 },
213+ { CCI_REG8(0x0101), 0x00 },
214+
215+ /* analog */
216+ { CCI_REG8(0x0342), 0x07 },
217+ { CCI_REG8(0x0343), 0x10 },
218+ { CCI_REG8(0x0220), 0x07 },
219+ { CCI_REG8(0x0221), 0xd0 },
220+ { CCI_REG8(0x0202), 0x03 },
221+ { CCI_REG8(0x0203), 0x32 },
222+ { CCI_REG8(0x0340), 0x04 },
223+ { CCI_REG8(0x0341), 0x08 },
224+ { CCI_REG8(0x0219), 0x00 },
225+ { CCI_REG8(0x0346), 0x01 },
226+ { CCI_REG8(0x0347), 0x00 },
227+ { CCI_REG8(0x0d14), 0x00 },
228+ { CCI_REG8(0x0d13), 0x05 },
229+ { CCI_REG8(0x0d16), 0x05 },
230+ { CCI_REG8(0x0d15), 0x1d },
231+ { CCI_REG8(0x00c0), 0x0a },
232+ { CCI_REG8(0x00c1), 0x30 },
233+ { CCI_REG8(0x034a), 0x05 },
234+ { CCI_REG8(0x034b), 0xb0 },
235+ { CCI_REG8(0x0e0a), 0x00 },
236+ { CCI_REG8(0x0e0b), 0x00 },
237+ { CCI_REG8(0x0e0e), 0x03 },
238+ { CCI_REG8(0x0e0f), 0x00 },
239+ { CCI_REG8(0x0e06), 0x0a },
240+ { CCI_REG8(0x0e23), 0x15 },
241+ { CCI_REG8(0x0e24), 0x15 },
242+ { CCI_REG8(0x0e2a), 0x10 },
243+ { CCI_REG8(0x0e2b), 0x10 },
244+ { CCI_REG8(0x0e17), 0x49 },
245+ { CCI_REG8(0x0e1b), 0x1c },
246+ { CCI_REG8(0x0e3a), 0x36 },
247+ { CCI_REG8(0x0d11), 0x84 },
248+ { CCI_REG8(0x0e52), 0x14 },
249+ { CCI_REG8(0x000b), 0x0e },
250+ { CCI_REG8(0x0008), 0x03 },
251+ { CCI_REG8(0x0223), 0x16 },
252+ { CCI_REG8(0x0d27), 0x39 },
253+ { CCI_REG8(0x0d22), 0x00 },
254+ { CCI_REG8(0x03f6), 0x0d },
255+ { CCI_REG8(0x0d04), 0x07 },
256+ { CCI_REG8(0x03f3), 0x72 },
257+ { CCI_REG8(0x03f4), 0xb8 },
258+ { CCI_REG8(0x03f5), 0xbc },
259+ { CCI_REG8(0x0d02), 0x73 },
260+
261+ /* auto load start */
262+ { CCI_REG8(0x00cb), 0xfc },
263+
264+ /* OUT 1280x720 */
265+ { CCI_REG8(0x0350), 0x01 },
266+ { CCI_REG8(0x0353), 0x00 },
267+ { CCI_REG8(0x0354), 0x0c },
268+ { CCI_REG16(0x034c), 1280 }, /* Width */
269+ { CCI_REG8(0x021f), 0x14 },
270+
271+ /* MIPI */
272+ { CCI_REG8(0x0107), 0x05 },
273+ { CCI_REG8(0x0117), 0x01 },
274+ { CCI_REG8(0x0d81), 0x00 },
275+ { CCI_REG8(0x0d84), 0x06 },
276+ { CCI_REG8(0x0d85), 0x40 },
277+ { CCI_REG8(0x0d86), 0x03 },
278+ { CCI_REG8(0x0d87), 0x21 },
279+ { CCI_REG8(0x0db3), 0x03 },
280+ { CCI_REG8(0x0db4), 0x04 },
281+ { CCI_REG8(0x0db5), 0x0d },
282+ { CCI_REG8(0x0db6), 0x01 },
283+ { CCI_REG8(0x0db8), 0x04 },
284+ { CCI_REG8(0x0db9), 0x06 },
285+ { CCI_REG8(0x0d93), 0x03 },
286+ { CCI_REG8(0x0d94), 0x04 },
287+ { CCI_REG8(0x0d95), 0x05 },
288+ { CCI_REG8(0x0d99), 0x06 },
289+ { CCI_REG8(0x0084), 0x01 },
290+ { CCI_REG8(0x0110), 0x01 },
291+};
292+
293+static const struct cci_reg_sequence mode_table_common[] = {
294+ { GC05A2_STREAMING_REG, 0x00 },
295+ /* system */
296+ { CCI_REG8(0x0315), 0xd4 },
297+ { CCI_REG8(0x0d06), 0x01 },
298+ { CCI_REG8(0x0a70), 0x80 },
299+ { CCI_REG8(0x031a), 0x00 },
300+ { CCI_REG8(0x0314), 0x00 },
301+ { CCI_REG8(0x0130), 0x08 },
302+ { CCI_REG8(0x0132), 0x01 },
303+ { CCI_REG8(0x0136), 0x38 },
304+ { CCI_REG8(0x0137), 0x03 },
305+ { CCI_REG8(0x0134), 0x5b },
306+ { CCI_REG8(0x031c), 0xe0 },
307+ { CCI_REG8(0x0d82), 0x14 },
308+ { CCI_REG8(0x0dd1), 0x56 },
309+ { CCI_REG8(0x0af4), 0x01 },
310+ { CCI_REG8(0x0002), 0x10 },
311+ { CCI_REG8(0x00c3), 0x34 },
312+ { CCI_REG8(0x00c4), 0x00 },
313+ { CCI_REG8(0x00c5), 0x01 },
314+ { CCI_REG8(0x0af6), 0x00 },
315+ { CCI_REG8(0x0ba0), 0x17 },
316+ { CCI_REG8(0x0ba1), 0x00 },
317+ { CCI_REG8(0x0ba2), 0x00 },
318+ { CCI_REG8(0x0ba3), 0x00 },
319+ { CCI_REG8(0x0ba4), 0x03 },
320+ { CCI_REG8(0x0ba5), 0x00 },
321+ { CCI_REG8(0x0ba6), 0x00 },
322+ { CCI_REG8(0x0ba7), 0x00 },
323+ { CCI_REG8(0x0ba8), 0x40 },
324+ { CCI_REG8(0x0ba9), 0x00 },
325+ { CCI_REG8(0x0baa), 0x00 },
326+ { CCI_REG8(0x0bab), 0x00 },
327+ { CCI_REG8(0x0bac), 0x40 },
328+ { CCI_REG8(0x0bad), 0x00 },
329+ { CCI_REG8(0x0bae), 0x00 },
330+ { CCI_REG8(0x0baf), 0x00 },
331+ { CCI_REG8(0x0bb0), 0x02 },
332+ { CCI_REG8(0x0bb1), 0x00 },
333+ { CCI_REG8(0x0bb2), 0x00 },
334+ { CCI_REG8(0x0bb3), 0x00 },
335+ { CCI_REG8(0x0bb8), 0x02 },
336+ { CCI_REG8(0x0bb9), 0x00 },
337+ { CCI_REG8(0x0bba), 0x00 },
338+ { CCI_REG8(0x0bbb), 0x00 },
339+ { CCI_REG8(0x0a70), 0x80 },
340+ { CCI_REG8(0x0a71), 0x00 },
341+ { CCI_REG8(0x0a72), 0x00 },
342+ { CCI_REG8(0x0a66), 0x00 },
343+ { CCI_REG8(0x0a67), 0x80 },
344+ { CCI_REG8(0x0a4d), 0x4e },
345+ { CCI_REG8(0x0a50), 0x00 },
346+ { CCI_REG8(0x0a4f), 0x0c },
347+ { CCI_REG8(0x0a66), 0x00 },
348+ { CCI_REG8(0x00ca), 0x00 },
349+ { CCI_REG8(0x00cc), 0x00 },
350+ { CCI_REG8(0x00cd), 0x00 },
351+ { CCI_REG8(0x0aa1), 0x00 },
352+ { CCI_REG8(0x0aa2), 0xe0 },
353+ { CCI_REG8(0x0aa3), 0x00 },
354+ { CCI_REG8(0x0aa4), 0x40 },
355+ { CCI_REG8(0x0a90), 0x03 },
356+ { CCI_REG8(0x0a91), 0x0e },
357+ { CCI_REG8(0x0a94), 0x80 },
358+ { CCI_REG8(0x0af6), 0x20 },
359+ { CCI_REG8(0x0b00), 0x91 },
360+ { CCI_REG8(0x0b01), 0x17 },
361+ { CCI_REG8(0x0b02), 0x01 },
362+ { CCI_REG8(0x0b03), 0x00 },
363+ { CCI_REG8(0x0b04), 0x01 },
364+ { CCI_REG8(0x0b05), 0x17 },
365+ { CCI_REG8(0x0b06), 0x01 },
366+ { CCI_REG8(0x0b07), 0x00 },
367+ { CCI_REG8(0x0ae9), 0x01 },
368+ { CCI_REG8(0x0aea), 0x02 },
369+ { CCI_REG8(0x0ae8), 0x53 },
370+ { CCI_REG8(0x0ae8), 0x43 },
371+ { CCI_REG8(0x0af6), 0x30 },
372+ { CCI_REG8(0x0b00), 0x08 },
373+ { CCI_REG8(0x0b01), 0x0f },
374+ { CCI_REG8(0x0b02), 0x00 },
375+ { CCI_REG8(0x0b04), 0x1c },
376+ { CCI_REG8(0x0b05), 0x24 },
377+ { CCI_REG8(0x0b06), 0x00 },
378+ { CCI_REG8(0x0b08), 0x30 },
379+ { CCI_REG8(0x0b09), 0x40 },
380+ { CCI_REG8(0x0b0a), 0x00 },
381+ { CCI_REG8(0x0b0c), 0x0e },
382+ { CCI_REG8(0x0b0d), 0x2a },
383+ { CCI_REG8(0x0b0e), 0x00 },
384+ { CCI_REG8(0x0b10), 0x0e },
385+ { CCI_REG8(0x0b11), 0x2b },
386+ { CCI_REG8(0x0b12), 0x00 },
387+ { CCI_REG8(0x0b14), 0x0e },
388+ { CCI_REG8(0x0b15), 0x23 },
389+ { CCI_REG8(0x0b16), 0x00 },
390+ { CCI_REG8(0x0b18), 0x0e },
391+ { CCI_REG8(0x0b19), 0x24 },
392+ { CCI_REG8(0x0b1a), 0x00 },
393+ { CCI_REG8(0x0b1c), 0x0c },
394+ { CCI_REG8(0x0b1d), 0x0c },
395+ { CCI_REG8(0x0b1e), 0x00 },
396+ { CCI_REG8(0x0b20), 0x03 },
397+ { CCI_REG8(0x0b21), 0x03 },
398+ { CCI_REG8(0x0b22), 0x00 },
399+ { CCI_REG8(0x0b24), 0x0e },
400+ { CCI_REG8(0x0b25), 0x0e },
401+ { CCI_REG8(0x0b26), 0x00 },
402+ { CCI_REG8(0x0b28), 0x03 },
403+ { CCI_REG8(0x0b29), 0x03 },
404+ { CCI_REG8(0x0b2a), 0x00 },
405+ { CCI_REG8(0x0b2c), 0x12 },
406+ { CCI_REG8(0x0b2d), 0x12 },
407+ { CCI_REG8(0x0b2e), 0x00 },
408+ { CCI_REG8(0x0b30), 0x08 },
409+ { CCI_REG8(0x0b31), 0x08 },
410+ { CCI_REG8(0x0b32), 0x00 },
411+ { CCI_REG8(0x0b34), 0x14 },
412+ { CCI_REG8(0x0b35), 0x14 },
413+ { CCI_REG8(0x0b36), 0x00 },
414+ { CCI_REG8(0x0b38), 0x10 },
415+ { CCI_REG8(0x0b39), 0x10 },
416+ { CCI_REG8(0x0b3a), 0x00 },
417+ { CCI_REG8(0x0b3c), 0x16 },
418+ { CCI_REG8(0x0b3d), 0x16 },
419+ { CCI_REG8(0x0b3e), 0x00 },
420+ { CCI_REG8(0x0b40), 0x10 },
421+ { CCI_REG8(0x0b41), 0x10 },
422+ { CCI_REG8(0x0b42), 0x00 },
423+ { CCI_REG8(0x0b44), 0x19 },
424+ { CCI_REG8(0x0b45), 0x19 },
425+ { CCI_REG8(0x0b46), 0x00 },
426+ { CCI_REG8(0x0b48), 0x16 },
427+ { CCI_REG8(0x0b49), 0x16 },
428+ { CCI_REG8(0x0b4a), 0x00 },
429+ { CCI_REG8(0x0b4c), 0x19 },
430+ { CCI_REG8(0x0b4d), 0x19 },
431+ { CCI_REG8(0x0b4e), 0x00 },
432+ { CCI_REG8(0x0b50), 0x16 },
433+ { CCI_REG8(0x0b51), 0x16 },
434+ { CCI_REG8(0x0b52), 0x00 },
435+ { CCI_REG8(0x0b80), 0x01 },
436+ { CCI_REG8(0x0b81), 0x00 },
437+ { CCI_REG8(0x0b82), 0x00 },
438+ { CCI_REG8(0x0b84), 0x00 },
439+ { CCI_REG8(0x0b85), 0x00 },
440+ { CCI_REG8(0x0b86), 0x00 },
441+ { CCI_REG8(0x0b88), 0x01 },
442+ { CCI_REG8(0x0b89), 0x6a },
443+ { CCI_REG8(0x0b8a), 0x00 },
444+ { CCI_REG8(0x0b8c), 0x00 },
445+ { CCI_REG8(0x0b8d), 0x01 },
446+ { CCI_REG8(0x0b8e), 0x00 },
447+ { CCI_REG8(0x0b90), 0x01 },
448+ { CCI_REG8(0x0b91), 0xf6 },
449+ { CCI_REG8(0x0b92), 0x00 },
450+ { CCI_REG8(0x0b94), 0x00 },
451+ { CCI_REG8(0x0b95), 0x02 },
452+ { CCI_REG8(0x0b96), 0x00 },
453+ { CCI_REG8(0x0b98), 0x02 },
454+ { CCI_REG8(0x0b99), 0xc4 },
455+ { CCI_REG8(0x0b9a), 0x00 },
456+ { CCI_REG8(0x0b9c), 0x00 },
457+ { CCI_REG8(0x0b9d), 0x03 },
458+ { CCI_REG8(0x0b9e), 0x00 },
459+ { CCI_REG8(0x0ba0), 0x03 },
460+ { CCI_REG8(0x0ba1), 0xd8 },
461+ { CCI_REG8(0x0ba2), 0x00 },
462+ { CCI_REG8(0x0ba4), 0x00 },
463+ { CCI_REG8(0x0ba5), 0x04 },
464+ { CCI_REG8(0x0ba6), 0x00 },
465+ { CCI_REG8(0x0ba8), 0x05 },
466+ { CCI_REG8(0x0ba9), 0x4d },
467+ { CCI_REG8(0x0baa), 0x00 },
468+ { CCI_REG8(0x0bac), 0x00 },
469+ { CCI_REG8(0x0bad), 0x05 },
470+ { CCI_REG8(0x0bae), 0x00 },
471+ { CCI_REG8(0x0bb0), 0x07 },
472+ { CCI_REG8(0x0bb1), 0x3e },
473+ { CCI_REG8(0x0bb2), 0x00 },
474+ { CCI_REG8(0x0bb4), 0x00 },
475+ { CCI_REG8(0x0bb5), 0x06 },
476+ { CCI_REG8(0x0bb6), 0x00 },
477+ { CCI_REG8(0x0bb8), 0x0a },
478+ { CCI_REG8(0x0bb9), 0x1a },
479+ { CCI_REG8(0x0bba), 0x00 },
480+ { CCI_REG8(0x0bbc), 0x09 },
481+ { CCI_REG8(0x0bbd), 0x36 },
482+ { CCI_REG8(0x0bbe), 0x00 },
483+ { CCI_REG8(0x0bc0), 0x0e },
484+ { CCI_REG8(0x0bc1), 0x66 },
485+ { CCI_REG8(0x0bc2), 0x00 },
486+ { CCI_REG8(0x0bc4), 0x10 },
487+ { CCI_REG8(0x0bc5), 0x06 },
488+ { CCI_REG8(0x0bc6), 0x00 },
489+ { CCI_REG8(0x02c1), 0xe0 },
490+ { CCI_REG8(0x0207), 0x04 },
491+ { CCI_REG8(0x02c2), 0x10 },
492+ { CCI_REG8(0x02c3), 0x74 },
493+ { CCI_REG8(0x02c5), 0x09 },
494+ { CCI_REG8(0x02c1), 0xe0 },
495+ { CCI_REG8(0x0207), 0x04 },
496+ { CCI_REG8(0x02c2), 0x10 },
497+ { CCI_REG8(0x02c5), 0x09 },
498+ { CCI_REG8(0x02c1), 0xe0 },
499+ { CCI_REG8(0x0207), 0x04 },
500+ { CCI_REG8(0x02c2), 0x10 },
501+ { CCI_REG8(0x02c5), 0x09 },
502+ { CCI_REG8(0x0aa1), 0x15 },
503+ { CCI_REG8(0x0aa2), 0x50 },
504+ { CCI_REG8(0x0aa3), 0x00 },
505+ { CCI_REG8(0x0aa4), 0x09 },
506+ { CCI_REG8(0x0a90), 0x25 },
507+ { CCI_REG8(0x0a91), 0x0e },
508+ { CCI_REG8(0x0a94), 0x80 },
509+
510+ /* ISP */
511+ { CCI_REG8(0x0050), 0x00 },
512+ { CCI_REG8(0x0089), 0x83 },
513+ { CCI_REG8(0x005a), 0x40 },
514+ { CCI_REG8(0x00c3), 0x35 },
515+ { CCI_REG8(0x00c4), 0x80 },
516+ { CCI_REG8(0x0080), 0x10 },
517+ { CCI_REG8(0x0040), 0x12 },
518+ { CCI_REG8(0x0053), 0x0a },
519+ { CCI_REG8(0x0054), 0x44 },
520+ { CCI_REG8(0x0055), 0x32 },
521+ { CCI_REG8(0x0058), 0x89 },
522+ { CCI_REG8(0x004a), 0x03 },
523+ { CCI_REG8(0x0048), 0xf0 },
524+ { CCI_REG8(0x0049), 0x0f },
525+ { CCI_REG8(0x0041), 0x20 },
526+ { CCI_REG8(0x0043), 0x0a },
527+ { CCI_REG8(0x009d), 0x08 },
528+ { CCI_REG8(0x0236), 0x40 },
529+ { CCI_REG8(0x0204), 0x04 },
530+ { CCI_REG8(0x0205), 0x00 },
531+ { CCI_REG8(0x02b3), 0x00 },
532+ { CCI_REG8(0x02b4), 0x00 },
533+ { CCI_REG8(0x009e), 0x01 },
534+ { CCI_REG8(0x009f), 0x94 },
535+
536+ /* auto load REG */
537+ { CCI_REG8(0x0aa1), 0x10 },
538+ { CCI_REG8(0x0aa2), 0xf8 },
539+ { CCI_REG8(0x0aa3), 0x00 },
540+ { CCI_REG8(0x0aa4), 0x1f },
541+ { CCI_REG8(0x0a90), 0x11 },
542+ { CCI_REG8(0x0a91), 0x0e },
543+ { CCI_REG8(0x0a94), 0x80 },
544+ { CCI_REG8(0x03fe), 0x00 },
545+ { CCI_REG8(0x0a90), 0x00 },
546+ { CCI_REG8(0x0a70), 0x00 },
547+ { CCI_REG8(0x0a67), 0x00 },
548+ { CCI_REG8(0x0af4), 0x29 },
549+
550+ /* DPHY */
551+ { CCI_REG8(0x0d80), 0x07 },
552+ { CCI_REG8(0x0dd3), 0x18 },
553+
554+ /* CISCTL_Reset */
555+ { CCI_REG8(0x031c), 0x80 },
556+ { CCI_REG8(0x03fe), 0x30 },
557+ { CCI_REG8(0x0d17), 0x06 },
558+ { CCI_REG8(0x03fe), 0x00 },
559+ { CCI_REG8(0x0d17), 0x00 },
560+ { CCI_REG8(0x031c), 0x93 },
561+ { CCI_REG8(0x03fe), 0x00 },
562+ { CCI_REG8(0x031c), 0x80 },
563+ { CCI_REG8(0x03fe), 0x30 },
564+ { CCI_REG8(0x0d17), 0x06 },
565+ { CCI_REG8(0x03fe), 0x00 },
566+ { CCI_REG8(0x0d17), 0x00 },
567+ { CCI_REG8(0x031c), 0x93 },
568+};
569+
570+struct gc05a2_mode {
571+ u32 width;
572+ u32 height;
573+ const struct gc05a2_reg_list reg_list;
574+
575+ u32 hts; /* Horizontal timining size */
576+ u32 vts_def; /* Default vertical timining size */
577+ u32 vts_min; /* Min vertical timining size */
578+};
579+
580+/* Declare modes in order, from biggest to smallest height. */
581+static const struct gc05a2_mode gc05a2_modes[] = {
582+ {
583+ /* 2592*1944@30fps */
584+ .width = GC05A2_NATIVE_WIDTH,
585+ .height = GC05A2_NATIVE_HEIGHT,
586+ .reg_list = {
587+ .num_of_regs = ARRAY_SIZE(mode_2592x1944),
588+ .regs = mode_2592x1944,
589+ },
590+ .hts = 3664,
591+ .vts_def = 2032,
592+ .vts_min = 2032,
593+ },
594+ {
595+ /* 1280*720@60fps */
596+ .width = 1280,
597+ .height = 720,
598+ .reg_list = {
599+ .num_of_regs = ARRAY_SIZE(mode_1280x720),
600+ .regs = mode_1280x720,
601+ },
602+ .hts = 3616,
603+ .vts_def = 1032,
604+ .vts_min = 1032,
605+ },
606+};
607+
608+static inline struct gc05a2 *to_gc05a2(struct v4l2_subdev *sd)
609+{
610+ return container_of(sd, struct gc05a2, sd);
611+}
612+
613+static int gc05a2_power_on(struct device *dev)
614+{
615+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
616+ struct gc05a2 *gc05a2 = to_gc05a2(sd);
617+ int ret;
618+
619+ ret = regulator_bulk_enable(ARRAY_SIZE(gc05a2_supply_name),
620+ gc05a2->supplies);
621+ if (ret < 0) {
622+ dev_err(gc05a2->dev, "failed to enable regulators: %d\n", ret);
623+ return ret;
624+ }
625+
626+ ret = clk_prepare_enable(gc05a2->xclk);
627+ if (ret < 0) {
628+ regulator_bulk_disable(ARRAY_SIZE(gc05a2_supply_name),
629+ gc05a2->supplies);
630+ dev_err(gc05a2->dev, "clk prepare enable failed\n");
631+ return ret;
632+ }
633+
634+ fsleep(GC05A2_SLEEP_US);
635+
636+ gpiod_set_value_cansleep(gc05a2->reset_gpio, 0);
637+ fsleep(GC05A2_SLEEP_US);
638+
639+ return 0;
640+}
641+
642+static int gc05a2_power_off(struct device *dev)
643+{
644+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
645+ struct gc05a2 *gc05a2 = to_gc05a2(sd);
646+
647+ clk_disable_unprepare(gc05a2->xclk);
648+ gpiod_set_value_cansleep(gc05a2->reset_gpio, 1);
649+ regulator_bulk_disable(ARRAY_SIZE(gc05a2_supply_name),
650+ gc05a2->supplies);
651+
652+ return 0;
653+}
654+
655+static int gc05a2_enum_mbus_code(struct v4l2_subdev *sd,
656+ struct v4l2_subdev_state *sd_state,
657+ struct v4l2_subdev_mbus_code_enum *code)
658+{
659+ if (code->index > 0)
660+ return -EINVAL;
661+
662+ code->code = GC05A2_MBUS_CODE;
663+
664+ return 0;
665+}
666+
667+static int gc05a2_enum_frame_size(struct v4l2_subdev *subdev,
668+ struct v4l2_subdev_state *sd_state,
669+ struct v4l2_subdev_frame_size_enum *fse)
670+{
671+ if (fse->code != GC05A2_MBUS_CODE)
672+ return -EINVAL;
673+
674+ if (fse->index >= ARRAY_SIZE(gc05a2_modes))
675+ return -EINVAL;
676+
677+ fse->min_width = gc05a2_modes[fse->index].width;
678+ fse->max_width = gc05a2_modes[fse->index].width;
679+ fse->min_height = gc05a2_modes[fse->index].height;
680+ fse->max_height = gc05a2_modes[fse->index].height;
681+
682+ return 0;
683+}
684+
685+static int gc05a2_update_cur_mode_controls(struct gc05a2 *gc05a2,
686+ const struct gc05a2_mode *mode)
687+{
688+ s64 exposure_max, h_blank;
689+ int ret;
690+
691+ ret = __v4l2_ctrl_modify_range(gc05a2->vblank,
692+ mode->vts_min - mode->height,
693+ GC05A2_VTS_MAX - mode->height, 1,
694+ mode->vts_def - mode->height);
695+ if (ret) {
696+ dev_err(gc05a2->dev, "VB ctrl range update failed\n");
697+ return ret;
698+ }
699+
700+ h_blank = mode->hts - mode->width;
701+ ret = __v4l2_ctrl_modify_range(gc05a2->hblank, h_blank, h_blank, 1,
702+ h_blank);
703+ if (ret) {
704+ dev_err(gc05a2->dev, "HB ctrl range update failed\n");
705+ return ret;
706+ }
707+
708+ exposure_max = mode->vts_def - GC05A2_EXP_MARGIN;
709+ ret = __v4l2_ctrl_modify_range(gc05a2->exposure, GC05A2_EXP_MIN,
710+ exposure_max, GC05A2_EXP_STEP,
711+ exposure_max);
712+ if (ret) {
713+ dev_err(gc05a2->dev, "exposure ctrl range update failed\n");
714+ return ret;
715+ }
716+
717+ return 0;
718+}
719+
720+static void gc05a2_update_pad_format(struct gc05a2 *gc08a3,
721+ const struct gc05a2_mode *mode,
722+ struct v4l2_mbus_framefmt *fmt)
723+{
724+ fmt->width = mode->width;
725+ fmt->height = mode->height;
726+ fmt->code = GC05A2_MBUS_CODE;
727+ fmt->field = V4L2_FIELD_NONE;
728+ fmt->colorspace = V4L2_COLORSPACE_RAW;
729+ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
730+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
731+ fmt->xfer_func = V4L2_XFER_FUNC_NONE;
732+}
733+
734+static int gc05a2_set_format(struct v4l2_subdev *sd,
735+ struct v4l2_subdev_state *state,
736+ struct v4l2_subdev_format *fmt)
737+{
738+ struct gc05a2 *gc05a2 = to_gc05a2(sd);
739+ struct v4l2_mbus_framefmt *mbus_fmt;
740+ struct v4l2_rect *crop;
741+ const struct gc05a2_mode *mode;
742+
743+ mode = v4l2_find_nearest_size(gc05a2_modes, ARRAY_SIZE(gc05a2_modes),
744+ width, height, fmt->format.width,
745+ fmt->format.height);
746+
747+ /* update crop info to subdev state */
748+ crop = v4l2_subdev_state_get_crop(state, 0);
749+ crop->width = mode->width;
750+ crop->height = mode->height;
751+
752+ /* update fmt info to subdev state */
753+ gc05a2_update_pad_format(gc05a2, mode, &fmt->format);
754+ mbus_fmt = v4l2_subdev_state_get_format(state, 0);
755+ *mbus_fmt = fmt->format;
756+
757+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
758+ return 0;
759+ gc05a2->cur_mode = mode;
760+ gc05a2_update_cur_mode_controls(gc05a2, mode);
761+
762+ return 0;
763+}
764+
765+static int gc05a2_get_selection(struct v4l2_subdev *sd,
766+ struct v4l2_subdev_state *state,
767+ struct v4l2_subdev_selection *sel)
768+{
769+ switch (sel->target) {
770+ case V4L2_SEL_TGT_CROP_DEFAULT:
771+ case V4L2_SEL_TGT_CROP:
772+ sel->r = *v4l2_subdev_state_get_crop(state, 0);
773+ break;
774+ case V4L2_SEL_TGT_CROP_BOUNDS:
775+ sel->r.top = 0;
776+ sel->r.left = 0;
777+ sel->r.width = GC05A2_NATIVE_WIDTH;
778+ sel->r.height = GC05A2_NATIVE_HEIGHT;
779+ break;
780+ default:
781+ return -EINVAL;
782+ }
783+
784+ return 0;
785+}
786+
787+static int gc05a2_init_state(struct v4l2_subdev *sd,
788+ struct v4l2_subdev_state *state)
789+{
790+ struct v4l2_subdev_format fmt = {
791+ .which = V4L2_SUBDEV_FORMAT_TRY,
792+ .pad = 0,
793+ .format = {
794+ .code = GC05A2_MBUS_CODE,
795+ .width = gc05a2_modes[0].width,
796+ .height = gc05a2_modes[0].height,
797+ },
798+ };
799+
800+ gc05a2_set_format(sd, state, &fmt);
801+
802+ return 0;
803+}
804+
805+static int gc05a2_set_ctrl_hflip(struct gc05a2 *gc05a2, u32 ctrl_val)
806+{
807+ int ret;
808+ u64 val;
809+
810+ ret = cci_read(gc05a2->regmap, GC05A2_FLIP_REG, &val, NULL);
811+ if (ret) {
812+ dev_err(gc05a2->dev, "read hflip register failed: %d\n", ret);
813+ return ret;
814+ }
815+
816+ return cci_update_bits(gc05a2->regmap, GC05A2_FLIP_REG,
817+ GC05A2_FLIP_H_MASK,
818+ ctrl_val ? GC05A2_FLIP_H_MASK : 0, NULL);
819+}
820+
821+static int gc05a2_set_ctrl_vflip(struct gc05a2 *gc05a2, u32 ctrl_val)
822+{
823+ int ret;
824+ u64 val;
825+
826+ ret = cci_read(gc05a2->regmap, GC05A2_FLIP_REG, &val, NULL);
827+ if (ret) {
828+ dev_err(gc05a2->dev, "read vflip register failed: %d\n", ret);
829+ return ret;
830+ }
831+
832+ return cci_update_bits(gc05a2->regmap, GC05A2_FLIP_REG,
833+ GC05A2_FLIP_V_MASK,
834+ ctrl_val ? GC05A2_FLIP_V_MASK : 0, NULL);
835+}
836+
837+static int gc05a2_test_pattern(struct gc05a2 *gc05a2, u32 pattern_menu)
838+{
839+ u32 pattern;
840+ int ret;
841+
842+ if (pattern_menu) {
843+ switch (pattern_menu) {
844+ case 1:
845+ case 2:
846+ case 3:
847+ case 4:
848+ case 5:
849+ case 6:
850+ case 7:
851+ pattern = pattern_menu << 4;
852+ break;
853+
854+ case 8:
855+ pattern = 0;
856+ break;
857+
858+ case 9:
859+ pattern = 4;
860+ break;
861+
862+ default:
863+ /* Set pattern to 0, it's a safe default. */
864+ pattern = 0;
865+ break;
866+ }
867+
868+ ret = cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_IDX,
869+ pattern, NULL);
870+ if (ret)
871+ return ret;
872+
873+ return cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_EN,
874+ GC05A2_TEST_PATTERN_EN, NULL);
875+ } else {
876+ return cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_EN,
877+ 0x00, NULL);
878+ }
879+}
880+
881+static int gc05a2_set_ctrl(struct v4l2_ctrl *ctrl)
882+{
883+ struct gc05a2 *gc05a2 =
884+ container_of(ctrl->handler, struct gc05a2, ctrls);
885+ int ret = 0;
886+ s64 exposure_max;
887+ struct v4l2_subdev_state *state;
888+ const struct v4l2_mbus_framefmt *format;
889+
890+ state = v4l2_subdev_get_locked_active_state(&gc05a2->sd);
891+ format = v4l2_subdev_state_get_format(state, 0);
892+
893+ if (ctrl->id == V4L2_CID_VBLANK) {
894+ /* Update max exposure while meeting expected vblanking */
895+ exposure_max = format->height + ctrl->val - GC05A2_EXP_MARGIN;
896+ __v4l2_ctrl_modify_range(gc05a2->exposure,
897+ gc05a2->exposure->minimum,
898+ exposure_max, gc05a2->exposure->step,
899+ exposure_max);
900+ }
901+
902+ /*
903+ * Applying V4L2 control value only happens
904+ * when power is on for streaming.
905+ */
906+ if (!pm_runtime_get_if_active(gc05a2->dev))
907+ return 0;
908+
909+ switch (ctrl->id) {
910+ case V4L2_CID_EXPOSURE:
911+ ret = cci_write(gc05a2->regmap, GC05A2_EXP_REG,
912+ ctrl->val, NULL);
913+ break;
914+
915+ case V4L2_CID_ANALOGUE_GAIN:
916+ ret = cci_write(gc05a2->regmap, GC05A2_AGAIN_REG,
917+ ctrl->val, NULL);
918+ break;
919+
920+ case V4L2_CID_VBLANK:
921+ ret = cci_write(gc05a2->regmap, GC05A2_FRAME_LENGTH_REG,
922+ gc05a2->cur_mode->height + ctrl->val, NULL);
923+ break;
924+
925+ case V4L2_CID_HFLIP:
926+ ret = gc05a2_set_ctrl_hflip(gc05a2, ctrl->val);
927+ break;
928+
929+ case V4L2_CID_VFLIP:
930+ ret = gc05a2_set_ctrl_vflip(gc05a2, ctrl->val);
931+ break;
932+
933+ case V4L2_CID_TEST_PATTERN:
934+ ret = gc05a2_test_pattern(gc05a2, ctrl->val);
935+ break;
936+
937+ default:
938+ break;
939+ }
940+
941+ pm_runtime_put(gc05a2->dev);
942+
943+ return ret;
944+}
945+
946+static const struct v4l2_ctrl_ops gc05a2_ctrl_ops = {
947+ .s_ctrl = gc05a2_set_ctrl,
948+};
949+
950+static int gc05a2_identify_module(struct gc05a2 *gc05a2)
951+{
952+ u64 val;
953+ int ret;
954+
955+ if (gc05a2->identified)
956+ return 0;
957+
958+ ret = cci_read(gc05a2->regmap, GC05A2_REG_CHIP_ID, &val, NULL);
959+ if (ret)
960+ return ret;
961+
962+ if (val != GC05A2_CHIP_ID) {
963+ dev_err(gc05a2->dev, "chip id mismatch: 0x%x!=0x%llx",
964+ GC05A2_CHIP_ID, val);
965+ return -ENXIO;
966+ }
967+
968+ gc05a2->identified = true;
969+
970+ return 0;
971+}
972+
973+static int gc05a2_start_streaming(struct gc05a2 *gc05a2)
974+{
975+ const struct gc05a2_mode *mode;
976+ const struct gc05a2_reg_list *reg_list;
977+ int ret;
978+
979+ ret = pm_runtime_resume_and_get(gc05a2->dev);
980+ if (ret < 0)
981+ return ret;
982+
983+ ret = gc05a2_identify_module(gc05a2);
984+ if (ret)
985+ goto err_rpm_put;
986+
987+ ret = cci_multi_reg_write(gc05a2->regmap,
988+ mode_table_common,
989+ ARRAY_SIZE(mode_table_common), NULL);
990+ if (ret)
991+ goto err_rpm_put;
992+
993+ mode = gc05a2->cur_mode;
994+ reg_list = &mode->reg_list;
995+
996+ ret = cci_multi_reg_write(gc05a2->regmap,
997+ reg_list->regs, reg_list->num_of_regs, NULL);
998+ if (ret < 0)
999+ goto err_rpm_put;
1000+
1001+ ret = __v4l2_ctrl_handler_setup(&gc05a2->ctrls);
1002+ if (ret < 0) {
1003+ dev_err(gc05a2->dev, "could not sync v4l2 controls\n");
1004+ goto err_rpm_put;
1005+ }
1006+
1007+ ret = cci_write(gc05a2->regmap, GC05A2_STREAMING_REG, 1, NULL);
1008+ if (ret < 0) {
1009+ dev_err(gc05a2->dev, "write STREAMING_REG failed: %d\n", ret);
1010+ goto err_rpm_put;
1011+ }
1012+
1013+ return 0;
1014+
1015+err_rpm_put:
1016+ pm_runtime_put(gc05a2->dev);
1017+ return ret;
1018+}
1019+
1020+static int gc05a2_stop_streaming(struct gc05a2 *gc05a2)
1021+{
1022+ int ret;
1023+
1024+ ret = cci_write(gc05a2->regmap, GC05A2_STREAMING_REG, 0, NULL);
1025+ if (ret < 0)
1026+ dev_err(gc05a2->dev, "could not sent stop streaming %d\n", ret);
1027+
1028+ pm_runtime_put(gc05a2->dev);
1029+ return ret;
1030+}
1031+
1032+static int gc05a2_s_stream(struct v4l2_subdev *subdev, int enable)
1033+{
1034+ struct gc05a2 *gc05a2 = to_gc05a2(subdev);
1035+ struct v4l2_subdev_state *state;
1036+ int ret;
1037+
1038+ state = v4l2_subdev_lock_and_get_active_state(subdev);
1039+
1040+ if (enable)
1041+ ret = gc05a2_start_streaming(gc05a2);
1042+ else
1043+ ret = gc05a2_stop_streaming(gc05a2);
1044+
1045+ v4l2_subdev_unlock_state(state);
1046+
1047+ return ret;
1048+}
1049+
1050+static const struct v4l2_subdev_video_ops gc05a2_video_ops = {
1051+ .s_stream = gc05a2_s_stream,
1052+};
1053+
1054+static const struct v4l2_subdev_pad_ops gc05a2_subdev_pad_ops = {
1055+ .enum_mbus_code = gc05a2_enum_mbus_code,
1056+ .enum_frame_size = gc05a2_enum_frame_size,
1057+ .get_fmt = v4l2_subdev_get_fmt,
1058+ .set_fmt = gc05a2_set_format,
1059+ .get_selection = gc05a2_get_selection,
1060+};
1061+
1062+static const struct v4l2_subdev_core_ops gc05a2_core_ops = {
1063+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
1064+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
1065+};
1066+
1067+static const struct v4l2_subdev_ops gc05a2_subdev_ops = {
1068+ .core = &gc05a2_core_ops,
1069+ .video = &gc05a2_video_ops,
1070+ .pad = &gc05a2_subdev_pad_ops,
1071+};
1072+
1073+static const struct v4l2_subdev_internal_ops gc05a2_internal_ops = {
1074+ .init_state = gc05a2_init_state,
1075+};
1076+
1077+static int gc05a2_get_regulators(struct device *dev, struct gc05a2 *gc05a2)
1078+{
1079+ unsigned int i;
1080+
1081+ for (i = 0; i < ARRAY_SIZE(gc05a2_supply_name); i++)
1082+ gc05a2->supplies[i].supply = gc05a2_supply_name[i];
1083+
1084+ return devm_regulator_bulk_get(dev, ARRAY_SIZE(gc05a2_supply_name),
1085+ gc05a2->supplies);
1086+}
1087+
1088+static int gc05a2_parse_fwnode(struct gc05a2 *gc05a2)
1089+{
1090+ struct fwnode_handle *endpoint;
1091+ struct v4l2_fwnode_endpoint bus_cfg = {
1092+ .bus_type = V4L2_MBUS_CSI2_DPHY,
1093+ };
1094+ int ret;
1095+ struct device *dev = gc05a2->dev;
1096+
1097+ endpoint =
1098+ fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0,
1099+ FWNODE_GRAPH_ENDPOINT_NEXT);
1100+ if (!endpoint)
1101+ return dev_err_probe(dev, -EINVAL, "Missing endpoint node\n");
1102+
1103+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &bus_cfg);
1104+ if (ret) {
1105+ dev_err_probe(dev, ret, "parsing endpoint node failed\n");
1106+ goto done;
1107+ }
1108+
1109+ ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies,
1110+ bus_cfg.nr_of_link_frequencies,
1111+ gc05a2_link_freq_menu_items,
1112+ ARRAY_SIZE(gc05a2_link_freq_menu_items),
1113+ &gc05a2->link_freq_bitmap);
1114+ if (ret)
1115+ goto done;
1116+
1117+done:
1118+ v4l2_fwnode_endpoint_free(&bus_cfg);
1119+ fwnode_handle_put(endpoint);
1120+ return ret;
1121+}
1122+
1123+static u64 gc05a2_to_pixel_rate(u32 f_index)
1124+{
1125+ u64 pixel_rate =
1126+ gc05a2_link_freq_menu_items[f_index] * 2 * GC05A2_DATA_LANES;
1127+
1128+ return div_u64(pixel_rate, GC05A2_RGB_DEPTH);
1129+}
1130+
1131+static int gc05a2_init_controls(struct gc05a2 *gc05a2)
1132+{
1133+ struct i2c_client *client = v4l2_get_subdevdata(&gc05a2->sd);
1134+ const struct gc05a2_mode *mode = &gc05a2_modes[0];
1135+ const struct v4l2_ctrl_ops *ops = &gc05a2_ctrl_ops;
1136+ struct v4l2_fwnode_device_properties props;
1137+ struct v4l2_ctrl_handler *ctrl_hdlr;
1138+ s64 exposure_max, h_blank;
1139+ int ret;
1140+
1141+ ctrl_hdlr = &gc05a2->ctrls;
1142+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 9);
1143+ if (ret)
1144+ return ret;
1145+
1146+ gc05a2->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
1147+ V4L2_CID_HFLIP, 0, 1, 1, 0);
1148+ gc05a2->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
1149+ V4L2_CID_VFLIP, 0, 1, 1, 0);
1150+ v4l2_ctrl_cluster(2, &gc05a2->hflip);
1151+
1152+ gc05a2->link_freq =
1153+ v4l2_ctrl_new_int_menu(ctrl_hdlr,
1154+ &gc05a2_ctrl_ops,
1155+ V4L2_CID_LINK_FREQ,
1156+ ARRAY_SIZE(gc05a2_link_freq_menu_items) - 1,
1157+ 0,
1158+ gc05a2_link_freq_menu_items);
1159+ if (gc05a2->link_freq)
1160+ gc05a2->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1161+
1162+ gc05a2->pixel_rate =
1163+ v4l2_ctrl_new_std(ctrl_hdlr,
1164+ &gc05a2_ctrl_ops,
1165+ V4L2_CID_PIXEL_RATE, 0,
1166+ gc05a2_to_pixel_rate(0),
1167+ 1,
1168+ gc05a2_to_pixel_rate(0));
1169+
1170+ gc05a2->vblank =
1171+ v4l2_ctrl_new_std(ctrl_hdlr,
1172+ &gc05a2_ctrl_ops, V4L2_CID_VBLANK,
1173+ mode->vts_min - mode->height,
1174+ GC05A2_VTS_MAX - mode->height, 1,
1175+ mode->vts_def - mode->height);
1176+
1177+ h_blank = mode->hts - mode->width;
1178+ gc05a2->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
1179+ V4L2_CID_HBLANK, h_blank, h_blank, 1,
1180+ h_blank);
1181+ if (gc05a2->hblank)
1182+ gc05a2->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1183+
1184+ v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
1185+ V4L2_CID_ANALOGUE_GAIN, GC05A2_AGAIN_MIN,
1186+ GC05A2_AGAIN_MAX, GC05A2_AGAIN_STEP,
1187+ GC05A2_AGAIN_MIN);
1188+
1189+ exposure_max = mode->vts_def - GC05A2_EXP_MARGIN;
1190+ gc05a2->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
1191+ V4L2_CID_EXPOSURE, GC05A2_EXP_MIN,
1192+ exposure_max, GC05A2_EXP_STEP,
1193+ exposure_max);
1194+
1195+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &gc05a2_ctrl_ops,
1196+ V4L2_CID_TEST_PATTERN,
1197+ ARRAY_SIZE(gc05a2_test_pattern_menu) - 1,
1198+ 0, 0, gc05a2_test_pattern_menu);
1199+
1200+ /* register properties to fwnode (e.g. rotation, orientation) */
1201+ ret = v4l2_fwnode_device_parse(&client->dev, &props);
1202+ if (ret)
1203+ goto error_ctrls;
1204+
1205+ ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, ops, &props);
1206+ if (ret)
1207+ goto error_ctrls;
1208+
1209+ if (ctrl_hdlr->error) {
1210+ ret = ctrl_hdlr->error;
1211+ goto error_ctrls;
1212+ }
1213+
1214+ gc05a2->sd.ctrl_handler = ctrl_hdlr;
1215+
1216+ return 0;
1217+
1218+error_ctrls:
1219+ v4l2_ctrl_handler_free(ctrl_hdlr);
1220+
1221+ return ret;
1222+}
1223+
1224+static int gc05a2_probe(struct i2c_client *client)
1225+{
1226+ struct device *dev = &client->dev;
1227+ struct gc05a2 *gc05a2;
1228+ int ret;
1229+
1230+ gc05a2 = devm_kzalloc(dev, sizeof(*gc05a2), GFP_KERNEL);
1231+ if (!gc05a2)
1232+ return -ENOMEM;
1233+
1234+ gc05a2->dev = dev;
1235+
1236+ ret = gc05a2_parse_fwnode(gc05a2);
1237+ if (ret)
1238+ return ret;
1239+
1240+ gc05a2->regmap = devm_cci_regmap_init_i2c(client, 16);
1241+ if (IS_ERR(gc05a2->regmap))
1242+ return dev_err_probe(dev, PTR_ERR(gc05a2->regmap),
1243+ "failed to init CCI\n");
1244+
1245+ gc05a2->xclk = devm_clk_get(dev, NULL);
1246+ if (IS_ERR(gc05a2->xclk))
1247+ return dev_err_probe(dev, PTR_ERR(gc05a2->xclk),
1248+ "failed to get xclk\n");
1249+
1250+ ret = clk_set_rate(gc05a2->xclk, GC05A2_DEFAULT_CLK_FREQ);
1251+ if (ret)
1252+ return dev_err_probe(dev, ret,
1253+ "failed to set xclk frequency\n");
1254+
1255+ ret = gc05a2_get_regulators(dev, gc05a2);
1256+ if (ret < 0)
1257+ return dev_err_probe(dev, ret,
1258+ "failed to get regulators\n");
1259+
1260+ gc05a2->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
1261+ if (IS_ERR(gc05a2->reset_gpio))
1262+ return dev_err_probe(dev, PTR_ERR(gc05a2->reset_gpio),
1263+ "failed to get gpio\n");
1264+
1265+ v4l2_i2c_subdev_init(&gc05a2->sd, client, &gc05a2_subdev_ops);
1266+ gc05a2->sd.internal_ops = &gc05a2_internal_ops;
1267+ gc05a2->cur_mode = &gc05a2_modes[0];
1268+
1269+ ret = gc05a2_init_controls(gc05a2);
1270+ if (ret)
1271+ return dev_err_probe(dev, ret,
1272+ "failed to init controls\n");
1273+
1274+ gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
1275+ V4L2_SUBDEV_FL_HAS_EVENTS;
1276+ gc05a2->pad.flags = MEDIA_PAD_FL_SOURCE;
1277+ gc05a2->sd.dev = &client->dev;
1278+ gc05a2->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1279+
1280+ ret = media_entity_pads_init(&gc05a2->sd.entity, 1, &gc05a2->pad);
1281+ if (ret < 0) {
1282+ dev_err_probe(dev, ret, "could not register media entity\n");
1283+ goto err_v4l2_ctrl_handler_free;
1284+ }
1285+
1286+ gc05a2->sd.state_lock = gc05a2->ctrls.lock;
1287+ ret = v4l2_subdev_init_finalize(&gc05a2->sd);
1288+ if (ret < 0) {
1289+ dev_err_probe(dev, ret, "v4l2 subdev init error\n");
1290+ goto err_media_entity_cleanup;
1291+ }
1292+
1293+ pm_runtime_enable(gc05a2->dev);
1294+ pm_runtime_set_autosuspend_delay(gc05a2->dev, 1000);
1295+ pm_runtime_use_autosuspend(gc05a2->dev);
1296+ pm_runtime_idle(gc05a2->dev);
1297+
1298+ ret = v4l2_async_register_subdev_sensor(&gc05a2->sd);
1299+ if (ret < 0) {
1300+ dev_err_probe(dev, ret, "could not register v4l2 device\n");
1301+ goto err_rpm;
1302+ }
1303+
1304+ return 0;
1305+
1306+err_rpm:
1307+ pm_runtime_disable(gc05a2->dev);
1308+ v4l2_subdev_cleanup(&gc05a2->sd);
1309+
1310+err_media_entity_cleanup:
1311+ media_entity_cleanup(&gc05a2->sd.entity);
1312+
1313+err_v4l2_ctrl_handler_free:
1314+ v4l2_ctrl_handler_free(&gc05a2->ctrls);
1315+
1316+ return ret;
1317+}
1318+
1319+static void gc05a2_remove(struct i2c_client *client)
1320+{
1321+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
1322+ struct gc05a2 *gc05a2 = to_gc05a2(sd);
1323+
1324+ v4l2_async_unregister_subdev(&gc05a2->sd);
1325+ v4l2_subdev_cleanup(sd);
1326+ media_entity_cleanup(&gc05a2->sd.entity);
1327+ v4l2_ctrl_handler_free(&gc05a2->ctrls);
1328+
1329+ pm_runtime_disable(&client->dev);
1330+ if (!pm_runtime_status_suspended(&client->dev))
1331+ gc05a2_power_off(gc05a2->dev);
1332+ pm_runtime_set_suspended(&client->dev);
1333+}
1334+
1335+static const struct of_device_id gc05a2_of_match[] = {
1336+ { .compatible = "galaxycore,gc05a2" },
1337+ {}
1338+};
1339+MODULE_DEVICE_TABLE(of, gc05a2_of_match);
1340+
1341+static DEFINE_RUNTIME_DEV_PM_OPS(gc05a2_pm_ops,
1342+ gc05a2_power_off,
1343+ gc05a2_power_on,
1344+ NULL);
1345+
1346+static struct i2c_driver gc05a2_i2c_driver = {
1347+ .driver = {
1348+ .of_match_table = gc05a2_of_match,
1349+ .pm = pm_ptr(&gc05a2_pm_ops),
1350+ .name = "gc05a2",
1351+ },
1352+ .probe = gc05a2_probe,
1353+ .remove = gc05a2_remove,
1354+};
1355+module_i2c_driver(gc05a2_i2c_driver);
1356+
1357+MODULE_DESCRIPTION("GalaxyCore gc05a2 Camera driver");
1358+MODULE_AUTHOR("Zhi Mao <zhi.mao@mediatek.com>");
1359+MODULE_LICENSE("GPL");
drivers/media/i2c/gc08a3.c+1339−0
@@ -0,0 +1,1339 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Driver for GalaxyCore gc08a3 image sensor
4+ *
5+ * Copyright 2024 MediaTek
6+ *
7+ * Zhi Mao <zhi.mao@mediatek.com>
8+ */
9+#include <linux/array_size.h>
10+#include <linux/bits.h>
11+#include <linux/clk.h>
12+#include <linux/container_of.h>
13+#include <linux/delay.h>
14+#include <linux/device.h>
15+#include <linux/err.h>
16+#include <linux/gpio/consumer.h>
17+#include <linux/math64.h>
18+#include <linux/mod_devicetable.h>
19+#include <linux/pm_runtime.h>
20+#include <linux/property.h>
21+#include <linux/regulator/consumer.h>
22+#include <linux/types.h>
23+#include <linux/units.h>
24+
25+#include <media/v4l2-cci.h>
26+#include <media/v4l2-ctrls.h>
27+#include <media/v4l2-event.h>
28+#include <media/v4l2-fwnode.h>
29+#include <media/v4l2-subdev.h>
30+
31+#define GC08A3_REG_TEST_PATTERN_EN CCI_REG8(0x008c)
32+#define GC08A3_REG_TEST_PATTERN_IDX CCI_REG8(0x008d)
33+#define GC08A3_TEST_PATTERN_EN 0x01
34+
35+#define GC08A3_STREAMING_REG CCI_REG8(0x0100)
36+
37+#define GC08A3_FLIP_REG CCI_REG8(0x0101)
38+#define GC08A3_FLIP_H_MASK BIT(0)
39+#define GC08A3_FLIP_V_MASK BIT(1)
40+
41+#define GC08A3_EXP_REG CCI_REG16(0x0202)
42+#define GC08A3_EXP_MARGIN 16
43+#define GC08A3_EXP_MIN 4
44+#define GC08A3_EXP_STEP 1
45+
46+#define GC08A3_AGAIN_REG CCI_REG16(0x0204)
47+#define GC08A3_AGAIN_MIN 1024
48+#define GC08A3_AGAIN_MAX (1024 * 16)
49+#define GC08A3_AGAIN_STEP 1
50+
51+#define GC08A3_FRAME_LENGTH_REG CCI_REG16(0x0340)
52+#define GC08A3_VTS_MAX 0xfff0
53+
54+#define GC08A3_REG_CHIP_ID CCI_REG16(0x03f0)
55+#define GC08A3_CHIP_ID 0x08a3
56+
57+#define GC08A3_NATIVE_WIDTH 3264
58+#define GC08A3_NATIVE_HEIGHT 2448
59+
60+#define GC08A3_DEFAULT_CLK_FREQ (24 * HZ_PER_MHZ)
61+#define GC08A3_MBUS_CODE MEDIA_BUS_FMT_SRGGB10_1X10
62+#define GC08A3_DATA_LANES 4
63+
64+#define GC08A3_RGB_DEPTH 10
65+
66+#define GC08A3_SLEEP_US (2 * USEC_PER_MSEC)
67+
68+static const char *const gc08a3_test_pattern_menu[] = {
69+ "No Pattern", "Solid Black", "Colour Bar", "Solid White",
70+ "Solid Red", "Solid Green", "Solid Blue", "Solid Yellow",
71+};
72+
73+static const s64 gc08a3_link_freq_menu_items[] = {
74+ (336 * HZ_PER_MHZ),
75+ (207 * HZ_PER_MHZ),
76+};
77+
78+static const char *const gc08a3_supply_name[] = {
79+ "avdd",
80+ "dvdd",
81+ "dovdd",
82+};
83+
84+struct gc08a3 {
85+ struct device *dev;
86+ struct v4l2_subdev sd;
87+ struct media_pad pad;
88+
89+ struct clk *xclk;
90+ struct regulator_bulk_data supplies[ARRAY_SIZE(gc08a3_supply_name)];
91+ struct gpio_desc *reset_gpio;
92+
93+ struct v4l2_ctrl_handler ctrls;
94+ struct v4l2_ctrl *pixel_rate;
95+ struct v4l2_ctrl *link_freq;
96+ struct v4l2_ctrl *exposure;
97+ struct v4l2_ctrl *vblank;
98+ struct v4l2_ctrl *hblank;
99+ struct v4l2_ctrl *hflip;
100+ struct v4l2_ctrl *vflip;
101+
102+ struct regmap *regmap;
103+ unsigned long link_freq_bitmap;
104+ const struct gc08a3_mode *cur_mode;
105+};
106+
107+struct gc08a3_reg_list {
108+ u32 num_of_regs;
109+ const struct cci_reg_sequence *regs;
110+};
111+
112+static const struct cci_reg_sequence mode_3264x2448[] = {
113+ /* system */
114+ { CCI_REG8(0x0336), 0x70 },
115+ { CCI_REG8(0x0383), 0xbb },
116+ { CCI_REG8(0x0344), 0x00 },
117+ { CCI_REG8(0x0345), 0x06 },
118+ { CCI_REG8(0x0346), 0x00 },
119+ { CCI_REG8(0x0347), 0x04 },
120+ { CCI_REG8(0x0348), 0x0c },
121+ { CCI_REG8(0x0349), 0xd0 },
122+ { CCI_REG8(0x034a), 0x09 },
123+ { CCI_REG8(0x034b), 0x9c },
124+ { CCI_REG8(0x0202), 0x09 },
125+ { CCI_REG8(0x0203), 0x04 },
126+ { CCI_REG8(0x0340), 0x09 },
127+ { CCI_REG8(0x0341), 0xf4 },
128+ { CCI_REG8(0x0342), 0x07 },
129+ { CCI_REG8(0x0343), 0x1c },
130+
131+ { CCI_REG8(0x0226), 0x00 },
132+ { CCI_REG8(0x0227), 0x28 },
133+ { CCI_REG8(0x0e38), 0x49 },
134+ { CCI_REG8(0x0210), 0x13 },
135+ { CCI_REG8(0x0218), 0x00 },
136+ { CCI_REG8(0x0241), 0x88 },
137+ { CCI_REG8(0x0392), 0x60 },
138+
139+ /* ISP */
140+ { CCI_REG8(0x00a2), 0x00 },
141+ { CCI_REG8(0x00a3), 0x00 },
142+ { CCI_REG8(0x00ab), 0x00 },
143+ { CCI_REG8(0x00ac), 0x00 },
144+
145+ /* GAIN */
146+ { CCI_REG8(0x0204), 0x04 },
147+ { CCI_REG8(0x0205), 0x00 },
148+ { CCI_REG8(0x0050), 0x5c },
149+ { CCI_REG8(0x0051), 0x44 },
150+
151+ /* out window */
152+ { CCI_REG8(0x009a), 0x66 },
153+ { CCI_REG8(0x0351), 0x00 },
154+ { CCI_REG8(0x0352), 0x06 },
155+ { CCI_REG8(0x0353), 0x00 },
156+ { CCI_REG8(0x0354), 0x08 },
157+ { CCI_REG8(0x034c), 0x0c },
158+ { CCI_REG8(0x034d), 0xc0 },
159+ { CCI_REG8(0x034e), 0x09 },
160+ { CCI_REG8(0x034f), 0x90 },
161+
162+ /* MIPI */
163+ { CCI_REG8(0x0114), 0x03 },
164+ { CCI_REG8(0x0180), 0x65 },
165+ { CCI_REG8(0x0181), 0xf0 },
166+ { CCI_REG8(0x0185), 0x01 },
167+ { CCI_REG8(0x0115), 0x30 },
168+ { CCI_REG8(0x011b), 0x12 },
169+ { CCI_REG8(0x011c), 0x12 },
170+ { CCI_REG8(0x0121), 0x06 },
171+ { CCI_REG8(0x0122), 0x06 },
172+ { CCI_REG8(0x0123), 0x15 },
173+ { CCI_REG8(0x0124), 0x01 },
174+ { CCI_REG8(0x0125), 0x0b },
175+ { CCI_REG8(0x0126), 0x08 },
176+ { CCI_REG8(0x0129), 0x06 },
177+ { CCI_REG8(0x012a), 0x08 },
178+ { CCI_REG8(0x012b), 0x08 },
179+
180+ { CCI_REG8(0x0a73), 0x60 },
181+ { CCI_REG8(0x0a70), 0x11 },
182+ { CCI_REG8(0x0313), 0x80 },
183+ { CCI_REG8(0x0aff), 0x00 },
184+ { CCI_REG8(0x0a70), 0x00 },
185+ { CCI_REG8(0x00a4), 0x80 },
186+ { CCI_REG8(0x0316), 0x01 },
187+ { CCI_REG8(0x0a67), 0x00 },
188+ { CCI_REG8(0x0084), 0x10 },
189+ { CCI_REG8(0x0102), 0x09 },
190+};
191+
192+static const struct cci_reg_sequence mode_1920x1080[] = {
193+ /* system */
194+ { CCI_REG8(0x0336), 0x45 },
195+ { CCI_REG8(0x0383), 0x8b },
196+ { CCI_REG8(0x0344), 0x02 },
197+ { CCI_REG8(0x0345), 0xa6 },
198+ { CCI_REG8(0x0346), 0x02 },
199+ { CCI_REG8(0x0347), 0xb0 },
200+ { CCI_REG8(0x0348), 0x07 },
201+ { CCI_REG8(0x0349), 0x90 },
202+ { CCI_REG8(0x034a), 0x04 },
203+ { CCI_REG8(0x034b), 0x44 },
204+ { CCI_REG8(0x0202), 0x03 },
205+ { CCI_REG8(0x0203), 0x00 },
206+ { CCI_REG8(0x0340), 0x04 },
207+ { CCI_REG8(0x0341), 0xfc },
208+ { CCI_REG8(0x0342), 0x07 },
209+ { CCI_REG8(0x0343), 0x1c },
210+ { CCI_REG8(0x0226), 0x00 },
211+ { CCI_REG8(0x0227), 0x88 },
212+ { CCI_REG8(0x0e38), 0x49 },
213+ { CCI_REG8(0x0210), 0x13 },
214+ { CCI_REG8(0x0218), 0x00 },
215+ { CCI_REG8(0x0241), 0x88 },
216+ { CCI_REG8(0x0392), 0x60 },
217+
218+ /* ISP */
219+ { CCI_REG8(0x00a2), 0xac },
220+ { CCI_REG8(0x00a3), 0x02 },
221+ { CCI_REG8(0x00ab), 0xa0 },
222+ { CCI_REG8(0x00ac), 0x02 },
223+
224+ /* GAIN */
225+ { CCI_REG8(0x0204), 0x04 },
226+ { CCI_REG8(0x0205), 0x00 },
227+ { CCI_REG8(0x0050), 0x38 },
228+ { CCI_REG8(0x0051), 0x20 },
229+
230+ /* out window */
231+ { CCI_REG8(0x009a), 0x66 },
232+ { CCI_REG8(0x0351), 0x00 },
233+ { CCI_REG8(0x0352), 0x06 },
234+ { CCI_REG8(0x0353), 0x00 },
235+ { CCI_REG8(0x0354), 0x08 },
236+ { CCI_REG8(0x034c), 0x07 },
237+ { CCI_REG8(0x034d), 0x80 },
238+ { CCI_REG8(0x034e), 0x04 },
239+ { CCI_REG8(0x034f), 0x38 },
240+
241+ /* MIPI */
242+ { CCI_REG8(0x0114), 0x03 },
243+ { CCI_REG8(0x0180), 0x65 },
244+ { CCI_REG8(0x0181), 0xf0 },
245+ { CCI_REG8(0x0185), 0x01 },
246+ { CCI_REG8(0x0115), 0x30 },
247+ { CCI_REG8(0x011b), 0x12 },
248+ { CCI_REG8(0x011c), 0x12 },
249+ { CCI_REG8(0x0121), 0x02 },
250+ { CCI_REG8(0x0122), 0x03 },
251+ { CCI_REG8(0x0123), 0x0c },
252+ { CCI_REG8(0x0124), 0x00 },
253+ { CCI_REG8(0x0125), 0x09 },
254+ { CCI_REG8(0x0126), 0x06 },
255+ { CCI_REG8(0x0129), 0x04 },
256+ { CCI_REG8(0x012a), 0x03 },
257+ { CCI_REG8(0x012b), 0x06 },
258+
259+ { CCI_REG8(0x0a73), 0x60 },
260+ { CCI_REG8(0x0a70), 0x11 },
261+ { CCI_REG8(0x0313), 0x80 },
262+ { CCI_REG8(0x0aff), 0x00 },
263+ { CCI_REG8(0x0a70), 0x00 },
264+ { CCI_REG8(0x00a4), 0x80 },
265+ { CCI_REG8(0x0316), 0x01 },
266+ { CCI_REG8(0x0a67), 0x00 },
267+ { CCI_REG8(0x0084), 0x10 },
268+ { CCI_REG8(0x0102), 0x09 },
269+};
270+
271+static const struct cci_reg_sequence mode_table_common[] = {
272+ { GC08A3_STREAMING_REG, 0x00 },
273+ /* system */
274+ { CCI_REG8(0x031c), 0x60 },
275+ { CCI_REG8(0x0337), 0x04 },
276+ { CCI_REG8(0x0335), 0x51 },
277+ { CCI_REG8(0x0336), 0x70 },
278+ { CCI_REG8(0x0383), 0xbb },
279+ { CCI_REG8(0x031a), 0x00 },
280+ { CCI_REG8(0x0321), 0x10 },
281+ { CCI_REG8(0x0327), 0x03 },
282+ { CCI_REG8(0x0325), 0x40 },
283+ { CCI_REG8(0x0326), 0x23 },
284+ { CCI_REG8(0x0314), 0x11 },
285+ { CCI_REG8(0x0315), 0xd6 },
286+ { CCI_REG8(0x0316), 0x01 },
287+ { CCI_REG8(0x0334), 0x40 },
288+ { CCI_REG8(0x0324), 0x42 },
289+ { CCI_REG8(0x031c), 0x00 },
290+ { CCI_REG8(0x031c), 0x9f },
291+ { CCI_REG8(0x039a), 0x13 },
292+ { CCI_REG8(0x0084), 0x30 },
293+ { CCI_REG8(0x02b3), 0x08 },
294+ { CCI_REG8(0x0057), 0x0c },
295+ { CCI_REG8(0x05c3), 0x50 },
296+ { CCI_REG8(0x0311), 0x90 },
297+ { CCI_REG8(0x05a0), 0x02 },
298+ { CCI_REG8(0x0074), 0x0a },
299+ { CCI_REG8(0x0059), 0x11 },
300+ { CCI_REG8(0x0070), 0x05 },
301+ { CCI_REG8(0x0101), 0x00 },
302+
303+ /* analog */
304+ { CCI_REG8(0x0344), 0x00 },
305+ { CCI_REG8(0x0345), 0x06 },
306+ { CCI_REG8(0x0346), 0x00 },
307+ { CCI_REG8(0x0347), 0x04 },
308+ { CCI_REG8(0x0348), 0x0c },
309+ { CCI_REG8(0x0349), 0xd0 },
310+ { CCI_REG8(0x034a), 0x09 },
311+ { CCI_REG8(0x034b), 0x9c },
312+ { CCI_REG8(0x0202), 0x09 },
313+ { CCI_REG8(0x0203), 0x04 },
314+
315+ { CCI_REG8(0x0219), 0x05 },
316+ { CCI_REG8(0x0226), 0x00 },
317+ { CCI_REG8(0x0227), 0x28 },
318+ { CCI_REG8(0x0e0a), 0x00 },
319+ { CCI_REG8(0x0e0b), 0x00 },
320+ { CCI_REG8(0x0e24), 0x04 },
321+ { CCI_REG8(0x0e25), 0x04 },
322+ { CCI_REG8(0x0e26), 0x00 },
323+ { CCI_REG8(0x0e27), 0x10 },
324+ { CCI_REG8(0x0e01), 0x74 },
325+ { CCI_REG8(0x0e03), 0x47 },
326+ { CCI_REG8(0x0e04), 0x33 },
327+ { CCI_REG8(0x0e05), 0x44 },
328+ { CCI_REG8(0x0e06), 0x44 },
329+ { CCI_REG8(0x0e0c), 0x1e },
330+ { CCI_REG8(0x0e17), 0x3a },
331+ { CCI_REG8(0x0e18), 0x3c },
332+ { CCI_REG8(0x0e19), 0x40 },
333+ { CCI_REG8(0x0e1a), 0x42 },
334+ { CCI_REG8(0x0e28), 0x21 },
335+ { CCI_REG8(0x0e2b), 0x68 },
336+ { CCI_REG8(0x0e2c), 0x0d },
337+ { CCI_REG8(0x0e2d), 0x08 },
338+ { CCI_REG8(0x0e34), 0xf4 },
339+ { CCI_REG8(0x0e35), 0x44 },
340+ { CCI_REG8(0x0e36), 0x07 },
341+ { CCI_REG8(0x0e38), 0x49 },
342+ { CCI_REG8(0x0210), 0x13 },
343+ { CCI_REG8(0x0218), 0x00 },
344+ { CCI_REG8(0x0241), 0x88 },
345+ { CCI_REG8(0x0e32), 0x00 },
346+ { CCI_REG8(0x0e33), 0x18 },
347+ { CCI_REG8(0x0e42), 0x03 },
348+ { CCI_REG8(0x0e43), 0x80 },
349+ { CCI_REG8(0x0e44), 0x04 },
350+ { CCI_REG8(0x0e45), 0x00 },
351+ { CCI_REG8(0x0e4f), 0x04 },
352+ { CCI_REG8(0x057a), 0x20 },
353+ { CCI_REG8(0x0381), 0x7c },
354+ { CCI_REG8(0x0382), 0x9b },
355+ { CCI_REG8(0x0384), 0xfb },
356+ { CCI_REG8(0x0389), 0x38 },
357+ { CCI_REG8(0x038a), 0x03 },
358+ { CCI_REG8(0x0390), 0x6a },
359+ { CCI_REG8(0x0391), 0x0b },
360+ { CCI_REG8(0x0392), 0x60 },
361+ { CCI_REG8(0x0393), 0xc1 },
362+ { CCI_REG8(0x0396), 0xff },
363+ { CCI_REG8(0x0398), 0x62 },
364+
365+ /* cisctl reset */
366+ { CCI_REG8(0x031c), 0x80 },
367+ { CCI_REG8(0x03fe), 0x10 },
368+ { CCI_REG8(0x03fe), 0x00 },
369+ { CCI_REG8(0x031c), 0x9f },
370+ { CCI_REG8(0x03fe), 0x00 },
371+ { CCI_REG8(0x03fe), 0x00 },
372+ { CCI_REG8(0x03fe), 0x00 },
373+ { CCI_REG8(0x03fe), 0x00 },
374+ { CCI_REG8(0x031c), 0x80 },
375+ { CCI_REG8(0x03fe), 0x10 },
376+ { CCI_REG8(0x03fe), 0x00 },
377+ { CCI_REG8(0x031c), 0x9f },
378+ { CCI_REG8(0x0360), 0x01 },
379+ { CCI_REG8(0x0360), 0x00 },
380+ { CCI_REG8(0x0316), 0x09 },
381+ { CCI_REG8(0x0a67), 0x80 },
382+ { CCI_REG8(0x0313), 0x00 },
383+ { CCI_REG8(0x0a53), 0x0e },
384+ { CCI_REG8(0x0a65), 0x17 },
385+ { CCI_REG8(0x0a68), 0xa1 },
386+ { CCI_REG8(0x0a58), 0x00 },
387+ { CCI_REG8(0x0ace), 0x0c },
388+ { CCI_REG8(0x00a4), 0x00 },
389+ { CCI_REG8(0x00a5), 0x01 },
390+ { CCI_REG8(0x00a7), 0x09 },
391+ { CCI_REG8(0x00a8), 0x9c },
392+ { CCI_REG8(0x00a9), 0x0c },
393+ { CCI_REG8(0x00aa), 0xd0 },
394+ { CCI_REG8(0x0a8a), 0x00 },
395+ { CCI_REG8(0x0a8b), 0xe0 },
396+ { CCI_REG8(0x0a8c), 0x13 },
397+ { CCI_REG8(0x0a8d), 0xe8 },
398+ { CCI_REG8(0x0a90), 0x0a },
399+ { CCI_REG8(0x0a91), 0x10 },
400+ { CCI_REG8(0x0a92), 0xf8 },
401+ { CCI_REG8(0x0a71), 0xf2 },
402+ { CCI_REG8(0x0a72), 0x12 },
403+ { CCI_REG8(0x0a73), 0x64 },
404+ { CCI_REG8(0x0a75), 0x41 },
405+ { CCI_REG8(0x0a70), 0x07 },
406+ { CCI_REG8(0x0313), 0x80 },
407+
408+ /* ISP */
409+ { CCI_REG8(0x00a0), 0x01 },
410+ { CCI_REG8(0x0080), 0xd2 },
411+ { CCI_REG8(0x0081), 0x3f },
412+ { CCI_REG8(0x0087), 0x51 },
413+ { CCI_REG8(0x0089), 0x03 },
414+ { CCI_REG8(0x009b), 0x40 },
415+ { CCI_REG8(0x05a0), 0x82 },
416+ { CCI_REG8(0x05ac), 0x00 },
417+ { CCI_REG8(0x05ad), 0x01 },
418+ { CCI_REG8(0x05ae), 0x00 },
419+ { CCI_REG8(0x0800), 0x0a },
420+ { CCI_REG8(0x0801), 0x14 },
421+ { CCI_REG8(0x0802), 0x28 },
422+ { CCI_REG8(0x0803), 0x34 },
423+ { CCI_REG8(0x0804), 0x0e },
424+ { CCI_REG8(0x0805), 0x33 },
425+ { CCI_REG8(0x0806), 0x03 },
426+ { CCI_REG8(0x0807), 0x8a },
427+ { CCI_REG8(0x0808), 0x50 },
428+ { CCI_REG8(0x0809), 0x00 },
429+ { CCI_REG8(0x080a), 0x34 },
430+ { CCI_REG8(0x080b), 0x03 },
431+ { CCI_REG8(0x080c), 0x26 },
432+ { CCI_REG8(0x080d), 0x03 },
433+ { CCI_REG8(0x080e), 0x18 },
434+ { CCI_REG8(0x080f), 0x03 },
435+ { CCI_REG8(0x0810), 0x10 },
436+ { CCI_REG8(0x0811), 0x03 },
437+ { CCI_REG8(0x0812), 0x00 },
438+ { CCI_REG8(0x0813), 0x00 },
439+ { CCI_REG8(0x0814), 0x01 },
440+ { CCI_REG8(0x0815), 0x00 },
441+ { CCI_REG8(0x0816), 0x01 },
442+ { CCI_REG8(0x0817), 0x00 },
443+ { CCI_REG8(0x0818), 0x00 },
444+ { CCI_REG8(0x0819), 0x0a },
445+ { CCI_REG8(0x081a), 0x01 },
446+ { CCI_REG8(0x081b), 0x6c },
447+ { CCI_REG8(0x081c), 0x00 },
448+ { CCI_REG8(0x081d), 0x0b },
449+ { CCI_REG8(0x081e), 0x02 },
450+ { CCI_REG8(0x081f), 0x00 },
451+ { CCI_REG8(0x0820), 0x00 },
452+ { CCI_REG8(0x0821), 0x0c },
453+ { CCI_REG8(0x0822), 0x02 },
454+ { CCI_REG8(0x0823), 0xd9 },
455+ { CCI_REG8(0x0824), 0x00 },
456+ { CCI_REG8(0x0825), 0x0d },
457+ { CCI_REG8(0x0826), 0x03 },
458+ { CCI_REG8(0x0827), 0xf0 },
459+ { CCI_REG8(0x0828), 0x00 },
460+ { CCI_REG8(0x0829), 0x0e },
461+ { CCI_REG8(0x082a), 0x05 },
462+ { CCI_REG8(0x082b), 0x94 },
463+ { CCI_REG8(0x082c), 0x09 },
464+ { CCI_REG8(0x082d), 0x6e },
465+ { CCI_REG8(0x082e), 0x07 },
466+ { CCI_REG8(0x082f), 0xe6 },
467+ { CCI_REG8(0x0830), 0x10 },
468+ { CCI_REG8(0x0831), 0x0e },
469+ { CCI_REG8(0x0832), 0x0b },
470+ { CCI_REG8(0x0833), 0x2c },
471+ { CCI_REG8(0x0834), 0x14 },
472+ { CCI_REG8(0x0835), 0xae },
473+ { CCI_REG8(0x0836), 0x0f },
474+ { CCI_REG8(0x0837), 0xc4 },
475+ { CCI_REG8(0x0838), 0x18 },
476+ { CCI_REG8(0x0839), 0x0e },
477+ { CCI_REG8(0x05ac), 0x01 },
478+ { CCI_REG8(0x059a), 0x00 },
479+ { CCI_REG8(0x059b), 0x00 },
480+ { CCI_REG8(0x059c), 0x01 },
481+ { CCI_REG8(0x0598), 0x00 },
482+ { CCI_REG8(0x0597), 0x14 },
483+ { CCI_REG8(0x05ab), 0x09 },
484+ { CCI_REG8(0x05a4), 0x02 },
485+ { CCI_REG8(0x05a3), 0x05 },
486+ { CCI_REG8(0x05a0), 0xc2 },
487+ { CCI_REG8(0x0207), 0xc4 },
488+
489+ /* GAIN */
490+ { CCI_REG8(0x0208), 0x01 },
491+ { CCI_REG8(0x0209), 0x72 },
492+ { CCI_REG8(0x0204), 0x04 },
493+ { CCI_REG8(0x0205), 0x00 },
494+
495+ { CCI_REG8(0x0040), 0x22 },
496+ { CCI_REG8(0x0041), 0x20 },
497+ { CCI_REG8(0x0043), 0x10 },
498+ { CCI_REG8(0x0044), 0x00 },
499+ { CCI_REG8(0x0046), 0x08 },
500+ { CCI_REG8(0x0047), 0xf0 },
501+ { CCI_REG8(0x0048), 0x0f },
502+ { CCI_REG8(0x004b), 0x0f },
503+ { CCI_REG8(0x004c), 0x00 },
504+ { CCI_REG8(0x0050), 0x5c },
505+ { CCI_REG8(0x0051), 0x44 },
506+ { CCI_REG8(0x005b), 0x03 },
507+ { CCI_REG8(0x00c0), 0x00 },
508+ { CCI_REG8(0x00c1), 0x80 },
509+ { CCI_REG8(0x00c2), 0x31 },
510+ { CCI_REG8(0x00c3), 0x00 },
511+ { CCI_REG8(0x0460), 0x04 },
512+ { CCI_REG8(0x0462), 0x08 },
513+ { CCI_REG8(0x0464), 0x0e },
514+ { CCI_REG8(0x0466), 0x0a },
515+ { CCI_REG8(0x0468), 0x12 },
516+ { CCI_REG8(0x046a), 0x12 },
517+ { CCI_REG8(0x046c), 0x10 },
518+ { CCI_REG8(0x046e), 0x0c },
519+ { CCI_REG8(0x0461), 0x03 },
520+ { CCI_REG8(0x0463), 0x03 },
521+ { CCI_REG8(0x0465), 0x03 },
522+ { CCI_REG8(0x0467), 0x03 },
523+ { CCI_REG8(0x0469), 0x04 },
524+ { CCI_REG8(0x046b), 0x04 },
525+ { CCI_REG8(0x046d), 0x04 },
526+ { CCI_REG8(0x046f), 0x04 },
527+ { CCI_REG8(0x0470), 0x04 },
528+ { CCI_REG8(0x0472), 0x10 },
529+ { CCI_REG8(0x0474), 0x26 },
530+ { CCI_REG8(0x0476), 0x38 },
531+ { CCI_REG8(0x0478), 0x20 },
532+ { CCI_REG8(0x047a), 0x30 },
533+ { CCI_REG8(0x047c), 0x38 },
534+ { CCI_REG8(0x047e), 0x60 },
535+ { CCI_REG8(0x0471), 0x05 },
536+ { CCI_REG8(0x0473), 0x05 },
537+ { CCI_REG8(0x0475), 0x05 },
538+ { CCI_REG8(0x0477), 0x05 },
539+ { CCI_REG8(0x0479), 0x04 },
540+ { CCI_REG8(0x047b), 0x04 },
541+ { CCI_REG8(0x047d), 0x04 },
542+ { CCI_REG8(0x047f), 0x04 },
543+};
544+
545+struct gc08a3_mode {
546+ u32 width;
547+ u32 height;
548+ const struct gc08a3_reg_list reg_list;
549+
550+ u32 hts; /* Horizontal timining size */
551+ u32 vts_def; /* Default vertical timining size */
552+ u32 vts_min; /* Min vertical timining size */
553+};
554+
555+/* Declare modes in order, from biggest to smallest height. */
556+static const struct gc08a3_mode gc08a3_modes[] = {
557+ {
558+ /* 3264*2448@30fps */
559+ .width = GC08A3_NATIVE_WIDTH,
560+ .height = GC08A3_NATIVE_HEIGHT,
561+ .reg_list = {
562+ .num_of_regs = ARRAY_SIZE(mode_3264x2448),
563+ .regs = mode_3264x2448,
564+ },
565+ .hts = 3640,
566+ .vts_def = 2548,
567+ .vts_min = 2548,
568+ },
569+ {
570+ /* 1920*1080@60fps */
571+ .width = 1920,
572+ .height = 1080,
573+ .reg_list = {
574+ .num_of_regs = ARRAY_SIZE(mode_1920x1080),
575+ .regs = mode_1920x1080,
576+ },
577+ .hts = 3640,
578+ .vts_def = 1276,
579+ .vts_min = 1276,
580+ },
581+};
582+
583+static inline struct gc08a3 *to_gc08a3(struct v4l2_subdev *sd)
584+{
585+ return container_of(sd, struct gc08a3, sd);
586+}
587+
588+static int gc08a3_power_on(struct device *dev)
589+{
590+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
591+ struct gc08a3 *gc08a3 = to_gc08a3(sd);
592+ int ret;
593+
594+ ret = regulator_bulk_enable(ARRAY_SIZE(gc08a3_supply_name),
595+ gc08a3->supplies);
596+ if (ret < 0) {
597+ dev_err(gc08a3->dev, "failed to enable regulators: %d\n", ret);
598+ return ret;
599+ }
600+
601+ ret = clk_prepare_enable(gc08a3->xclk);
602+ if (ret < 0) {
603+ regulator_bulk_disable(ARRAY_SIZE(gc08a3_supply_name),
604+ gc08a3->supplies);
605+ dev_err(gc08a3->dev, "clk prepare enable failed\n");
606+ return ret;
607+ }
608+
609+ fsleep(GC08A3_SLEEP_US);
610+
611+ gpiod_set_value_cansleep(gc08a3->reset_gpio, 0);
612+ fsleep(GC08A3_SLEEP_US);
613+
614+ return 0;
615+}
616+
617+static int gc08a3_power_off(struct device *dev)
618+{
619+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
620+ struct gc08a3 *gc08a3 = to_gc08a3(sd);
621+
622+ clk_disable_unprepare(gc08a3->xclk);
623+ gpiod_set_value_cansleep(gc08a3->reset_gpio, 1);
624+ regulator_bulk_disable(ARRAY_SIZE(gc08a3_supply_name),
625+ gc08a3->supplies);
626+
627+ return 0;
628+}
629+
630+static int gc08a3_enum_mbus_code(struct v4l2_subdev *sd,
631+ struct v4l2_subdev_state *sd_state,
632+ struct v4l2_subdev_mbus_code_enum *code)
633+{
634+ if (code->index > 0)
635+ return -EINVAL;
636+
637+ code->code = GC08A3_MBUS_CODE;
638+
639+ return 0;
640+}
641+
642+static int gc08a3_enum_frame_size(struct v4l2_subdev *subdev,
643+ struct v4l2_subdev_state *sd_state,
644+ struct v4l2_subdev_frame_size_enum *fse)
645+{
646+ if (fse->code != GC08A3_MBUS_CODE)
647+ return -EINVAL;
648+
649+ if (fse->index >= ARRAY_SIZE(gc08a3_modes))
650+ return -EINVAL;
651+
652+ fse->min_width = gc08a3_modes[fse->index].width;
653+ fse->max_width = gc08a3_modes[fse->index].width;
654+ fse->min_height = gc08a3_modes[fse->index].height;
655+ fse->max_height = gc08a3_modes[fse->index].height;
656+
657+ return 0;
658+}
659+
660+static int gc08a3_update_cur_mode_controls(struct gc08a3 *gc08a3,
661+ const struct gc08a3_mode *mode)
662+{
663+ s64 exposure_max, h_blank;
664+ int ret;
665+
666+ ret = __v4l2_ctrl_modify_range(gc08a3->vblank,
667+ mode->vts_min - mode->height,
668+ GC08A3_VTS_MAX - mode->height, 1,
669+ mode->vts_def - mode->height);
670+ if (ret) {
671+ dev_err(gc08a3->dev, "VB ctrl range update failed\n");
672+ return ret;
673+ }
674+
675+ h_blank = mode->hts - mode->width;
676+ ret = __v4l2_ctrl_modify_range(gc08a3->hblank, h_blank, h_blank, 1,
677+ h_blank);
678+ if (ret) {
679+ dev_err(gc08a3->dev, "HB ctrl range update failed\n");
680+ return ret;
681+ }
682+
683+ exposure_max = mode->vts_def - GC08A3_EXP_MARGIN;
684+ ret = __v4l2_ctrl_modify_range(gc08a3->exposure, GC08A3_EXP_MIN,
685+ exposure_max, GC08A3_EXP_STEP,
686+ exposure_max);
687+ if (ret) {
688+ dev_err(gc08a3->dev, "exposure ctrl range update failed\n");
689+ return ret;
690+ }
691+
692+ return 0;
693+}
694+
695+static void gc08a3_update_pad_format(struct gc08a3 *gc08a3,
696+ const struct gc08a3_mode *mode,
697+ struct v4l2_mbus_framefmt *fmt)
698+{
699+ fmt->width = mode->width;
700+ fmt->height = mode->height;
701+ fmt->code = GC08A3_MBUS_CODE;
702+ fmt->field = V4L2_FIELD_NONE;
703+ fmt->colorspace = V4L2_COLORSPACE_RAW;
704+ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
705+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
706+ fmt->xfer_func = V4L2_XFER_FUNC_NONE;
707+}
708+
709+static int gc08a3_set_format(struct v4l2_subdev *sd,
710+ struct v4l2_subdev_state *state,
711+ struct v4l2_subdev_format *fmt)
712+{
713+ struct gc08a3 *gc08a3 = to_gc08a3(sd);
714+ struct v4l2_mbus_framefmt *mbus_fmt;
715+ struct v4l2_rect *crop;
716+ const struct gc08a3_mode *mode;
717+
718+ mode = v4l2_find_nearest_size(gc08a3_modes, ARRAY_SIZE(gc08a3_modes),
719+ width, height, fmt->format.width,
720+ fmt->format.height);
721+
722+ /* update crop info to subdev state */
723+ crop = v4l2_subdev_state_get_crop(state, 0);
724+ crop->width = mode->width;
725+ crop->height = mode->height;
726+
727+ /* update fmt info to subdev state */
728+ gc08a3_update_pad_format(gc08a3, mode, &fmt->format);
729+ mbus_fmt = v4l2_subdev_state_get_format(state, 0);
730+ *mbus_fmt = fmt->format;
731+
732+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
733+ return 0;
734+
735+ gc08a3->cur_mode = mode;
736+ gc08a3_update_cur_mode_controls(gc08a3, mode);
737+
738+ return 0;
739+}
740+
741+static int gc08a3_get_selection(struct v4l2_subdev *sd,
742+ struct v4l2_subdev_state *state,
743+ struct v4l2_subdev_selection *sel)
744+{
745+ switch (sel->target) {
746+ case V4L2_SEL_TGT_CROP_DEFAULT:
747+ case V4L2_SEL_TGT_CROP:
748+ sel->r = *v4l2_subdev_state_get_crop(state, 0);
749+ break;
750+ case V4L2_SEL_TGT_CROP_BOUNDS:
751+ sel->r.top = 0;
752+ sel->r.left = 0;
753+ sel->r.width = GC08A3_NATIVE_WIDTH;
754+ sel->r.height = GC08A3_NATIVE_HEIGHT;
755+ break;
756+ default:
757+ return -EINVAL;
758+ }
759+
760+ return 0;
761+}
762+
763+static int gc08a3_init_state(struct v4l2_subdev *sd,
764+ struct v4l2_subdev_state *state)
765+{
766+ struct v4l2_subdev_format fmt = {
767+ .which = V4L2_SUBDEV_FORMAT_TRY,
768+ .pad = 0,
769+ .format = {
770+ .code = GC08A3_MBUS_CODE,
771+ .width = gc08a3_modes[0].width,
772+ .height = gc08a3_modes[0].height,
773+ },
774+ };
775+
776+ gc08a3_set_format(sd, state, &fmt);
777+
778+ return 0;
779+}
780+
781+static int gc08a3_set_ctrl_hflip(struct gc08a3 *gc08a3, u32 ctrl_val)
782+{
783+ int ret;
784+ u64 val;
785+
786+ ret = cci_read(gc08a3->regmap, GC08A3_FLIP_REG, &val, NULL);
787+ if (ret) {
788+ dev_err(gc08a3->dev, "read hflip register failed: %d\n", ret);
789+ return ret;
790+ }
791+
792+ return cci_update_bits(gc08a3->regmap, GC08A3_FLIP_REG,
793+ GC08A3_FLIP_H_MASK,
794+ ctrl_val ? GC08A3_FLIP_H_MASK : 0, NULL);
795+}
796+
797+static int gc08a3_set_ctrl_vflip(struct gc08a3 *gc08a3, u32 ctrl_val)
798+{
799+ int ret;
800+ u64 val;
801+
802+ ret = cci_read(gc08a3->regmap, GC08A3_FLIP_REG, &val, NULL);
803+ if (ret) {
804+ dev_err(gc08a3->dev, "read vflip register failed: %d\n", ret);
805+ return ret;
806+ }
807+
808+ return cci_update_bits(gc08a3->regmap, GC08A3_FLIP_REG,
809+ GC08A3_FLIP_V_MASK,
810+ ctrl_val ? GC08A3_FLIP_V_MASK : 0, NULL);
811+}
812+
813+static int gc08a3_test_pattern(struct gc08a3 *gc08a3, u32 pattern_menu)
814+{
815+ u32 pattern;
816+ int ret;
817+
818+ if (pattern_menu) {
819+ switch (pattern_menu) {
820+ case 1:
821+ pattern = 0x00;
822+ break;
823+ case 2:
824+ pattern = 0x10;
825+ break;
826+ case 3:
827+ case 4:
828+ case 5:
829+ case 6:
830+ case 7:
831+ pattern = pattern_menu + 1;
832+ break;
833+ default:
834+ pattern = 0x00;
835+ break;
836+ }
837+
838+ ret = cci_write(gc08a3->regmap, GC08A3_REG_TEST_PATTERN_IDX,
839+ pattern, NULL);
840+ if (ret)
841+ return ret;
842+
843+ return cci_write(gc08a3->regmap, GC08A3_REG_TEST_PATTERN_EN,
844+ GC08A3_TEST_PATTERN_EN, NULL);
845+ } else {
846+ return cci_write(gc08a3->regmap, GC08A3_REG_TEST_PATTERN_EN,
847+ 0x00, NULL);
848+ }
849+}
850+
851+static int gc08a3_set_ctrl(struct v4l2_ctrl *ctrl)
852+{
853+ struct gc08a3 *gc08a3 =
854+ container_of(ctrl->handler, struct gc08a3, ctrls);
855+ int ret = 0;
856+ s64 exposure_max;
857+ struct v4l2_subdev_state *state;
858+ const struct v4l2_mbus_framefmt *format;
859+
860+ state = v4l2_subdev_get_locked_active_state(&gc08a3->sd);
861+ format = v4l2_subdev_state_get_format(state, 0);
862+
863+ if (ctrl->id == V4L2_CID_VBLANK) {
864+ /* Update max exposure while meeting expected vblanking */
865+ exposure_max = format->height + ctrl->val - GC08A3_EXP_MARGIN;
866+ __v4l2_ctrl_modify_range(gc08a3->exposure,
867+ gc08a3->exposure->minimum,
868+ exposure_max, gc08a3->exposure->step,
869+ exposure_max);
870+ }
871+
872+ /*
873+ * Applying V4L2 control value only happens
874+ * when power is on for streaming.
875+ */
876+ if (!pm_runtime_get_if_active(gc08a3->dev))
877+ return 0;
878+
879+ switch (ctrl->id) {
880+ case V4L2_CID_EXPOSURE:
881+ ret = cci_write(gc08a3->regmap, GC08A3_EXP_REG,
882+ ctrl->val, NULL);
883+ break;
884+
885+ case V4L2_CID_ANALOGUE_GAIN:
886+ ret = cci_write(gc08a3->regmap, GC08A3_AGAIN_REG,
887+ ctrl->val, NULL);
888+ break;
889+
890+ case V4L2_CID_VBLANK:
891+ ret = cci_write(gc08a3->regmap, GC08A3_FRAME_LENGTH_REG,
892+ gc08a3->cur_mode->height + ctrl->val, NULL);
893+ break;
894+
895+ case V4L2_CID_HFLIP:
896+ ret = gc08a3_set_ctrl_hflip(gc08a3, ctrl->val);
897+ break;
898+
899+ case V4L2_CID_VFLIP:
900+ ret = gc08a3_set_ctrl_vflip(gc08a3, ctrl->val);
901+ break;
902+
903+ case V4L2_CID_TEST_PATTERN:
904+ ret = gc08a3_test_pattern(gc08a3, ctrl->val);
905+ break;
906+
907+ default:
908+ break;
909+ }
910+
911+ pm_runtime_put(gc08a3->dev);
912+
913+ return ret;
914+}
915+
916+static const struct v4l2_ctrl_ops gc08a3_ctrl_ops = {
917+ .s_ctrl = gc08a3_set_ctrl,
918+};
919+
920+static int gc08a3_start_streaming(struct gc08a3 *gc08a3)
921+{
922+ const struct gc08a3_mode *mode;
923+ const struct gc08a3_reg_list *reg_list;
924+ int ret;
925+
926+ ret = pm_runtime_resume_and_get(gc08a3->dev);
927+ if (ret < 0)
928+ return ret;
929+
930+ ret = cci_multi_reg_write(gc08a3->regmap,
931+ mode_table_common,
932+ ARRAY_SIZE(mode_table_common), NULL);
933+ if (ret)
934+ goto err_rpm_put;
935+
936+ mode = gc08a3->cur_mode;
937+ reg_list = &mode->reg_list;
938+ ret = cci_multi_reg_write(gc08a3->regmap,
939+ reg_list->regs, reg_list->num_of_regs, NULL);
940+ if (ret < 0)
941+ goto err_rpm_put;
942+
943+ ret = __v4l2_ctrl_handler_setup(&gc08a3->ctrls);
944+ if (ret < 0) {
945+ dev_err(gc08a3->dev, "could not sync v4l2 controls\n");
946+ goto err_rpm_put;
947+ }
948+
949+ ret = cci_write(gc08a3->regmap, GC08A3_STREAMING_REG, 1, NULL);
950+ if (ret < 0) {
951+ dev_err(gc08a3->dev, "write STRAEMING_REG failed: %d\n", ret);
952+ goto err_rpm_put;
953+ }
954+
955+ return 0;
956+
957+err_rpm_put:
958+ pm_runtime_put(gc08a3->dev);
959+ return ret;
960+}
961+
962+static int gc08a3_stop_streaming(struct gc08a3 *gc08a3)
963+{
964+ int ret;
965+
966+ ret = cci_write(gc08a3->regmap, GC08A3_STREAMING_REG, 0, NULL);
967+ if (ret < 0)
968+ dev_err(gc08a3->dev, "could not sent stop streaming %d\n", ret);
969+
970+ pm_runtime_put(gc08a3->dev);
971+ return ret;
972+}
973+
974+static int gc08a3_s_stream(struct v4l2_subdev *subdev, int enable)
975+{
976+ struct gc08a3 *gc08a3 = to_gc08a3(subdev);
977+ struct v4l2_subdev_state *state;
978+ int ret;
979+
980+ state = v4l2_subdev_lock_and_get_active_state(subdev);
981+
982+ if (enable)
983+ ret = gc08a3_start_streaming(gc08a3);
984+ else
985+ ret = gc08a3_stop_streaming(gc08a3);
986+
987+ v4l2_subdev_unlock_state(state);
988+
989+ return ret;
990+}
991+
992+static const struct v4l2_subdev_video_ops gc08a3_video_ops = {
993+ .s_stream = gc08a3_s_stream,
994+};
995+
996+static const struct v4l2_subdev_pad_ops gc08a3_subdev_pad_ops = {
997+ .enum_mbus_code = gc08a3_enum_mbus_code,
998+ .enum_frame_size = gc08a3_enum_frame_size,
999+ .get_fmt = v4l2_subdev_get_fmt,
1000+ .set_fmt = gc08a3_set_format,
1001+ .get_selection = gc08a3_get_selection,
1002+};
1003+
1004+static const struct v4l2_subdev_core_ops gc08a3_core_ops = {
1005+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
1006+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
1007+};
1008+
1009+static const struct v4l2_subdev_ops gc08a3_subdev_ops = {
1010+ .core = &gc08a3_core_ops,
1011+ .video = &gc08a3_video_ops,
1012+ .pad = &gc08a3_subdev_pad_ops,
1013+};
1014+
1015+static const struct v4l2_subdev_internal_ops gc08a3_internal_ops = {
1016+ .init_state = gc08a3_init_state,
1017+};
1018+
1019+static int gc08a3_get_regulators(struct device *dev, struct gc08a3 *gc08a3)
1020+{
1021+ unsigned int i;
1022+
1023+ for (i = 0; i < ARRAY_SIZE(gc08a3_supply_name); i++)
1024+ gc08a3->supplies[i].supply = gc08a3_supply_name[i];
1025+
1026+ return devm_regulator_bulk_get(dev, ARRAY_SIZE(gc08a3_supply_name),
1027+ gc08a3->supplies);
1028+}
1029+
1030+static int gc08a3_parse_fwnode(struct gc08a3 *gc08a3)
1031+{
1032+ struct fwnode_handle *endpoint;
1033+ struct v4l2_fwnode_endpoint bus_cfg = {
1034+ .bus_type = V4L2_MBUS_CSI2_DPHY,
1035+ };
1036+ int ret;
1037+ struct device *dev = gc08a3->dev;
1038+
1039+ endpoint =
1040+ fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0,
1041+ FWNODE_GRAPH_ENDPOINT_NEXT);
1042+ if (!endpoint) {
1043+ dev_err(dev, "endpoint node not found\n");
1044+ return -EINVAL;
1045+ }
1046+
1047+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &bus_cfg);
1048+ if (ret) {
1049+ dev_err(dev, "parsing endpoint node failed\n");
1050+ goto done;
1051+ }
1052+
1053+ ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies,
1054+ bus_cfg.nr_of_link_frequencies,
1055+ gc08a3_link_freq_menu_items,
1056+ ARRAY_SIZE(gc08a3_link_freq_menu_items),
1057+ &gc08a3->link_freq_bitmap);
1058+ if (ret)
1059+ goto done;
1060+
1061+done:
1062+ v4l2_fwnode_endpoint_free(&bus_cfg);
1063+ fwnode_handle_put(endpoint);
1064+ return ret;
1065+}
1066+
1067+static u64 gc08a3_to_pixel_rate(u32 f_index)
1068+{
1069+ u64 pixel_rate =
1070+ gc08a3_link_freq_menu_items[f_index] * 2 * GC08A3_DATA_LANES;
1071+
1072+ return div_u64(pixel_rate, GC08A3_RGB_DEPTH);
1073+}
1074+
1075+static int gc08a3_init_controls(struct gc08a3 *gc08a3)
1076+{
1077+ struct i2c_client *client = v4l2_get_subdevdata(&gc08a3->sd);
1078+ const struct gc08a3_mode *mode = &gc08a3_modes[0];
1079+ const struct v4l2_ctrl_ops *ops = &gc08a3_ctrl_ops;
1080+ struct v4l2_fwnode_device_properties props;
1081+ struct v4l2_ctrl_handler *ctrl_hdlr;
1082+ s64 exposure_max, h_blank;
1083+ int ret;
1084+
1085+ ctrl_hdlr = &gc08a3->ctrls;
1086+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 9);
1087+ if (ret)
1088+ return ret;
1089+
1090+ gc08a3->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &gc08a3_ctrl_ops,
1091+ V4L2_CID_HFLIP, 0, 1, 1, 0);
1092+ gc08a3->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &gc08a3_ctrl_ops,
1093+ V4L2_CID_VFLIP, 0, 1, 1, 0);
1094+ v4l2_ctrl_cluster(2, &gc08a3->hflip);
1095+
1096+ gc08a3->link_freq =
1097+ v4l2_ctrl_new_int_menu(ctrl_hdlr,
1098+ &gc08a3_ctrl_ops,
1099+ V4L2_CID_LINK_FREQ,
1100+ ARRAY_SIZE(gc08a3_link_freq_menu_items) - 1,
1101+ 0,
1102+ gc08a3_link_freq_menu_items);
1103+ if (gc08a3->link_freq)
1104+ gc08a3->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1105+
1106+ gc08a3->pixel_rate =
1107+ v4l2_ctrl_new_std(ctrl_hdlr,
1108+ &gc08a3_ctrl_ops,
1109+ V4L2_CID_PIXEL_RATE, 0,
1110+ gc08a3_to_pixel_rate(0),
1111+ 1,
1112+ gc08a3_to_pixel_rate(0));
1113+
1114+ gc08a3->vblank =
1115+ v4l2_ctrl_new_std(ctrl_hdlr,
1116+ &gc08a3_ctrl_ops, V4L2_CID_VBLANK,
1117+ mode->vts_min - mode->height,
1118+ GC08A3_VTS_MAX - mode->height, 1,
1119+ mode->vts_def - mode->height);
1120+
1121+ h_blank = mode->hts - mode->width;
1122+ gc08a3->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &gc08a3_ctrl_ops,
1123+ V4L2_CID_HBLANK, h_blank, h_blank, 1,
1124+ h_blank);
1125+ if (gc08a3->hblank)
1126+ gc08a3->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1127+
1128+ v4l2_ctrl_new_std(ctrl_hdlr, &gc08a3_ctrl_ops,
1129+ V4L2_CID_ANALOGUE_GAIN, GC08A3_AGAIN_MIN,
1130+ GC08A3_AGAIN_MAX, GC08A3_AGAIN_STEP,
1131+ GC08A3_AGAIN_MIN);
1132+
1133+ exposure_max = mode->vts_def - GC08A3_EXP_MARGIN;
1134+ gc08a3->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &gc08a3_ctrl_ops,
1135+ V4L2_CID_EXPOSURE, GC08A3_EXP_MIN,
1136+ exposure_max, GC08A3_EXP_STEP,
1137+ exposure_max);
1138+
1139+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &gc08a3_ctrl_ops,
1140+ V4L2_CID_TEST_PATTERN,
1141+ ARRAY_SIZE(gc08a3_test_pattern_menu) - 1,
1142+ 0, 0, gc08a3_test_pattern_menu);
1143+
1144+ /* register properties to fwnode (e.g. rotation, orientation) */
1145+ ret = v4l2_fwnode_device_parse(&client->dev, &props);
1146+ if (ret)
1147+ goto error_ctrls;
1148+
1149+ ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, ops, &props);
1150+ if (ret)
1151+ goto error_ctrls;
1152+
1153+ if (ctrl_hdlr->error) {
1154+ ret = ctrl_hdlr->error;
1155+ goto error_ctrls;
1156+ }
1157+
1158+ gc08a3->sd.ctrl_handler = ctrl_hdlr;
1159+
1160+ return 0;
1161+
1162+error_ctrls:
1163+ v4l2_ctrl_handler_free(ctrl_hdlr);
1164+
1165+ return ret;
1166+}
1167+
1168+static int gc08a3_identify_module(struct gc08a3 *gc08a3)
1169+{
1170+ u64 val;
1171+ int ret;
1172+
1173+ ret = cci_read(gc08a3->regmap, GC08A3_REG_CHIP_ID, &val, NULL);
1174+ if (ret) {
1175+ dev_err(gc08a3->dev, "failed to read chip id");
1176+ return ret;
1177+ }
1178+
1179+ if (val != GC08A3_CHIP_ID) {
1180+ dev_err(gc08a3->dev, "chip id mismatch: 0x%x!=0x%llx",
1181+ GC08A3_CHIP_ID, val);
1182+ return -ENXIO;
1183+ }
1184+
1185+ return 0;
1186+}
1187+
1188+static int gc08a3_probe(struct i2c_client *client)
1189+{
1190+ struct device *dev = &client->dev;
1191+ struct gc08a3 *gc08a3;
1192+ int ret;
1193+
1194+ gc08a3 = devm_kzalloc(dev, sizeof(*gc08a3), GFP_KERNEL);
1195+ if (!gc08a3)
1196+ return -ENOMEM;
1197+
1198+ gc08a3->dev = dev;
1199+
1200+ ret = gc08a3_parse_fwnode(gc08a3);
1201+ if (ret)
1202+ return ret;
1203+
1204+ gc08a3->regmap = devm_cci_regmap_init_i2c(client, 16);
1205+ if (IS_ERR(gc08a3->regmap))
1206+ return dev_err_probe(dev, PTR_ERR(gc08a3->regmap),
1207+ "failed to init CCI\n");
1208+
1209+ gc08a3->xclk = devm_clk_get(dev, NULL);
1210+ if (IS_ERR(gc08a3->xclk))
1211+ return dev_err_probe(dev, PTR_ERR(gc08a3->xclk),
1212+ "failed to get xclk\n");
1213+
1214+ ret = clk_set_rate(gc08a3->xclk, GC08A3_DEFAULT_CLK_FREQ);
1215+ if (ret)
1216+ return dev_err_probe(dev, ret,
1217+ "failed to set xclk frequency\n");
1218+
1219+ ret = gc08a3_get_regulators(dev, gc08a3);
1220+ if (ret < 0)
1221+ return dev_err_probe(dev, ret,
1222+ "failed to get regulators\n");
1223+
1224+ gc08a3->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
1225+ if (IS_ERR(gc08a3->reset_gpio))
1226+ return dev_err_probe(dev, PTR_ERR(gc08a3->reset_gpio),
1227+ "failed to get gpio\n");
1228+
1229+ v4l2_i2c_subdev_init(&gc08a3->sd, client, &gc08a3_subdev_ops);
1230+ gc08a3->sd.internal_ops = &gc08a3_internal_ops;
1231+ gc08a3->cur_mode = &gc08a3_modes[0];
1232+
1233+ ret = gc08a3_power_on(gc08a3->dev);
1234+ if (ret)
1235+ return dev_err_probe(dev, ret,
1236+ "failed to sensor power on\n");
1237+
1238+ ret = gc08a3_identify_module(gc08a3);
1239+ if (ret) {
1240+ dev_err(&client->dev, "failed to find sensor: %d\n", ret);
1241+ goto err_power_off;
1242+ }
1243+
1244+ ret = gc08a3_init_controls(gc08a3);
1245+ if (ret) {
1246+ dev_err(&client->dev, "failed to init controls: %d", ret);
1247+ goto err_power_off;
1248+ }
1249+
1250+ gc08a3->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
1251+ V4L2_SUBDEV_FL_HAS_EVENTS;
1252+ gc08a3->pad.flags = MEDIA_PAD_FL_SOURCE;
1253+ gc08a3->sd.dev = &client->dev;
1254+ gc08a3->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1255+
1256+ ret = media_entity_pads_init(&gc08a3->sd.entity, 1, &gc08a3->pad);
1257+ if (ret < 0) {
1258+ dev_err(dev, "could not register media entity\n");
1259+ goto err_v4l2_ctrl_handler_free;
1260+ }
1261+
1262+ gc08a3->sd.state_lock = gc08a3->ctrls.lock;
1263+ ret = v4l2_subdev_init_finalize(&gc08a3->sd);
1264+ if (ret < 0) {
1265+ dev_err(dev, "v4l2 subdev init error: %d\n", ret);
1266+ goto err_media_entity_cleanup;
1267+ }
1268+
1269+ pm_runtime_set_active(gc08a3->dev);
1270+ pm_runtime_enable(gc08a3->dev);
1271+ pm_runtime_set_autosuspend_delay(gc08a3->dev, 1000);
1272+ pm_runtime_use_autosuspend(gc08a3->dev);
1273+ pm_runtime_idle(gc08a3->dev);
1274+
1275+ ret = v4l2_async_register_subdev_sensor(&gc08a3->sd);
1276+ if (ret < 0) {
1277+ dev_err(dev, "could not register v4l2 device\n");
1278+ goto err_rpm;
1279+ }
1280+
1281+ return 0;
1282+
1283+err_rpm:
1284+ pm_runtime_disable(gc08a3->dev);
1285+ v4l2_subdev_cleanup(&gc08a3->sd);
1286+
1287+err_media_entity_cleanup:
1288+ media_entity_cleanup(&gc08a3->sd.entity);
1289+
1290+err_v4l2_ctrl_handler_free:
1291+ v4l2_ctrl_handler_free(gc08a3->sd.ctrl_handler);
1292+
1293+err_power_off:
1294+ gc08a3_power_off(gc08a3->dev);
1295+
1296+ return ret;
1297+}
1298+
1299+static void gc08a3_remove(struct i2c_client *client)
1300+{
1301+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
1302+ struct gc08a3 *gc08a3 = to_gc08a3(sd);
1303+
1304+ v4l2_async_unregister_subdev(&gc08a3->sd);
1305+ v4l2_subdev_cleanup(sd);
1306+ media_entity_cleanup(&gc08a3->sd.entity);
1307+ v4l2_ctrl_handler_free(&gc08a3->ctrls);
1308+
1309+ pm_runtime_disable(&client->dev);
1310+ if (!pm_runtime_status_suspended(&client->dev))
1311+ gc08a3_power_off(gc08a3->dev);
1312+ pm_runtime_set_suspended(&client->dev);
1313+}
1314+
1315+static const struct of_device_id gc08a3_of_match[] = {
1316+ { .compatible = "galaxycore,gc08a3" },
1317+ {}
1318+};
1319+MODULE_DEVICE_TABLE(of, gc08a3_of_match);
1320+
1321+static DEFINE_RUNTIME_DEV_PM_OPS(gc08a3_pm_ops,
1322+ gc08a3_power_off,
1323+ gc08a3_power_on,
1324+ NULL);
1325+
1326+static struct i2c_driver gc08a3_i2c_driver = {
1327+ .driver = {
1328+ .of_match_table = gc08a3_of_match,
1329+ .pm = pm_ptr(&gc08a3_pm_ops),
1330+ .name = "gc08a3",
1331+ },
1332+ .probe = gc08a3_probe,
1333+ .remove = gc08a3_remove,
1334+};
1335+module_i2c_driver(gc08a3_i2c_driver);
1336+
1337+MODULE_DESCRIPTION("GalaxyCore gc08a3 Camera driver");
1338+MODULE_AUTHOR("Zhi Mao <zhi.mao@mediatek.com>");
1339+MODULE_LICENSE("GPL");
drivers/media/i2c/gc2145.c+72−18
@@ -68,8 +68,7 @@ · 67 unmodified lines
6868 #define GC2145_DPHY_CLK_DELAY BIT(4)
6969 #define GC2145_DPHY_LANE0_DELAY BIT(5)
7070 #define GC2145_DPHY_LANE1_DELAY BIT(6)
71−#define GC2145_REG_FIFO_FULL_LVL_LOW CCI_REG8(0x04)
72−#define GC2145_REG_FIFO_FULL_LVL_HIGH CCI_REG8(0x05)
71+#define GC2145_REG_FIFO_FULL_LVL CCI_REG16_LE(0x04)
7372 #define GC2145_REG_FIFO_MODE CCI_REG8(0x06)
7473 #define GC2145_FIFO_MODE_READ_GATE BIT(3)
7574 #define GC2145_FIFO_MODE_MIPI_CLK_MODULE BIT(7)
@@ -79,8 +78,7 @@ · 3 unmodified lines
7978 #define GC2145_CSI2_MODE_MIPI_EN BIT(4)
8079 #define GC2145_CSI2_MODE_EN BIT(7)
8180 #define GC2145_REG_MIPI_DT CCI_REG8(0x11)
82−#define GC2145_REG_LWC_LOW CCI_REG8(0x12)
83−#define GC2145_REG_LWC_HIGH CCI_REG8(0x13)
81+#define GC2145_REG_LWC CCI_REG16_LE(0x12)
8482 #define GC2145_REG_DPHY_MODE CCI_REG8(0x15)
8583 #define GC2145_DPHY_MODE_TRIGGER_PROG BIT(4)
8684 #define GC2145_REG_FIFO_GATE_MODE CCI_REG8(0x17)
@@ -542,45 +540,82 @@ static const struct gc2145_mode supported_modes[] = { · 455 unmodified lines
542540 /**
543541 * struct gc2145_format - GC2145 pixel format description
544542 * @code: media bus (MBUS) associated code
543+ * @colorspace: V4L2 colorspace
545544 * @datatype: MIPI CSI2 data type
546545 * @output_fmt: GC2145 output format
547546 * @switch_bit: GC2145 first/second switch
547+ * @row_col_switch: GC2145 switch row and/or column
548548 */
549549 struct gc2145_format {
550550 unsigned int code;
551+ unsigned int colorspace;
551552 unsigned char datatype;
552553 unsigned char output_fmt;
553554 bool switch_bit;
555+ unsigned char row_col_switch;
554556 };
555557
556558 /* All supported formats */
557559 static const struct gc2145_format supported_formats[] = {
558560 {
559561 .code = MEDIA_BUS_FMT_UYVY8_1X16,
562+ .colorspace = V4L2_COLORSPACE_SRGB,
560563 .datatype = MIPI_CSI2_DT_YUV422_8B,
561564 .output_fmt = 0x00,
562565 },
563566 {
564567 .code = MEDIA_BUS_FMT_VYUY8_1X16,
568+ .colorspace = V4L2_COLORSPACE_SRGB,
565569 .datatype = MIPI_CSI2_DT_YUV422_8B,
566570 .output_fmt = 0x01,
567571 },
568572 {
569573 .code = MEDIA_BUS_FMT_YUYV8_1X16,
574+ .colorspace = V4L2_COLORSPACE_SRGB,
570575 .datatype = MIPI_CSI2_DT_YUV422_8B,
571576 .output_fmt = 0x02,
572577 },
573578 {
574579 .code = MEDIA_BUS_FMT_YVYU8_1X16,
580+ .colorspace = V4L2_COLORSPACE_SRGB,
575581 .datatype = MIPI_CSI2_DT_YUV422_8B,
576582 .output_fmt = 0x03,
577583 },
578584 {
579585 .code = MEDIA_BUS_FMT_RGB565_1X16,
586+ .colorspace = V4L2_COLORSPACE_SRGB,
580587 .datatype = MIPI_CSI2_DT_RGB565,
581588 .output_fmt = 0x06,
582589 .switch_bit = true,
583590 },
591+ {
592+ .code = MEDIA_BUS_FMT_SGRBG8_1X8,
593+ .colorspace = V4L2_COLORSPACE_RAW,
594+ .datatype = MIPI_CSI2_DT_RAW8,
595+ .output_fmt = 0x17,
596+ .row_col_switch = GC2145_SYNC_MODE_COL_SWITCH,
597+ },
598+ {
599+ .code = MEDIA_BUS_FMT_SRGGB8_1X8,
600+ .colorspace = V4L2_COLORSPACE_RAW,
601+ .datatype = MIPI_CSI2_DT_RAW8,
602+ .output_fmt = 0x17,
603+ .row_col_switch = GC2145_SYNC_MODE_COL_SWITCH | GC2145_SYNC_MODE_ROW_SWITCH,
604+ },
605+ {
606+ .code = MEDIA_BUS_FMT_SBGGR8_1X8,
607+ .colorspace = V4L2_COLORSPACE_RAW,
608+ .datatype = MIPI_CSI2_DT_RAW8,
609+ .output_fmt = 0x17,
610+ .row_col_switch = 0,
611+ },
612+ {
613+ .code = MEDIA_BUS_FMT_SGBRG8_1X8,
614+ .colorspace = V4L2_COLORSPACE_RAW,
615+ .datatype = MIPI_CSI2_DT_RAW8,
616+ .output_fmt = 0x17,
617+ .row_col_switch = GC2145_SYNC_MODE_ROW_SWITCH,
618+ },
584619 };
585620
586621 struct gc2145_ctrls {
@@ -641,7 +676,8 @@ gc2145_get_format_code(struct gc2145 *gc2145, u32 code) · 54 unmodified lines
641676
642677 static void gc2145_update_pad_format(struct gc2145 *gc2145,
643678 const struct gc2145_mode *mode,
644− struct v4l2_mbus_framefmt *fmt, u32 code)
679+ struct v4l2_mbus_framefmt *fmt, u32 code,
680+ u32 colorspace)
645681 {
646682 fmt->code = code;
647683 fmt->width = mode->width;
@@ -663,7 +699,8 @@ static int gc2145_init_state(struct v4l2_subdev *sd, · 15 unmodified lines
663699 /* Initialize pad format */
664700 format = v4l2_subdev_state_get_format(state, 0);
665701 gc2145_update_pad_format(gc2145, &supported_modes[0], format,
666− MEDIA_BUS_FMT_RGB565_1X16);
702+ MEDIA_BUS_FMT_RGB565_1X16,
703+ V4L2_COLORSPACE_SRGB);
667704
668705 /* Initialize crop rectangle. */
669706 crop = v4l2_subdev_state_get_crop(state, 0);
@@ -754,7 +791,13 @@ static int gc2145_set_pad_format(struct v4l2_subdev *sd, · 84 unmodified lines
754791 width, height,
755792 fmt->format.width, fmt->format.height);
756793
757− gc2145_update_pad_format(gc2145, mode, &fmt->format, gc2145_fmt->code);
794+ /* In RAW mode, VGA is not possible so use 720p instead */
795+ if (gc2145_fmt->colorspace == V4L2_COLORSPACE_RAW &&
796+ mode == &supported_modes[GC2145_MODE_640X480])
797+ mode = &supported_modes[GC2145_MODE_1280X720];
798+
799+ gc2145_update_pad_format(gc2145, mode, &fmt->format, gc2145_fmt->code,
800+ gc2145_fmt->colorspace);
758801 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
759802 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
760803 gc2145->mode = mode;
@@ -811,9 +854,12 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145, · 50 unmodified lines
811854 * For RAW8, LWC = image width
812855 * For RAW10, LWC = image width * 1.25
813856 */
814− lwc = gc2145->mode->width * 2;
815− cci_write(gc2145->regmap, GC2145_REG_LWC_HIGH, lwc >> 8, &ret);
816− cci_write(gc2145->regmap, GC2145_REG_LWC_LOW, lwc & 0xff, &ret);
857+ if (gc2145_format->colorspace != V4L2_COLORSPACE_RAW)
858+ lwc = gc2145->mode->width * 2;
859+ else
860+ lwc = gc2145->mode->width;
861+
862+ cci_write(gc2145->regmap, GC2145_REG_LWC, lwc, &ret);
817863
818864 /*
819865 * Adjust the MIPI FIFO Full Level
@@ -821,21 +867,25 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145, · 1 unmodified line
821867 * 1280x720 / 1600x1200 (aka no scaler) non RAW: 0x0001
822868 * 1600x1200 RAW: 0x0190
823869 */
824− if (gc2145->mode->width == 1280 || gc2145->mode->width == 1600)
825− fifo_full_lvl = 0x0001;
826− else
870+ if (gc2145_format->colorspace != V4L2_COLORSPACE_RAW) {
871+ if (gc2145->mode->width == 1280 || gc2145->mode->width == 1600)
872+ fifo_full_lvl = 0x0001;
873+ else
874+ fifo_full_lvl = 0x0190;
875+ } else {
827876 fifo_full_lvl = 0x0190;
877+ }
828878
829− cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL_HIGH,
830− fifo_full_lvl >> 8, &ret);
831− cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL_LOW,
832− fifo_full_lvl & 0xff, &ret);
879+ cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL,
880+ fifo_full_lvl, &ret);
833881
834882 /*
835883 * Set the FIFO gate mode / MIPI wdiv set:
836884 * 0xf1 in case of RAW mode and 0xf0 otherwise
837885 */
838− cci_write(gc2145->regmap, GC2145_REG_FIFO_GATE_MODE, 0xf0, &ret);
886+ cci_write(gc2145->regmap, GC2145_REG_FIFO_GATE_MODE,
887+ gc2145_format->colorspace == V4L2_COLORSPACE_RAW ?
888+ 0xf1 : 0xf0, &ret);
839889
840890 /* Set the MIPI data type */
841891 cci_write(gc2145->regmap, GC2145_REG_MIPI_DT,
@@ -883,6 +933,10 @@ static int gc2145_start_streaming(struct gc2145 *gc2145, · 41 unmodified lines
883933 GC2145_BYPASS_MODE_SWITCH,
884934 gc2145_format->switch_bit ? GC2145_BYPASS_MODE_SWITCH
885935 : 0, &ret);
936+ cci_update_bits(gc2145->regmap, GC2145_REG_SYNC_MODE,
937+ GC2145_SYNC_MODE_COL_SWITCH |
938+ GC2145_SYNC_MODE_ROW_SWITCH,
939+ gc2145_format->row_col_switch, &ret);
886940 if (ret) {
887941 dev_err(&client->dev, "%s failed to write regs\n", __func__);
888942 goto err_rpm_put;
drivers/media/i2c/hi846.c+1−1
@@ -1851,7 +1851,7 @@ static int hi846_get_selection(struct v4l2_subdev *sd, · 1850 unmodified lines
18511851 mutex_lock(&hi846->mutex);
18521852 switch (sel->which) {
18531853 case V4L2_SUBDEV_FORMAT_TRY:
1854− v4l2_subdev_state_get_crop(sd_state, sel->pad);
1854+ sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad);
18551855 break;
18561856 case V4L2_SUBDEV_FORMAT_ACTIVE:
18571857 sel->r = hi846->cur_mode->crop;
drivers/media/i2c/imx219.c+1−1
@@ -162,8 +162,8 @@ static const struct cci_reg_sequence imx219_common_regs[] = { · 161 unmodified lines
162162 { IMX219_REG_MODE_SELECT, 0x00 }, /* Mode Select */
163163
164164 /* To Access Addresses 3000-5fff, send the following commands */
165− { CCI_REG8(0x30eb), 0x0c },
166165 { CCI_REG8(0x30eb), 0x05 },
166+ { CCI_REG8(0x30eb), 0x0c },
167167 { CCI_REG8(0x300a), 0xff },
168168 { CCI_REG8(0x300b), 0xff },
169169 { CCI_REG8(0x30eb), 0x05 },
drivers/media/i2c/imx258.c+810−614
@@ -7,97 +7,150 @@ · 6 unmodified lines
77 #include <linux/i2c.h>
88 #include <linux/module.h>
99 #include <linux/pm_runtime.h>
10+#include <linux/regulator/consumer.h>
11+#include <media/v4l2-cci.h>
1012 #include <media/v4l2-ctrls.h>
1113 #include <media/v4l2-device.h>
1214 #include <media/v4l2-fwnode.h>
1315 #include <asm/unaligned.h>
1416
15−#define IMX258_REG_VALUE_08BIT 1
16−#define IMX258_REG_VALUE_16BIT 2
17−
18−#define IMX258_REG_MODE_SELECT 0x0100
17+#define IMX258_REG_MODE_SELECT CCI_REG8(0x0100)
1918 #define IMX258_MODE_STANDBY 0x00
2019 #define IMX258_MODE_STREAMING 0x01
2120
21+#define IMX258_REG_RESET CCI_REG8(0x0103)
22+
2223 /* Chip ID */
23−#define IMX258_REG_CHIP_ID 0x0016
24+#define IMX258_REG_CHIP_ID CCI_REG16(0x0016)
2425 #define IMX258_CHIP_ID 0x0258
2526
2627 /* V_TIMING internal */
2728 #define IMX258_VTS_30FPS 0x0c50
2829 #define IMX258_VTS_30FPS_2K 0x0638
2930 #define IMX258_VTS_30FPS_VGA 0x034c
30−#define IMX258_VTS_MAX 0xffff
31−
32−/*Frame Length Line*/
33−#define IMX258_FLL_MIN 0x08a6
34−#define IMX258_FLL_MAX 0xffff
35−#define IMX258_FLL_STEP 1
36−#define IMX258_FLL_DEFAULT 0x0c98
31+#define IMX258_VTS_MAX 65525
3732
3833 /* HBLANK control - read only */
3934 #define IMX258_PPL_DEFAULT 5352
4035
4136 /* Exposure control */
42−#define IMX258_REG_EXPOSURE 0x0202
37+#define IMX258_REG_EXPOSURE CCI_REG16(0x0202)
38+#define IMX258_EXPOSURE_OFFSET 10
4339 #define IMX258_EXPOSURE_MIN 4
4440 #define IMX258_EXPOSURE_STEP 1
4541 #define IMX258_EXPOSURE_DEFAULT 0x640
46−#define IMX258_EXPOSURE_MAX 65535
42+#define IMX258_EXPOSURE_MAX (IMX258_VTS_MAX - IMX258_EXPOSURE_OFFSET)
4743
4844 /* Analog gain control */
49−#define IMX258_REG_ANALOG_GAIN 0x0204
45+#define IMX258_REG_ANALOG_GAIN CCI_REG16(0x0204)
5046 #define IMX258_ANA_GAIN_MIN 0
5147 #define IMX258_ANA_GAIN_MAX 480
5248 #define IMX258_ANA_GAIN_STEP 1
5349 #define IMX258_ANA_GAIN_DEFAULT 0x0
5450
5551 /* Digital gain control */
56−#define IMX258_REG_GR_DIGITAL_GAIN 0x020e
57−#define IMX258_REG_R_DIGITAL_GAIN 0x0210
58−#define IMX258_REG_B_DIGITAL_GAIN 0x0212
59−#define IMX258_REG_GB_DIGITAL_GAIN 0x0214
52+#define IMX258_REG_GR_DIGITAL_GAIN CCI_REG16(0x020e)
53+#define IMX258_REG_R_DIGITAL_GAIN CCI_REG16(0x0210)
54+#define IMX258_REG_B_DIGITAL_GAIN CCI_REG16(0x0212)
55+#define IMX258_REG_GB_DIGITAL_GAIN CCI_REG16(0x0214)
6056 #define IMX258_DGTL_GAIN_MIN 0
6157 #define IMX258_DGTL_GAIN_MAX 4096 /* Max = 0xFFF */
6258 #define IMX258_DGTL_GAIN_DEFAULT 1024
6359 #define IMX258_DGTL_GAIN_STEP 1
6460
6561 /* HDR control */
66−#define IMX258_REG_HDR 0x0220
62+#define IMX258_REG_HDR CCI_REG8(0x0220)
6763 #define IMX258_HDR_ON BIT(0)
68−#define IMX258_REG_HDR_RATIO 0x0222
64+#define IMX258_REG_HDR_RATIO CCI_REG8(0x0222)
6965 #define IMX258_HDR_RATIO_MIN 0
7066 #define IMX258_HDR_RATIO_MAX 5
7167 #define IMX258_HDR_RATIO_STEP 1
7268 #define IMX258_HDR_RATIO_DEFAULT 0x0
7369
7470 /* Test Pattern Control */
75−#define IMX258_REG_TEST_PATTERN 0x0600
71+#define IMX258_REG_TEST_PATTERN CCI_REG16(0x0600)
72+
73+#define IMX258_CLK_BLANK_STOP CCI_REG8(0x4040)
7674
7775 /* Orientation */
78−#define REG_MIRROR_FLIP_CONTROL 0x0101
79−#define REG_CONFIG_MIRROR_FLIP 0x03
80−#define REG_CONFIG_FLIP_TEST_PATTERN 0x02
76+#define REG_MIRROR_FLIP_CONTROL CCI_REG8(0x0101)
77+#define REG_CONFIG_MIRROR_HFLIP 0x01
78+#define REG_CONFIG_MIRROR_VFLIP 0x02
79+
80+/* IMX258 native and active pixel array size. */
81+#define IMX258_NATIVE_WIDTH 4224U
82+#define IMX258_NATIVE_HEIGHT 3192U
83+#define IMX258_PIXEL_ARRAY_LEFT 8U
84+#define IMX258_PIXEL_ARRAY_TOP 16U
85+#define IMX258_PIXEL_ARRAY_WIDTH 4208U
86+#define IMX258_PIXEL_ARRAY_HEIGHT 3120U
87+
88+/* regs */
89+#define IMX258_REG_PLL_MULT_DRIV CCI_REG8(0x0310)
90+#define IMX258_REG_IVTPXCK_DIV CCI_REG8(0x0301)
91+#define IMX258_REG_IVTSYCK_DIV CCI_REG8(0x0303)
92+#define IMX258_REG_PREPLLCK_VT_DIV CCI_REG8(0x0305)
93+#define IMX258_REG_IOPPXCK_DIV CCI_REG8(0x0309)
94+#define IMX258_REG_IOPSYCK_DIV CCI_REG8(0x030b)
95+#define IMX258_REG_PREPLLCK_OP_DIV CCI_REG8(0x030d)
96+#define IMX258_REG_PHASE_PIX_OUTEN CCI_REG8(0x3030)
97+#define IMX258_REG_PDPIX_DATA_RATE CCI_REG8(0x3032)
98+#define IMX258_REG_SCALE_MODE CCI_REG8(0x0401)
99+#define IMX258_REG_SCALE_MODE_EXT CCI_REG8(0x3038)
100+#define IMX258_REG_AF_WINDOW_MODE CCI_REG8(0x7bcd)
101+#define IMX258_REG_FRM_LENGTH_CTL CCI_REG8(0x0350)
102+#define IMX258_REG_CSI_LANE_MODE CCI_REG8(0x0114)
103+#define IMX258_REG_X_EVN_INC CCI_REG8(0x0381)
104+#define IMX258_REG_X_ODD_INC CCI_REG8(0x0383)
105+#define IMX258_REG_Y_EVN_INC CCI_REG8(0x0385)
106+#define IMX258_REG_Y_ODD_INC CCI_REG8(0x0387)
107+#define IMX258_REG_BINNING_MODE CCI_REG8(0x0900)
108+#define IMX258_REG_BINNING_TYPE_V CCI_REG8(0x0901)
109+#define IMX258_REG_FORCE_FD_SUM CCI_REG8(0x300d)
110+#define IMX258_REG_DIG_CROP_X_OFFSET CCI_REG16(0x0408)
111+#define IMX258_REG_DIG_CROP_Y_OFFSET CCI_REG16(0x040a)
112+#define IMX258_REG_DIG_CROP_IMAGE_WIDTH CCI_REG16(0x040c)
113+#define IMX258_REG_DIG_CROP_IMAGE_HEIGHT CCI_REG16(0x040e)
114+#define IMX258_REG_SCALE_M CCI_REG16(0x0404)
115+#define IMX258_REG_X_OUT_SIZE CCI_REG16(0x034c)
116+#define IMX258_REG_Y_OUT_SIZE CCI_REG16(0x034e)
117+#define IMX258_REG_X_ADD_STA CCI_REG16(0x0344)
118+#define IMX258_REG_Y_ADD_STA CCI_REG16(0x0346)
119+#define IMX258_REG_X_ADD_END CCI_REG16(0x0348)
120+#define IMX258_REG_Y_ADD_END CCI_REG16(0x034a)
121+#define IMX258_REG_EXCK_FREQ CCI_REG16(0x0136)
122+#define IMX258_REG_CSI_DT_FMT CCI_REG16(0x0112)
123+#define IMX258_REG_LINE_LENGTH_PCK CCI_REG16(0x0342)
124+#define IMX258_REG_SCALE_M_EXT CCI_REG16(0x303a)
125+#define IMX258_REG_FRM_LENGTH_LINES CCI_REG16(0x0340)
126+#define IMX258_REG_FINE_INTEG_TIME CCI_REG8(0x0200)
127+#define IMX258_REG_PLL_IVT_MPY CCI_REG16(0x0306)
128+#define IMX258_REG_PLL_IOP_MPY CCI_REG16(0x030e)
129+#define IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H CCI_REG16(0x0820)
130+#define IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L CCI_REG16(0x0822)
81131
82−/* Input clock frequency in Hz */
83−#define IMX258_INPUT_CLOCK_FREQ 19200000
132+struct imx258_reg_list {
133+ u32 num_of_regs;
134+ const struct cci_reg_sequence *regs;
135+};
84136
85−struct imx258_reg {
86− u16 address;
87− u8 val;
137+struct imx258_link_cfg {
138+ unsigned int lf_to_pix_rate_factor;
139+ struct imx258_reg_list reg_list;
88140 };
89141
90−struct imx258_reg_list {
91− u32 num_of_regs;
92− const struct imx258_reg *regs;
142+enum {
143+ IMX258_2_LANE_MODE,
144+ IMX258_4_LANE_MODE,
145+ IMX258_LANE_CONFIGS,
93146 };
94147
95148 /* Link frequency config */
96149 struct imx258_link_freq_config {
97150 u32 pixels_per_line;
98151
99− /* PLL registers for this link frequency */
100− struct imx258_reg_list reg_list;
152+ /* Configuration for this link frequency / num lanes selection */
153+ struct imx258_link_cfg link_cfg[IMX258_LANE_CONFIGS];
101154 };
102155
103156 /* Mode : resolution and related config&values */
@@ -115,400 +168,307 @@ struct imx258_mode { · 11 unmodified lines
115168 u32 link_freq_index;
116169 /* Default register values */
117170 struct imx258_reg_list reg_list;
171+
172+ /* Analog crop rectangle */
173+ struct v4l2_rect crop;
174+};
175+
176+/*
177+ * 4208x3120 @ 30 fps needs 1267Mbps/lane, 4 lanes.
178+ * To avoid further computation of clock settings, adopt the same per
179+ * lane data rate when using 2 lanes, thus allowing a maximum of 15fps.
180+ */
181+static const struct cci_reg_sequence mipi_1267mbps_19_2mhz_2l[] = {
182+ { IMX258_REG_EXCK_FREQ, 0x1333 },
183+ { IMX258_REG_IVTPXCK_DIV, 10 },
184+ { IMX258_REG_IVTSYCK_DIV, 2 },
185+ { IMX258_REG_PREPLLCK_VT_DIV, 3 },
186+ { IMX258_REG_PLL_IVT_MPY, 198 },
187+ { IMX258_REG_IOPPXCK_DIV, 10 },
188+ { IMX258_REG_IOPSYCK_DIV, 1 },
189+ { IMX258_REG_PREPLLCK_OP_DIV, 2 },
190+ { IMX258_REG_PLL_IOP_MPY, 216 },
191+ { IMX258_REG_PLL_MULT_DRIV, 0 },
192+
193+ { IMX258_REG_CSI_LANE_MODE, 1 },
194+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 1267 * 2 },
195+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
196+};
197+
198+static const struct cci_reg_sequence mipi_1267mbps_19_2mhz_4l[] = {
199+ { IMX258_REG_EXCK_FREQ, 0x1333 },
200+ { IMX258_REG_IVTPXCK_DIV, 5 },
201+ { IMX258_REG_IVTSYCK_DIV, 2 },
202+ { IMX258_REG_PREPLLCK_VT_DIV, 3 },
203+ { IMX258_REG_PLL_IVT_MPY, 198 },
204+ { IMX258_REG_IOPPXCK_DIV, 10 },
205+ { IMX258_REG_IOPSYCK_DIV, 1 },
206+ { IMX258_REG_PREPLLCK_OP_DIV, 2 },
207+ { IMX258_REG_PLL_IOP_MPY, 216 },
208+ { IMX258_REG_PLL_MULT_DRIV, 0 },
209+
210+ { IMX258_REG_CSI_LANE_MODE, 3 },
211+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 1267 * 4 },
212+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
213+};
214+
215+static const struct cci_reg_sequence mipi_1272mbps_24mhz_2l[] = {
216+ { IMX258_REG_EXCK_FREQ, 0x1800 },
217+ { IMX258_REG_IVTPXCK_DIV, 10 },
218+ { IMX258_REG_IVTSYCK_DIV, 2 },
219+ { IMX258_REG_PREPLLCK_VT_DIV, 4 },
220+ { IMX258_REG_PLL_IVT_MPY, 212 },
221+ { IMX258_REG_IOPPXCK_DIV, 10 },
222+ { IMX258_REG_IOPSYCK_DIV, 1 },
223+ { IMX258_REG_PREPLLCK_OP_DIV, 2 },
224+ { IMX258_REG_PLL_IOP_MPY, 216 },
225+ { IMX258_REG_PLL_MULT_DRIV, 0 },
226+
227+ { IMX258_REG_CSI_LANE_MODE, 1 },
228+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 1272 * 2 },
229+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
230+};
231+
232+static const struct cci_reg_sequence mipi_1272mbps_24mhz_4l[] = {
233+ { IMX258_REG_EXCK_FREQ, 0x1800 },
234+ { IMX258_REG_IVTPXCK_DIV, 5 },
235+ { IMX258_REG_IVTSYCK_DIV, 2 },
236+ { IMX258_REG_PREPLLCK_VT_DIV, 4 },
237+ { IMX258_REG_PLL_IVT_MPY, 212 },
238+ { IMX258_REG_IOPPXCK_DIV, 10 },
239+ { IMX258_REG_IOPSYCK_DIV, 1 },
240+ { IMX258_REG_PREPLLCK_OP_DIV, 2 },
241+ { IMX258_REG_PLL_IOP_MPY, 216 },
242+ { IMX258_REG_PLL_MULT_DRIV, 0 },
243+
244+ { IMX258_REG_CSI_LANE_MODE, 3 },
245+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 1272 * 4 },
246+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
247+};
248+
249+static const struct cci_reg_sequence mipi_640mbps_19_2mhz_2l[] = {
250+ { IMX258_REG_EXCK_FREQ, 0x1333 },
251+ { IMX258_REG_IVTPXCK_DIV, 5 },
252+ { IMX258_REG_IVTSYCK_DIV, 2 },
253+ { IMX258_REG_PREPLLCK_VT_DIV, 3 },
254+ { IMX258_REG_PLL_IVT_MPY, 100 },
255+ { IMX258_REG_IOPPXCK_DIV, 10 },
256+ { IMX258_REG_IOPSYCK_DIV, 1 },
257+ { IMX258_REG_PREPLLCK_OP_DIV, 2 },
258+ { IMX258_REG_PLL_IOP_MPY, 216 },
259+ { IMX258_REG_PLL_MULT_DRIV, 0 },
260+
261+ { IMX258_REG_CSI_LANE_MODE, 1 },
262+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 640 * 2 },
263+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
264+};
265+
266+static const struct cci_reg_sequence mipi_640mbps_19_2mhz_4l[] = {
267+ { IMX258_REG_EXCK_FREQ, 0x1333 },
268+ { IMX258_REG_IVTPXCK_DIV, 5 },
269+ { IMX258_REG_IVTSYCK_DIV, 2 },
270+ { IMX258_REG_PREPLLCK_VT_DIV, 3 },
271+ { IMX258_REG_PLL_IVT_MPY, 100 },
272+ { IMX258_REG_IOPPXCK_DIV, 10 },
273+ { IMX258_REG_IOPSYCK_DIV, 1 },
274+ { IMX258_REG_PREPLLCK_OP_DIV, 2 },
275+ { IMX258_REG_PLL_IOP_MPY, 216 },
276+ { IMX258_REG_PLL_MULT_DRIV, 0 },
277+
278+ { IMX258_REG_CSI_LANE_MODE, 3 },
279+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 640 * 4 },
280+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
118281 };
119282
120−/* 4208x3118 needs 1267Mbps/lane, 4 lanes */
121−static const struct imx258_reg mipi_data_rate_1267mbps[] = {
122− { 0x0301, 0x05 },
123− { 0x0303, 0x02 },
124− { 0x0305, 0x03 },
125− { 0x0306, 0x00 },
126− { 0x0307, 0xC6 },
127− { 0x0309, 0x0A },
128− { 0x030B, 0x01 },
129− { 0x030D, 0x02 },
130− { 0x030E, 0x00 },
131− { 0x030F, 0xD8 },
132− { 0x0310, 0x00 },
133− { 0x0820, 0x13 },
134− { 0x0821, 0x4C },
135− { 0x0822, 0xCC },
136− { 0x0823, 0xCC },
283+static const struct cci_reg_sequence mipi_642mbps_24mhz_2l[] = {
284+ { IMX258_REG_EXCK_FREQ, 0x1800 },
285+ { IMX258_REG_IVTPXCK_DIV, 5 },
286+ { IMX258_REG_IVTSYCK_DIV, 2 },
287+ { IMX258_REG_PREPLLCK_VT_DIV, 4 },
288+ { IMX258_REG_PLL_IVT_MPY, 107 },
289+ { IMX258_REG_IOPPXCK_DIV, 10 },
290+ { IMX258_REG_IOPSYCK_DIV, 1 },
291+ { IMX258_REG_PREPLLCK_OP_DIV, 2 },
292+ { IMX258_REG_PLL_IOP_MPY, 216 },
293+ { IMX258_REG_PLL_MULT_DRIV, 0 },
294+
295+ { IMX258_REG_CSI_LANE_MODE, 1 },
296+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 642 * 2 },
297+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
137298 };
138299
139−static const struct imx258_reg mipi_data_rate_640mbps[] = {
140− { 0x0301, 0x05 },
141− { 0x0303, 0x02 },
142− { 0x0305, 0x03 },
143− { 0x0306, 0x00 },
144− { 0x0307, 0x64 },
145− { 0x0309, 0x0A },
146− { 0x030B, 0x01 },
147− { 0x030D, 0x02 },
148− { 0x030E, 0x00 },
149− { 0x030F, 0xD8 },
150− { 0x0310, 0x00 },
151− { 0x0820, 0x0A },
152− { 0x0821, 0x00 },
153− { 0x0822, 0x00 },
154− { 0x0823, 0x00 },
300+static const struct cci_reg_sequence mipi_642mbps_24mhz_4l[] = {
301+ { IMX258_REG_EXCK_FREQ, 0x1800 },
302+ { IMX258_REG_IVTPXCK_DIV, 5 },
303+ { IMX258_REG_IVTSYCK_DIV, 2 },
304+ { IMX258_REG_PREPLLCK_VT_DIV, 4 },
305+ { IMX258_REG_PLL_IVT_MPY, 107 },
306+ { IMX258_REG_IOPPXCK_DIV, 10 },
307+ { IMX258_REG_IOPSYCK_DIV, 1 },
308+ { IMX258_REG_PREPLLCK_OP_DIV, 2 },
309+ { IMX258_REG_PLL_IOP_MPY, 216 },
310+ { IMX258_REG_PLL_MULT_DRIV, 0 },
311+
312+ { IMX258_REG_CSI_LANE_MODE, 3 },
313+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 642 * 4 },
314+ { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
155315 };
156316
157−static const struct imx258_reg mode_4208x3118_regs[] = {
158− { 0x0136, 0x13 },
159− { 0x0137, 0x33 },
160− { 0x3051, 0x00 },
161− { 0x3052, 0x00 },
162− { 0x4E21, 0x14 },
163− { 0x6B11, 0xCF },
164− { 0x7FF0, 0x08 },
165− { 0x7FF1, 0x0F },
166− { 0x7FF2, 0x08 },
167− { 0x7FF3, 0x1B },
168− { 0x7FF4, 0x23 },
169− { 0x7FF5, 0x60 },
170− { 0x7FF6, 0x00 },
171− { 0x7FF7, 0x01 },
172− { 0x7FF8, 0x00 },
173− { 0x7FF9, 0x78 },
174− { 0x7FFA, 0x00 },
175− { 0x7FFB, 0x00 },
176− { 0x7FFC, 0x00 },
177− { 0x7FFD, 0x00 },
178− { 0x7FFE, 0x00 },
179− { 0x7FFF, 0x03 },
180− { 0x7F76, 0x03 },
181− { 0x7F77, 0xFE },
182− { 0x7FA8, 0x03 },
183− { 0x7FA9, 0xFE },
184− { 0x7B24, 0x81 },
185− { 0x7B25, 0x00 },
186− { 0x6564, 0x07 },
187− { 0x6B0D, 0x41 },
188− { 0x653D, 0x04 },
189− { 0x6B05, 0x8C },
190− { 0x6B06, 0xF9 },
191− { 0x6B08, 0x65 },
192− { 0x6B09, 0xFC },
193− { 0x6B0A, 0xCF },
194− { 0x6B0B, 0xD2 },
195− { 0x6700, 0x0E },
196− { 0x6707, 0x0E },
197− { 0x9104, 0x00 },
198− { 0x4648, 0x7F },
199− { 0x7420, 0x00 },
200− { 0x7421, 0x1C },
201− { 0x7422, 0x00 },
202− { 0x7423, 0xD7 },
203− { 0x5F04, 0x00 },
204− { 0x5F05, 0xED },
205− { 0x0112, 0x0A },
206− { 0x0113, 0x0A },
207− { 0x0114, 0x03 },
208− { 0x0342, 0x14 },
209− { 0x0343, 0xE8 },
210− { 0x0340, 0x0C },
211− { 0x0341, 0x50 },
212− { 0x0344, 0x00 },
213− { 0x0345, 0x00 },
214− { 0x0346, 0x00 },
215− { 0x0347, 0x00 },
216− { 0x0348, 0x10 },
217− { 0x0349, 0x6F },
218− { 0x034A, 0x0C },
219− { 0x034B, 0x2E },
220− { 0x0381, 0x01 },
221− { 0x0383, 0x01 },
222− { 0x0385, 0x01 },
223− { 0x0387, 0x01 },
224− { 0x0900, 0x00 },
225− { 0x0901, 0x11 },
226− { 0x0401, 0x00 },
227− { 0x0404, 0x00 },
228− { 0x0405, 0x10 },
229− { 0x0408, 0x00 },
230− { 0x0409, 0x00 },
231− { 0x040A, 0x00 },
232− { 0x040B, 0x00 },
233− { 0x040C, 0x10 },
234− { 0x040D, 0x70 },
235− { 0x040E, 0x0C },
236− { 0x040F, 0x30 },
237− { 0x3038, 0x00 },
238− { 0x303A, 0x00 },
239− { 0x303B, 0x10 },
240− { 0x300D, 0x00 },
241− { 0x034C, 0x10 },
242− { 0x034D, 0x70 },
243− { 0x034E, 0x0C },
244− { 0x034F, 0x30 },
245− { 0x0350, 0x01 },
246− { 0x0202, 0x0C },
247− { 0x0203, 0x46 },
248− { 0x0204, 0x00 },
249− { 0x0205, 0x00 },
250− { 0x020E, 0x01 },
251− { 0x020F, 0x00 },
252− { 0x0210, 0x01 },
253− { 0x0211, 0x00 },
254− { 0x0212, 0x01 },
255− { 0x0213, 0x00 },
256− { 0x0214, 0x01 },
257− { 0x0215, 0x00 },
258− { 0x7BCD, 0x00 },
259− { 0x94DC, 0x20 },
260− { 0x94DD, 0x20 },
261− { 0x94DE, 0x20 },
262− { 0x95DC, 0x20 },
263− { 0x95DD, 0x20 },
264− { 0x95DE, 0x20 },
265− { 0x7FB0, 0x00 },
266− { 0x9010, 0x3E },
267− { 0x9419, 0x50 },
268− { 0x941B, 0x50 },
269− { 0x9519, 0x50 },
270− { 0x951B, 0x50 },
271− { 0x3030, 0x00 },
272− { 0x3032, 0x00 },
273− { 0x0220, 0x00 },
317+static const struct cci_reg_sequence mode_common_regs[] = {
318+ { CCI_REG8(0x3051), 0x00 },
319+ { CCI_REG8(0x6B11), 0xCF },
320+ { CCI_REG8(0x7FF0), 0x08 },
321+ { CCI_REG8(0x7FF1), 0x0F },
322+ { CCI_REG8(0x7FF2), 0x08 },
323+ { CCI_REG8(0x7FF3), 0x1B },
324+ { CCI_REG8(0x7FF4), 0x23 },
325+ { CCI_REG8(0x7FF5), 0x60 },
326+ { CCI_REG8(0x7FF6), 0x00 },
327+ { CCI_REG8(0x7FF7), 0x01 },
328+ { CCI_REG8(0x7FF8), 0x00 },
329+ { CCI_REG8(0x7FF9), 0x78 },
330+ { CCI_REG8(0x7FFA), 0x00 },
331+ { CCI_REG8(0x7FFB), 0x00 },
332+ { CCI_REG8(0x7FFC), 0x00 },
333+ { CCI_REG8(0x7FFD), 0x00 },
334+ { CCI_REG8(0x7FFE), 0x00 },
335+ { CCI_REG8(0x7FFF), 0x03 },
336+ { CCI_REG8(0x7F76), 0x03 },
337+ { CCI_REG8(0x7F77), 0xFE },
338+ { CCI_REG8(0x7FA8), 0x03 },
339+ { CCI_REG8(0x7FA9), 0xFE },
340+ { CCI_REG8(0x7B24), 0x81 },
341+ { CCI_REG8(0x6564), 0x07 },
342+ { CCI_REG8(0x6B0D), 0x41 },
343+ { CCI_REG8(0x653D), 0x04 },
344+ { CCI_REG8(0x6B05), 0x8C },
345+ { CCI_REG8(0x6B06), 0xF9 },
346+ { CCI_REG8(0x6B08), 0x65 },
347+ { CCI_REG8(0x6B09), 0xFC },
348+ { CCI_REG8(0x6B0A), 0xCF },
349+ { CCI_REG8(0x6B0B), 0xD2 },
350+ { CCI_REG8(0x6700), 0x0E },
351+ { CCI_REG8(0x6707), 0x0E },
352+ { CCI_REG8(0x9104), 0x00 },
353+ { CCI_REG8(0x4648), 0x7F },
354+ { CCI_REG8(0x7420), 0x00 },
355+ { CCI_REG8(0x7421), 0x1C },
356+ { CCI_REG8(0x7422), 0x00 },
357+ { CCI_REG8(0x7423), 0xD7 },
358+ { CCI_REG8(0x5F04), 0x00 },
359+ { CCI_REG8(0x5F05), 0xED },
360+ {IMX258_REG_CSI_DT_FMT, 0x0a0a},
361+ {IMX258_REG_LINE_LENGTH_PCK, 5352},
362+ {IMX258_REG_X_ADD_STA, 0},
363+ {IMX258_REG_Y_ADD_STA, 0},
364+ {IMX258_REG_X_ADD_END, 4207},
365+ {IMX258_REG_Y_ADD_END, 3119},
366+ {IMX258_REG_X_EVN_INC, 1},
367+ {IMX258_REG_X_ODD_INC, 1},
368+ {IMX258_REG_Y_EVN_INC, 1},
369+ {IMX258_REG_Y_ODD_INC, 1},
370+ {IMX258_REG_DIG_CROP_X_OFFSET, 0},
371+ {IMX258_REG_DIG_CROP_Y_OFFSET, 0},
372+ {IMX258_REG_DIG_CROP_IMAGE_WIDTH, 4208},
373+ {IMX258_REG_SCALE_MODE_EXT, 0},
374+ {IMX258_REG_SCALE_M_EXT, 16},
375+ {IMX258_REG_FORCE_FD_SUM, 0},
376+ {IMX258_REG_FRM_LENGTH_CTL, 0},
377+ {IMX258_REG_ANALOG_GAIN, 0},
378+ {IMX258_REG_GR_DIGITAL_GAIN, 256},
379+ {IMX258_REG_R_DIGITAL_GAIN, 256},
380+ {IMX258_REG_B_DIGITAL_GAIN, 256},
381+ {IMX258_REG_GB_DIGITAL_GAIN, 256},
382+ {IMX258_REG_AF_WINDOW_MODE, 0},
383+ { CCI_REG8(0x94DC), 0x20 },
384+ { CCI_REG8(0x94DD), 0x20 },
385+ { CCI_REG8(0x94DE), 0x20 },
386+ { CCI_REG8(0x95DC), 0x20 },
387+ { CCI_REG8(0x95DD), 0x20 },
388+ { CCI_REG8(0x95DE), 0x20 },
389+ { CCI_REG8(0x7FB0), 0x00 },
390+ { CCI_REG8(0x9010), 0x3E },
391+ { CCI_REG8(0x9419), 0x50 },
392+ { CCI_REG8(0x941B), 0x50 },
393+ { CCI_REG8(0x9519), 0x50 },
394+ { CCI_REG8(0x951B), 0x50 },
395+ {IMX258_REG_PHASE_PIX_OUTEN, 0},
396+ {IMX258_REG_PDPIX_DATA_RATE, 0},
397+ {IMX258_REG_HDR, 0},
274398 };
275399
276−static const struct imx258_reg mode_2104_1560_regs[] = {
277− { 0x0136, 0x13 },
278− { 0x0137, 0x33 },
279− { 0x3051, 0x00 },
280− { 0x3052, 0x00 },
281− { 0x4E21, 0x14 },
282− { 0x6B11, 0xCF },
283− { 0x7FF0, 0x08 },
284− { 0x7FF1, 0x0F },
285− { 0x7FF2, 0x08 },
286− { 0x7FF3, 0x1B },
287− { 0x7FF4, 0x23 },
288− { 0x7FF5, 0x60 },
289− { 0x7FF6, 0x00 },
290− { 0x7FF7, 0x01 },
291− { 0x7FF8, 0x00 },
292− { 0x7FF9, 0x78 },
293− { 0x7FFA, 0x00 },
294− { 0x7FFB, 0x00 },
295− { 0x7FFC, 0x00 },
296− { 0x7FFD, 0x00 },
297− { 0x7FFE, 0x00 },
298− { 0x7FFF, 0x03 },
299− { 0x7F76, 0x03 },
300− { 0x7F77, 0xFE },
301− { 0x7FA8, 0x03 },
302− { 0x7FA9, 0xFE },
303− { 0x7B24, 0x81 },
304− { 0x7B25, 0x00 },
305− { 0x6564, 0x07 },
306− { 0x6B0D, 0x41 },
307− { 0x653D, 0x04 },
308− { 0x6B05, 0x8C },
309− { 0x6B06, 0xF9 },
310− { 0x6B08, 0x65 },
311− { 0x6B09, 0xFC },
312− { 0x6B0A, 0xCF },
313− { 0x6B0B, 0xD2 },
314− { 0x6700, 0x0E },
315− { 0x6707, 0x0E },
316− { 0x9104, 0x00 },
317− { 0x4648, 0x7F },
318− { 0x7420, 0x00 },
319− { 0x7421, 0x1C },
320− { 0x7422, 0x00 },
321− { 0x7423, 0xD7 },
322− { 0x5F04, 0x00 },
323− { 0x5F05, 0xED },
324− { 0x0112, 0x0A },
325− { 0x0113, 0x0A },
326− { 0x0114, 0x03 },
327− { 0x0342, 0x14 },
328− { 0x0343, 0xE8 },
329− { 0x0340, 0x06 },
330− { 0x0341, 0x38 },
331− { 0x0344, 0x00 },
332− { 0x0345, 0x00 },
333− { 0x0346, 0x00 },
334− { 0x0347, 0x00 },
335− { 0x0348, 0x10 },
336− { 0x0349, 0x6F },
337− { 0x034A, 0x0C },
338− { 0x034B, 0x2E },
339− { 0x0381, 0x01 },
340− { 0x0383, 0x01 },
341− { 0x0385, 0x01 },
342− { 0x0387, 0x01 },
343− { 0x0900, 0x01 },
344− { 0x0901, 0x12 },
345− { 0x0401, 0x01 },
346− { 0x0404, 0x00 },
347− { 0x0405, 0x20 },
348− { 0x0408, 0x00 },
349− { 0x0409, 0x02 },
350− { 0x040A, 0x00 },
351− { 0x040B, 0x00 },
352− { 0x040C, 0x10 },
353− { 0x040D, 0x6A },
354− { 0x040E, 0x06 },
355− { 0x040F, 0x18 },
356− { 0x3038, 0x00 },
357− { 0x303A, 0x00 },
358− { 0x303B, 0x10 },
359− { 0x300D, 0x00 },
360− { 0x034C, 0x08 },
361− { 0x034D, 0x38 },
362− { 0x034E, 0x06 },
363− { 0x034F, 0x18 },
364− { 0x0350, 0x01 },
365− { 0x0202, 0x06 },
366− { 0x0203, 0x2E },
367− { 0x0204, 0x00 },
368− { 0x0205, 0x00 },
369− { 0x020E, 0x01 },
370− { 0x020F, 0x00 },
371− { 0x0210, 0x01 },
372− { 0x0211, 0x00 },
373− { 0x0212, 0x01 },
374− { 0x0213, 0x00 },
375− { 0x0214, 0x01 },
376− { 0x0215, 0x00 },
377− { 0x7BCD, 0x01 },
378− { 0x94DC, 0x20 },
379− { 0x94DD, 0x20 },
380− { 0x94DE, 0x20 },
381− { 0x95DC, 0x20 },
382− { 0x95DD, 0x20 },
383− { 0x95DE, 0x20 },
384− { 0x7FB0, 0x00 },
385− { 0x9010, 0x3E },
386− { 0x9419, 0x50 },
387− { 0x941B, 0x50 },
388− { 0x9519, 0x50 },
389− { 0x951B, 0x50 },
390− { 0x3030, 0x00 },
391− { 0x3032, 0x00 },
392− { 0x0220, 0x00 },
400+static const struct cci_reg_sequence mode_4208x3120_regs[] = {
401+ {IMX258_REG_BINNING_MODE, 0},
402+ {IMX258_REG_BINNING_TYPE_V, 0x11},
403+ {IMX258_REG_SCALE_MODE, 0},
404+ {IMX258_REG_SCALE_M, 16},
405+ {IMX258_REG_DIG_CROP_IMAGE_HEIGHT, 3120},
406+ {IMX258_REG_X_OUT_SIZE, 4208},
407+ {IMX258_REG_Y_OUT_SIZE, 3120},
393408 };
394409
395−static const struct imx258_reg mode_1048_780_regs[] = {
396− { 0x0136, 0x13 },
397− { 0x0137, 0x33 },
398− { 0x3051, 0x00 },
399− { 0x3052, 0x00 },
400− { 0x4E21, 0x14 },
401− { 0x6B11, 0xCF },
402− { 0x7FF0, 0x08 },
403− { 0x7FF1, 0x0F },
404− { 0x7FF2, 0x08 },
405− { 0x7FF3, 0x1B },
406− { 0x7FF4, 0x23 },
407− { 0x7FF5, 0x60 },
408− { 0x7FF6, 0x00 },
409− { 0x7FF7, 0x01 },
410− { 0x7FF8, 0x00 },
411− { 0x7FF9, 0x78 },
412− { 0x7FFA, 0x00 },
413− { 0x7FFB, 0x00 },
414− { 0x7FFC, 0x00 },
415− { 0x7FFD, 0x00 },
416− { 0x7FFE, 0x00 },
417− { 0x7FFF, 0x03 },
418− { 0x7F76, 0x03 },
419− { 0x7F77, 0xFE },
420− { 0x7FA8, 0x03 },
421− { 0x7FA9, 0xFE },
422− { 0x7B24, 0x81 },
423− { 0x7B25, 0x00 },
424− { 0x6564, 0x07 },
425− { 0x6B0D, 0x41 },
426− { 0x653D, 0x04 },
427− { 0x6B05, 0x8C },
428− { 0x6B06, 0xF9 },
429− { 0x6B08, 0x65 },
430− { 0x6B09, 0xFC },
431− { 0x6B0A, 0xCF },
432− { 0x6B0B, 0xD2 },
433− { 0x6700, 0x0E },
434− { 0x6707, 0x0E },
435− { 0x9104, 0x00 },
436− { 0x4648, 0x7F },
437− { 0x7420, 0x00 },
438− { 0x7421, 0x1C },
439− { 0x7422, 0x00 },
440− { 0x7423, 0xD7 },
441− { 0x5F04, 0x00 },
442− { 0x5F05, 0xED },
443− { 0x0112, 0x0A },
444− { 0x0113, 0x0A },
445− { 0x0114, 0x03 },
446− { 0x0342, 0x14 },
447− { 0x0343, 0xE8 },
448− { 0x0340, 0x03 },
449− { 0x0341, 0x4C },
450− { 0x0344, 0x00 },
451− { 0x0345, 0x00 },
452− { 0x0346, 0x00 },
453− { 0x0347, 0x00 },
454− { 0x0348, 0x10 },
455− { 0x0349, 0x6F },
456− { 0x034A, 0x0C },
457− { 0x034B, 0x2E },
458− { 0x0381, 0x01 },
459− { 0x0383, 0x01 },
460− { 0x0385, 0x01 },
461− { 0x0387, 0x01 },
462− { 0x0900, 0x01 },
463− { 0x0901, 0x14 },
464− { 0x0401, 0x01 },
465− { 0x0404, 0x00 },
466− { 0x0405, 0x40 },
467− { 0x0408, 0x00 },
468− { 0x0409, 0x06 },
469− { 0x040A, 0x00 },
470− { 0x040B, 0x00 },
471− { 0x040C, 0x10 },
472− { 0x040D, 0x64 },
473− { 0x040E, 0x03 },
474− { 0x040F, 0x0C },
475− { 0x3038, 0x00 },
476− { 0x303A, 0x00 },
477− { 0x303B, 0x10 },
478− { 0x300D, 0x00 },
479− { 0x034C, 0x04 },
480− { 0x034D, 0x18 },
481− { 0x034E, 0x03 },
482− { 0x034F, 0x0C },
483− { 0x0350, 0x01 },
484− { 0x0202, 0x03 },
485− { 0x0203, 0x42 },
486− { 0x0204, 0x00 },
487− { 0x0205, 0x00 },
488− { 0x020E, 0x01 },
489− { 0x020F, 0x00 },
490− { 0x0210, 0x01 },
491− { 0x0211, 0x00 },
492− { 0x0212, 0x01 },
493− { 0x0213, 0x00 },
494− { 0x0214, 0x01 },
495− { 0x0215, 0x00 },
496− { 0x7BCD, 0x00 },
497− { 0x94DC, 0x20 },
498− { 0x94DD, 0x20 },
499− { 0x94DE, 0x20 },
500− { 0x95DC, 0x20 },
501− { 0x95DD, 0x20 },
502− { 0x95DE, 0x20 },
503− { 0x7FB0, 0x00 },
504− { 0x9010, 0x3E },
505− { 0x9419, 0x50 },
506− { 0x941B, 0x50 },
507− { 0x9519, 0x50 },
508− { 0x951B, 0x50 },
509− { 0x3030, 0x00 },
510− { 0x3032, 0x00 },
511− { 0x0220, 0x00 },
410+static const struct cci_reg_sequence mode_2104_1560_regs[] = {
411+ {IMX258_REG_BINNING_MODE, 1},
412+ {IMX258_REG_BINNING_TYPE_V, 0x12},
413+ {IMX258_REG_SCALE_MODE, 1},
414+ {IMX258_REG_SCALE_M, 32},
415+ {IMX258_REG_DIG_CROP_IMAGE_HEIGHT, 1560},
416+ {IMX258_REG_X_OUT_SIZE, 2104},
417+ {IMX258_REG_Y_OUT_SIZE, 1560},
418+};
419+
420+static const struct cci_reg_sequence mode_1048_780_regs[] = {
421+ {IMX258_REG_BINNING_MODE, 1},
422+ {IMX258_REG_BINNING_TYPE_V, 0x14},
423+ {IMX258_REG_SCALE_MODE, 1},
424+ {IMX258_REG_SCALE_M, 64},
425+ {IMX258_REG_DIG_CROP_IMAGE_HEIGHT, 780},
426+ {IMX258_REG_X_OUT_SIZE, 1048},
427+ {IMX258_REG_Y_OUT_SIZE, 780},
428+};
429+
430+struct imx258_variant_cfg {
431+ const struct cci_reg_sequence *regs;
432+ unsigned int num_regs;
433+};
434+
435+static const struct cci_reg_sequence imx258_cfg_regs[] = {
436+ { CCI_REG8(0x3052), 0x00 },
437+ { CCI_REG8(0x4E21), 0x14 },
438+ { CCI_REG8(0x7B25), 0x00 },
439+};
440+
441+static const struct imx258_variant_cfg imx258_cfg = {
442+ .regs = imx258_cfg_regs,
443+ .num_regs = ARRAY_SIZE(imx258_cfg_regs),
444+};
445+
446+static const struct cci_reg_sequence imx258_pdaf_cfg_regs[] = {
447+ { CCI_REG8(0x3052), 0x01 },
448+ { CCI_REG8(0x4E21), 0x10 },
449+ { CCI_REG8(0x7B25), 0x01 },
450+};
451+
452+static const struct imx258_variant_cfg imx258_pdaf_cfg = {
453+ .regs = imx258_pdaf_cfg_regs,
454+ .num_regs = ARRAY_SIZE(imx258_pdaf_cfg_regs),
455+};
456+
457+/*
458+ * The supported formats.
459+ * This table MUST contain 4 entries per format, to cover the various flip
460+ * combinations in the order
461+ * - no flip
462+ * - h flip
463+ * - v flip
464+ * - h&v flips
465+ */
466+static const u32 codes[] = {
467+ /* 10-bit modes. */
468+ MEDIA_BUS_FMT_SRGGB10_1X10,
469+ MEDIA_BUS_FMT_SGRBG10_1X10,
470+ MEDIA_BUS_FMT_SGBRG10_1X10,
471+ MEDIA_BUS_FMT_SBGGR10_1X10
512472 };
513473
514474 static const char * const imx258_test_pattern_menu[] = {
@@ -519,9 +479,15 @@ static const char * const imx258_test_pattern_menu[] = { · 4 unmodified lines
519479 "Pseudorandom Sequence (PN9)",
520480 };
521481
522−/* Configurations for supported link frequencies */
523−#define IMX258_LINK_FREQ_634MHZ 633600000ULL
524−#define IMX258_LINK_FREQ_320MHZ 320000000ULL
482+/* regulator supplies */
483+static const char * const imx258_supply_name[] = {
484+ /* Supplies can be enabled in any order */
485+ "vana", /* Analog (2.8V) supply */
486+ "vdig", /* Digital Core (1.2V) supply */
487+ "vif", /* IF (1.8V) supply */
488+};
489+
490+#define IMX258_NUM_SUPPLIES ARRAY_SIZE(imx258_supply_name)
525491
526492 enum {
527493 IMX258_LINK_FREQ_1267MBPS,
@@ -529,37 +495,96 @@ enum { · 1 unmodified line
529495 };
530496
531497 /*
532− * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
533− * data rate => double data rate; number of lanes => 4; bits per pixel => 10
498+ * Pixel rate does not necessarily relate to link frequency on this sensor as
499+ * there is a FIFO between the pixel array pipeline and the MIPI serializer.
500+ * The recommendation from Sony is that the pixel array is always run with a
501+ * line length of 5352 pixels, which means that there is a large amount of
502+ * blanking time for the 1048x780 mode. There is no need to replicate this
503+ * blanking on the CSI2 bus, and the configuration of register 0x0301 allows the
504+ * divider to be altered.
505+ *
506+ * The actual factor between link frequency and pixel rate is in the
507+ * imx258_link_cfg, so use this to convert between the two.
508+ * bits per pixel being 10, and D-PHY being DDR is assumed by this function, so
509+ * the value is only the combination of number of lanes and pixel clock divider.
534510 */
535−static u64 link_freq_to_pixel_rate(u64 f)
511+static u64 link_freq_to_pixel_rate(u64 f, const struct imx258_link_cfg *link_cfg)
536512 {
537− f *= 2 * 4;
513+ f *= 2 * link_cfg->lf_to_pix_rate_factor;
538514 do_div(f, 10);
539515
540516 return f;
541517 }
542518
543519 /* Menu items for LINK_FREQ V4L2 control */
544−static const s64 link_freq_menu_items[] = {
545− IMX258_LINK_FREQ_634MHZ,
546− IMX258_LINK_FREQ_320MHZ,
520+/* Configurations for supported link frequencies */
521+static const s64 link_freq_menu_items_19_2[] = {
522+ 633600000ULL,
523+ 320000000ULL,
547524 };
548525
526+static const s64 link_freq_menu_items_24[] = {
527+ 636000000ULL,
528+ 321000000ULL,
529+};
530+
531+#define REGS(_list) { .num_of_regs = ARRAY_SIZE(_list), .regs = _list, }
532+
549533 /* Link frequency configs */
550−static const struct imx258_link_freq_config link_freq_configs[] = {
534+static const struct imx258_link_freq_config link_freq_configs_19_2[] = {
551535 [IMX258_LINK_FREQ_1267MBPS] = {
552536 .pixels_per_line = IMX258_PPL_DEFAULT,
553− .reg_list = {
554− .num_of_regs = ARRAY_SIZE(mipi_data_rate_1267mbps),
555− .regs = mipi_data_rate_1267mbps,
537+ .link_cfg = {
538+ [IMX258_2_LANE_MODE] = {
539+ .lf_to_pix_rate_factor = 2 * 2,
540+ .reg_list = REGS(mipi_1267mbps_19_2mhz_2l),
541+ },
542+ [IMX258_4_LANE_MODE] = {
543+ .lf_to_pix_rate_factor = 4,
544+ .reg_list = REGS(mipi_1267mbps_19_2mhz_4l),
545+ },
556546 }
557547 },
558548 [IMX258_LINK_FREQ_640MBPS] = {
559549 .pixels_per_line = IMX258_PPL_DEFAULT,
560− .reg_list = {
561− .num_of_regs = ARRAY_SIZE(mipi_data_rate_640mbps),
562− .regs = mipi_data_rate_640mbps,
550+ .link_cfg = {
551+ [IMX258_2_LANE_MODE] = {
552+ .lf_to_pix_rate_factor = 2,
553+ .reg_list = REGS(mipi_640mbps_19_2mhz_2l),
554+ },
555+ [IMX258_4_LANE_MODE] = {
556+ .lf_to_pix_rate_factor = 4,
557+ .reg_list = REGS(mipi_640mbps_19_2mhz_4l),
558+ },
559+ }
560+ },
561+};
562+
563+static const struct imx258_link_freq_config link_freq_configs_24[] = {
564+ [IMX258_LINK_FREQ_1267MBPS] = {
565+ .pixels_per_line = IMX258_PPL_DEFAULT,
566+ .link_cfg = {
567+ [IMX258_2_LANE_MODE] = {
568+ .lf_to_pix_rate_factor = 2,
569+ .reg_list = REGS(mipi_1272mbps_24mhz_2l),
570+ },
571+ [IMX258_4_LANE_MODE] = {
572+ .lf_to_pix_rate_factor = 4,
573+ .reg_list = REGS(mipi_1272mbps_24mhz_4l),
574+ },
575+ }
576+ },
577+ [IMX258_LINK_FREQ_640MBPS] = {
578+ .pixels_per_line = IMX258_PPL_DEFAULT,
579+ .link_cfg = {
580+ [IMX258_2_LANE_MODE] = {
581+ .lf_to_pix_rate_factor = 2 * 2,
582+ .reg_list = REGS(mipi_642mbps_24mhz_2l),
583+ },
584+ [IMX258_4_LANE_MODE] = {
585+ .lf_to_pix_rate_factor = 4,
586+ .reg_list = REGS(mipi_642mbps_24mhz_4l),
587+ },
563588 }
564589 },
565590 };
@@ -568,14 +593,20 @@ static const struct imx258_link_freq_config link_freq_configs[] = { · 2 unmodified lines
568593 static const struct imx258_mode supported_modes[] = {
569594 {
570595 .width = 4208,
571− .height = 3118,
596+ .height = 3120,
572597 .vts_def = IMX258_VTS_30FPS,
573598 .vts_min = IMX258_VTS_30FPS,
574599 .reg_list = {
575− .num_of_regs = ARRAY_SIZE(mode_4208x3118_regs),
576− .regs = mode_4208x3118_regs,
600+ .num_of_regs = ARRAY_SIZE(mode_4208x3120_regs),
601+ .regs = mode_4208x3120_regs,
577602 },
578603 .link_freq_index = IMX258_LINK_FREQ_1267MBPS,
604+ .crop = {
605+ .left = IMX258_PIXEL_ARRAY_LEFT,
606+ .top = IMX258_PIXEL_ARRAY_TOP,
607+ .width = 4208,
608+ .height = 3120,
609+ },
579610 },
580611 {
581612 .width = 2104,
@@ -587,6 +618,12 @@ static const struct imx258_mode supported_modes[] = { · 5 unmodified lines
587618 .regs = mode_2104_1560_regs,
588619 },
589620 .link_freq_index = IMX258_LINK_FREQ_640MBPS,
621+ .crop = {
622+ .left = IMX258_PIXEL_ARRAY_LEFT,
623+ .top = IMX258_PIXEL_ARRAY_TOP,
624+ .width = 4208,
625+ .height = 3120,
626+ },
590627 },
591628 {
592629 .width = 1048,
@@ -598,12 +635,21 @@ static const struct imx258_mode supported_modes[] = { · 5 unmodified lines
598635 .regs = mode_1048_780_regs,
599636 },
600637 .link_freq_index = IMX258_LINK_FREQ_640MBPS,
638+ .crop = {
639+ .left = IMX258_PIXEL_ARRAY_LEFT,
640+ .top = IMX258_PIXEL_ARRAY_TOP,
641+ .width = 4208,
642+ .height = 3120,
643+ },
601644 },
602645 };
603646
604647 struct imx258 {
605648 struct v4l2_subdev sd;
606649 struct media_pad pad;
650+ struct regmap *regmap;
651+
652+ const struct imx258_variant_cfg *variant_cfg;
607653
608654 struct v4l2_ctrl_handler ctrl_handler;
609655 /* V4L2 Controls */
@@ -612,10 +658,18 @@ struct imx258 { · 2 unmodified lines
612658 struct v4l2_ctrl *vblank;
613659 struct v4l2_ctrl *hblank;
614660 struct v4l2_ctrl *exposure;
661+ struct v4l2_ctrl *hflip;
662+ struct v4l2_ctrl *vflip;
615663
616664 /* Current mode */
617665 const struct imx258_mode *cur_mode;
618666
667+ unsigned long link_freq_bitmap;
668+ const struct imx258_link_freq_config *link_freq_configs;
669+ const s64 *link_freq_menu_items;
670+ unsigned int lane_mode_idx;
671+ unsigned int csi2_flags;
672+
619673 /*
620674 * Mutex for serialized access:
621675 * Protect sensor module set pad format and start/stop streaming safely.
@@ -623,6 +677,7 @@ struct imx258 { · 1 unmodified line
623677 struct mutex mutex;
624678
625679 struct clk *clk;
680+ struct regulator_bulk_data supplies[IMX258_NUM_SUPPLIES];
626681 };
627682
628683 static inline struct imx258 *to_imx258(struct v4l2_subdev *_sd)
@@ -630,120 +685,66 @@ static inline struct imx258 *to_imx258(struct v4l2_subdev *_sd) · 1 unmodified line
630685 return container_of(_sd, struct imx258, sd);
631686 }
632687
633−/* Read registers up to 2 at a time */
634−static int imx258_read_reg(struct imx258 *imx258, u16 reg, u32 len, u32 *val)
688+/* Get bayer order based on flip setting. */
689+static u32 imx258_get_format_code(const struct imx258 *imx258)
635690 {
636− struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
637− struct i2c_msg msgs[2];
638− u8 addr_buf[2] = { reg >> 8, reg & 0xff };
639− u8 data_buf[4] = { 0, };
640− int ret;
641−
642− if (len > 4)
643− return -EINVAL;
644−
645− /* Write register address */
646− msgs[0].addr = client->addr;
647− msgs[0].flags = 0;
648− msgs[0].len = ARRAY_SIZE(addr_buf);
649− msgs[0].buf = addr_buf;
650−
651− /* Read data from register */
652− msgs[1].addr = client->addr;
653− msgs[1].flags = I2C_M_RD;
654− msgs[1].len = len;
655− msgs[1].buf = &data_buf[4 - len];
656−
657− ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
658− if (ret != ARRAY_SIZE(msgs))
659− return -EIO;
660−
661− *val = get_unaligned_be32(data_buf);
662−
663− return 0;
664−}
665−
666−/* Write registers up to 2 at a time */
667−static int imx258_write_reg(struct imx258 *imx258, u16 reg, u32 len, u32 val)
668−{
669− struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
670− u8 buf[6];
671−
672− if (len > 4)
673− return -EINVAL;
674−
675− put_unaligned_be16(reg, buf);
676− put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
677− if (i2c_master_send(client, buf, len + 2) != len + 2)
678− return -EIO;
679−
680− return 0;
681−}
682−
683−/* Write a list of registers */
684−static int imx258_write_regs(struct imx258 *imx258,
685− const struct imx258_reg *regs, u32 len)
686−{
687− struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
688691 unsigned int i;
689− int ret;
690692
691− for (i = 0; i < len; i++) {
692− ret = imx258_write_reg(imx258, regs[i].address, 1,
693− regs[i].val);
694− if (ret) {
695− dev_err_ratelimited(
696− &client->dev,
697− "Failed to write reg 0x%4.4x. error = %d\n",
698− regs[i].address, ret);
693+ lockdep_assert_held(&imx258->mutex);
699694
700− return ret;
701− }
702− }
695+ i = (imx258->vflip->val ? 2 : 0) |
696+ (imx258->hflip->val ? 1 : 0);
703697
704− return 0;
698+ return codes[i];
705699 }
706700
707701 /* Open sub-device */
708702 static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
709703 {
704+ struct imx258 *imx258 = to_imx258(sd);
710705 struct v4l2_mbus_framefmt *try_fmt =
711706 v4l2_subdev_state_get_format(fh->state, 0);
707+ struct v4l2_rect *try_crop;
712708
713709 /* Initialize try_fmt */
714710 try_fmt->width = supported_modes[0].width;
715711 try_fmt->height = supported_modes[0].height;
716− try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
712+ try_fmt->code = imx258_get_format_code(imx258);
717713 try_fmt->field = V4L2_FIELD_NONE;
718714
715+ /* Initialize try_crop */
716+ try_crop = v4l2_subdev_state_get_crop(fh->state, 0);
717+ try_crop->left = IMX258_PIXEL_ARRAY_LEFT;
718+ try_crop->top = IMX258_PIXEL_ARRAY_TOP;
719+ try_crop->width = IMX258_PIXEL_ARRAY_WIDTH;
720+ try_crop->height = IMX258_PIXEL_ARRAY_HEIGHT;
721+
719722 return 0;
720723 }
721724
722−static int imx258_update_digital_gain(struct imx258 *imx258, u32 len, u32 val)
725+static int imx258_update_digital_gain(struct imx258 *imx258, u32 val)
723726 {
724− int ret;
727+ int ret = 0;
725728
726− ret = imx258_write_reg(imx258, IMX258_REG_GR_DIGITAL_GAIN,
727− IMX258_REG_VALUE_16BIT,
728− val);
729− if (ret)
730− return ret;
731− ret = imx258_write_reg(imx258, IMX258_REG_GB_DIGITAL_GAIN,
732− IMX258_REG_VALUE_16BIT,
733− val);
734− if (ret)
735− return ret;
736− ret = imx258_write_reg(imx258, IMX258_REG_R_DIGITAL_GAIN,
737− IMX258_REG_VALUE_16BIT,
738− val);
739− if (ret)
740− return ret;
741− ret = imx258_write_reg(imx258, IMX258_REG_B_DIGITAL_GAIN,
742− IMX258_REG_VALUE_16BIT,
743− val);
744− if (ret)
745− return ret;
746− return 0;
729+ cci_write(imx258->regmap, IMX258_REG_GR_DIGITAL_GAIN, val, &ret);
730+ cci_write(imx258->regmap, IMX258_REG_GB_DIGITAL_GAIN, val, &ret);
731+ cci_write(imx258->regmap, IMX258_REG_R_DIGITAL_GAIN, val, &ret);
732+ cci_write(imx258->regmap, IMX258_REG_B_DIGITAL_GAIN, val, &ret);
733+
734+ return ret;
735+}
736+
737+static void imx258_adjust_exposure_range(struct imx258 *imx258)
738+{
739+ int exposure_max, exposure_def;
740+
741+ /* Honour the VBLANK limits when setting exposure. */
742+ exposure_max = imx258->cur_mode->height + imx258->vblank->val -
743+ IMX258_EXPOSURE_OFFSET;
744+ exposure_def = min(exposure_max, imx258->exposure->val);
745+ __v4l2_ctrl_modify_range(imx258->exposure, imx258->exposure->minimum,
746+ exposure_max, imx258->exposure->step,
747+ exposure_def);
747748 }
748749
749750 static int imx258_set_ctrl(struct v4l2_ctrl *ctrl)
@@ -753,6 +754,13 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl) · 3 unmodified lines
753754 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
754755 int ret = 0;
755756
757+ /*
758+ * The VBLANK control may change the limits of usable exposure, so check
759+ * and adjust if necessary.
760+ */
761+ if (ctrl->id == V4L2_CID_VBLANK)
762+ imx258_adjust_exposure_range(imx258);
763+
756764 /*
757765 * Applying V4L2 control value only happens
758766 * when power is up for streaming
@@ -762,44 +770,46 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl) · 3 unmodified lines
762770
763771 switch (ctrl->id) {
764772 case V4L2_CID_ANALOGUE_GAIN:
765− ret = imx258_write_reg(imx258, IMX258_REG_ANALOG_GAIN,
766− IMX258_REG_VALUE_16BIT,
767− ctrl->val);
773+ ret = cci_write(imx258->regmap, IMX258_REG_ANALOG_GAIN,
774+ ctrl->val, NULL);
768775 break;
769776 case V4L2_CID_EXPOSURE:
770− ret = imx258_write_reg(imx258, IMX258_REG_EXPOSURE,
771− IMX258_REG_VALUE_16BIT,
772− ctrl->val);
777+ ret = cci_write(imx258->regmap, IMX258_REG_EXPOSURE,
778+ ctrl->val, NULL);
773779 break;
774780 case V4L2_CID_DIGITAL_GAIN:
775− ret = imx258_update_digital_gain(imx258, IMX258_REG_VALUE_16BIT,
776− ctrl->val);
781+ ret = imx258_update_digital_gain(imx258, ctrl->val);
777782 break;
778783 case V4L2_CID_TEST_PATTERN:
779− ret = imx258_write_reg(imx258, IMX258_REG_TEST_PATTERN,
780− IMX258_REG_VALUE_16BIT,
781− ctrl->val);
782− ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL,
783− IMX258_REG_VALUE_08BIT,
784− !ctrl->val ? REG_CONFIG_MIRROR_FLIP :
785− REG_CONFIG_FLIP_TEST_PATTERN);
784+ ret = cci_write(imx258->regmap, IMX258_REG_TEST_PATTERN,
785+ ctrl->val, NULL);
786786 break;
787787 case V4L2_CID_WIDE_DYNAMIC_RANGE:
788788 if (!ctrl->val) {
789− ret = imx258_write_reg(imx258, IMX258_REG_HDR,
790− IMX258_REG_VALUE_08BIT,
791− IMX258_HDR_RATIO_MIN);
789+ ret = cci_write(imx258->regmap, IMX258_REG_HDR,
790+ IMX258_HDR_RATIO_MIN, NULL);
792791 } else {
793− ret = imx258_write_reg(imx258, IMX258_REG_HDR,
794− IMX258_REG_VALUE_08BIT,
795− IMX258_HDR_ON);
792+ ret = cci_write(imx258->regmap, IMX258_REG_HDR,
793+ IMX258_HDR_ON, NULL);
796794 if (ret)
797795 break;
798− ret = imx258_write_reg(imx258, IMX258_REG_HDR_RATIO,
799− IMX258_REG_VALUE_08BIT,
800− BIT(IMX258_HDR_RATIO_MAX));
796+ ret = cci_write(imx258->regmap, IMX258_REG_HDR_RATIO,
797+ BIT(IMX258_HDR_RATIO_MAX), NULL);
801798 }
802799 break;
800+ case V4L2_CID_VBLANK:
801+ ret = cci_write(imx258->regmap, IMX258_REG_FRM_LENGTH_LINES,
802+ imx258->cur_mode->height + ctrl->val, NULL);
803+ break;
804+ case V4L2_CID_VFLIP:
805+ case V4L2_CID_HFLIP:
806+ ret = cci_write(imx258->regmap, REG_MIRROR_FLIP_CONTROL,
807+ (imx258->hflip->val ?
808+ REG_CONFIG_MIRROR_HFLIP : 0) |
809+ (imx258->vflip->val ?
810+ REG_CONFIG_MIRROR_VFLIP : 0),
811+ NULL);
812+ break;
803813 default:
804814 dev_info(&client->dev,
805815 "ctrl(id:0x%x,val:0x%x) is not handled\n",
@@ -821,11 +831,13 @@ static int imx258_enum_mbus_code(struct v4l2_subdev *sd, · 15 unmodified lines
821831 struct v4l2_subdev_state *sd_state,
822832 struct v4l2_subdev_mbus_code_enum *code)
823833 {
824− /* Only one bayer order(GRBG) is supported */
834+ struct imx258 *imx258 = to_imx258(sd);
835+
836+ /* Only one bayer format (10 bit) is supported */
825837 if (code->index > 0)
826838 return -EINVAL;
827839
828− code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
840+ code->code = imx258_get_format_code(imx258);
829841
830842 return 0;
831843 }
@@ -834,10 +846,11 @@ static int imx258_enum_frame_size(struct v4l2_subdev *sd, · 2 unmodified lines
834846 struct v4l2_subdev_state *sd_state,
835847 struct v4l2_subdev_frame_size_enum *fse)
836848 {
849+ struct imx258 *imx258 = to_imx258(sd);
837850 if (fse->index >= ARRAY_SIZE(supported_modes))
838851 return -EINVAL;
839852
840− if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
853+ if (fse->code != imx258_get_format_code(imx258))
841854 return -EINVAL;
842855
843856 fse->min_width = supported_modes[fse->index].width;
@@ -848,12 +861,13 @@ static int imx258_enum_frame_size(struct v4l2_subdev *sd, · 4 unmodified lines
848861 return 0;
849862 }
850863
851−static void imx258_update_pad_format(const struct imx258_mode *mode,
864+static void imx258_update_pad_format(struct imx258 *imx258,
865+ const struct imx258_mode *mode,
852866 struct v4l2_subdev_format *fmt)
853867 {
854868 fmt->format.width = mode->width;
855869 fmt->format.height = mode->height;
856− fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
870+ fmt->format.code = imx258_get_format_code(imx258);
857871 fmt->format.field = V4L2_FIELD_NONE;
858872 }
859873
@@ -865,7 +879,7 @@ static int __imx258_get_pad_format(struct imx258 *imx258, · 5 unmodified lines
865879 fmt->format = *v4l2_subdev_state_get_format(sd_state,
866880 fmt->pad);
867881 else
868− imx258_update_pad_format(imx258->cur_mode, fmt);
882+ imx258_update_pad_format(imx258, imx258->cur_mode, fmt);
869883
870884 return 0;
871885 }
@@ -889,8 +903,10 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 17 unmodified lines
889903 struct v4l2_subdev_format *fmt)
890904 {
891905 struct imx258 *imx258 = to_imx258(sd);
892− const struct imx258_mode *mode;
906+ const struct imx258_link_freq_config *link_freq_cfgs;
907+ const struct imx258_link_cfg *link_cfg;
893908 struct v4l2_mbus_framefmt *framefmt;
909+ const struct imx258_mode *mode;
894910 s32 vblank_def;
895911 s32 vblank_min;
896912 s64 h_blank;
@@ -899,13 +915,12 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 2 unmodified lines
899915
900916 mutex_lock(&imx258->mutex);
901917
902− /* Only one raw bayer(GBRG) order is supported */
903− fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
918+ fmt->format.code = imx258_get_format_code(imx258);
904919
905920 mode = v4l2_find_nearest_size(supported_modes,
906921 ARRAY_SIZE(supported_modes), width, height,
907922 fmt->format.width, fmt->format.height);
908− imx258_update_pad_format(mode, fmt);
923+ imx258_update_pad_format(imx258, mode, fmt);
909924 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
910925 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
911926 *framefmt = fmt->format;
@@ -913,9 +928,14 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 1 unmodified line
913928 imx258->cur_mode = mode;
914929 __v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index);
915930
916− link_freq = link_freq_menu_items[mode->link_freq_index];
917− pixel_rate = link_freq_to_pixel_rate(link_freq);
918− __v4l2_ctrl_s_ctrl_int64(imx258->pixel_rate, pixel_rate);
931+ link_freq = imx258->link_freq_menu_items[mode->link_freq_index];
932+ link_freq_cfgs =
933+ &imx258->link_freq_configs[mode->link_freq_index];
934+
935+ link_cfg = &link_freq_cfgs->link_cfg[imx258->lane_mode_idx];
936+ pixel_rate = link_freq_to_pixel_rate(link_freq, link_cfg);
937+ __v4l2_ctrl_modify_range(imx258->pixel_rate, pixel_rate,
938+ pixel_rate, 1, pixel_rate);
919939 /* Update limits and set FPS to default */
920940 vblank_def = imx258->cur_mode->vts_def -
921941 imx258->cur_mode->height;
@@ -927,7 +947,7 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 5 unmodified lines
927947 vblank_def);
928948 __v4l2_ctrl_s_ctrl(imx258->vblank, vblank_def);
929949 h_blank =
930− link_freq_configs[mode->link_freq_index].pixels_per_line
950+ imx258->link_freq_configs[mode->link_freq_index].pixels_per_line
931951 - imx258->cur_mode->width;
932952 __v4l2_ctrl_modify_range(imx258->hblank, h_blank,
933953 h_blank, 1, h_blank);
@@ -938,48 +958,125 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 4 unmodified lines
938958 return 0;
939959 }
940960
961+static const struct v4l2_rect *
962+__imx258_get_pad_crop(struct imx258 *imx258,
963+ struct v4l2_subdev_state *sd_state,
964+ unsigned int pad, enum v4l2_subdev_format_whence which)
965+{
966+ switch (which) {
967+ case V4L2_SUBDEV_FORMAT_TRY:
968+ return v4l2_subdev_state_get_crop(sd_state, pad);
969+ case V4L2_SUBDEV_FORMAT_ACTIVE:
970+ return &imx258->cur_mode->crop;
971+ }
972+
973+ return NULL;
974+}
975+
976+static int imx258_get_selection(struct v4l2_subdev *sd,
977+ struct v4l2_subdev_state *sd_state,
978+ struct v4l2_subdev_selection *sel)
979+{
980+ switch (sel->target) {
981+ case V4L2_SEL_TGT_CROP: {
982+ struct imx258 *imx258 = to_imx258(sd);
983+
984+ mutex_lock(&imx258->mutex);
985+ sel->r = *__imx258_get_pad_crop(imx258, sd_state, sel->pad,
986+ sel->which);
987+ mutex_unlock(&imx258->mutex);
988+
989+ return 0;
990+ }
991+
992+ case V4L2_SEL_TGT_NATIVE_SIZE:
993+ sel->r.left = 0;
994+ sel->r.top = 0;
995+ sel->r.width = IMX258_NATIVE_WIDTH;
996+ sel->r.height = IMX258_NATIVE_HEIGHT;
997+
998+ return 0;
999+
1000+ case V4L2_SEL_TGT_CROP_DEFAULT:
1001+ case V4L2_SEL_TGT_CROP_BOUNDS:
1002+ sel->r.left = IMX258_PIXEL_ARRAY_LEFT;
1003+ sel->r.top = IMX258_PIXEL_ARRAY_TOP;
1004+ sel->r.width = IMX258_PIXEL_ARRAY_WIDTH;
1005+ sel->r.height = IMX258_PIXEL_ARRAY_HEIGHT;
1006+
1007+ return 0;
1008+ }
1009+
1010+ return -EINVAL;
1011+}
1012+
9411013 /* Start streaming */
9421014 static int imx258_start_streaming(struct imx258 *imx258)
9431015 {
9441016 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
9451017 const struct imx258_reg_list *reg_list;
1018+ const struct imx258_link_freq_config *link_freq_cfg;
9461019 int ret, link_freq_index;
9471020
1021+ ret = cci_write(imx258->regmap, IMX258_REG_RESET, 0x01, NULL);
1022+ if (ret) {
1023+ dev_err(&client->dev, "%s failed to reset sensor\n", __func__);
1024+ return ret;
1025+ }
1026+
1027+ /* 12ms is required from poweron to standby */
1028+ fsleep(12000);
1029+
9481030 /* Setup PLL */
9491031 link_freq_index = imx258->cur_mode->link_freq_index;
950− reg_list = &link_freq_configs[link_freq_index].reg_list;
951− ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
1032+ link_freq_cfg = &imx258->link_freq_configs[link_freq_index];
1033+
1034+ reg_list = &link_freq_cfg->link_cfg[imx258->lane_mode_idx].reg_list;
1035+ ret = cci_multi_reg_write(imx258->regmap, reg_list->regs, reg_list->num_of_regs, NULL);
9521036 if (ret) {
9531037 dev_err(&client->dev, "%s failed to set plls\n", __func__);
9541038 return ret;
9551039 }
9561040
957− /* Apply default values of current mode */
958− reg_list = &imx258->cur_mode->reg_list;
959− ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
1041+ ret = cci_multi_reg_write(imx258->regmap, mode_common_regs,
1042+ ARRAY_SIZE(mode_common_regs), NULL);
9601043 if (ret) {
961− dev_err(&client->dev, "%s failed to set mode\n", __func__);
1044+ dev_err(&client->dev, "%s failed to set common regs\n", __func__);
9621045 return ret;
9631046 }
9641047
965− /* Set Orientation be 180 degree */
966− ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL,
967− IMX258_REG_VALUE_08BIT, REG_CONFIG_MIRROR_FLIP);
1048+ ret = cci_multi_reg_write(imx258->regmap, imx258->variant_cfg->regs,
1049+ imx258->variant_cfg->num_regs, NULL);
9681050 if (ret) {
969− dev_err(&client->dev, "%s failed to set orientation\n",
1051+ dev_err(&client->dev, "%s failed to set variant config\n",
9701052 __func__);
9711053 return ret;
9721054 }
9731055
1056+ ret = cci_write(imx258->regmap, IMX258_CLK_BLANK_STOP,
1057+ !!(imx258->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK),
1058+ NULL);
1059+ if (ret) {
1060+ dev_err(&client->dev, "%s failed to set clock lane mode\n", __func__);
1061+ return ret;
1062+ }
1063+
1064+ /* Apply default values of current mode */
1065+ reg_list = &imx258->cur_mode->reg_list;
1066+ ret = cci_multi_reg_write(imx258->regmap, reg_list->regs, reg_list->num_of_regs, NULL);
1067+ if (ret) {
1068+ dev_err(&client->dev, "%s failed to set mode\n", __func__);
1069+ return ret;
1070+ }
1071+
9741072 /* Apply customized values from user */
9751073 ret = __v4l2_ctrl_handler_setup(imx258->sd.ctrl_handler);
9761074 if (ret)
9771075 return ret;
9781076
9791077 /* set stream on register */
980− return imx258_write_reg(imx258, IMX258_REG_MODE_SELECT,
981− IMX258_REG_VALUE_08BIT,
982− IMX258_MODE_STREAMING);
1078+ return cci_write(imx258->regmap, IMX258_REG_MODE_SELECT,
1079+ IMX258_MODE_STREAMING, NULL);
9831080 }
9841081
9851082 /* Stop streaming */
@@ -989,8 +1086,8 @@ static int imx258_stop_streaming(struct imx258 *imx258) · 3 unmodified lines
9891086 int ret;
9901087
9911088 /* set stream off register */
992− ret = imx258_write_reg(imx258, IMX258_REG_MODE_SELECT,
993− IMX258_REG_VALUE_08BIT, IMX258_MODE_STANDBY);
1089+ ret = cci_write(imx258->regmap, IMX258_REG_MODE_SELECT,
1090+ IMX258_MODE_STANDBY, NULL);
9941091 if (ret)
9951092 dev_err(&client->dev, "%s failed to set stream\n", __func__);
9961093
@@ -1007,9 +1104,19 @@ static int imx258_power_on(struct device *dev) · 10 unmodified lines
10071104 struct imx258 *imx258 = to_imx258(sd);
10081105 int ret;
10091106
1107+ ret = regulator_bulk_enable(IMX258_NUM_SUPPLIES,
1108+ imx258->supplies);
1109+ if (ret) {
1110+ dev_err(dev, "%s: failed to enable regulators\n",
1111+ __func__);
1112+ return ret;
1113+ }
1114+
10101115 ret = clk_prepare_enable(imx258->clk);
1011− if (ret)
1116+ if (ret) {
10121117 dev_err(dev, "failed to enable clock\n");
1118+ regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies);
1119+ }
10131120
10141121 return ret;
10151122 }
@@ -1020,6 +1127,7 @@ static int imx258_power_off(struct device *dev) · 4 unmodified lines
10201127 struct imx258 *imx258 = to_imx258(sd);
10211128
10221129 clk_disable_unprepare(imx258->clk);
1130+ regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies);
10231131
10241132 return 0;
10251133 }
@@ -1066,10 +1174,10 @@ static int imx258_identify_module(struct imx258 *imx258) · 40 unmodified lines
10661174 {
10671175 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
10681176 int ret;
1069− u32 val;
1177+ u64 val;
10701178
1071− ret = imx258_read_reg(imx258, IMX258_REG_CHIP_ID,
1072− IMX258_REG_VALUE_16BIT, &val);
1179+ ret = cci_read(imx258->regmap, IMX258_REG_CHIP_ID,
1180+ &val, NULL);
10731181 if (ret) {
10741182 dev_err(&client->dev, "failed to read chip id %x\n",
10751183 IMX258_CHIP_ID);
@@ -1077,7 +1185,7 @@ static int imx258_identify_module(struct imx258 *imx258) · 1 unmodified line
10771185 }
10781186
10791187 if (val != IMX258_CHIP_ID) {
1080− dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
1188+ dev_err(&client->dev, "chip id mismatch: %x!=%llx\n",
10811189 IMX258_CHIP_ID, val);
10821190 return -EIO;
10831191 }
@@ -1094,6 +1202,7 @@ static const struct v4l2_subdev_pad_ops imx258_pad_ops = { · 10 unmodified lines
10941202 .get_fmt = imx258_get_pad_format,
10951203 .set_fmt = imx258_set_pad_format,
10961204 .enum_frame_size = imx258_enum_frame_size,
1205+ .get_selection = imx258_get_selection,
10971206 };
10981207
10991208 static const struct v4l2_subdev_ops imx258_subdev_ops = {
@@ -1109,13 +1218,13 @@ static const struct v4l2_subdev_internal_ops imx258_internal_ops = { · 9 unmodified lines
11091218 static int imx258_init_controls(struct imx258 *imx258)
11101219 {
11111220 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
1221+ const struct imx258_link_freq_config *link_freq_cfgs;
11121222 struct v4l2_fwnode_device_properties props;
11131223 struct v4l2_ctrl_handler *ctrl_hdlr;
1114− struct v4l2_ctrl *vflip, *hflip;
1224+ const struct imx258_link_cfg *link_cfg;
11151225 s64 vblank_def;
11161226 s64 vblank_min;
1117− s64 pixel_rate_min;
1118− s64 pixel_rate_max;
1227+ s64 pixel_rate;
11191228 int ret;
11201229
11211230 ctrl_hdlr = &imx258->ctrl_handler;
@@ -1128,32 +1237,33 @@ static int imx258_init_controls(struct imx258 *imx258) · 6 unmodified lines
11281237 imx258->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
11291238 &imx258_ctrl_ops,
11301239 V4L2_CID_LINK_FREQ,
1131− ARRAY_SIZE(link_freq_menu_items) - 1,
1240+ ARRAY_SIZE(link_freq_menu_items_19_2) - 1,
11321241 0,
1133− link_freq_menu_items);
1242+ imx258->link_freq_menu_items);
11341243
11351244 if (imx258->link_freq)
11361245 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
11371246
1138− /* The driver only supports one bayer order and flips by default. */
1139− hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
1140− V4L2_CID_HFLIP, 1, 1, 1, 1);
1141− if (hflip)
1142− hflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1247+ imx258->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
1248+ V4L2_CID_HFLIP, 0, 1, 1, 1);
1249+ if (imx258->hflip)
1250+ imx258->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
1251+
1252+ imx258->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
1253+ V4L2_CID_VFLIP, 0, 1, 1, 1);
1254+ if (imx258->vflip)
1255+ imx258->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
11431256
1144− vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
1145− V4L2_CID_VFLIP, 1, 1, 1, 1);
1146− if (vflip)
1147− vflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1257+ link_freq_cfgs = &imx258->link_freq_configs[0];
1258+ link_cfg = link_freq_cfgs[imx258->lane_mode_idx].link_cfg;
1259+ pixel_rate = link_freq_to_pixel_rate(imx258->link_freq_menu_items[0],
1260+ link_cfg);
11481261
1149− pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
1150− pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]);
11511262 /* By default, PIXEL_RATE is read only */
11521263 imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
11531264 V4L2_CID_PIXEL_RATE,
1154− pixel_rate_min, pixel_rate_max,
1155− 1, pixel_rate_max);
1156−
1265+ pixel_rate, pixel_rate,
1266+ 1, pixel_rate);
11571267
11581268 vblank_def = imx258->cur_mode->vts_def - imx258->cur_mode->height;
11591269 vblank_min = imx258->cur_mode->vts_min - imx258->cur_mode->height;
@@ -1163,9 +1273,6 @@ static int imx258_init_controls(struct imx258 *imx258) · 3 unmodified lines
11631273 IMX258_VTS_MAX - imx258->cur_mode->height, 1,
11641274 vblank_def);
11651275
1166− if (imx258->vblank)
1167− imx258->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1168−
11691276 imx258->hblank = v4l2_ctrl_new_std(
11701277 ctrl_hdlr, &imx258_ctrl_ops, V4L2_CID_HBLANK,
11711278 IMX258_PPL_DEFAULT - imx258->cur_mode->width,
@@ -1232,9 +1339,25 @@ static void imx258_free_controls(struct imx258 *imx258) · 60 unmodified lines
12321339 mutex_destroy(&imx258->mutex);
12331340 }
12341341
1342+static int imx258_get_regulators(struct imx258 *imx258,
1343+ struct i2c_client *client)
1344+{
1345+ unsigned int i;
1346+
1347+ for (i = 0; i < IMX258_NUM_SUPPLIES; i++)
1348+ imx258->supplies[i].supply = imx258_supply_name[i];
1349+
1350+ return devm_regulator_bulk_get(&client->dev,
1351+ IMX258_NUM_SUPPLIES, imx258->supplies);
1352+}
1353+
12351354 static int imx258_probe(struct i2c_client *client)
12361355 {
12371356 struct imx258 *imx258;
1357+ struct fwnode_handle *endpoint;
1358+ struct v4l2_fwnode_endpoint ep = {
1359+ .bus_type = V4L2_MBUS_CSI2_DPHY
1360+ };
12381361 int ret;
12391362 u32 val = 0;
12401363
@@ -1242,6 +1365,18 @@ static int imx258_probe(struct i2c_client *client) · 1 unmodified line
12421365 if (!imx258)
12431366 return -ENOMEM;
12441367
1368+ imx258->regmap = devm_cci_regmap_init_i2c(client, 16);
1369+ if (IS_ERR(imx258->regmap)) {
1370+ ret = PTR_ERR(imx258->regmap);
1371+ dev_err(&client->dev, "failed to initialize CCI: %d\n", ret);
1372+ return ret;
1373+ }
1374+
1375+ ret = imx258_get_regulators(imx258, client);
1376+ if (ret)
1377+ return dev_err_probe(&client->dev, ret,
1378+ "failed to get regulators\n");
1379+
12451380 imx258->clk = devm_clk_get_optional(&client->dev, NULL);
12461381 if (IS_ERR(imx258->clk))
12471382 return dev_err_probe(&client->dev, PTR_ERR(imx258->clk),
@@ -1254,18 +1389,74 @@ static int imx258_probe(struct i2c_client *client) · 6 unmodified lines
12541389 } else {
12551390 val = clk_get_rate(imx258->clk);
12561391 }
1257− if (val != IMX258_INPUT_CLOCK_FREQ) {
1258− dev_err(&client->dev, "input clock frequency not supported\n");
1392+
1393+ switch (val) {
1394+ case 19200000:
1395+ imx258->link_freq_configs = link_freq_configs_19_2;
1396+ imx258->link_freq_menu_items = link_freq_menu_items_19_2;
1397+ break;
1398+ case 24000000:
1399+ imx258->link_freq_configs = link_freq_configs_24;
1400+ imx258->link_freq_menu_items = link_freq_menu_items_24;
1401+ break;
1402+ default:
1403+ dev_err(&client->dev, "input clock frequency of %u not supported\n",
1404+ val);
12591405 return -EINVAL;
12601406 }
12611407
1408+ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
1409+ if (!endpoint) {
1410+ dev_err(&client->dev, "Endpoint node not found\n");
1411+ return -EINVAL;
1412+ }
1413+
1414+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep);
1415+ fwnode_handle_put(endpoint);
1416+ if (ret) {
1417+ dev_err(&client->dev, "Parsing endpoint node failed\n");
1418+ return ret;
1419+ }
1420+
1421+ ret = v4l2_link_freq_to_bitmap(&client->dev,
1422+ ep.link_frequencies,
1423+ ep.nr_of_link_frequencies,
1424+ imx258->link_freq_menu_items,
1425+ ARRAY_SIZE(link_freq_menu_items_19_2),
1426+ &imx258->link_freq_bitmap);
1427+ if (ret) {
1428+ dev_err(&client->dev, "Link frequency not supported\n");
1429+ goto error_endpoint_free;
1430+ }
1431+
1432+ /* Get number of data lanes */
1433+ switch (ep.bus.mipi_csi2.num_data_lanes) {
1434+ case 2:
1435+ imx258->lane_mode_idx = IMX258_2_LANE_MODE;
1436+ break;
1437+ case 4:
1438+ imx258->lane_mode_idx = IMX258_4_LANE_MODE;
1439+ break;
1440+ default:
1441+ dev_err(&client->dev, "Invalid data lanes: %u\n",
1442+ ep.bus.mipi_csi2.num_data_lanes);
1443+ ret = -EINVAL;
1444+ goto error_endpoint_free;
1445+ }
1446+
1447+ imx258->csi2_flags = ep.bus.mipi_csi2.flags;
1448+
1449+ imx258->variant_cfg = device_get_match_data(&client->dev);
1450+ if (!imx258->variant_cfg)
1451+ imx258->variant_cfg = &imx258_cfg;
1452+
12621453 /* Initialize subdev */
12631454 v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);
12641455
12651456 /* Will be powered off via pm_runtime_idle */
12661457 ret = imx258_power_on(&client->dev);
12671458 if (ret)
1268− return ret;
1459+ goto error_endpoint_free;
12691460
12701461 /* Check module identity */
12711462 ret = imx258_identify_module(imx258);
@@ -1298,6 +1489,7 @@ static int imx258_probe(struct i2c_client *client) · 26 unmodified lines
12981489 pm_runtime_set_active(&client->dev);
12991490 pm_runtime_enable(&client->dev);
13001491 pm_runtime_idle(&client->dev);
1492+ v4l2_fwnode_endpoint_free(&ep);
13011493
13021494 return 0;
13031495
@@ -1310,6 +1502,9 @@ error_handler_free: · 6 unmodified lines
13101502 error_identify:
13111503 imx258_power_off(&client->dev);
13121504
1505+error_endpoint_free:
1506+ v4l2_fwnode_endpoint_free(&ep);
1507+
13131508 return ret;
13141509 }
13151510
@@ -1342,7 +1537,8 @@ MODULE_DEVICE_TABLE(acpi, imx258_acpi_ids); · 26 unmodified lines
13421537 #endif
13431538
13441539 static const struct of_device_id imx258_dt_ids[] = {
1345− { .compatible = "sony,imx258" },
1540+ { .compatible = "sony,imx258", .data = &imx258_cfg },
1541+ { .compatible = "sony,imx258-pdaf", .data = &imx258_pdaf_cfg },
13461542 { /* sentinel */ }
13471543 };
13481544 MODULE_DEVICE_TABLE(of, imx258_dt_ids);
drivers/media/i2c/imx283.c+1612−0
@@ -0,0 +1,1612 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * V4L2 Support for the IMX283
4+ *
5+ * Diagonal 15.86 mm (Type 1) CMOS Image Sensor with Square Pixel for Color
6+ * Cameras.
7+ *
8+ * Copyright (C) 2024 Ideas on Board Oy.
9+ *
10+ * Based on Sony IMX283 driver prepared by Will Whang
11+ *
12+ * Based on Sony imx477 camera driver
13+ * Copyright (C) 2019-2020 Raspberry Pi (Trading) Ltd
14+ */
15+
16+#include <linux/array_size.h>
17+#include <linux/bitops.h>
18+#include <linux/container_of.h>
19+#include <linux/clk.h>
20+#include <linux/delay.h>
21+#include <linux/err.h>
22+#include <linux/gpio/consumer.h>
23+#include <linux/i2c.h>
24+#include <linux/minmax.h>
25+#include <linux/module.h>
26+#include <linux/mutex.h>
27+#include <linux/pm_runtime.h>
28+#include <linux/property.h>
29+#include <linux/regulator/consumer.h>
30+#include <linux/types.h>
31+#include <linux/units.h>
32+#include <media/v4l2-cci.h>
33+#include <media/v4l2-ctrls.h>
34+#include <media/v4l2-device.h>
35+#include <media/v4l2-event.h>
36+#include <media/v4l2-fwnode.h>
37+#include <media/v4l2-mediabus.h>
38+
39+/* Chip ID */
40+#define IMX283_REG_CHIP_ID CCI_REG8(0x3000)
41+#define IMX283_CHIP_ID 0x0b // Default power on state
42+
43+#define IMX283_REG_STANDBY CCI_REG8(0x3000)
44+#define IMX283_ACTIVE 0
45+#define IMX283_STANDBY BIT(0)
46+#define IMX283_STBLOGIC BIT(1)
47+#define IMX283_STBMIPI BIT(2)
48+#define IMX283_STBDV BIT(3)
49+#define IMX283_SLEEP BIT(4)
50+
51+#define IMX283_REG_CLAMP CCI_REG8(0x3001)
52+#define IMX283_CLPSQRST BIT(4)
53+
54+#define IMX283_REG_PLSTMG08 CCI_REG8(0x3003)
55+#define IMX283_PLSTMG08_VAL 0x77
56+
57+#define IMX283_REG_MDSEL1 CCI_REG8(0x3004)
58+#define IMX283_REG_MDSEL2 CCI_REG8(0x3005)
59+#define IMX283_REG_MDSEL3 CCI_REG8(0x3006)
60+#define IMX283_MDSEL3_VCROP_EN BIT(5)
61+#define IMX283_REG_MDSEL4 CCI_REG8(0x3007)
62+#define IMX283_MDSEL4_VCROP_EN (BIT(4) | BIT(6))
63+
64+#define IMX283_REG_SVR CCI_REG16_LE(0x3009)
65+
66+#define IMX283_REG_HTRIMMING CCI_REG8(0x300b)
67+#define IMX283_MDVREV BIT(0) /* VFLIP */
68+#define IMX283_HTRIMMING_EN BIT(4)
69+
70+#define IMX283_REG_VWINPOS CCI_REG16_LE(0x300f)
71+#define IMX283_REG_VWIDCUT CCI_REG16_LE(0x3011)
72+
73+#define IMX283_REG_MDSEL7 CCI_REG16_LE(0x3013)
74+
75+/* CSI Clock Configuration */
76+#define IMX283_REG_TCLKPOST CCI_REG8(0x3018)
77+#define IMX283_REG_THSPREPARE CCI_REG8(0x301a)
78+#define IMX283_REG_THSZERO CCI_REG8(0x301c)
79+#define IMX283_REG_THSTRAIL CCI_REG8(0x301e)
80+#define IMX283_REG_TCLKTRAIL CCI_REG8(0x3020)
81+#define IMX283_REG_TCLKPREPARE CCI_REG8(0x3022)
82+#define IMX283_REG_TCLKZERO CCI_REG16_LE(0x3024)
83+#define IMX283_REG_TLPX CCI_REG8(0x3026)
84+#define IMX283_REG_THSEXIT CCI_REG8(0x3028)
85+#define IMX283_REG_TCLKPRE CCI_REG8(0x302a)
86+#define IMX283_REG_SYSMODE CCI_REG8(0x3104)
87+
88+#define IMX283_REG_Y_OUT_SIZE CCI_REG16_LE(0x302f)
89+#define IMX283_REG_WRITE_VSIZE CCI_REG16_LE(0x3031)
90+#define IMX283_REG_OB_SIZE_V CCI_REG8(0x3033)
91+
92+/* HMAX internal HBLANK */
93+#define IMX283_REG_HMAX CCI_REG16_LE(0x3036)
94+#define IMX283_HMAX_MAX (BIT(16) - 1)
95+
96+/* VMAX internal VBLANK */
97+#define IMX283_REG_VMAX CCI_REG24_LE(0x3038)
98+#define IMX283_VMAX_MAX (BIT(16) - 1)
99+
100+/* SHR internal */
101+#define IMX283_REG_SHR CCI_REG16_LE(0x303b)
102+#define IMX283_SHR_MIN 11
103+
104+/*
105+ * Analog gain control
106+ * Gain [dB] = -20log{(2048 - value [10:0]) /2048}
107+ * Range: 0dB to approximately +27dB
108+ */
109+#define IMX283_REG_ANALOG_GAIN CCI_REG16_LE(0x3042)
110+#define IMX283_ANA_GAIN_MIN 0
111+#define IMX283_ANA_GAIN_MAX 1957
112+#define IMX283_ANA_GAIN_STEP 1
113+#define IMX283_ANA_GAIN_DEFAULT 0x0
114+
115+/*
116+ * Digital gain control
117+ * Gain [dB] = value * 6
118+ * Range: 0dB to +18db
119+ */
120+#define IMX283_REG_DIGITAL_GAIN CCI_REG8(0x3044)
121+#define IMX283_DGTL_GAIN_MIN 0
122+#define IMX283_DGTL_GAIN_MAX 3
123+#define IMX283_DGTL_GAIN_DEFAULT 0
124+#define IMX283_DGTL_GAIN_STEP 1
125+
126+#define IMX283_REG_HTRIMMING_START CCI_REG16_LE(0x3058)
127+#define IMX283_REG_HTRIMMING_END CCI_REG16_LE(0x305a)
128+
129+#define IMX283_REG_MDSEL18 CCI_REG16_LE(0x30f6)
130+
131+/* Master Mode Operation Control */
132+#define IMX283_REG_XMSTA CCI_REG8(0x3105)
133+#define IMX283_XMSTA BIT(0)
134+
135+#define IMX283_REG_SYNCDRV CCI_REG8(0x3107)
136+#define IMX283_SYNCDRV_XHS_XVS (0xa0 | 0x02)
137+#define IMX283_SYNCDRV_HIZ (0xa0 | 0x03)
138+
139+/* PLL Standby */
140+#define IMX283_REG_STBPL CCI_REG8(0x320b)
141+#define IMX283_STBPL_NORMAL 0x00
142+#define IMX283_STBPL_STANDBY 0x03
143+
144+/* Input Frequency Setting */
145+#define IMX283_REG_PLRD1 CCI_REG8(0x36c1)
146+#define IMX283_REG_PLRD2 CCI_REG16_LE(0x36c2)
147+#define IMX283_REG_PLRD3 CCI_REG8(0x36f7)
148+#define IMX283_REG_PLRD4 CCI_REG8(0x36f8)
149+
150+#define IMX283_REG_PLSTMG02 CCI_REG8(0x36aa)
151+#define IMX283_PLSTMG02_VAL 0x00
152+
153+#define IMX283_REG_EBD_X_OUT_SIZE CCI_REG16_LE(0x3a54)
154+
155+/* Test pattern generator */
156+#define IMX283_REG_TPG_CTRL CCI_REG8(0x3156)
157+#define IMX283_TPG_CTRL_CLKEN BIT(0)
158+#define IMX283_TPG_CTRL_PATEN BIT(4)
159+
160+#define IMX283_REG_TPG_PAT CCI_REG8(0x3157)
161+#define IMX283_TPG_PAT_ALL_000 0x00
162+#define IMX283_TPG_PAT_ALL_FFF 0x01
163+#define IMX283_TPG_PAT_ALL_555 0x02
164+#define IMX283_TPG_PAT_ALL_AAA 0x03
165+#define IMX283_TPG_PAT_H_COLOR_BARS 0x0a
166+#define IMX283_TPG_PAT_V_COLOR_BARS 0x0b
167+
168+/* Exposure control */
169+#define IMX283_EXPOSURE_MIN 52
170+#define IMX283_EXPOSURE_STEP 1
171+#define IMX283_EXPOSURE_DEFAULT 1000
172+#define IMX283_EXPOSURE_MAX 49865
173+
174+#define IMAGE_PAD 0
175+
176+#define IMX283_XCLR_MIN_DELAY_US (1 * USEC_PER_MSEC)
177+#define IMX283_XCLR_DELAY_RANGE_US (1 * USEC_PER_MSEC)
178+
179+/* IMX283 native and active pixel array size. */
180+static const struct v4l2_rect imx283_native_area = {
181+ .top = 0,
182+ .left = 0,
183+ .width = 5592,
184+ .height = 3710,
185+};
186+
187+static const struct v4l2_rect imx283_active_area = {
188+ .top = 40,
189+ .left = 108,
190+ .width = 5472,
191+ .height = 3648,
192+};
193+
194+struct imx283_reg_list {
195+ unsigned int num_of_regs;
196+ const struct cci_reg_sequence *regs;
197+};
198+
199+/* Mode : resolution and related config values */
200+struct imx283_mode {
201+ unsigned int mode;
202+
203+ /* Bits per pixel */
204+ unsigned int bpp;
205+
206+ /* Frame width */
207+ unsigned int width;
208+
209+ /* Frame height */
210+ unsigned int height;
211+
212+ /*
213+ * Minimum horizontal timing in pixel-units
214+ *
215+ * Note that HMAX is written in 72MHz units, and the datasheet assumes a
216+ * 720MHz link frequency. Convert datasheet values with the following:
217+ *
218+ * For 12 bpp modes (480Mbps) convert with:
219+ * hmax = [hmax in 72MHz units] * 480 / 72
220+ *
221+ * For 10 bpp modes (576Mbps) convert with:
222+ * hmax = [hmax in 72MHz units] * 576 / 72
223+ */
224+ u32 min_hmax;
225+
226+ /* minimum V-timing in lines */
227+ u32 min_vmax;
228+
229+ /* default H-timing */
230+ u32 default_hmax;
231+
232+ /* default V-timing */
233+ u32 default_vmax;
234+
235+ /* minimum SHR */
236+ u32 min_shr;
237+
238+ /*
239+ * Per-mode vertical crop constants used to calculate values
240+ * of IMX283REG_WIDCUT and IMX283_REG_VWINPOS.
241+ */
242+ u32 veff;
243+ u32 vst;
244+ u32 vct;
245+
246+ /* Horizontal and vertical binning ratio */
247+ u8 hbin_ratio;
248+ u8 vbin_ratio;
249+
250+ /* Optical Blanking */
251+ u32 horizontal_ob;
252+ u32 vertical_ob;
253+
254+ /* Analog crop rectangle. */
255+ struct v4l2_rect crop;
256+};
257+
258+struct imx283_input_frequency {
259+ unsigned int mhz;
260+ unsigned int reg_count;
261+ struct cci_reg_sequence regs[4];
262+};
263+
264+static const struct imx283_input_frequency imx283_frequencies[] = {
265+ {
266+ .mhz = 6 * HZ_PER_MHZ,
267+ .reg_count = 4,
268+ .regs = {
269+ { IMX283_REG_PLRD1, 0x00 },
270+ { IMX283_REG_PLRD2, 0x00f0 },
271+ { IMX283_REG_PLRD3, 0x00 },
272+ { IMX283_REG_PLRD4, 0xc0 },
273+ },
274+ },
275+ {
276+ .mhz = 12 * HZ_PER_MHZ,
277+ .reg_count = 4,
278+ .regs = {
279+ { IMX283_REG_PLRD1, 0x01 },
280+ { IMX283_REG_PLRD2, 0x00f0 },
281+ { IMX283_REG_PLRD3, 0x01 },
282+ { IMX283_REG_PLRD4, 0xc0 },
283+ },
284+ },
285+ {
286+ .mhz = 18 * HZ_PER_MHZ,
287+ .reg_count = 4,
288+ .regs = {
289+ { IMX283_REG_PLRD1, 0x01 },
290+ { IMX283_REG_PLRD2, 0x00a0 },
291+ { IMX283_REG_PLRD3, 0x01 },
292+ { IMX283_REG_PLRD4, 0x80 },
293+ },
294+ },
295+ {
296+ .mhz = 24 * HZ_PER_MHZ,
297+ .reg_count = 4,
298+ .regs = {
299+ { IMX283_REG_PLRD1, 0x02 },
300+ { IMX283_REG_PLRD2, 0x00f0 },
301+ { IMX283_REG_PLRD3, 0x02 },
302+ { IMX283_REG_PLRD4, 0xc0 },
303+ },
304+ },
305+};
306+
307+enum imx283_modes {
308+ IMX283_MODE_0,
309+ IMX283_MODE_1,
310+ IMX283_MODE_1A,
311+ IMX283_MODE_1S,
312+ IMX283_MODE_2,
313+ IMX283_MODE_2A,
314+ IMX283_MODE_3,
315+ IMX283_MODE_4,
316+ IMX283_MODE_5,
317+ IMX283_MODE_6,
318+};
319+
320+struct imx283_readout_mode {
321+ u8 mdsel1;
322+ u8 mdsel2;
323+ u8 mdsel3;
324+ u8 mdsel4;
325+};
326+
327+static const struct imx283_readout_mode imx283_readout_modes[] = {
328+ /* All pixel scan modes */
329+ [IMX283_MODE_0] = { 0x04, 0x03, 0x10, 0x00 }, /* 12 bit */
330+ [IMX283_MODE_1] = { 0x04, 0x01, 0x00, 0x00 }, /* 10 bit */
331+ [IMX283_MODE_1A] = { 0x04, 0x01, 0x20, 0x50 }, /* 10 bit */
332+ [IMX283_MODE_1S] = { 0x04, 0x41, 0x20, 0x50 }, /* 10 bit */
333+
334+ /* Horizontal / Vertical 2/2-line binning */
335+ [IMX283_MODE_2] = { 0x0d, 0x11, 0x50, 0x00 }, /* 12 bit */
336+ [IMX283_MODE_2A] = { 0x0d, 0x11, 0x70, 0x50 }, /* 12 bit */
337+
338+ /* Horizontal / Vertical 3/3-line binning */
339+ [IMX283_MODE_3] = { 0x1e, 0x18, 0x10, 0x00 }, /* 12 bit */
340+
341+ /* Vertical 2/9 subsampling, horizontal 3 binning cropping */
342+ [IMX283_MODE_4] = { 0x29, 0x18, 0x30, 0x50 }, /* 12 bit */
343+
344+ /* Vertical 2/19 subsampling binning, horizontal 3 binning */
345+ [IMX283_MODE_5] = { 0x2d, 0x18, 0x10, 0x00 }, /* 12 bit */
346+
347+ /* Vertical 2 binning horizontal 2/4, subsampling 16:9 cropping */
348+ [IMX283_MODE_6] = { 0x18, 0x21, 0x00, 0x09 }, /* 10 bit */
349+
350+ /*
351+ * New modes should make sure the offset period is complied.
352+ * See imx283_exposure() for reference.
353+ */
354+};
355+
356+static const struct cci_reg_sequence mipi_data_rate_1440Mbps[] = {
357+ /* The default register settings provide the 1440Mbps rate */
358+ { CCI_REG8(0x36c5), 0x00 }, /* Undocumented */
359+ { CCI_REG8(0x3ac4), 0x00 }, /* Undocumented */
360+
361+ { IMX283_REG_STBPL, 0x00 },
362+ { IMX283_REG_TCLKPOST, 0xa7 },
363+ { IMX283_REG_THSPREPARE, 0x6f },
364+ { IMX283_REG_THSZERO, 0x9f },
365+ { IMX283_REG_THSTRAIL, 0x5f },
366+ { IMX283_REG_TCLKTRAIL, 0x5f },
367+ { IMX283_REG_TCLKPREPARE, 0x6f },
368+ { IMX283_REG_TCLKZERO, 0x017f },
369+ { IMX283_REG_TLPX, 0x4f },
370+ { IMX283_REG_THSEXIT, 0x47 },
371+ { IMX283_REG_TCLKPRE, 0x07 },
372+ { IMX283_REG_SYSMODE, 0x02 },
373+};
374+
375+static const struct cci_reg_sequence mipi_data_rate_720Mbps[] = {
376+ /* Undocumented Additions "For 720MBps" Setting */
377+ { CCI_REG8(0x36c5), 0x01 }, /* Undocumented */
378+ { CCI_REG8(0x3ac4), 0x01 }, /* Undocumented */
379+
380+ { IMX283_REG_STBPL, 0x00 },
381+ { IMX283_REG_TCLKPOST, 0x77 },
382+ { IMX283_REG_THSPREPARE, 0x37 },
383+ { IMX283_REG_THSZERO, 0x67 },
384+ { IMX283_REG_THSTRAIL, 0x37 },
385+ { IMX283_REG_TCLKTRAIL, 0x37 },
386+ { IMX283_REG_TCLKPREPARE, 0x37 },
387+ { IMX283_REG_TCLKZERO, 0xdf },
388+ { IMX283_REG_TLPX, 0x2f },
389+ { IMX283_REG_THSEXIT, 0x47 },
390+ { IMX283_REG_TCLKPRE, 0x0f },
391+ { IMX283_REG_SYSMODE, 0x02 },
392+};
393+
394+static const s64 link_frequencies[] = {
395+ 720 * HZ_PER_MHZ, /* 1440 Mbps lane data rate */
396+ 360 * HZ_PER_MHZ, /* 720 Mbps data lane rate */
397+};
398+
399+static const struct imx283_reg_list link_freq_reglist[] = {
400+ { /* 720 MHz */
401+ .num_of_regs = ARRAY_SIZE(mipi_data_rate_1440Mbps),
402+ .regs = mipi_data_rate_1440Mbps,
403+ },
404+ { /* 360 MHz */
405+ .num_of_regs = ARRAY_SIZE(mipi_data_rate_720Mbps),
406+ .regs = mipi_data_rate_720Mbps,
407+ },
408+};
409+
410+/* Mode configs */
411+static const struct imx283_mode supported_modes_12bit[] = {
412+ {
413+ /* 20MPix 21.40 fps readout mode 0 */
414+ .mode = IMX283_MODE_0,
415+ .bpp = 12,
416+ .width = 5472,
417+ .height = 3648,
418+ .min_hmax = 5914, /* 887 @ 480MHz/72MHz */
419+ .min_vmax = 3793, /* Lines */
420+
421+ .veff = 3694,
422+ .vst = 0,
423+ .vct = 0,
424+
425+ .hbin_ratio = 1,
426+ .vbin_ratio = 1,
427+
428+ /* 20.00 FPS */
429+ .default_hmax = 6000, /* 900 @ 480MHz/72MHz */
430+ .default_vmax = 4000,
431+
432+ .min_shr = 11,
433+ .horizontal_ob = 96,
434+ .vertical_ob = 16,
435+ .crop = {
436+ .top = 40,
437+ .left = 108,
438+ .width = 5472,
439+ .height = 3648,
440+ },
441+ },
442+ {
443+ /*
444+ * Readout mode 2 : 2/2 binned mode (2736x1824)
445+ */
446+ .mode = IMX283_MODE_2,
447+ .bpp = 12,
448+ .width = 2736,
449+ .height = 1824,
450+ .min_hmax = 2414, /* Pixels (362 * 480MHz/72MHz + padding) */
451+ .min_vmax = 3840, /* Lines */
452+
453+ /* 50.00 FPS */
454+ .default_hmax = 2500, /* 375 @ 480MHz/72Mhz */
455+ .default_vmax = 3840,
456+
457+ .veff = 1824,
458+ .vst = 0,
459+ .vct = 0,
460+
461+ .hbin_ratio = 2,
462+ .vbin_ratio = 2,
463+
464+ .min_shr = 12,
465+ .horizontal_ob = 48,
466+ .vertical_ob = 4,
467+
468+ .crop = {
469+ .top = 40,
470+ .left = 108,
471+ .width = 5472,
472+ .height = 3648,
473+ },
474+ },
475+};
476+
477+static const struct imx283_mode supported_modes_10bit[] = {
478+ {
479+ /* 20MPix 25.48 fps readout mode 1 */
480+ .mode = IMX283_MODE_1,
481+ .bpp = 10,
482+ .width = 5472,
483+ .height = 3648,
484+ .min_hmax = 5960, /* 745 @ 576MHz / 72MHz */
485+ .min_vmax = 3793,
486+
487+ /* 25.00 FPS */
488+ .default_hmax = 6000, /* 750 @ 576MHz / 72MHz */
489+ .default_vmax = 3840,
490+
491+ .min_shr = 10,
492+ .horizontal_ob = 96,
493+ .vertical_ob = 16,
494+ .crop = {
495+ .top = 40,
496+ .left = 108,
497+ .width = 5472,
498+ .height = 3648,
499+ },
500+ },
501+};
502+
503+static const u32 imx283_mbus_codes[] = {
504+ MEDIA_BUS_FMT_SRGGB12_1X12,
505+ MEDIA_BUS_FMT_SRGGB10_1X10,
506+};
507+
508+/* regulator supplies */
509+static const char *const imx283_supply_name[] = {
510+ "vadd", /* Analog (2.9V) supply */
511+ "vdd1", /* Supply Voltage 2 (1.8V) supply */
512+ "vdd2", /* Supply Voltage 3 (1.2V) supply */
513+};
514+
515+struct imx283 {
516+ struct device *dev;
517+ struct regmap *cci;
518+
519+ const struct imx283_input_frequency *freq;
520+
521+ struct v4l2_subdev sd;
522+ struct media_pad pad;
523+
524+ struct clk *xclk;
525+
526+ struct gpio_desc *reset_gpio;
527+ struct regulator_bulk_data supplies[ARRAY_SIZE(imx283_supply_name)];
528+
529+ /* V4L2 Controls */
530+ struct v4l2_ctrl_handler ctrl_handler;
531+ struct v4l2_ctrl *exposure;
532+ struct v4l2_ctrl *vblank;
533+ struct v4l2_ctrl *hblank;
534+ struct v4l2_ctrl *vflip;
535+
536+ unsigned long link_freq_bitmap;
537+
538+ u16 hmax;
539+ u32 vmax;
540+};
541+
542+static inline struct imx283 *to_imx283(struct v4l2_subdev *sd)
543+{
544+ return container_of_const(sd, struct imx283, sd);
545+}
546+
547+static inline void get_mode_table(unsigned int code,
548+ const struct imx283_mode **mode_list,
549+ unsigned int *num_modes)
550+{
551+ switch (code) {
552+ case MEDIA_BUS_FMT_SRGGB12_1X12:
553+ case MEDIA_BUS_FMT_SGRBG12_1X12:
554+ case MEDIA_BUS_FMT_SGBRG12_1X12:
555+ case MEDIA_BUS_FMT_SBGGR12_1X12:
556+ *mode_list = supported_modes_12bit;
557+ *num_modes = ARRAY_SIZE(supported_modes_12bit);
558+ break;
559+
560+ case MEDIA_BUS_FMT_SRGGB10_1X10:
561+ case MEDIA_BUS_FMT_SGRBG10_1X10:
562+ case MEDIA_BUS_FMT_SGBRG10_1X10:
563+ case MEDIA_BUS_FMT_SBGGR10_1X10:
564+ *mode_list = supported_modes_10bit;
565+ *num_modes = ARRAY_SIZE(supported_modes_10bit);
566+ break;
567+ default:
568+ *mode_list = NULL;
569+ *num_modes = 0;
570+ break;
571+ }
572+}
573+
574+/* Calculate the Pixel Rate based on the current mode */
575+static u64 imx283_pixel_rate(struct imx283 *imx283,
576+ const struct imx283_mode *mode)
577+{
578+ u64 link_frequency = link_frequencies[__ffs(imx283->link_freq_bitmap)];
579+ unsigned int bpp = mode->bpp;
580+ const unsigned int ddr = 2; /* Double Data Rate */
581+ const unsigned int lanes = 4; /* Only 4 lane support */
582+ u64 numerator = link_frequency * ddr * lanes;
583+
584+ do_div(numerator, bpp);
585+
586+ return numerator;
587+}
588+
589+/* Convert from a variable pixel_rate to 72 MHz clock cycles */
590+static u64 imx283_internal_clock(unsigned int pixel_rate, unsigned int pixels)
591+{
592+ /*
593+ * Determine the following operation without overflow:
594+ * pixels = 72 Mhz / pixel_rate
595+ *
596+ * The internal clock at 72MHz and Pixel Rate (between 240 and 576MHz)
597+ * can easily overflow this calculation, so pre-divide to simplify.
598+ */
599+ const u32 iclk_pre = 72;
600+ const u32 pclk_pre = pixel_rate / HZ_PER_MHZ;
601+ u64 numerator = pixels * iclk_pre;
602+
603+ do_div(numerator, pclk_pre);
604+
605+ return numerator;
606+}
607+
608+/* Internal clock (72MHz) to Pixel Rate clock (Variable) */
609+static u64 imx283_iclk_to_pix(unsigned int pixel_rate, unsigned int cycles)
610+{
611+ /*
612+ * Determine the following operation without overflow:
613+ * cycles * pixel_rate / 72 MHz
614+ *
615+ * The internal clock at 72MHz and Pixel Rate (between 240 and 576MHz)
616+ * can easily overflow this calculation, so pre-divide to simplify.
617+ */
618+ const u32 iclk_pre = 72;
619+ const u32 pclk_pre = pixel_rate / HZ_PER_MHZ;
620+ u64 numerator = cycles * pclk_pre;
621+
622+ do_div(numerator, iclk_pre);
623+
624+ return numerator;
625+}
626+
627+/* Determine the exposure based on current hmax, vmax and a given SHR */
628+static u32 imx283_exposure(struct imx283 *imx283,
629+ const struct imx283_mode *mode, u64 shr)
630+{
631+ u32 svr = 0; /* SVR feature is not currently supported */
632+ u32 offset;
633+ u64 numerator;
634+
635+ /* Number of clocks per internal offset period */
636+ offset = mode->mode == IMX283_MODE_0 ? 209 : 157;
637+ numerator = (imx283->vmax * (svr + 1) - shr) * imx283->hmax + offset;
638+
639+ do_div(numerator, imx283->hmax);
640+
641+ return clamp(numerator, 0, U32_MAX);
642+}
643+
644+static void imx283_exposure_limits(struct imx283 *imx283,
645+ const struct imx283_mode *mode,
646+ s64 *min_exposure, s64 *max_exposure)
647+{
648+ u32 svr = 0; /* SVR feature is not currently supported */
649+ u64 min_shr = mode->min_shr;
650+ /* Global Shutter is not supported */
651+ u64 max_shr = (svr + 1) * imx283->vmax - 4;
652+
653+ max_shr = min(max_shr, BIT(16) - 1);
654+
655+ *min_exposure = imx283_exposure(imx283, mode, max_shr);
656+ *max_exposure = imx283_exposure(imx283, mode, min_shr);
657+}
658+
659+/*
660+ * Integration Time [s] = [ {VMAX x (SVR + 1) – (SHR)} x HMAX + offset ]
661+ * / [ 72 x 10^6 ]
662+ */
663+static u32 imx283_shr(struct imx283 *imx283, const struct imx283_mode *mode,
664+ u32 exposure)
665+{
666+ u32 svr = 0; /* SVR feature is not currently supported */
667+ u32 offset;
668+ u64 temp;
669+
670+ /* Number of clocks per internal offset period */
671+ offset = mode->mode == IMX283_MODE_0 ? 209 : 157;
672+ temp = ((u64)exposure * imx283->hmax - offset);
673+ do_div(temp, imx283->hmax);
674+
675+ return (imx283->vmax * (svr + 1) - temp);
676+}
677+
678+static const char * const imx283_tpg_menu[] = {
679+ "Disabled",
680+ "All 000h",
681+ "All FFFh",
682+ "All 555h",
683+ "All AAAh",
684+ "Horizontal color bars",
685+ "Vertical color bars",
686+};
687+
688+static const int imx283_tpg_val[] = {
689+ IMX283_TPG_PAT_ALL_000,
690+ IMX283_TPG_PAT_ALL_000,
691+ IMX283_TPG_PAT_ALL_FFF,
692+ IMX283_TPG_PAT_ALL_555,
693+ IMX283_TPG_PAT_ALL_AAA,
694+ IMX283_TPG_PAT_H_COLOR_BARS,
695+ IMX283_TPG_PAT_V_COLOR_BARS,
696+};
697+
698+static int imx283_update_test_pattern(struct imx283 *imx283, u32 pattern_index)
699+{
700+ int ret;
701+
702+ if (pattern_index >= ARRAY_SIZE(imx283_tpg_val))
703+ return -EINVAL;
704+
705+ if (!pattern_index)
706+ return cci_write(imx283->cci, IMX283_REG_TPG_CTRL, 0x00, NULL);
707+
708+ ret = cci_write(imx283->cci, IMX283_REG_TPG_PAT,
709+ imx283_tpg_val[pattern_index], NULL);
710+ if (ret)
711+ return ret;
712+
713+ return cci_write(imx283->cci, IMX283_REG_TPG_CTRL,
714+ IMX283_TPG_CTRL_CLKEN | IMX283_TPG_CTRL_PATEN, NULL);
715+}
716+
717+static int imx283_set_ctrl(struct v4l2_ctrl *ctrl)
718+{
719+ struct imx283 *imx283 = container_of(ctrl->handler, struct imx283,
720+ ctrl_handler);
721+ const struct imx283_mode *mode;
722+ struct v4l2_mbus_framefmt *fmt;
723+ const struct imx283_mode *mode_list;
724+ struct v4l2_subdev_state *state;
725+ unsigned int num_modes;
726+ u64 shr, pixel_rate;
727+ int ret = 0;
728+
729+ state = v4l2_subdev_get_locked_active_state(&imx283->sd);
730+ fmt = v4l2_subdev_state_get_format(state, 0);
731+
732+ get_mode_table(fmt->code, &mode_list, &num_modes);
733+ mode = v4l2_find_nearest_size(mode_list, num_modes, width, height,
734+ fmt->width, fmt->height);
735+
736+ /*
737+ * The VBLANK control may change the limits of usable exposure, so check
738+ * and adjust if necessary.
739+ */
740+ if (ctrl->id == V4L2_CID_VBLANK) {
741+ /* Honour the VBLANK limits when setting exposure. */
742+ s64 current_exposure, max_exposure, min_exposure;
743+
744+ imx283->vmax = mode->height + ctrl->val;
745+
746+ imx283_exposure_limits(imx283, mode,
747+ &min_exposure, &max_exposure);
748+
749+ current_exposure = imx283->exposure->val;
750+ current_exposure = clamp(current_exposure, min_exposure,
751+ max_exposure);
752+
753+ __v4l2_ctrl_modify_range(imx283->exposure, min_exposure,
754+ max_exposure, 1, current_exposure);
755+ }
756+
757+ /*
758+ * Applying V4L2 control value only happens
759+ * when power is up for streaming
760+ */
761+ if (!pm_runtime_get_if_active(imx283->dev))
762+ return 0;
763+
764+ switch (ctrl->id) {
765+ case V4L2_CID_EXPOSURE:
766+ shr = imx283_shr(imx283, mode, ctrl->val);
767+ dev_dbg(imx283->dev, "V4L2_CID_EXPOSURE : %d - SHR: %lld\n",
768+ ctrl->val, shr);
769+ ret = cci_write(imx283->cci, IMX283_REG_SHR, shr, NULL);
770+ break;
771+
772+ case V4L2_CID_HBLANK:
773+ pixel_rate = imx283_pixel_rate(imx283, mode);
774+ imx283->hmax = imx283_internal_clock(pixel_rate, mode->width + ctrl->val);
775+ dev_dbg(imx283->dev, "V4L2_CID_HBLANK : %d HMAX : %u\n",
776+ ctrl->val, imx283->hmax);
777+ ret = cci_write(imx283->cci, IMX283_REG_HMAX, imx283->hmax, NULL);
778+ break;
779+
780+ case V4L2_CID_VBLANK:
781+ imx283->vmax = mode->height + ctrl->val;
782+ dev_dbg(imx283->dev, "V4L2_CID_VBLANK : %d VMAX : %u\n",
783+ ctrl->val, imx283->vmax);
784+ ret = cci_write(imx283->cci, IMX283_REG_VMAX, imx283->vmax, NULL);
785+ break;
786+
787+ case V4L2_CID_ANALOGUE_GAIN:
788+ ret = cci_write(imx283->cci, IMX283_REG_ANALOG_GAIN, ctrl->val, NULL);
789+ break;
790+
791+ case V4L2_CID_DIGITAL_GAIN:
792+ ret = cci_write(imx283->cci, IMX283_REG_DIGITAL_GAIN, ctrl->val, NULL);
793+ break;
794+
795+ case V4L2_CID_VFLIP:
796+ /*
797+ * VFLIP is managed by BIT(0) of IMX283_REG_HTRIMMING address, hence
798+ * both need to be set simultaneously.
799+ */
800+ if (ctrl->val) {
801+ cci_write(imx283->cci, IMX283_REG_HTRIMMING,
802+ IMX283_HTRIMMING_EN | IMX283_MDVREV, &ret);
803+ } else {
804+ cci_write(imx283->cci, IMX283_REG_HTRIMMING,
805+ IMX283_HTRIMMING_EN, &ret);
806+ }
807+ break;
808+
809+ case V4L2_CID_TEST_PATTERN:
810+ ret = imx283_update_test_pattern(imx283, ctrl->val);
811+ break;
812+
813+ default:
814+ dev_err(imx283->dev, "ctrl(id:0x%x, val:0x%x) is not handled\n",
815+ ctrl->id, ctrl->val);
816+ break;
817+ }
818+
819+ pm_runtime_put(imx283->dev);
820+
821+ return ret;
822+}
823+
824+static const struct v4l2_ctrl_ops imx283_ctrl_ops = {
825+ .s_ctrl = imx283_set_ctrl,
826+};
827+
828+static int imx283_enum_mbus_code(struct v4l2_subdev *sd,
829+ struct v4l2_subdev_state *sd_state,
830+ struct v4l2_subdev_mbus_code_enum *code)
831+{
832+ if (code->index >= ARRAY_SIZE(imx283_mbus_codes))
833+ return -EINVAL;
834+
835+ code->code = imx283_mbus_codes[code->index];
836+
837+ return 0;
838+}
839+
840+static int imx283_enum_frame_size(struct v4l2_subdev *sd,
841+ struct v4l2_subdev_state *sd_state,
842+ struct v4l2_subdev_frame_size_enum *fse)
843+{
844+ const struct imx283_mode *mode_list;
845+ unsigned int num_modes;
846+
847+ get_mode_table(fse->code, &mode_list, &num_modes);
848+
849+ if (fse->index >= num_modes)
850+ return -EINVAL;
851+
852+ fse->min_width = mode_list[fse->index].width;
853+ fse->max_width = fse->min_width;
854+ fse->min_height = mode_list[fse->index].height;
855+ fse->max_height = fse->min_height;
856+
857+ return 0;
858+}
859+
860+static void imx283_update_image_pad_format(struct imx283 *imx283,
861+ const struct imx283_mode *mode,
862+ struct v4l2_mbus_framefmt *format)
863+{
864+ format->width = mode->width;
865+ format->height = mode->height;
866+ format->field = V4L2_FIELD_NONE;
867+ format->colorspace = V4L2_COLORSPACE_RAW;
868+ format->ycbcr_enc = V4L2_YCBCR_ENC_601;
869+ format->quantization = V4L2_QUANTIZATION_FULL_RANGE;
870+ format->xfer_func = V4L2_XFER_FUNC_NONE;
871+}
872+
873+static int imx283_init_state(struct v4l2_subdev *sd,
874+ struct v4l2_subdev_state *state)
875+{
876+ struct imx283 *imx283 = to_imx283(sd);
877+ struct v4l2_mbus_framefmt *format;
878+ const struct imx283_mode *mode;
879+ struct v4l2_rect *crop;
880+
881+ /* Initialize try_fmt */
882+ format = v4l2_subdev_state_get_format(state, IMAGE_PAD);
883+
884+ mode = &supported_modes_12bit[0];
885+ format->code = MEDIA_BUS_FMT_SRGGB12_1X12;
886+ imx283_update_image_pad_format(imx283, mode, format);
887+
888+ /* Initialize crop rectangle to mode default */
889+ crop = v4l2_subdev_state_get_crop(state, IMAGE_PAD);
890+ *crop = mode->crop;
891+
892+ return 0;
893+}
894+
895+static void imx283_set_framing_limits(struct imx283 *imx283,
896+ const struct imx283_mode *mode)
897+{
898+ u64 pixel_rate = imx283_pixel_rate(imx283, mode);
899+ u64 min_hblank, max_hblank, def_hblank;
900+
901+ /* Initialise hmax and vmax for exposure calculations */
902+ imx283->hmax = imx283_internal_clock(pixel_rate, mode->default_hmax);
903+ imx283->vmax = mode->default_vmax;
904+
905+ /*
906+ * Horizontal Blanking
907+ * Convert the HMAX_MAX (72MHz) to Pixel rate values for HBLANK_MAX
908+ */
909+ min_hblank = mode->min_hmax - mode->width;
910+ max_hblank = imx283_iclk_to_pix(pixel_rate, IMX283_HMAX_MAX) - mode->width;
911+ def_hblank = mode->default_hmax - mode->width;
912+ __v4l2_ctrl_modify_range(imx283->hblank, min_hblank, max_hblank, 1,
913+ def_hblank);
914+ __v4l2_ctrl_s_ctrl(imx283->hblank, def_hblank);
915+
916+ /* Vertical Blanking */
917+ __v4l2_ctrl_modify_range(imx283->vblank, mode->min_vmax - mode->height,
918+ IMX283_VMAX_MAX - mode->height, 1,
919+ mode->default_vmax - mode->height);
920+ __v4l2_ctrl_s_ctrl(imx283->vblank, mode->default_vmax - mode->height);
921+}
922+
923+static int imx283_set_pad_format(struct v4l2_subdev *sd,
924+ struct v4l2_subdev_state *sd_state,
925+ struct v4l2_subdev_format *fmt)
926+{
927+ struct v4l2_mbus_framefmt *format;
928+ const struct imx283_mode *mode;
929+ struct imx283 *imx283 = to_imx283(sd);
930+ const struct imx283_mode *mode_list;
931+ unsigned int num_modes;
932+
933+ get_mode_table(fmt->format.code, &mode_list, &num_modes);
934+
935+ mode = v4l2_find_nearest_size(mode_list, num_modes, width, height,
936+ fmt->format.width, fmt->format.height);
937+
938+ fmt->format.width = mode->width;
939+ fmt->format.height = mode->height;
940+ fmt->format.field = V4L2_FIELD_NONE;
941+ fmt->format.colorspace = V4L2_COLORSPACE_RAW;
942+ fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_601;
943+ fmt->format.quantization = V4L2_QUANTIZATION_FULL_RANGE;
944+ fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
945+
946+ format = v4l2_subdev_state_get_format(sd_state, 0);
947+
948+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
949+ imx283_set_framing_limits(imx283, mode);
950+
951+ *format = fmt->format;
952+
953+ return 0;
954+}
955+
956+static int imx283_standby_cancel(struct imx283 *imx283)
957+{
958+ unsigned int link_freq_idx;
959+ int ret = 0;
960+
961+ cci_write(imx283->cci, IMX283_REG_STANDBY,
962+ IMX283_STBLOGIC | IMX283_STBDV, &ret);
963+
964+ /* Configure PLL clocks based on the xclk */
965+ cci_multi_reg_write(imx283->cci, imx283->freq->regs,
966+ imx283->freq->reg_count, &ret);
967+
968+ dev_dbg(imx283->dev, "Using clk freq %ld MHz",
969+ imx283->freq->mhz / HZ_PER_MHZ);
970+
971+ /* Initialise communication */
972+ cci_write(imx283->cci, IMX283_REG_PLSTMG08, IMX283_PLSTMG08_VAL, &ret);
973+ cci_write(imx283->cci, IMX283_REG_PLSTMG02, IMX283_PLSTMG02_VAL, &ret);
974+
975+ /* Enable PLL */
976+ cci_write(imx283->cci, IMX283_REG_STBPL, IMX283_STBPL_NORMAL, &ret);
977+
978+ /* Configure the MIPI link speed */
979+ link_freq_idx = __ffs(imx283->link_freq_bitmap);
980+ cci_multi_reg_write(imx283->cci, link_freq_reglist[link_freq_idx].regs,
981+ link_freq_reglist[link_freq_idx].num_of_regs,
982+ &ret);
983+
984+ /* 1st Stabilisation period of 1 ms or more */
985+ usleep_range(1000, 2000);
986+
987+ /* Activate */
988+ cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_ACTIVE, &ret);
989+
990+ /* 2nd Stabilisation period of 19ms or more */
991+ usleep_range(19000, 20000);
992+
993+ cci_write(imx283->cci, IMX283_REG_CLAMP, IMX283_CLPSQRST, &ret);
994+ cci_write(imx283->cci, IMX283_REG_XMSTA, 0, &ret);
995+ cci_write(imx283->cci, IMX283_REG_SYNCDRV, IMX283_SYNCDRV_XHS_XVS, &ret);
996+
997+ return ret;
998+}
999+
1000+/* Start streaming */
1001+static int imx283_start_streaming(struct imx283 *imx283,
1002+ struct v4l2_subdev_state *state)
1003+{
1004+ const struct imx283_readout_mode *readout;
1005+ const struct imx283_mode *mode;
1006+ const struct v4l2_mbus_framefmt *fmt;
1007+ const struct imx283_mode *mode_list;
1008+ unsigned int num_modes;
1009+ u32 v_widcut;
1010+ s32 v_pos;
1011+ u32 write_v_size;
1012+ u32 y_out_size;
1013+ int ret = 0;
1014+
1015+ fmt = v4l2_subdev_state_get_format(state, 0);
1016+ get_mode_table(fmt->code, &mode_list, &num_modes);
1017+ mode = v4l2_find_nearest_size(mode_list, num_modes, width, height,
1018+ fmt->width, fmt->height);
1019+
1020+ ret = imx283_standby_cancel(imx283);
1021+ if (ret) {
1022+ dev_err(imx283->dev, "failed to cancel standby\n");
1023+ return ret;
1024+ }
1025+
1026+ /*
1027+ * Set the readout mode registers.
1028+ * MDSEL3 and MDSEL4 are updated to enable Arbitrary Vertical Cropping.
1029+ */
1030+ readout = &imx283_readout_modes[mode->mode];
1031+ cci_write(imx283->cci, IMX283_REG_MDSEL1, readout->mdsel1, &ret);
1032+ cci_write(imx283->cci, IMX283_REG_MDSEL2, readout->mdsel2, &ret);
1033+ cci_write(imx283->cci, IMX283_REG_MDSEL3,
1034+ readout->mdsel3 | IMX283_MDSEL3_VCROP_EN, &ret);
1035+ cci_write(imx283->cci, IMX283_REG_MDSEL4,
1036+ readout->mdsel4 | IMX283_MDSEL4_VCROP_EN, &ret);
1037+
1038+ /* Mode 1S specific entries from the Readout Drive Mode Tables */
1039+ if (mode->mode == IMX283_MODE_1S) {
1040+ cci_write(imx283->cci, IMX283_REG_MDSEL7, 0x01, &ret);
1041+ cci_write(imx283->cci, IMX283_REG_MDSEL18, 0x1098, &ret);
1042+ }
1043+
1044+ if (ret) {
1045+ dev_err(imx283->dev, "failed to set readout\n");
1046+ return ret;
1047+ }
1048+
1049+ /* Initialise SVR. Unsupported for now - Always 0 */
1050+ cci_write(imx283->cci, IMX283_REG_SVR, 0x00, &ret);
1051+
1052+ dev_dbg(imx283->dev, "Mode: Size %d x %d\n", mode->width, mode->height);
1053+ dev_dbg(imx283->dev, "Analogue Crop (in the mode) %d,%d %dx%d\n",
1054+ mode->crop.left,
1055+ mode->crop.top,
1056+ mode->crop.width,
1057+ mode->crop.height);
1058+
1059+ y_out_size = mode->crop.height / mode->vbin_ratio;
1060+ write_v_size = y_out_size + mode->vertical_ob;
1061+ /*
1062+ * cropping start position = (VWINPOS – Vst) × 2
1063+ * cropping width = Veff – (VWIDCUT – Vct) × 2
1064+ */
1065+ v_pos = imx283->vflip->val ?
1066+ ((-mode->crop.top / mode->vbin_ratio) / 2) + mode->vst :
1067+ ((mode->crop.top / mode->vbin_ratio) / 2) + mode->vst;
1068+ v_widcut = ((mode->veff - y_out_size) / 2) + mode->vct;
1069+
1070+ cci_write(imx283->cci, IMX283_REG_Y_OUT_SIZE, y_out_size, &ret);
1071+ cci_write(imx283->cci, IMX283_REG_WRITE_VSIZE, write_v_size, &ret);
1072+ cci_write(imx283->cci, IMX283_REG_VWIDCUT, v_widcut, &ret);
1073+ cci_write(imx283->cci, IMX283_REG_VWINPOS, v_pos, &ret);
1074+
1075+ cci_write(imx283->cci, IMX283_REG_OB_SIZE_V, mode->vertical_ob, &ret);
1076+
1077+ /* TODO: Validate mode->crop is fully contained within imx283_native_area */
1078+ cci_write(imx283->cci, IMX283_REG_HTRIMMING_START, mode->crop.left, &ret);
1079+ cci_write(imx283->cci, IMX283_REG_HTRIMMING_END,
1080+ mode->crop.left + mode->crop.width, &ret);
1081+
1082+ /* Disable embedded data */
1083+ cci_write(imx283->cci, IMX283_REG_EBD_X_OUT_SIZE, 0, &ret);
1084+
1085+ /* Apply customized values from controls (HMAX/VMAX/SHR) */
1086+ ret = __v4l2_ctrl_handler_setup(imx283->sd.ctrl_handler);
1087+
1088+ return ret;
1089+}
1090+
1091+static int imx283_enable_streams(struct v4l2_subdev *sd,
1092+ struct v4l2_subdev_state *state, u32 pad,
1093+ u64 streams_mask)
1094+{
1095+ struct imx283 *imx283 = to_imx283(sd);
1096+ int ret;
1097+
1098+ if (pad != IMAGE_PAD)
1099+ return -EINVAL;
1100+
1101+ ret = pm_runtime_get_sync(imx283->dev);
1102+ if (ret < 0) {
1103+ pm_runtime_put_noidle(imx283->dev);
1104+ return ret;
1105+ }
1106+
1107+ ret = imx283_start_streaming(imx283, state);
1108+ if (ret)
1109+ goto err_rpm_put;
1110+
1111+ return 0;
1112+
1113+err_rpm_put:
1114+ pm_runtime_mark_last_busy(imx283->dev);
1115+ pm_runtime_put_autosuspend(imx283->dev);
1116+
1117+ return ret;
1118+}
1119+
1120+static int imx283_disable_streams(struct v4l2_subdev *sd,
1121+ struct v4l2_subdev_state *state, u32 pad,
1122+ u64 streams_mask)
1123+{
1124+ struct imx283 *imx283 = to_imx283(sd);
1125+ int ret;
1126+
1127+ if (pad != IMAGE_PAD)
1128+ return -EINVAL;
1129+
1130+ ret = cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_STBLOGIC, NULL);
1131+ if (ret)
1132+ dev_err(imx283->dev, "Failed to stop stream\n");
1133+
1134+ pm_runtime_mark_last_busy(imx283->dev);
1135+ pm_runtime_put_autosuspend(imx283->dev);
1136+
1137+ return ret;
1138+}
1139+
1140+/* Power/clock management functions */
1141+static int imx283_power_on(struct imx283 *imx283)
1142+{
1143+ int ret;
1144+
1145+ ret = regulator_bulk_enable(ARRAY_SIZE(imx283_supply_name),
1146+ imx283->supplies);
1147+ if (ret) {
1148+ dev_err(imx283->dev, "failed to enable regulators\n");
1149+ return ret;
1150+ }
1151+
1152+ ret = clk_prepare_enable(imx283->xclk);
1153+ if (ret) {
1154+ dev_err(imx283->dev, "failed to enable clock\n");
1155+ goto reg_off;
1156+ }
1157+
1158+ gpiod_set_value_cansleep(imx283->reset_gpio, 0);
1159+
1160+ usleep_range(IMX283_XCLR_MIN_DELAY_US,
1161+ IMX283_XCLR_MIN_DELAY_US + IMX283_XCLR_DELAY_RANGE_US);
1162+
1163+ return 0;
1164+
1165+reg_off:
1166+ regulator_bulk_disable(ARRAY_SIZE(imx283_supply_name), imx283->supplies);
1167+ return ret;
1168+}
1169+
1170+static int imx283_power_off(struct imx283 *imx283)
1171+{
1172+ gpiod_set_value_cansleep(imx283->reset_gpio, 1);
1173+ regulator_bulk_disable(ARRAY_SIZE(imx283_supply_name), imx283->supplies);
1174+ clk_disable_unprepare(imx283->xclk);
1175+
1176+ return 0;
1177+}
1178+
1179+static int imx283_runtime_resume(struct device *dev)
1180+{
1181+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
1182+ struct imx283 *imx283 = to_imx283(sd);
1183+
1184+ return imx283_power_on(imx283);
1185+}
1186+
1187+static int imx283_runtime_suspend(struct device *dev)
1188+{
1189+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
1190+ struct imx283 *imx283 = to_imx283(sd);
1191+
1192+ imx283_power_off(imx283);
1193+
1194+ return 0;
1195+}
1196+
1197+static int imx283_get_regulators(struct imx283 *imx283)
1198+{
1199+ unsigned int i;
1200+
1201+ for (i = 0; i < ARRAY_SIZE(imx283_supply_name); i++)
1202+ imx283->supplies[i].supply = imx283_supply_name[i];
1203+
1204+ return devm_regulator_bulk_get(imx283->dev,
1205+ ARRAY_SIZE(imx283_supply_name),
1206+ imx283->supplies);
1207+}
1208+
1209+/* Verify chip ID */
1210+static int imx283_identify_module(struct imx283 *imx283)
1211+{
1212+ int ret;
1213+ u64 val;
1214+
1215+ ret = cci_read(imx283->cci, IMX283_REG_CHIP_ID, &val, NULL);
1216+ if (ret) {
1217+ dev_err(imx283->dev, "failed to read chip id %x, with error %d\n",
1218+ IMX283_CHIP_ID, ret);
1219+ return ret;
1220+ }
1221+
1222+ if (val != IMX283_CHIP_ID) {
1223+ dev_err(imx283->dev, "chip id mismatch: %x!=%llx\n",
1224+ IMX283_CHIP_ID, val);
1225+ return -EIO;
1226+ }
1227+
1228+ return 0;
1229+}
1230+
1231+static int imx283_get_selection(struct v4l2_subdev *sd,
1232+ struct v4l2_subdev_state *sd_state,
1233+ struct v4l2_subdev_selection *sel)
1234+{
1235+ switch (sel->target) {
1236+ case V4L2_SEL_TGT_CROP: {
1237+ sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
1238+ return 0;
1239+ }
1240+
1241+ case V4L2_SEL_TGT_NATIVE_SIZE:
1242+ sel->r = imx283_native_area;
1243+ return 0;
1244+
1245+ case V4L2_SEL_TGT_CROP_DEFAULT:
1246+ case V4L2_SEL_TGT_CROP_BOUNDS:
1247+ sel->r = imx283_active_area;
1248+ return 0;
1249+ default:
1250+ return -EINVAL;
1251+ }
1252+}
1253+
1254+static const struct v4l2_subdev_core_ops imx283_core_ops = {
1255+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
1256+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
1257+};
1258+
1259+static const struct v4l2_subdev_video_ops imx283_video_ops = {
1260+ .s_stream = v4l2_subdev_s_stream_helper,
1261+};
1262+
1263+static const struct v4l2_subdev_pad_ops imx283_pad_ops = {
1264+ .enum_mbus_code = imx283_enum_mbus_code,
1265+ .get_fmt = v4l2_subdev_get_fmt,
1266+ .set_fmt = imx283_set_pad_format,
1267+ .get_selection = imx283_get_selection,
1268+ .enum_frame_size = imx283_enum_frame_size,
1269+ .enable_streams = imx283_enable_streams,
1270+ .disable_streams = imx283_disable_streams,
1271+};
1272+
1273+static const struct v4l2_subdev_internal_ops imx283_internal_ops = {
1274+ .init_state = imx283_init_state,
1275+};
1276+
1277+static const struct v4l2_subdev_ops imx283_subdev_ops = {
1278+ .core = &imx283_core_ops,
1279+ .video = &imx283_video_ops,
1280+ .pad = &imx283_pad_ops,
1281+};
1282+
1283+/* Initialize control handlers */
1284+static int imx283_init_controls(struct imx283 *imx283)
1285+{
1286+ struct v4l2_ctrl_handler *ctrl_hdlr;
1287+ struct v4l2_fwnode_device_properties props;
1288+ struct v4l2_ctrl *link_freq;
1289+ const struct imx283_mode *mode = &supported_modes_12bit[0];
1290+ u64 min_hblank, max_hblank, def_hblank;
1291+ u64 pixel_rate;
1292+ int ret;
1293+
1294+ ctrl_hdlr = &imx283->ctrl_handler;
1295+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 16);
1296+ if (ret)
1297+ return ret;
1298+
1299+ /*
1300+ * Create the controls here, but mode specific limits are setup
1301+ * in the imx283_set_framing_limits() call below.
1302+ */
1303+
1304+ /* By default, PIXEL_RATE is read only */
1305+ pixel_rate = imx283_pixel_rate(imx283, mode);
1306+ v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops,
1307+ V4L2_CID_PIXEL_RATE, pixel_rate,
1308+ pixel_rate, 1, pixel_rate);
1309+
1310+ link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx283_ctrl_ops,
1311+ V4L2_CID_LINK_FREQ,
1312+ __fls(imx283->link_freq_bitmap),
1313+ __ffs(imx283->link_freq_bitmap),
1314+ link_frequencies);
1315+ if (link_freq)
1316+ link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1317+
1318+ /* Initialise vblank/hblank/exposure based on the current mode. */
1319+ imx283->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops,
1320+ V4L2_CID_VBLANK,
1321+ mode->min_vmax - mode->height,
1322+ IMX283_VMAX_MAX, 1,
1323+ mode->default_vmax - mode->height);
1324+
1325+ min_hblank = mode->min_hmax - mode->width;
1326+ max_hblank = imx283_iclk_to_pix(pixel_rate, IMX283_HMAX_MAX) - mode->width;
1327+ def_hblank = mode->default_hmax - mode->width;
1328+ imx283->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops,
1329+ V4L2_CID_HBLANK, min_hblank, max_hblank,
1330+ 1, def_hblank);
1331+
1332+ imx283->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops,
1333+ V4L2_CID_EXPOSURE,
1334+ IMX283_EXPOSURE_MIN,
1335+ IMX283_EXPOSURE_MAX,
1336+ IMX283_EXPOSURE_STEP,
1337+ IMX283_EXPOSURE_DEFAULT);
1338+
1339+ v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
1340+ IMX283_ANA_GAIN_MIN, IMX283_ANA_GAIN_MAX,
1341+ IMX283_ANA_GAIN_STEP, IMX283_ANA_GAIN_DEFAULT);
1342+
1343+ v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
1344+ IMX283_DGTL_GAIN_MIN, IMX283_DGTL_GAIN_MAX,
1345+ IMX283_DGTL_GAIN_STEP, IMX283_DGTL_GAIN_DEFAULT);
1346+
1347+ imx283->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx283_ctrl_ops, V4L2_CID_VFLIP,
1348+ 0, 1, 1, 0);
1349+ if (imx283->vflip)
1350+ imx283->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
1351+
1352+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx283_ctrl_ops,
1353+ V4L2_CID_TEST_PATTERN,
1354+ ARRAY_SIZE(imx283_tpg_menu) - 1,
1355+ 0, 0, imx283_tpg_menu);
1356+
1357+ if (ctrl_hdlr->error) {
1358+ ret = ctrl_hdlr->error;
1359+ dev_err(imx283->dev, "control init failed (%d)\n", ret);
1360+ goto error;
1361+ }
1362+
1363+ ret = v4l2_fwnode_device_parse(imx283->dev, &props);
1364+ if (ret)
1365+ goto error;
1366+
1367+ ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx283_ctrl_ops,
1368+ &props);
1369+ if (ret)
1370+ goto error;
1371+
1372+ imx283->sd.ctrl_handler = ctrl_hdlr;
1373+
1374+ mutex_lock(imx283->ctrl_handler.lock);
1375+
1376+ /* Setup exposure and frame/line length limits. */
1377+ imx283_set_framing_limits(imx283, mode);
1378+
1379+ mutex_unlock(imx283->ctrl_handler.lock);
1380+
1381+ return 0;
1382+
1383+error:
1384+ v4l2_ctrl_handler_free(ctrl_hdlr);
1385+
1386+ return ret;
1387+}
1388+
1389+static int imx283_parse_endpoint(struct imx283 *imx283)
1390+{
1391+ struct fwnode_handle *fwnode;
1392+ struct v4l2_fwnode_endpoint bus_cfg = {
1393+ .bus_type = V4L2_MBUS_CSI2_DPHY
1394+ };
1395+ struct fwnode_handle *ep;
1396+ int ret;
1397+
1398+ fwnode = dev_fwnode(imx283->dev);
1399+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
1400+ if (!ep) {
1401+ dev_err(imx283->dev, "Failed to get next endpoint\n");
1402+ return -ENXIO;
1403+ }
1404+
1405+ ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
1406+ fwnode_handle_put(ep);
1407+ if (ret)
1408+ return ret;
1409+
1410+ if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) {
1411+ dev_err(imx283->dev,
1412+ "number of CSI2 data lanes %d is not supported\n",
1413+ bus_cfg.bus.mipi_csi2.num_data_lanes);
1414+ ret = -EINVAL;
1415+ goto done_endpoint_free;
1416+ }
1417+
1418+ ret = v4l2_link_freq_to_bitmap(imx283->dev, bus_cfg.link_frequencies,
1419+ bus_cfg.nr_of_link_frequencies,
1420+ link_frequencies, ARRAY_SIZE(link_frequencies),
1421+ &imx283->link_freq_bitmap);
1422+
1423+done_endpoint_free:
1424+ v4l2_fwnode_endpoint_free(&bus_cfg);
1425+
1426+ return ret;
1427+};
1428+
1429+static int imx283_probe(struct i2c_client *client)
1430+{
1431+ struct imx283 *imx283;
1432+ unsigned int i;
1433+ unsigned int xclk_freq;
1434+ int ret;
1435+
1436+ imx283 = devm_kzalloc(&client->dev, sizeof(*imx283), GFP_KERNEL);
1437+ if (!imx283)
1438+ return -ENOMEM;
1439+
1440+ imx283->dev = &client->dev;
1441+
1442+ v4l2_i2c_subdev_init(&imx283->sd, client, &imx283_subdev_ops);
1443+
1444+ imx283->cci = devm_cci_regmap_init_i2c(client, 16);
1445+ if (IS_ERR(imx283->cci)) {
1446+ ret = PTR_ERR(imx283->cci);
1447+ dev_err(imx283->dev, "failed to initialize CCI: %d\n", ret);
1448+ return ret;
1449+ }
1450+
1451+ /* Get system clock (xclk) */
1452+ imx283->xclk = devm_clk_get(imx283->dev, NULL);
1453+ if (IS_ERR(imx283->xclk)) {
1454+ return dev_err_probe(imx283->dev, PTR_ERR(imx283->xclk),
1455+ "failed to get xclk\n");
1456+ }
1457+
1458+ xclk_freq = clk_get_rate(imx283->xclk);
1459+ for (i = 0; i < ARRAY_SIZE(imx283_frequencies); i++) {
1460+ if (xclk_freq == imx283_frequencies[i].mhz) {
1461+ imx283->freq = &imx283_frequencies[i];
1462+ break;
1463+ }
1464+ }
1465+ if (!imx283->freq) {
1466+ dev_err(imx283->dev, "xclk frequency unsupported: %d Hz\n", xclk_freq);
1467+ return -EINVAL;
1468+ }
1469+
1470+ ret = imx283_get_regulators(imx283);
1471+ if (ret) {
1472+ return dev_err_probe(imx283->dev, ret,
1473+ "failed to get regulators\n");
1474+ }
1475+
1476+ ret = imx283_parse_endpoint(imx283);
1477+ if (ret) {
1478+ dev_err(imx283->dev, "failed to parse endpoint configuration\n");
1479+ return ret;
1480+ }
1481+
1482+ /* Request optional enable pin */
1483+ imx283->reset_gpio = devm_gpiod_get_optional(imx283->dev, "reset",
1484+ GPIOD_OUT_LOW);
1485+ if (IS_ERR(imx283->reset_gpio))
1486+ return dev_err_probe(imx283->dev, PTR_ERR(imx283->reset_gpio),
1487+ "failed to get reset GPIO\n");
1488+
1489+ /*
1490+ * The sensor must be powered for imx283_identify_module()
1491+ * to be able to read the CHIP_ID register
1492+ */
1493+ ret = imx283_power_on(imx283);
1494+ if (ret)
1495+ return ret;
1496+
1497+ ret = imx283_identify_module(imx283);
1498+ if (ret)
1499+ goto error_power_off;
1500+
1501+ /*
1502+ * Enable runtime PM with autosuspend. As the device has been powered
1503+ * manually, mark it as active, and increase the usage count without
1504+ * resuming the device.
1505+ */
1506+ pm_runtime_set_active(imx283->dev);
1507+ pm_runtime_get_noresume(imx283->dev);
1508+ pm_runtime_enable(imx283->dev);
1509+ pm_runtime_set_autosuspend_delay(imx283->dev, 1000);
1510+ pm_runtime_use_autosuspend(imx283->dev);
1511+
1512+ /* This needs the pm runtime to be registered. */
1513+ ret = imx283_init_controls(imx283);
1514+ if (ret)
1515+ goto error_pm;
1516+
1517+ /* Initialize subdev */
1518+ imx283->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
1519+ V4L2_SUBDEV_FL_HAS_EVENTS;
1520+ imx283->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1521+ imx283->sd.internal_ops = &imx283_internal_ops;
1522+
1523+ /* Initialize source pads */
1524+ imx283->pad.flags = MEDIA_PAD_FL_SOURCE;
1525+
1526+ ret = media_entity_pads_init(&imx283->sd.entity, 1, &imx283->pad);
1527+ if (ret) {
1528+ dev_err(imx283->dev, "failed to init entity pads: %d\n", ret);
1529+ goto error_handler_free;
1530+ }
1531+
1532+ imx283->sd.state_lock = imx283->ctrl_handler.lock;
1533+ ret = v4l2_subdev_init_finalize(&imx283->sd);
1534+ if (ret < 0) {
1535+ dev_err(imx283->dev, "subdev init error: %d\n", ret);
1536+ goto error_media_entity;
1537+ }
1538+
1539+ ret = v4l2_async_register_subdev_sensor(&imx283->sd);
1540+ if (ret < 0) {
1541+ dev_err(imx283->dev, "failed to register sensor sub-device: %d\n", ret);
1542+ goto error_subdev_cleanup;
1543+ }
1544+
1545+ /*
1546+ * Decrease the PM usage count. The device will get suspended after the
1547+ * autosuspend delay, turning the power off.
1548+ */
1549+ pm_runtime_mark_last_busy(imx283->dev);
1550+ pm_runtime_put_autosuspend(imx283->dev);
1551+
1552+ return 0;
1553+
1554+error_subdev_cleanup:
1555+ v4l2_subdev_cleanup(&imx283->sd);
1556+
1557+error_media_entity:
1558+ media_entity_cleanup(&imx283->sd.entity);
1559+
1560+error_handler_free:
1561+ v4l2_ctrl_handler_free(imx283->sd.ctrl_handler);
1562+
1563+error_pm:
1564+ pm_runtime_disable(imx283->dev);
1565+ pm_runtime_set_suspended(imx283->dev);
1566+error_power_off:
1567+ imx283_power_off(imx283);
1568+
1569+ return ret;
1570+}
1571+
1572+static void imx283_remove(struct i2c_client *client)
1573+{
1574+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
1575+ struct imx283 *imx283 = to_imx283(sd);
1576+
1577+ v4l2_async_unregister_subdev(sd);
1578+ v4l2_subdev_cleanup(&imx283->sd);
1579+ media_entity_cleanup(&sd->entity);
1580+ v4l2_ctrl_handler_free(imx283->sd.ctrl_handler);
1581+
1582+ pm_runtime_disable(imx283->dev);
1583+ if (!pm_runtime_status_suspended(imx283->dev))
1584+ imx283_power_off(imx283);
1585+ pm_runtime_set_suspended(imx283->dev);
1586+}
1587+
1588+static DEFINE_RUNTIME_DEV_PM_OPS(imx283_pm_ops, imx283_runtime_suspend,
1589+ imx283_runtime_resume, NULL);
1590+
1591+static const struct of_device_id imx283_dt_ids[] = {
1592+ { .compatible = "sony,imx283" },
1593+ { /* sentinel */ }
1594+};
1595+MODULE_DEVICE_TABLE(of, imx283_dt_ids);
1596+
1597+static struct i2c_driver imx283_i2c_driver = {
1598+ .driver = {
1599+ .name = "imx283",
1600+ .pm = pm_ptr(&imx283_pm_ops),
1601+ .of_match_table = imx283_dt_ids,
1602+ },
1603+ .probe = imx283_probe,
1604+ .remove = imx283_remove,
1605+};
1606+module_i2c_driver(imx283_i2c_driver);
1607+
1608+MODULE_AUTHOR("Will Whang <will@willwhang.com>");
1609+MODULE_AUTHOR("Kieran Bingham <kieran.bingham@ideasonboard.com>");
1610+MODULE_AUTHOR("Umang Jain <umang.jain@ideasonboard.com>");
1611+MODULE_DESCRIPTION("Sony IMX283 Sensor Driver");
1612+MODULE_LICENSE("GPL");
drivers/media/i2c/imx412.c+4−5
@@ -542,14 +542,13 @@ static int imx412_update_controls(struct imx412 *imx412, · 541 unmodified lines
542542 */
543543 static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain)
544544 {
545− u32 lpfr, shutter;
545+ u32 lpfr;
546546 int ret;
547547
548548 lpfr = imx412->vblank + imx412->cur_mode->height;
549− shutter = lpfr - exposure;
550549
551− dev_dbg(imx412->dev, "Set exp %u, analog gain %u, shutter %u, lpfr %u",
552− exposure, gain, shutter, lpfr);
550+ dev_dbg(imx412->dev, "Set exp %u, analog gain %u, lpfr %u",
551+ exposure, gain, lpfr);
553552
554553 ret = imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 1);
555554 if (ret)
@@ -559,7 +558,7 @@ static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain) · 3 unmodified lines
559558 if (ret)
560559 goto error_release_group_hold;
561560
562− ret = imx412_write_reg(imx412, IMX412_REG_EXPOSURE_CIT, 2, shutter);
561+ ret = imx412_write_reg(imx412, IMX412_REG_EXPOSURE_CIT, 2, exposure);
563562 if (ret)
564563 goto error_release_group_hold;
565564
drivers/media/i2c/ks0127.c+0−8
@@ -175,14 +175,6 @@ MODULE_LICENSE("GPL"); · 174 unmodified lines
175175 * mga_dev : represents one ks0127 chip.
176176 ****************************************************************************/
177177
178−struct adjust {
179− int contrast;
180− int bright;
181− int hue;
182− int ugain;
183− int vgain;
184−};
185−
186178 struct ks0127 {
187179 struct v4l2_subdev sd;
188180 v4l2_std_id norm;
drivers/media/i2c/max9286.c+68−113
@@ -19,7 +19,6 @@ · 18 unmodified lines
1919 #include <linux/i2c.h>
2020 #include <linux/i2c-mux.h>
2121 #include <linux/module.h>
22−#include <linux/mutex.h>
2322 #include <linux/of_graph.h>
2423 #include <linux/regulator/consumer.h>
2524 #include <linux/slab.h>
@@ -198,12 +197,6 @@ struct max9286_priv { · 172 unmodified lines
198197 struct v4l2_ctrl *pixelrate_ctrl;
199198 unsigned int pixelrate;
200199
201− struct v4l2_mbus_framefmt fmt[MAX9286_N_SINKS];
202− struct v4l2_fract interval;
203−
204− /* Protects controls and fmt structures */
205− struct mutex mutex;
206−
207200 unsigned int nsources;
208201 unsigned int source_mask;
209202 unsigned int route_mask;
@@ -576,11 +569,14 @@ static void max9286_set_video_format(struct max9286_priv *priv, · 366 unmodified lines
576569 MAX9286_INVVS | MAX9286_HVSRC_D14);
577570 }
578571
579−static void max9286_set_fsync_period(struct max9286_priv *priv)
572+static void max9286_set_fsync_period(struct max9286_priv *priv,
573+ struct v4l2_subdev_state *state)
580574 {
575+ const struct v4l2_fract *interval;
581576 u32 fsync;
582577
583− if (!priv->interval.numerator || !priv->interval.denominator) {
578+ interval = v4l2_subdev_state_get_interval(state, MAX9286_SRC_PAD);
579+ if (!interval->numerator || !interval->denominator) {
584580 /*
585581 * Special case, a null interval enables automatic FRAMESYNC
586582 * mode. FRAMESYNC is taken from the slowest link.
@@ -596,8 +592,8 @@ static void max9286_set_fsync_period(struct max9286_priv *priv) · 9 unmodified lines
596592 * The FRAMESYNC generator is configured with a period expressed as a
597593 * number of PCLK periods.
598594 */
599− fsync = div_u64((u64)priv->pixelrate * priv->interval.numerator,
600− priv->interval.denominator);
595+ fsync = div_u64((u64)priv->pixelrate * interval->numerator,
596+ interval->denominator);
601597
602598 dev_dbg(&priv->client->dev, "fsync period %u (pclk %u)\n", fsync,
603599 priv->pixelrate);
@@ -788,22 +784,25 @@ static void max9286_v4l2_notifier_unregister(struct max9286_priv *priv) · 184 unmodified lines
788784 static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
789785 {
790786 struct max9286_priv *priv = sd_to_max9286(sd);
787+ struct v4l2_subdev_state *state;
791788 struct max9286_source *source;
792789 unsigned int i;
793790 bool sync = false;
794− int ret;
791+ int ret = 0;
792+
793+ state = v4l2_subdev_lock_and_get_active_state(sd);
795794
796795 if (enable) {
797796 const struct v4l2_mbus_framefmt *format;
798797
799798 /*
800− * Get the format from the first used sink pad, as all sink
801− * formats must be identical.
799+ * Get the format from the source pad, as all formats must be
800+ * identical.
802801 */
803− format = &priv->fmt[__ffs(priv->bound_sources)];
802+ format = v4l2_subdev_state_get_format(state, MAX9286_SRC_PAD);
804803
805804 max9286_set_video_format(priv, format);
806− max9286_set_fsync_period(priv);
805+ max9286_set_fsync_period(priv, state);
807806
808807 /*
809808 * The frame sync between cameras is transmitted across the
@@ -816,12 +815,12 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) · 6 unmodified lines
816815 for_each_source(priv, source) {
817816 ret = v4l2_subdev_call(source->sd, video, s_stream, 1);
818817 if (ret)
819− return ret;
818+ goto unlock;
820819 }
821820
822821 ret = max9286_check_video_links(priv);
823822 if (ret)
824− return ret;
823+ goto unlock;
825824
826825 /*
827826 * Wait until frame synchronization is locked.
@@ -842,7 +841,8 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) · 14 unmodified lines
842841 if (!sync) {
843842 dev_err(&priv->client->dev,
844843 "Failed to get frame synchronization\n");
845− return -EXDEV; /* Invalid cross-device link */
844+ ret = -EXDEV; /* Invalid cross-device link */
845+ goto unlock;
846846 }
847847
848848 /*
@@ -865,26 +865,21 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) · 16 unmodified lines
865865 max9286_i2c_mux_close(priv);
866866 }
867867
868− return 0;
868+unlock:
869+ v4l2_subdev_unlock_state(state);
870+
871+ return ret;
869872 }
870873
871874 static int max9286_get_frame_interval(struct v4l2_subdev *sd,
872875 struct v4l2_subdev_state *sd_state,
873876 struct v4l2_subdev_frame_interval *interval)
874877 {
875− struct max9286_priv *priv = sd_to_max9286(sd);
876−
877− /*
878− * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
879− * subdev active state API.
880− */
881− if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
882− return -EINVAL;
883−
884878 if (interval->pad != MAX9286_SRC_PAD)
885879 return -EINVAL;
886880
887− interval->interval = priv->interval;
881+ interval->interval = *v4l2_subdev_state_get_interval(sd_state,
882+ interval->pad);
888883
889884 return 0;
890885 }
@@ -893,19 +888,11 @@ static int max9286_set_frame_interval(struct v4l2_subdev *sd, · 2 unmodified lines
893888 struct v4l2_subdev_state *sd_state,
894889 struct v4l2_subdev_frame_interval *interval)
895890 {
896− struct max9286_priv *priv = sd_to_max9286(sd);
897−
898− /*
899− * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2
900− * subdev active state API.
901− */
902− if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)
903− return -EINVAL;
904−
905891 if (interval->pad != MAX9286_SRC_PAD)
906892 return -EINVAL;
907893
908− priv->interval = interval->interval;
894+ *v4l2_subdev_state_get_interval(sd_state,
895+ interval->pad) = interval->interval;
909896
910897 return 0;
911898 }
@@ -914,39 +901,28 @@ static int max9286_enum_mbus_code(struct v4l2_subdev *sd, · 2 unmodified lines
914901 struct v4l2_subdev_state *sd_state,
915902 struct v4l2_subdev_mbus_code_enum *code)
916903 {
917− if (code->pad || code->index > 0)
904+ if (code->pad || code->index >= ARRAY_SIZE(max9286_formats))
918905 return -EINVAL;
919906
920− code->code = MEDIA_BUS_FMT_UYVY8_1X16;
907+ code->code = max9286_formats[code->index].code;
921908
922909 return 0;
923910 }
924911
925−static struct v4l2_mbus_framefmt *
926−max9286_get_pad_format(struct max9286_priv *priv,
927− struct v4l2_subdev_state *sd_state,
928− unsigned int pad, u32 which)
929−{
930− switch (which) {
931− case V4L2_SUBDEV_FORMAT_TRY:
932− return v4l2_subdev_state_get_format(sd_state, pad);
933− case V4L2_SUBDEV_FORMAT_ACTIVE:
934− return &priv->fmt[pad];
935− default:
936− return NULL;
937− }
938−}
939−
940912 static int max9286_set_fmt(struct v4l2_subdev *sd,
941− struct v4l2_subdev_state *sd_state,
913+ struct v4l2_subdev_state *state,
942914 struct v4l2_subdev_format *format)
943915 {
944916 struct max9286_priv *priv = sd_to_max9286(sd);
945− struct v4l2_mbus_framefmt *cfg_fmt;
917+ struct max9286_source *source;
946918 unsigned int i;
947919
920+ /*
921+ * Disable setting format on the source pad: format is propagated
922+ * from the sinks.
923+ */
948924 if (format->pad == MAX9286_SRC_PAD)
949− return -EINVAL;
925+ return v4l2_subdev_get_fmt(sd, state, format);
950926
951927 /* Validate the format. */
952928 for (i = 0; i < ARRAY_SIZE(max9286_formats); ++i) {
@@ -957,42 +933,17 @@ static int max9286_set_fmt(struct v4l2_subdev *sd, · 4 unmodified lines
957933 if (i == ARRAY_SIZE(max9286_formats))
958934 format->format.code = max9286_formats[0].code;
959935
960− cfg_fmt = max9286_get_pad_format(priv, sd_state, format->pad,
961− format->which);
962− if (!cfg_fmt)
963− return -EINVAL;
964−
965− mutex_lock(&priv->mutex);
966− *cfg_fmt = format->format;
967− mutex_unlock(&priv->mutex);
968−
969− return 0;
970−}
971−
972−static int max9286_get_fmt(struct v4l2_subdev *sd,
973− struct v4l2_subdev_state *sd_state,
974− struct v4l2_subdev_format *format)
975−{
976− struct max9286_priv *priv = sd_to_max9286(sd);
977− struct v4l2_mbus_framefmt *cfg_fmt;
978− unsigned int pad = format->pad;
979−
980936 /*
981− * Multiplexed Stream Support: Support link validation by returning the
982− * format of the first bound link. All links must have the same format,
983− * as we do not support mixing and matching of cameras connected to the
984− * max9286.
937+ * Apply the same format on all the other pad as all links must have the
938+ * same format.
985939 */
986− if (pad == MAX9286_SRC_PAD)
987− pad = __ffs(priv->bound_sources);
940+ for_each_source(priv, source) {
941+ unsigned int index = to_index(priv, source);
988942
989− cfg_fmt = max9286_get_pad_format(priv, sd_state, pad, format->which);
990− if (!cfg_fmt)
991− return -EINVAL;
943+ *v4l2_subdev_state_get_format(state, index) = format->format;
944+ }
992945
993− mutex_lock(&priv->mutex);
994− format->format = *cfg_fmt;
995− mutex_unlock(&priv->mutex);
946+ *v4l2_subdev_state_get_format(state, MAX9286_SRC_PAD) = format->format;
996947
997948 return 0;
998949 }
@@ -1003,7 +954,7 @@ static const struct v4l2_subdev_video_ops max9286_video_ops = { · 4 unmodified lines
1003954
1004955 static const struct v4l2_subdev_pad_ops max9286_pad_ops = {
1005956 .enum_mbus_code = max9286_enum_mbus_code,
1006− .get_fmt = max9286_get_fmt,
957+ .get_fmt = v4l2_subdev_get_fmt,
1007958 .set_fmt = max9286_set_fmt,
1008959 .get_frame_interval = max9286_get_frame_interval,
1009960 .set_frame_interval = max9286_set_frame_interval,
@@ -1025,26 +976,29 @@ static const struct v4l2_mbus_framefmt max9286_default_format = { · 15 unmodified lines
1025976 .xfer_func = V4L2_XFER_FUNC_DEFAULT,
1026977 };
1027978
1028−static void max9286_init_format(struct v4l2_mbus_framefmt *fmt)
979+static int max9286_init_state(struct v4l2_subdev *sd,
980+ struct v4l2_subdev_state *state)
1029981 {
1030− *fmt = max9286_default_format;
1031−}
982+ struct v4l2_fract *interval;
1032983
1033−static int max9286_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
1034−{
1035− struct v4l2_mbus_framefmt *format;
1036− unsigned int i;
984+ for (unsigned int i = 0; i < MAX9286_N_PADS; i++)
985+ *v4l2_subdev_state_get_format(state, i) = max9286_default_format;
1037986
1038− for (i = 0; i < MAX9286_N_SINKS; i++) {
1039− format = v4l2_subdev_state_get_format(fh->state, i);
1040− max9286_init_format(format);
1041− }
987+ /*
988+ * Special case: a null interval enables automatic FRAMESYNC mode.
989+ *
990+ * FRAMESYNC is taken from the slowest link. See register 0x01
991+ * configuration.
992+ */
993+ interval = v4l2_subdev_state_get_interval(state, MAX9286_SRC_PAD);
994+ interval->numerator = 0;
995+ interval->denominator = 0;
1042996
1043997 return 0;
1044998 }
1045999
10461000 static const struct v4l2_subdev_internal_ops max9286_subdev_internal_ops = {
1047− .open = max9286_open,
1001+ .init_state = max9286_init_state,
10481002 };
10491003
10501004 static const struct media_entity_operations max9286_media_ops = {
@@ -1079,10 +1033,6 @@ static int max9286_v4l2_register(struct max9286_priv *priv) · 28 unmodified lines
10791033 }
10801034
10811035 /* Configure V4L2 for the MAX9286 itself */
1082−
1083− for (i = 0; i < MAX9286_N_SINKS; i++)
1084− max9286_init_format(&priv->fmt[i]);
1085−
10861036 v4l2_i2c_subdev_init(&priv->sd, priv->client, &max9286_subdev_ops);
10871037 priv->sd.internal_ops = &max9286_subdev_internal_ops;
10881038 priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -1109,14 +1059,21 @@ static int max9286_v4l2_register(struct max9286_priv *priv) · 20 unmodified lines
11091059 if (ret)
11101060 goto err_async;
11111061
1062+ priv->sd.state_lock = priv->ctrls.lock;
1063+ ret = v4l2_subdev_init_finalize(&priv->sd);
1064+ if (ret)
1065+ goto err_async;
1066+
11121067 ret = v4l2_async_register_subdev(&priv->sd);
11131068 if (ret < 0) {
11141069 dev_err(dev, "Unable to register subdevice\n");
1115− goto err_async;
1070+ goto err_subdev;
11161071 }
11171072
11181073 return 0;
11191074
1075+err_subdev:
1076+ v4l2_subdev_cleanup(&priv->sd);
11201077 err_async:
11211078 v4l2_ctrl_handler_free(&priv->ctrls);
11221079 max9286_v4l2_notifier_unregister(priv);
@@ -1126,6 +1083,7 @@ err_async: · 3 unmodified lines
11261083
11271084 static void max9286_v4l2_unregister(struct max9286_priv *priv)
11281085 {
1086+ v4l2_subdev_cleanup(&priv->sd);
11291087 v4l2_ctrl_handler_free(&priv->ctrls);
11301088 v4l2_async_unregister_subdev(&priv->sd);
11311089 max9286_v4l2_notifier_unregister(priv);
@@ -1182,7 +1140,6 @@ static int max9286_setup(struct max9286_priv *priv) · 50 unmodified lines
11821140 max9286_write(priv, 0x69, (0xf & ~priv->route_mask));
11831141
11841142 max9286_set_video_format(priv, &max9286_default_format);
1185− max9286_set_fsync_period(priv);
11861143
11871144 cfg = max9286_read(priv, 0x1c);
11881145 if (cfg < 0)
@@ -1629,8 +1586,6 @@ static int max9286_probe(struct i2c_client *client) · 440 unmodified lines
16291586 if (!priv)
16301587 return -ENOMEM;
16311588
1632− mutex_init(&priv->mutex);
1633−
16341589 priv->client = client;
16351590
16361591 /* GPIO values default to high */
drivers/media/i2c/max96714.c+1024−0
@@ -0,0 +1,1024 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Maxim GMSL2 Deserializer Driver
4+ *
5+ * Copyright (C) 2024 Collabora Ltd.
6+ */
7+
8+#include <linux/bitfield.h>
9+#include <linux/bitops.h>
10+#include <linux/fwnode.h>
11+#include <linux/gpio/consumer.h>
12+#include <linux/i2c.h>
13+#include <linux/i2c-mux.h>
14+#include <linux/module.h>
15+#include <linux/regmap.h>
16+#include <linux/regulator/consumer.h>
17+
18+#include <media/v4l2-cci.h>
19+#include <media/v4l2-ctrls.h>
20+#include <media/v4l2-fwnode.h>
21+#include <media/v4l2-subdev.h>
22+
23+#define MAX96714_DEVICE_ID 0xc9
24+#define MAX96714F_DEVICE_ID 0xca
25+#define MAX96714_NPORTS 2
26+#define MAX96714_PAD_SINK 0
27+#define MAX96714_PAD_SOURCE 1
28+
29+/* DEV */
30+#define MAX96714_REG13 CCI_REG8(0x0d)
31+#define MAX96714_DEV_REV CCI_REG8(0x0e)
32+#define MAX96714_DEV_REV_MASK GENMASK(3, 0)
33+#define MAX96714_LINK_LOCK CCI_REG8(0x13)
34+#define MAX96714_LINK_LOCK_BIT BIT(3)
35+#define MAX96714_IO_CHK0 CCI_REG8(0x38)
36+#define MAX96714_PATTERN_CLK_FREQ GENMASK(1, 0)
37+/* VID_RX */
38+#define MAX96714_VIDEO_RX8 CCI_REG8(0x11a)
39+#define MAX96714_VID_LOCK BIT(6)
40+
41+/* VRX_PATGEN_0 */
42+#define MAX96714_PATGEN_0 CCI_REG8(0x240)
43+#define MAX96714_PATGEN_1 CCI_REG8(0x241)
44+#define MAX96714_PATGEN_MODE GENMASK(5, 4)
45+#define MAX96714_PATGEN_VS_DLY CCI_REG24(0x242)
46+#define MAX96714_PATGEN_VS_HIGH CCI_REG24(0x245)
47+#define MAX96714_PATGEN_VS_LOW CCI_REG24(0x248)
48+#define MAX96714_PATGEN_V2H CCI_REG24(0x24b)
49+#define MAX96714_PATGEN_HS_HIGH CCI_REG16(0x24e)
50+#define MAX96714_PATGEN_HS_LOW CCI_REG16(0x250)
51+#define MAX96714_PATGEN_HS_CNT CCI_REG16(0x252)
52+#define MAX96714_PATGEN_V2D CCI_REG24(0x254)
53+#define MAX96714_PATGEN_DE_HIGH CCI_REG16(0x257)
54+#define MAX96714_PATGEN_DE_LOW CCI_REG16(0x259)
55+#define MAX96714_PATGEN_DE_CNT CCI_REG16(0x25B)
56+#define MAX96714_PATGEN_GRAD_INC CCI_REG8(0x25d)
57+#define MAX96714_PATGEN_CHKB_COLOR_A CCI_REG24(0x25E)
58+#define MAX96714_PATGEN_CHKB_COLOR_B CCI_REG24(0x261)
59+#define MAX96714_PATGEN_CHKB_RPT_CNT_A CCI_REG8(0x264)
60+#define MAX96714_PATGEN_CHKB_RPT_CNT_B CCI_REG8(0x265)
61+#define MAX96714_PATGEN_CHKB_ALT CCI_REG8(0x266)
62+/* BACKTOP */
63+#define MAX96714_BACKTOP25 CCI_REG8(0x320)
64+#define CSI_DPLL_FREQ_MASK GENMASK(4, 0)
65+
66+/* MIPI_PHY */
67+#define MAX96714_MIPI_PHY0 CCI_REG8(0x330)
68+#define MAX96714_FORCE_CSI_OUT BIT(7)
69+#define MAX96714_MIPI_STDBY_N CCI_REG8(0x332)
70+#define MAX96714_MIPI_STDBY_MASK GENMASK(5, 4)
71+#define MAX96714_MIPI_LANE_MAP CCI_REG8(0x333)
72+#define MAX96714_MIPI_POLARITY CCI_REG8(0x335)
73+#define MAX96714_MIPI_POLARITY_MASK GENMASK(5, 0)
74+
75+/* MIPI_TX */
76+#define MAX96714_MIPI_LANE_CNT CCI_REG8(0x44a)
77+#define MAX96714_CSI2_LANE_CNT_MASK GENMASK(7, 6)
78+#define MAX96714_MIPI_TX52 CCI_REG8(0x474)
79+#define MAX96714_TUN_EN BIT(0)
80+
81+#define MHZ(v) ((u32)((v) * 1000000U))
82+
83+enum max96714_vpg_mode {
84+ MAX96714_VPG_DISABLED = 0,
85+ MAX96714_VPG_CHECKERBOARD = 1,
86+ MAX96714_VPG_GRADIENT = 2,
87+};
88+
89+struct max96714_rxport {
90+ struct {
91+ struct v4l2_subdev *sd;
92+ u16 pad;
93+ struct fwnode_handle *ep_fwnode;
94+ } source;
95+ struct regulator *poc;
96+};
97+
98+struct max96714_txport {
99+ struct v4l2_fwnode_endpoint vep;
100+};
101+
102+struct max96714_priv {
103+ struct i2c_client *client;
104+ struct regmap *regmap;
105+ struct gpio_desc *pd_gpio;
106+ struct max96714_rxport rxport;
107+ struct i2c_mux_core *mux;
108+ u64 enabled_source_streams;
109+ struct v4l2_subdev sd;
110+ struct media_pad pads[MAX96714_NPORTS];
111+ struct v4l2_mbus_config_mipi_csi2 mipi_csi2;
112+ struct v4l2_ctrl_handler ctrl_handler;
113+ struct v4l2_async_notifier notifier;
114+ s64 tx_link_freq;
115+ enum max96714_vpg_mode pattern;
116+};
117+
118+static inline struct max96714_priv *sd_to_max96714(struct v4l2_subdev *sd)
119+{
120+ return container_of(sd, struct max96714_priv, sd);
121+}
122+
123+static int max96714_enable_tx_port(struct max96714_priv *priv)
124+{
125+ return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N,
126+ MAX96714_MIPI_STDBY_MASK,
127+ MAX96714_MIPI_STDBY_MASK, NULL);
128+}
129+
130+static int max96714_disable_tx_port(struct max96714_priv *priv)
131+{
132+ return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N,
133+ MAX96714_MIPI_STDBY_MASK, 0, NULL);
134+}
135+
136+static bool max96714_tx_port_enabled(struct max96714_priv *priv)
137+{
138+ u64 val;
139+
140+ cci_read(priv->regmap, MAX96714_MIPI_STDBY_N, &val, NULL);
141+
142+ return val & MAX96714_MIPI_STDBY_MASK;
143+}
144+
145+static int max96714_apply_patgen_timing(struct max96714_priv *priv,
146+ struct v4l2_subdev_state *state)
147+{
148+ struct v4l2_mbus_framefmt *fmt =
149+ v4l2_subdev_state_get_format(state, MAX96714_PAD_SOURCE);
150+ const u32 h_active = fmt->width;
151+ const u32 h_fp = 88;
152+ const u32 h_sw = 44;
153+ const u32 h_bp = 148;
154+ u32 h_tot;
155+ const u32 v_active = fmt->height;
156+ const u32 v_fp = 4;
157+ const u32 v_sw = 5;
158+ const u32 v_bp = 36;
159+ u32 v_tot;
160+ int ret = 0;
161+
162+ h_tot = h_active + h_fp + h_sw + h_bp;
163+ v_tot = v_active + v_fp + v_sw + v_bp;
164+
165+ /* 75 Mhz pixel clock */
166+ cci_update_bits(priv->regmap, MAX96714_IO_CHK0,
167+ MAX96714_PATTERN_CLK_FREQ, 1, &ret);
168+
169+ dev_info(&priv->client->dev, "height: %d width: %d\n", fmt->height,
170+ fmt->width);
171+
172+ cci_write(priv->regmap, MAX96714_PATGEN_VS_DLY, 0, &ret);
173+ cci_write(priv->regmap, MAX96714_PATGEN_VS_HIGH, v_sw * h_tot, &ret);
174+ cci_write(priv->regmap, MAX96714_PATGEN_VS_LOW,
175+ (v_active + v_fp + v_bp) * h_tot, &ret);
176+ cci_write(priv->regmap, MAX96714_PATGEN_HS_HIGH, h_sw, &ret);
177+ cci_write(priv->regmap, MAX96714_PATGEN_HS_LOW, h_active + h_fp + h_bp,
178+ &ret);
179+ cci_write(priv->regmap, MAX96714_PATGEN_V2D,
180+ h_tot * (v_sw + v_bp) + (h_sw + h_bp), &ret);
181+ cci_write(priv->regmap, MAX96714_PATGEN_HS_CNT, v_tot, &ret);
182+ cci_write(priv->regmap, MAX96714_PATGEN_DE_HIGH, h_active, &ret);
183+ cci_write(priv->regmap, MAX96714_PATGEN_DE_LOW, h_fp + h_sw + h_bp,
184+ &ret);
185+ cci_write(priv->regmap, MAX96714_PATGEN_DE_CNT, v_active, &ret);
186+ /* B G R */
187+ cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_A, 0xfecc00, &ret);
188+ /* B G R */
189+ cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_B, 0x006aa7, &ret);
190+ cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_A, 0x3c, &ret);
191+ cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_B, 0x3c, &ret);
192+ cci_write(priv->regmap, MAX96714_PATGEN_CHKB_ALT, 0x3c, &ret);
193+ cci_write(priv->regmap, MAX96714_PATGEN_GRAD_INC, 0x10, &ret);
194+
195+ return ret;
196+}
197+
198+static int max96714_apply_patgen(struct max96714_priv *priv,
199+ struct v4l2_subdev_state *state)
200+{
201+ unsigned int val;
202+ int ret = 0;
203+
204+ if (priv->pattern)
205+ ret = max96714_apply_patgen_timing(priv, state);
206+
207+ cci_write(priv->regmap, MAX96714_PATGEN_0, priv->pattern ? 0xfb : 0,
208+ &ret);
209+
210+ val = FIELD_PREP(MAX96714_PATGEN_MODE, priv->pattern);
211+ cci_update_bits(priv->regmap, MAX96714_PATGEN_1, MAX96714_PATGEN_MODE,
212+ val, &ret);
213+ return ret;
214+}
215+
216+static int max96714_s_ctrl(struct v4l2_ctrl *ctrl)
217+{
218+ struct max96714_priv *priv =
219+ container_of(ctrl->handler, struct max96714_priv, ctrl_handler);
220+ int ret;
221+
222+ switch (ctrl->id) {
223+ case V4L2_CID_TEST_PATTERN:
224+ if (priv->enabled_source_streams)
225+ return -EBUSY;
226+ priv->pattern = ctrl->val;
227+ break;
228+ default:
229+ return -EINVAL;
230+ }
231+
232+ ret = cci_update_bits(priv->regmap, MAX96714_MIPI_PHY0,
233+ MAX96714_FORCE_CSI_OUT,
234+ priv->pattern ? MAX96714_FORCE_CSI_OUT : 0, NULL);
235+
236+ /* Pattern generator doesn't work with tunnel mode */
237+ return cci_update_bits(priv->regmap, MAX96714_MIPI_TX52,
238+ MAX96714_TUN_EN,
239+ priv->pattern ? 0 : MAX96714_TUN_EN, &ret);
240+}
241+
242+static const char * const max96714_test_pattern[] = {
243+ "Disabled",
244+ "Checkerboard",
245+ "Gradient"
246+};
247+
248+static const struct v4l2_ctrl_ops max96714_ctrl_ops = {
249+ .s_ctrl = max96714_s_ctrl,
250+};
251+
252+static int max96714_enable_streams(struct v4l2_subdev *sd,
253+ struct v4l2_subdev_state *state,
254+ u32 source_pad, u64 streams_mask)
255+{
256+ struct max96714_priv *priv = sd_to_max96714(sd);
257+ u64 sink_streams;
258+ int ret;
259+
260+ if (!priv->enabled_source_streams)
261+ max96714_enable_tx_port(priv);
262+
263+ ret = max96714_apply_patgen(priv, state);
264+ if (ret)
265+ goto err;
266+
267+ if (!priv->pattern) {
268+ if (!priv->rxport.source.sd) {
269+ ret = -ENODEV;
270+ goto err;
271+ }
272+
273+ sink_streams =
274+ v4l2_subdev_state_xlate_streams(state,
275+ MAX96714_PAD_SOURCE,
276+ MAX96714_PAD_SINK,
277+ &streams_mask);
278+
279+ ret = v4l2_subdev_enable_streams(priv->rxport.source.sd,
280+ priv->rxport.source.pad,
281+ sink_streams);
282+ if (ret)
283+ goto err;
284+ }
285+
286+ priv->enabled_source_streams |= streams_mask;
287+
288+ return 0;
289+
290+err:
291+ if (!priv->enabled_source_streams)
292+ max96714_disable_tx_port(priv);
293+
294+ return ret;
295+}
296+
297+static int max96714_disable_streams(struct v4l2_subdev *sd,
298+ struct v4l2_subdev_state *state,
299+ u32 source_pad, u64 streams_mask)
300+{
301+ struct max96714_priv *priv = sd_to_max96714(sd);
302+ u64 sink_streams;
303+
304+ if (!priv->pattern) {
305+ int ret;
306+
307+ sink_streams =
308+ v4l2_subdev_state_xlate_streams(state,
309+ MAX96714_PAD_SOURCE,
310+ MAX96714_PAD_SINK,
311+ &streams_mask);
312+
313+ ret = v4l2_subdev_disable_streams(priv->rxport.source.sd,
314+ priv->rxport.source.pad,
315+ sink_streams);
316+ if (ret)
317+ return ret;
318+ }
319+
320+ priv->enabled_source_streams &= ~streams_mask;
321+
322+ if (!priv->enabled_source_streams)
323+ max96714_disable_tx_port(priv);
324+
325+ return 0;
326+}
327+
328+static int max96714_set_fmt(struct v4l2_subdev *sd,
329+ struct v4l2_subdev_state *state,
330+ struct v4l2_subdev_format *format)
331+{
332+ struct max96714_priv *priv = sd_to_max96714(sd);
333+ struct v4l2_mbus_framefmt *fmt;
334+
335+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
336+ priv->enabled_source_streams)
337+ return -EBUSY;
338+
339+ /* No transcoding, source and sink formats must match. */
340+ if (format->pad == MAX96714_PAD_SOURCE)
341+ return v4l2_subdev_get_fmt(sd, state, format);
342+
343+ fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
344+ if (!fmt)
345+ return -EINVAL;
346+
347+ *fmt = format->format;
348+
349+ fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
350+ format->stream);
351+ if (!fmt)
352+ return -EINVAL;
353+
354+ *fmt = format->format;
355+
356+ return 0;
357+}
358+
359+static int _max96714_set_routing(struct v4l2_subdev *sd,
360+ struct v4l2_subdev_state *state,
361+ enum v4l2_subdev_format_whence which,
362+ struct v4l2_subdev_krouting *routing)
363+{
364+ static const struct v4l2_mbus_framefmt format = {
365+ .width = 1280,
366+ .height = 1080,
367+ .code = MEDIA_BUS_FMT_Y8_1X8,
368+ .field = V4L2_FIELD_NONE,
369+ };
370+ int ret;
371+
372+ /*
373+ * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until
374+ * frame desc is made dynamically allocated.
375+ */
376+ if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
377+ return -EINVAL;
378+
379+ ret = v4l2_subdev_routing_validate(sd, routing,
380+ V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
381+ if (ret)
382+ return ret;
383+
384+ return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
385+}
386+
387+static int max96714_set_routing(struct v4l2_subdev *sd,
388+ struct v4l2_subdev_state *state,
389+ enum v4l2_subdev_format_whence which,
390+ struct v4l2_subdev_krouting *routing)
391+{
392+ struct max96714_priv *priv = sd_to_max96714(sd);
393+
394+ if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
395+ return -EBUSY;
396+
397+ return _max96714_set_routing(sd, state, which, routing);
398+}
399+
400+static int max96714_init_state(struct v4l2_subdev *sd,
401+ struct v4l2_subdev_state *state)
402+{
403+ struct v4l2_subdev_route routes[] = {
404+ {
405+ .sink_pad = MAX96714_PAD_SINK,
406+ .sink_stream = 0,
407+ .source_pad = MAX96714_PAD_SOURCE,
408+ .source_stream = 0,
409+ .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
410+ }
411+ };
412+ struct v4l2_subdev_krouting routing = {
413+ .num_routes = ARRAY_SIZE(routes),
414+ .routes = routes,
415+ };
416+
417+ return _max96714_set_routing(sd, state, V4L2_SUBDEV_FORMAT_ACTIVE,
418+ &routing);
419+}
420+
421+static const struct v4l2_subdev_pad_ops max96714_pad_ops = {
422+ .enable_streams = max96714_enable_streams,
423+ .disable_streams = max96714_disable_streams,
424+
425+ .set_routing = max96714_set_routing,
426+ .get_fmt = v4l2_subdev_get_fmt,
427+ .set_fmt = max96714_set_fmt,
428+};
429+
430+static bool max96714_link_locked(struct max96714_priv *priv)
431+{
432+ u64 val = 0;
433+
434+ cci_read(priv->regmap, MAX96714_LINK_LOCK, &val, NULL);
435+
436+ return val & MAX96714_LINK_LOCK_BIT;
437+}
438+
439+static void max96714_link_status(struct max96714_priv *priv)
440+{
441+ struct device *dev = &priv->client->dev;
442+
443+ dev_info(dev, "Link locked:%d\n", max96714_link_locked(priv));
444+}
445+
446+static bool max96714_pipe_locked(struct max96714_priv *priv)
447+{
448+ u64 val;
449+
450+ cci_read(priv->regmap, MAX96714_VIDEO_RX8, &val, NULL);
451+
452+ return val & MAX96714_VID_LOCK;
453+}
454+
455+static void max96714_pipe_status(struct max96714_priv *priv)
456+{
457+ struct device *dev = &priv->client->dev;
458+
459+ dev_info(dev, "Pipe vidlock:%d\n", max96714_pipe_locked(priv));
460+}
461+
462+static void max96714_csi_status(struct max96714_priv *priv)
463+{
464+ struct device *dev = &priv->client->dev;
465+ u64 freq = 0;
466+
467+ cci_read(priv->regmap, MAX96714_BACKTOP25, &freq, NULL);
468+ freq = FIELD_GET(CSI_DPLL_FREQ_MASK, freq);
469+
470+ dev_info(dev, "CSI controller DPLL freq:%u00MHz CSIPHY enabled:%d\n",
471+ (u8)freq, max96714_tx_port_enabled(priv));
472+}
473+
474+static int max96714_log_status(struct v4l2_subdev *sd)
475+{
476+ struct max96714_priv *priv = sd_to_max96714(sd);
477+ struct device *dev = &priv->client->dev;
478+
479+ dev_info(dev, "Deserializer: max96714\n");
480+
481+ max96714_link_status(priv);
482+ max96714_pipe_status(priv);
483+ max96714_csi_status(priv);
484+
485+ return 0;
486+}
487+
488+static const struct v4l2_subdev_core_ops max96714_subdev_core_ops = {
489+ .log_status = max96714_log_status,
490+};
491+
492+static const struct v4l2_subdev_video_ops max96714_video_ops = {
493+ .s_stream = v4l2_subdev_s_stream_helper,
494+};
495+
496+static const struct v4l2_subdev_internal_ops max96714_internal_ops = {
497+ .init_state = max96714_init_state,
498+};
499+
500+static const struct v4l2_subdev_ops max96714_subdev_ops = {
501+ .video = &max96714_video_ops,
502+ .core = &max96714_subdev_core_ops,
503+ .pad = &max96714_pad_ops,
504+};
505+
506+static const struct media_entity_operations max96714_entity_ops = {
507+ .link_validate = v4l2_subdev_link_validate,
508+};
509+
510+static int max96714_notify_bound(struct v4l2_async_notifier *notifier,
511+ struct v4l2_subdev *subdev,
512+ struct v4l2_async_connection *asd)
513+{
514+ struct max96714_priv *priv = sd_to_max96714(notifier->sd);
515+ struct device *dev = &priv->client->dev;
516+ int ret;
517+
518+ ret = media_entity_get_fwnode_pad(&subdev->entity,
519+ priv->rxport.source.ep_fwnode,
520+ MEDIA_PAD_FL_SOURCE);
521+ if (ret < 0) {
522+ dev_err(dev, "Failed to find pad for %s\n", subdev->name);
523+ return ret;
524+ }
525+
526+ priv->rxport.source.sd = subdev;
527+ priv->rxport.source.pad = ret;
528+
529+ ret = media_create_pad_link(&priv->rxport.source.sd->entity,
530+ priv->rxport.source.pad, &priv->sd.entity,
531+ MAX96714_PAD_SINK,
532+ MEDIA_LNK_FL_ENABLED |
533+ MEDIA_LNK_FL_IMMUTABLE);
534+ if (ret) {
535+ dev_err(dev, "Unable to link %s:%u -> %s:%u\n",
536+ priv->rxport.source.sd->name, priv->rxport.source.pad,
537+ priv->sd.name, MAX96714_PAD_SINK);
538+ return ret;
539+ }
540+
541+ return 0;
542+}
543+
544+static const struct v4l2_async_notifier_operations max96714_notify_ops = {
545+ .bound = max96714_notify_bound,
546+};
547+
548+static int max96714_v4l2_notifier_register(struct max96714_priv *priv)
549+{
550+ struct device *dev = &priv->client->dev;
551+ struct max96714_rxport *rxport = &priv->rxport;
552+ struct v4l2_async_connection *asd;
553+ int ret;
554+
555+ if (!rxport->source.ep_fwnode)
556+ return 0;
557+
558+ v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
559+
560+ asd = v4l2_async_nf_add_fwnode(&priv->notifier,
561+ rxport->source.ep_fwnode,
562+ struct v4l2_async_connection);
563+ if (IS_ERR(asd)) {
564+ dev_err(dev, "Failed to add subdev: %pe", asd);
565+ v4l2_async_nf_cleanup(&priv->notifier);
566+ return PTR_ERR(asd);
567+ }
568+
569+ priv->notifier.ops = &max96714_notify_ops;
570+
571+ ret = v4l2_async_nf_register(&priv->notifier);
572+ if (ret) {
573+ dev_err(dev, "Failed to register subdev_notifier");
574+ v4l2_async_nf_cleanup(&priv->notifier);
575+ return ret;
576+ }
577+
578+ return 0;
579+}
580+
581+static int max96714_create_subdev(struct max96714_priv *priv)
582+{
583+ struct device *dev = &priv->client->dev;
584+ int ret;
585+
586+ v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96714_subdev_ops);
587+ priv->sd.internal_ops = &max96714_internal_ops;
588+
589+ v4l2_ctrl_handler_init(&priv->ctrl_handler, 1);
590+ priv->sd.ctrl_handler = &priv->ctrl_handler;
591+
592+ v4l2_ctrl_new_int_menu(&priv->ctrl_handler, NULL, V4L2_CID_LINK_FREQ,
593+ 0, 0, &priv->tx_link_freq);
594+ v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler,
595+ &max96714_ctrl_ops,
596+ V4L2_CID_TEST_PATTERN,
597+ ARRAY_SIZE(max96714_test_pattern) - 1,
598+ 0, 0, max96714_test_pattern);
599+ if (priv->ctrl_handler.error) {
600+ ret = priv->ctrl_handler.error;
601+ goto err_free_ctrl;
602+ }
603+
604+ priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
605+ priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
606+ priv->sd.entity.ops = &max96714_entity_ops;
607+
608+ priv->pads[MAX96714_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
609+ priv->pads[MAX96714_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
610+
611+ ret = media_entity_pads_init(&priv->sd.entity,
612+ MAX96714_NPORTS,
613+ priv->pads);
614+ if (ret)
615+ goto err_free_ctrl;
616+
617+ priv->sd.state_lock = priv->sd.ctrl_handler->lock;
618+
619+ ret = v4l2_subdev_init_finalize(&priv->sd);
620+ if (ret)
621+ goto err_entity_cleanup;
622+
623+ ret = max96714_v4l2_notifier_register(priv);
624+ if (ret) {
625+ dev_err(dev, "v4l2 subdev notifier register failed: %d\n", ret);
626+ goto err_subdev_cleanup;
627+ }
628+
629+ ret = v4l2_async_register_subdev(&priv->sd);
630+ if (ret) {
631+ dev_err(dev, "v4l2_async_register_subdev error: %d\n", ret);
632+ goto err_unreg_notif;
633+ }
634+
635+ return 0;
636+
637+err_unreg_notif:
638+ v4l2_async_nf_unregister(&priv->notifier);
639+ v4l2_async_nf_cleanup(&priv->notifier);
640+err_subdev_cleanup:
641+ v4l2_subdev_cleanup(&priv->sd);
642+err_entity_cleanup:
643+ media_entity_cleanup(&priv->sd.entity);
644+err_free_ctrl:
645+ v4l2_ctrl_handler_free(&priv->ctrl_handler);
646+
647+ return ret;
648+};
649+
650+static void max96714_destroy_subdev(struct max96714_priv *priv)
651+{
652+ v4l2_async_nf_unregister(&priv->notifier);
653+ v4l2_async_nf_cleanup(&priv->notifier);
654+ v4l2_async_unregister_subdev(&priv->sd);
655+
656+ v4l2_subdev_cleanup(&priv->sd);
657+
658+ media_entity_cleanup(&priv->sd.entity);
659+ v4l2_ctrl_handler_free(&priv->ctrl_handler);
660+}
661+
662+static int max96714_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
663+{
664+ return 0;
665+}
666+
667+static int max96714_i2c_mux_init(struct max96714_priv *priv)
668+{
669+ priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
670+ 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
671+ max96714_i2c_mux_select, NULL);
672+ if (!priv->mux)
673+ return -ENOMEM;
674+
675+ return i2c_mux_add_adapter(priv->mux, 0, 0);
676+}
677+
678+static int max96714_init_tx_port(struct max96714_priv *priv)
679+{
680+ struct v4l2_mbus_config_mipi_csi2 *mipi;
681+ unsigned long lanes_used = 0;
682+ unsigned int val, lane;
683+ int ret;
684+
685+ ret = max96714_disable_tx_port(priv);
686+
687+ mipi = &priv->mipi_csi2;
688+ val = div_u64(priv->tx_link_freq * 2, MHZ(100));
689+
690+ cci_update_bits(priv->regmap, MAX96714_BACKTOP25,
691+ CSI_DPLL_FREQ_MASK, val, &ret);
692+
693+ val = FIELD_PREP(MAX96714_CSI2_LANE_CNT_MASK, mipi->num_data_lanes - 1);
694+ cci_update_bits(priv->regmap, MAX96714_MIPI_LANE_CNT,
695+ MAX96714_CSI2_LANE_CNT_MASK, val, &ret);
696+
697+ /* lanes polarity */
698+ val = 0;
699+ for (lane = 0; lane < mipi->num_data_lanes + 1; lane++) {
700+ if (!mipi->lane_polarities[lane])
701+ continue;
702+ if (lane == 0)
703+ /* clock lane */
704+ val |= BIT(5);
705+ else if (lane < 3)
706+ /* Lane D0 and D1 */
707+ val |= BIT(lane - 1);
708+ else
709+ /* D2 and D3 */
710+ val |= BIT(lane);
711+ }
712+
713+ cci_update_bits(priv->regmap, MAX96714_MIPI_POLARITY,
714+ MAX96714_MIPI_POLARITY_MASK, val, &ret);
715+
716+ /* lanes mapping */
717+ val = 0;
718+ for (lane = 0; lane < mipi->num_data_lanes; lane++) {
719+ val |= (mipi->data_lanes[lane] - 1) << (lane * 2);
720+ lanes_used |= BIT(mipi->data_lanes[lane] - 1);
721+ }
722+
723+ /*
724+ * Unused lanes need to be mapped as well to not have
725+ * the same lanes mapped twice.
726+ */
727+ for (; lane < 4; lane++) {
728+ unsigned int idx = find_first_zero_bit(&lanes_used, 4);
729+
730+ val |= idx << (lane * 2);
731+ lanes_used |= BIT(idx);
732+ }
733+
734+ return cci_write(priv->regmap, MAX96714_MIPI_LANE_MAP, val, &ret);
735+}
736+
737+static int max96714_rxport_enable_poc(struct max96714_priv *priv)
738+{
739+ struct max96714_rxport *rxport = &priv->rxport;
740+
741+ if (!rxport->poc)
742+ return 0;
743+
744+ return regulator_enable(rxport->poc);
745+}
746+
747+static int max96714_rxport_disable_poc(struct max96714_priv *priv)
748+{
749+ struct max96714_rxport *rxport = &priv->rxport;
750+
751+ if (!rxport->poc)
752+ return 0;
753+
754+ return regulator_disable(rxport->poc);
755+}
756+
757+static int max96714_parse_dt_txport(struct max96714_priv *priv)
758+{
759+ struct device *dev = &priv->client->dev;
760+ struct v4l2_fwnode_endpoint vep = {
761+ .bus_type = V4L2_MBUS_CSI2_DPHY
762+ };
763+ struct fwnode_handle *ep_fwnode;
764+ u32 num_data_lanes;
765+ int ret;
766+
767+ ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
768+ MAX96714_PAD_SOURCE, 0, 0);
769+ if (!ep_fwnode)
770+ return -EINVAL;
771+
772+ ret = v4l2_fwnode_endpoint_alloc_parse(ep_fwnode, &vep);
773+ fwnode_handle_put(ep_fwnode);
774+ if (ret) {
775+ dev_err(dev, "tx: failed to parse endpoint data\n");
776+ return -EINVAL;
777+ }
778+
779+ if (vep.nr_of_link_frequencies != 1) {
780+ ret = -EINVAL;
781+ goto err_free_vep;
782+ }
783+
784+ priv->tx_link_freq = vep.link_frequencies[0];
785+ /* Min 50MHz, Max 1250MHz, 50MHz step */
786+ if (priv->tx_link_freq < MHZ(50) || priv->tx_link_freq > MHZ(1250) ||
787+ (u32)priv->tx_link_freq % MHZ(50)) {
788+ dev_err(dev, "tx: invalid link frequency\n");
789+ ret = -EINVAL;
790+ goto err_free_vep;
791+ }
792+
793+ num_data_lanes = vep.bus.mipi_csi2.num_data_lanes;
794+ if (num_data_lanes < 1 || num_data_lanes > 4) {
795+ dev_err(dev,
796+ "tx: invalid number of data lanes must be 1 to 4\n");
797+ ret = -EINVAL;
798+ goto err_free_vep;
799+ }
800+
801+ memcpy(&priv->mipi_csi2, &vep.bus.mipi_csi2, sizeof(priv->mipi_csi2));
802+
803+err_free_vep:
804+ v4l2_fwnode_endpoint_free(&vep);
805+
806+ return ret;
807+}
808+
809+static int max96714_parse_dt_rxport(struct max96714_priv *priv)
810+{
811+ static const char *poc_name = "port0-poc";
812+ struct max96714_rxport *rxport = &priv->rxport;
813+ struct device *dev = &priv->client->dev;
814+ struct fwnode_handle *ep_fwnode;
815+ int ret;
816+
817+ ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
818+ MAX96714_PAD_SINK, 0, 0);
819+ if (!ep_fwnode)
820+ return -ENOENT;
821+
822+ rxport->source.ep_fwnode = fwnode_graph_get_remote_endpoint(ep_fwnode);
823+ fwnode_handle_put(ep_fwnode);
824+
825+ if (!rxport->source.ep_fwnode) {
826+ dev_err(dev, "rx: no remote endpoint\n");
827+ return -EINVAL;
828+ }
829+
830+ rxport->poc = devm_regulator_get_optional(dev, poc_name);
831+ if (IS_ERR(rxport->poc)) {
832+ ret = PTR_ERR(rxport->poc);
833+ if (ret == -ENODEV) {
834+ rxport->poc = NULL;
835+ } else {
836+ dev_err(dev, "rx: failed to get POC supply: %d\n", ret);
837+ goto err_put_source_ep_fwnode;
838+ }
839+ }
840+
841+ return 0;
842+
843+err_put_source_ep_fwnode:
844+ fwnode_handle_put(rxport->source.ep_fwnode);
845+ return ret;
846+}
847+
848+static int max96714_parse_dt(struct max96714_priv *priv)
849+{
850+ int ret;
851+
852+ ret = max96714_parse_dt_txport(priv);
853+ if (ret)
854+ return ret;
855+
856+ ret = max96714_parse_dt_rxport(priv);
857+ /*
858+ * The deserializer can create a test pattern even if the
859+ * rx port is not connected to a serializer.
860+ */
861+ if (ret && ret == -ENOENT)
862+ ret = 0;
863+
864+ return ret;
865+}
866+
867+static int max96714_enable_core_hw(struct max96714_priv *priv)
868+{
869+ struct device *dev = &priv->client->dev;
870+ u64 val;
871+ int ret;
872+
873+ if (priv->pd_gpio) {
874+ /* wait min 2 ms for reset to complete */
875+ gpiod_set_value_cansleep(priv->pd_gpio, 1);
876+ fsleep(2000);
877+ gpiod_set_value_cansleep(priv->pd_gpio, 0);
878+ /* wait min 2 ms for power up to finish */
879+ fsleep(2000);
880+ }
881+
882+ ret = cci_read(priv->regmap, MAX96714_REG13, &val, NULL);
883+ if (ret) {
884+ dev_err_probe(dev, ret, "Cannot read first register, abort\n");
885+ goto err_pd_gpio;
886+ }
887+
888+ if (val != MAX96714_DEVICE_ID && val != MAX96714F_DEVICE_ID) {
889+ dev_err(dev, "Unsupported device id expected %x got %x\n",
890+ MAX96714F_DEVICE_ID, (u8)val);
891+ ret = -EOPNOTSUPP;
892+ goto err_pd_gpio;
893+ }
894+
895+ ret = cci_read(priv->regmap, MAX96714_DEV_REV, &val, NULL);
896+ if (ret)
897+ goto err_pd_gpio;
898+
899+ dev_dbg(dev, "Found %x (rev %lx)\n", MAX96714F_DEVICE_ID,
900+ (u8)val & MAX96714_DEV_REV_MASK);
901+
902+ ret = cci_read(priv->regmap, MAX96714_MIPI_TX52, &val, NULL);
903+ if (ret)
904+ goto err_pd_gpio;
905+
906+ if (!(val & MAX96714_TUN_EN)) {
907+ dev_err(dev, "Only supporting tunnel mode");
908+ ret = -EOPNOTSUPP;
909+ goto err_pd_gpio;
910+ }
911+
912+ return 0;
913+
914+err_pd_gpio:
915+ gpiod_set_value_cansleep(priv->pd_gpio, 1);
916+ return ret;
917+}
918+
919+static void max96714_disable_core_hw(struct max96714_priv *priv)
920+{
921+ gpiod_set_value_cansleep(priv->pd_gpio, 1);
922+}
923+
924+static int max96714_get_hw_resources(struct max96714_priv *priv)
925+{
926+ struct device *dev = &priv->client->dev;
927+
928+ priv->regmap = devm_cci_regmap_init_i2c(priv->client, 16);
929+ if (IS_ERR(priv->regmap))
930+ return PTR_ERR(priv->regmap);
931+
932+ priv->pd_gpio =
933+ devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH);
934+ if (IS_ERR(priv->pd_gpio))
935+ return dev_err_probe(dev, PTR_ERR(priv->pd_gpio),
936+ "Cannot get powerdown GPIO\n");
937+ return 0;
938+}
939+
940+static int max96714_probe(struct i2c_client *client)
941+{
942+ struct device *dev = &client->dev;
943+ struct max96714_priv *priv;
944+ int ret;
945+
946+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
947+ if (!priv)
948+ return -ENOMEM;
949+
950+ priv->client = client;
951+
952+ ret = max96714_get_hw_resources(priv);
953+ if (ret)
954+ return ret;
955+
956+ ret = max96714_enable_core_hw(priv);
957+ if (ret)
958+ return ret;
959+
960+ ret = max96714_parse_dt(priv);
961+ if (ret)
962+ goto err_disable_core_hw;
963+
964+ max96714_init_tx_port(priv);
965+
966+ ret = max96714_rxport_enable_poc(priv);
967+ if (ret)
968+ goto err_free_ports;
969+
970+ ret = max96714_i2c_mux_init(priv);
971+ if (ret)
972+ goto err_disable_poc;
973+
974+ ret = max96714_create_subdev(priv);
975+ if (ret)
976+ goto err_del_mux;
977+
978+ return 0;
979+
980+err_del_mux:
981+ i2c_mux_del_adapters(priv->mux);
982+err_disable_poc:
983+ max96714_rxport_disable_poc(priv);
984+err_free_ports:
985+ fwnode_handle_put(priv->rxport.source.ep_fwnode);
986+err_disable_core_hw:
987+ max96714_disable_core_hw(priv);
988+
989+ return ret;
990+}
991+
992+static void max96714_remove(struct i2c_client *client)
993+{
994+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
995+ struct max96714_priv *priv = sd_to_max96714(sd);
996+
997+ max96714_destroy_subdev(priv);
998+ i2c_mux_del_adapters(priv->mux);
999+ max96714_rxport_disable_poc(priv);
1000+ fwnode_handle_put(priv->rxport.source.ep_fwnode);
1001+ max96714_disable_core_hw(priv);
1002+ gpiod_set_value_cansleep(priv->pd_gpio, 1);
1003+}
1004+
1005+static const struct of_device_id max96714_of_ids[] = {
1006+ { .compatible = "maxim,max96714f" },
1007+ { }
1008+};
1009+MODULE_DEVICE_TABLE(of, max96714_of_ids);
1010+
1011+static struct i2c_driver max96714_i2c_driver = {
1012+ .driver = {
1013+ .name = "max96714",
1014+ .of_match_table = max96714_of_ids,
1015+ },
1016+ .probe = max96714_probe,
1017+ .remove = max96714_remove,
1018+};
1019+
1020+module_i2c_driver(max96714_i2c_driver);
1021+
1022+MODULE_LICENSE("GPL");
1023+MODULE_DESCRIPTION("Maxim Integrated GMSL2 Deserializers Driver");
1024+MODULE_AUTHOR("Julien Massot <julien.massot@collabora.com>");
drivers/media/i2c/max96717.c+927−0
@@ -0,0 +1,927 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Maxim GMSL2 Serializer Driver
4+ *
5+ * Copyright (C) 2024 Collabora Ltd.
6+ */
7+
8+#include <linux/bitfield.h>
9+#include <linux/clk.h>
10+#include <linux/clk-provider.h>
11+#include <linux/delay.h>
12+#include <linux/fwnode.h>
13+#include <linux/gpio/driver.h>
14+#include <linux/i2c-mux.h>
15+#include <linux/i2c.h>
16+#include <linux/regmap.h>
17+
18+#include <media/v4l2-cci.h>
19+#include <media/v4l2-fwnode.h>
20+#include <media/v4l2-subdev.h>
21+
22+#define MAX96717_DEVICE_ID 0xbf
23+#define MAX96717F_DEVICE_ID 0xc8
24+#define MAX96717_PORTS 2
25+#define MAX96717_PAD_SINK 0
26+#define MAX96717_PAD_SOURCE 1
27+
28+#define MAX96717_DEFAULT_CLKOUT_RATE 24000000UL
29+
30+/* DEV */
31+#define MAX96717_REG3 CCI_REG8(0x3)
32+#define MAX96717_RCLKSEL GENMASK(1, 0)
33+#define RCLKSEL_REF_PLL CCI_REG8(0x3)
34+#define MAX96717_REG6 CCI_REG8(0x6)
35+#define RCLKEN BIT(5)
36+#define MAX96717_DEV_ID CCI_REG8(0xd)
37+#define MAX96717_DEV_REV CCI_REG8(0xe)
38+#define MAX96717_DEV_REV_MASK GENMASK(3, 0)
39+
40+/* VID_TX Z */
41+#define MAX96717_VIDEO_TX2 CCI_REG8(0x112)
42+#define MAX96717_VIDEO_PCLKDET BIT(7)
43+
44+/* GPIO */
45+#define MAX96717_NUM_GPIO 11
46+#define MAX96717_GPIO_REG_A(gpio) CCI_REG8(0x2be + (gpio) * 3)
47+#define MAX96717_GPIO_OUT BIT(4)
48+#define MAX96717_GPIO_IN BIT(3)
49+#define MAX96717_GPIO_RX_EN BIT(2)
50+#define MAX96717_GPIO_TX_EN BIT(1)
51+#define MAX96717_GPIO_OUT_DIS BIT(0)
52+
53+/* FRONTTOP */
54+/* MAX96717 only have CSI port 'B' */
55+#define MAX96717_FRONTOP0 CCI_REG8(0x308)
56+#define MAX96717_START_PORT_B BIT(5)
57+
58+/* MIPI_RX */
59+#define MAX96717_MIPI_RX1 CCI_REG8(0x331)
60+#define MAX96717_MIPI_LANES_CNT GENMASK(5, 4)
61+#define MAX96717_MIPI_RX2 CCI_REG8(0x332) /* phy1 Lanes map */
62+#define MAX96717_PHY2_LANES_MAP GENMASK(7, 4)
63+#define MAX96717_MIPI_RX3 CCI_REG8(0x333) /* phy2 Lanes map */
64+#define MAX96717_PHY1_LANES_MAP GENMASK(3, 0)
65+#define MAX96717_MIPI_RX4 CCI_REG8(0x334) /* phy1 lane polarities */
66+#define MAX96717_PHY1_LANES_POL GENMASK(6, 4)
67+#define MAX96717_MIPI_RX5 CCI_REG8(0x335) /* phy2 lane polarities */
68+#define MAX96717_PHY2_LANES_POL GENMASK(2, 0)
69+
70+/* MIPI_RX_EXT */
71+#define MAX96717_MIPI_RX_EXT11 CCI_REG8(0x383)
72+#define MAX96717_TUN_MODE BIT(7)
73+
74+/* REF_VTG */
75+#define REF_VTG0 CCI_REG8(0x3f0)
76+#define REFGEN_PREDEF_EN BIT(6)
77+#define REFGEN_PREDEF_FREQ_MASK GENMASK(5, 4)
78+#define REFGEN_PREDEF_FREQ_ALT BIT(3)
79+#define REFGEN_RST BIT(1)
80+#define REFGEN_EN BIT(0)
81+
82+/* MISC */
83+#define PIO_SLEW_1 CCI_REG8(0x570)
84+
85+struct max96717_priv {
86+ struct i2c_client *client;
87+ struct regmap *regmap;
88+ struct i2c_mux_core *mux;
89+ struct v4l2_mbus_config_mipi_csi2 mipi_csi2;
90+ struct v4l2_subdev sd;
91+ struct media_pad pads[MAX96717_PORTS];
92+ struct v4l2_async_notifier notifier;
93+ struct v4l2_subdev *source_sd;
94+ u16 source_sd_pad;
95+ u64 enabled_source_streams;
96+ u8 pll_predef_index;
97+ struct clk_hw clk_hw;
98+ struct gpio_chip gpio_chip;
99+};
100+
101+static inline struct max96717_priv *sd_to_max96717(struct v4l2_subdev *sd)
102+{
103+ return container_of(sd, struct max96717_priv, sd);
104+}
105+
106+static inline struct max96717_priv *clk_hw_to_max96717(struct clk_hw *hw)
107+{
108+ return container_of(hw, struct max96717_priv, clk_hw);
109+}
110+
111+static int max96717_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
112+{
113+ return 0;
114+}
115+
116+static int max96717_i2c_mux_init(struct max96717_priv *priv)
117+{
118+ priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
119+ 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
120+ max96717_i2c_mux_select, NULL);
121+ if (!priv->mux)
122+ return -ENOMEM;
123+
124+ return i2c_mux_add_adapter(priv->mux, 0, 0);
125+}
126+
127+static inline int max96717_start_csi(struct max96717_priv *priv, bool start)
128+{
129+ return cci_update_bits(priv->regmap, MAX96717_FRONTOP0,
130+ MAX96717_START_PORT_B,
131+ start ? MAX96717_START_PORT_B : 0, NULL);
132+}
133+
134+static int max96717_gpiochip_get(struct gpio_chip *gpiochip,
135+ unsigned int offset)
136+{
137+ struct max96717_priv *priv = gpiochip_get_data(gpiochip);
138+ u64 val;
139+ int ret;
140+
141+ ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset),
142+ &val, NULL);
143+ if (ret)
144+ return ret;
145+
146+ if (val & MAX96717_GPIO_OUT_DIS)
147+ return !!(val & MAX96717_GPIO_IN);
148+ else
149+ return !!(val & MAX96717_GPIO_OUT);
150+}
151+
152+static void max96717_gpiochip_set(struct gpio_chip *gpiochip,
153+ unsigned int offset, int value)
154+{
155+ struct max96717_priv *priv = gpiochip_get_data(gpiochip);
156+
157+ cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
158+ MAX96717_GPIO_OUT, MAX96717_GPIO_OUT, NULL);
159+}
160+
161+static int max96717_gpio_get_direction(struct gpio_chip *gpiochip,
162+ unsigned int offset)
163+{
164+ struct max96717_priv *priv = gpiochip_get_data(gpiochip);
165+ u64 val;
166+ int ret;
167+
168+ ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset), &val, NULL);
169+ if (ret < 0)
170+ return ret;
171+
172+ return !!(val & MAX96717_GPIO_OUT_DIS);
173+}
174+
175+static int max96717_gpio_direction_out(struct gpio_chip *gpiochip,
176+ unsigned int offset, int value)
177+{
178+ struct max96717_priv *priv = gpiochip_get_data(gpiochip);
179+
180+ return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
181+ MAX96717_GPIO_OUT_DIS | MAX96717_GPIO_OUT,
182+ value ? MAX96717_GPIO_OUT : 0, NULL);
183+}
184+
185+static int max96717_gpio_direction_in(struct gpio_chip *gpiochip,
186+ unsigned int offset)
187+{
188+ struct max96717_priv *priv = gpiochip_get_data(gpiochip);
189+
190+ return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset),
191+ MAX96717_GPIO_OUT_DIS, MAX96717_GPIO_OUT_DIS,
192+ NULL);
193+}
194+
195+static int max96717_gpiochip_probe(struct max96717_priv *priv)
196+{
197+ struct device *dev = &priv->client->dev;
198+ struct gpio_chip *gc = &priv->gpio_chip;
199+ int i, ret = 0;
200+
201+ gc->label = dev_name(dev);
202+ gc->parent = dev;
203+ gc->owner = THIS_MODULE;
204+ gc->ngpio = MAX96717_NUM_GPIO;
205+ gc->base = -1;
206+ gc->can_sleep = true;
207+ gc->get_direction = max96717_gpio_get_direction;
208+ gc->direction_input = max96717_gpio_direction_in;
209+ gc->direction_output = max96717_gpio_direction_out;
210+ gc->set = max96717_gpiochip_set;
211+ gc->get = max96717_gpiochip_get;
212+ gc->of_gpio_n_cells = 2;
213+
214+ /* Disable GPIO forwarding */
215+ for (i = 0; i < gc->ngpio; i++)
216+ cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(i),
217+ MAX96717_GPIO_RX_EN | MAX96717_GPIO_TX_EN,
218+ 0, &ret);
219+
220+ if (ret)
221+ return ret;
222+
223+ ret = devm_gpiochip_add_data(dev, gc, priv);
224+ if (ret) {
225+ dev_err(dev, "Unable to create gpio_chip\n");
226+ return ret;
227+ }
228+
229+ return 0;
230+}
231+
232+static int _max96717_set_routing(struct v4l2_subdev *sd,
233+ struct v4l2_subdev_state *state,
234+ struct v4l2_subdev_krouting *routing)
235+{
236+ static const struct v4l2_mbus_framefmt format = {
237+ .width = 1280,
238+ .height = 1080,
239+ .code = MEDIA_BUS_FMT_Y8_1X8,
240+ .field = V4L2_FIELD_NONE,
241+ };
242+ int ret;
243+
244+ ret = v4l2_subdev_routing_validate(sd, routing,
245+ V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
246+ if (ret)
247+ return ret;
248+
249+ ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
250+ if (ret)
251+ return ret;
252+
253+ return 0;
254+}
255+
256+static int max96717_set_routing(struct v4l2_subdev *sd,
257+ struct v4l2_subdev_state *state,
258+ enum v4l2_subdev_format_whence which,
259+ struct v4l2_subdev_krouting *routing)
260+{
261+ struct max96717_priv *priv = sd_to_max96717(sd);
262+
263+ if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
264+ return -EBUSY;
265+
266+ return _max96717_set_routing(sd, state, routing);
267+}
268+
269+static int max96717_set_fmt(struct v4l2_subdev *sd,
270+ struct v4l2_subdev_state *state,
271+ struct v4l2_subdev_format *format)
272+{
273+ struct max96717_priv *priv = sd_to_max96717(sd);
274+ struct v4l2_mbus_framefmt *fmt;
275+ u64 stream_source_mask;
276+
277+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
278+ priv->enabled_source_streams)
279+ return -EBUSY;
280+
281+ /* No transcoding, source and sink formats must match. */
282+ if (format->pad == MAX96717_PAD_SOURCE)
283+ return v4l2_subdev_get_fmt(sd, state, format);
284+
285+ /* Set sink format */
286+ fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
287+ if (!fmt)
288+ return -EINVAL;
289+
290+ *fmt = format->format;
291+
292+ /* Propagate to source format */
293+ fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
294+ format->stream);
295+ if (!fmt)
296+ return -EINVAL;
297+ *fmt = format->format;
298+
299+ stream_source_mask = BIT(format->stream);
300+
301+ return v4l2_subdev_state_xlate_streams(state, MAX96717_PAD_SOURCE,
302+ MAX96717_PAD_SINK,
303+ &stream_source_mask);
304+}
305+
306+static int max96717_init_state(struct v4l2_subdev *sd,
307+ struct v4l2_subdev_state *state)
308+{
309+ struct v4l2_subdev_route routes[] = {
310+ {
311+ .sink_pad = MAX96717_PAD_SINK,
312+ .sink_stream = 0,
313+ .source_pad = MAX96717_PAD_SOURCE,
314+ .source_stream = 0,
315+ .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
316+ },
317+ };
318+ struct v4l2_subdev_krouting routing = {
319+ .num_routes = ARRAY_SIZE(routes),
320+ .routes = routes,
321+ };
322+
323+ return _max96717_set_routing(sd, state, &routing);
324+}
325+
326+static bool max96717_pipe_pclkdet(struct max96717_priv *priv)
327+{
328+ u64 val = 0;
329+
330+ cci_read(priv->regmap, MAX96717_VIDEO_TX2, &val, NULL);
331+
332+ return val & MAX96717_VIDEO_PCLKDET;
333+}
334+
335+static int max96717_log_status(struct v4l2_subdev *sd)
336+{
337+ struct max96717_priv *priv = sd_to_max96717(sd);
338+ struct device *dev = &priv->client->dev;
339+
340+ dev_info(dev, "Serializer: max96717\n");
341+ dev_info(dev, "Pipe: pclkdet:%d\n", max96717_pipe_pclkdet(priv));
342+
343+ return 0;
344+}
345+
346+static int max96717_enable_streams(struct v4l2_subdev *sd,
347+ struct v4l2_subdev_state *state, u32 pad,
348+ u64 streams_mask)
349+{
350+ struct max96717_priv *priv = sd_to_max96717(sd);
351+ struct device *dev = &priv->client->dev;
352+ u64 sink_streams;
353+ int ret;
354+
355+ sink_streams = v4l2_subdev_state_xlate_streams(state,
356+ MAX96717_PAD_SOURCE,
357+ MAX96717_PAD_SINK,
358+ &streams_mask);
359+
360+ if (!priv->enabled_source_streams)
361+ max96717_start_csi(priv, true);
362+
363+ ret = v4l2_subdev_enable_streams(priv->source_sd, priv->source_sd_pad,
364+ sink_streams);
365+ if (ret) {
366+ dev_err(dev, "Fail to start streams:%llu on remote subdev\n",
367+ sink_streams);
368+ goto stop_csi;
369+ }
370+
371+ priv->enabled_source_streams |= streams_mask;
372+
373+ return 0;
374+
375+stop_csi:
376+ if (!priv->enabled_source_streams)
377+ max96717_start_csi(priv, false);
378+ return ret;
379+}
380+
381+static int max96717_disable_streams(struct v4l2_subdev *sd,
382+ struct v4l2_subdev_state *state, u32 pad,
383+ u64 streams_mask)
384+{
385+ struct max96717_priv *priv = sd_to_max96717(sd);
386+ u64 sink_streams;
387+
388+ /*
389+ * Stop the CSI receiver first then the source,
390+ * otherwise the device may become unresponsive
391+ * while holding the I2C bus low.
392+ */
393+ priv->enabled_source_streams &= ~streams_mask;
394+ if (!priv->enabled_source_streams)
395+ max96717_start_csi(priv, false);
396+
397+ sink_streams = v4l2_subdev_state_xlate_streams(state,
398+ MAX96717_PAD_SOURCE,
399+ MAX96717_PAD_SINK,
400+ &streams_mask);
401+
402+ return v4l2_subdev_disable_streams(priv->source_sd, priv->source_sd_pad,
403+ sink_streams);
404+}
405+
406+static const struct v4l2_subdev_pad_ops max96717_pad_ops = {
407+ .enable_streams = max96717_enable_streams,
408+ .disable_streams = max96717_disable_streams,
409+ .set_routing = max96717_set_routing,
410+ .get_fmt = v4l2_subdev_get_fmt,
411+ .set_fmt = max96717_set_fmt,
412+};
413+
414+static const struct v4l2_subdev_core_ops max96717_subdev_core_ops = {
415+ .log_status = max96717_log_status,
416+};
417+
418+static const struct v4l2_subdev_internal_ops max96717_internal_ops = {
419+ .init_state = max96717_init_state,
420+};
421+
422+static const struct v4l2_subdev_ops max96717_subdev_ops = {
423+ .core = &max96717_subdev_core_ops,
424+ .pad = &max96717_pad_ops,
425+};
426+
427+static const struct media_entity_operations max96717_entity_ops = {
428+ .link_validate = v4l2_subdev_link_validate,
429+};
430+
431+static int max96717_notify_bound(struct v4l2_async_notifier *notifier,
432+ struct v4l2_subdev *source_subdev,
433+ struct v4l2_async_connection *asd)
434+{
435+ struct max96717_priv *priv = sd_to_max96717(notifier->sd);
436+ struct device *dev = &priv->client->dev;
437+ int ret;
438+
439+ ret = media_entity_get_fwnode_pad(&source_subdev->entity,
440+ source_subdev->fwnode,
441+ MEDIA_PAD_FL_SOURCE);
442+ if (ret < 0) {
443+ dev_err(dev, "Failed to find pad for %s\n",
444+ source_subdev->name);
445+ return ret;
446+ }
447+
448+ priv->source_sd = source_subdev;
449+ priv->source_sd_pad = ret;
450+
451+ ret = media_create_pad_link(&source_subdev->entity, priv->source_sd_pad,
452+ &priv->sd.entity, 0,
453+ MEDIA_LNK_FL_ENABLED |
454+ MEDIA_LNK_FL_IMMUTABLE);
455+ if (ret) {
456+ dev_err(dev, "Unable to link %s:%u -> %s:0\n",
457+ source_subdev->name, priv->source_sd_pad,
458+ priv->sd.name);
459+ return ret;
460+ }
461+
462+ return 0;
463+}
464+
465+static const struct v4l2_async_notifier_operations max96717_notify_ops = {
466+ .bound = max96717_notify_bound,
467+};
468+
469+static int max96717_v4l2_notifier_register(struct max96717_priv *priv)
470+{
471+ struct device *dev = &priv->client->dev;
472+ struct v4l2_async_connection *asd;
473+ struct fwnode_handle *ep_fwnode;
474+ int ret;
475+
476+ ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
477+ MAX96717_PAD_SINK, 0, 0);
478+ if (!ep_fwnode) {
479+ dev_err(dev, "No graph endpoint\n");
480+ return -ENODEV;
481+ }
482+
483+ v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
484+
485+ asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode,
486+ struct v4l2_async_connection);
487+
488+ fwnode_handle_put(ep_fwnode);
489+
490+ if (IS_ERR(asd)) {
491+ dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
492+ v4l2_async_nf_cleanup(&priv->notifier);
493+ return PTR_ERR(asd);
494+ }
495+
496+ priv->notifier.ops = &max96717_notify_ops;
497+
498+ ret = v4l2_async_nf_register(&priv->notifier);
499+ if (ret) {
500+ dev_err(dev, "Failed to register subdev_notifier");
501+ v4l2_async_nf_cleanup(&priv->notifier);
502+ return ret;
503+ }
504+
505+ return 0;
506+}
507+
508+static int max96717_subdev_init(struct max96717_priv *priv)
509+{
510+ struct device *dev = &priv->client->dev;
511+ int ret;
512+
513+ v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96717_subdev_ops);
514+ priv->sd.internal_ops = &max96717_internal_ops;
515+
516+ priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
517+ priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
518+ priv->sd.entity.ops = &max96717_entity_ops;
519+
520+ priv->pads[MAX96717_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
521+ priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
522+
523+ ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
524+ if (ret)
525+ return dev_err_probe(dev, ret, "Failed to init pads\n");
526+
527+ ret = v4l2_subdev_init_finalize(&priv->sd);
528+ if (ret) {
529+ dev_err_probe(dev, ret,
530+ "v4l2 subdev init finalized failed\n");
531+ goto err_entity_cleanup;
532+ }
533+ ret = max96717_v4l2_notifier_register(priv);
534+ if (ret) {
535+ dev_err_probe(dev, ret,
536+ "v4l2 subdev notifier register failed\n");
537+ goto err_free_state;
538+ }
539+
540+ ret = v4l2_async_register_subdev(&priv->sd);
541+ if (ret) {
542+ dev_err_probe(dev, ret, "v4l2_async_register_subdev error\n");
543+ goto err_unreg_notif;
544+ }
545+
546+ return 0;
547+
548+err_unreg_notif:
549+ v4l2_async_nf_unregister(&priv->notifier);
550+ v4l2_async_nf_cleanup(&priv->notifier);
551+err_free_state:
552+ v4l2_subdev_cleanup(&priv->sd);
553+err_entity_cleanup:
554+ media_entity_cleanup(&priv->sd.entity);
555+
556+ return ret;
557+}
558+
559+static void max96717_subdev_uninit(struct max96717_priv *priv)
560+{
561+ v4l2_async_unregister_subdev(&priv->sd);
562+ v4l2_async_nf_unregister(&priv->notifier);
563+ v4l2_async_nf_cleanup(&priv->notifier);
564+ v4l2_subdev_cleanup(&priv->sd);
565+ media_entity_cleanup(&priv->sd.entity);
566+}
567+
568+struct max96717_pll_predef_freq {
569+ unsigned long freq;
570+ bool is_alt;
571+ u8 val;
572+};
573+
574+static const struct max96717_pll_predef_freq max96717_predef_freqs[] = {
575+ { 13500000, true, 0 }, { 19200000, false, 0 },
576+ { 24000000, true, 1 }, { 27000000, false, 1 },
577+ { 37125000, false, 2 }, { 74250000, false, 3 },
578+};
579+
580+static unsigned long
581+max96717_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
582+{
583+ struct max96717_priv *priv = clk_hw_to_max96717(hw);
584+
585+ return max96717_predef_freqs[priv->pll_predef_index].freq;
586+}
587+
588+static unsigned int max96717_clk_find_best_index(struct max96717_priv *priv,
589+ unsigned long rate)
590+{
591+ unsigned int i, idx;
592+ unsigned long diff_new, diff_old;
593+
594+ diff_old = U32_MAX;
595+ idx = 0;
596+
597+ for (i = 0; i < ARRAY_SIZE(max96717_predef_freqs); i++) {
598+ diff_new = abs(rate - max96717_predef_freqs[i].freq);
599+ if (diff_new < diff_old) {
600+ diff_old = diff_new;
601+ idx = i;
602+ }
603+ }
604+
605+ return idx;
606+}
607+
608+static long max96717_clk_round_rate(struct clk_hw *hw, unsigned long rate,
609+ unsigned long *parent_rate)
610+{
611+ struct max96717_priv *priv = clk_hw_to_max96717(hw);
612+ struct device *dev = &priv->client->dev;
613+ unsigned int idx;
614+
615+ idx = max96717_clk_find_best_index(priv, rate);
616+
617+ if (rate != max96717_predef_freqs[idx].freq) {
618+ dev_warn(dev, "Request CLK freq:%lu, found CLK freq:%lu\n",
619+ rate, max96717_predef_freqs[idx].freq);
620+ }
621+
622+ return max96717_predef_freqs[idx].freq;
623+}
624+
625+static int max96717_clk_set_rate(struct clk_hw *hw, unsigned long rate,
626+ unsigned long parent_rate)
627+{
628+ struct max96717_priv *priv = clk_hw_to_max96717(hw);
629+ unsigned int val, idx;
630+ int ret = 0;
631+
632+ idx = max96717_clk_find_best_index(priv, rate);
633+
634+ val = FIELD_PREP(REFGEN_PREDEF_FREQ_MASK,
635+ max96717_predef_freqs[idx].val);
636+
637+ if (max96717_predef_freqs[idx].is_alt)
638+ val |= REFGEN_PREDEF_FREQ_ALT;
639+
640+ val |= REFGEN_RST | REFGEN_PREDEF_EN;
641+
642+ cci_write(priv->regmap, REF_VTG0, val, &ret);
643+ cci_update_bits(priv->regmap, REF_VTG0, REFGEN_RST | REFGEN_EN,
644+ REFGEN_EN, &ret);
645+ if (ret)
646+ return ret;
647+
648+ priv->pll_predef_index = idx;
649+
650+ return 0;
651+}
652+
653+static int max96717_clk_prepare(struct clk_hw *hw)
654+{
655+ struct max96717_priv *priv = clk_hw_to_max96717(hw);
656+
657+ return cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN,
658+ RCLKEN, NULL);
659+}
660+
661+static void max96717_clk_unprepare(struct clk_hw *hw)
662+{
663+ struct max96717_priv *priv = clk_hw_to_max96717(hw);
664+
665+ cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN, 0, NULL);
666+}
667+
668+static const struct clk_ops max96717_clk_ops = {
669+ .prepare = max96717_clk_prepare,
670+ .unprepare = max96717_clk_unprepare,
671+ .set_rate = max96717_clk_set_rate,
672+ .recalc_rate = max96717_clk_recalc_rate,
673+ .round_rate = max96717_clk_round_rate,
674+};
675+
676+static int max96717_register_clkout(struct max96717_priv *priv)
677+{
678+ struct device *dev = &priv->client->dev;
679+ struct clk_init_data init = { .ops = &max96717_clk_ops };
680+ int ret;
681+
682+ init.name = kasprintf(GFP_KERNEL, "max96717.%s.clk_out",
683+ dev_name(dev));
684+ if (!init.name)
685+ return -ENOMEM;
686+
687+ /* RCLKSEL Reference PLL output */
688+ ret = cci_update_bits(priv->regmap, MAX96717_REG3, MAX96717_RCLKSEL,
689+ MAX96717_RCLKSEL, NULL);
690+ /* MFP4 fastest slew rate */
691+ cci_update_bits(priv->regmap, PIO_SLEW_1, BIT(5) | BIT(4), 0, &ret);
692+ if (ret)
693+ goto free_init_name;
694+
695+ priv->clk_hw.init = &init;
696+
697+ /* Initialize to 24 MHz */
698+ ret = max96717_clk_set_rate(&priv->clk_hw,
699+ MAX96717_DEFAULT_CLKOUT_RATE, 0);
700+ if (ret < 0)
701+ goto free_init_name;
702+
703+ ret = devm_clk_hw_register(dev, &priv->clk_hw);
704+ kfree(init.name);
705+ if (ret)
706+ return dev_err_probe(dev, ret, "Cannot register clock HW\n");
707+
708+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
709+ &priv->clk_hw);
710+ if (ret)
711+ return dev_err_probe(dev, ret,
712+ "Cannot add OF clock provider\n");
713+
714+ return 0;
715+
716+free_init_name:
717+ kfree(init.name);
718+ return ret;
719+}
720+
721+static int max96717_init_csi_lanes(struct max96717_priv *priv)
722+{
723+ struct v4l2_mbus_config_mipi_csi2 *mipi = &priv->mipi_csi2;
724+ unsigned long lanes_used = 0;
725+ unsigned int nlanes, lane, val = 0;
726+ int ret;
727+
728+ nlanes = mipi->num_data_lanes;
729+
730+ ret = cci_update_bits(priv->regmap, MAX96717_MIPI_RX1,
731+ MAX96717_MIPI_LANES_CNT,
732+ FIELD_PREP(MAX96717_MIPI_LANES_CNT,
733+ nlanes - 1), NULL);
734+
735+ /* lanes polarity */
736+ for (lane = 0; lane < nlanes + 1; lane++) {
737+ if (!mipi->lane_polarities[lane])
738+ continue;
739+ /* Clock lane */
740+ if (lane == 0)
741+ val |= BIT(2);
742+ else if (lane < 3)
743+ val |= BIT(lane - 1);
744+ else
745+ val |= BIT(lane);
746+ }
747+
748+ cci_update_bits(priv->regmap, MAX96717_MIPI_RX5,
749+ MAX96717_PHY2_LANES_POL,
750+ FIELD_PREP(MAX96717_PHY2_LANES_POL, val), &ret);
751+
752+ cci_update_bits(priv->regmap, MAX96717_MIPI_RX4,
753+ MAX96717_PHY1_LANES_POL,
754+ FIELD_PREP(MAX96717_PHY1_LANES_POL,
755+ val >> 3), &ret);
756+ /* lanes mapping */
757+ for (lane = 0, val = 0; lane < nlanes; lane++) {
758+ val |= (mipi->data_lanes[lane] - 1) << (lane * 2);
759+ lanes_used |= BIT(mipi->data_lanes[lane] - 1);
760+ }
761+
762+ /*
763+ * Unused lanes need to be mapped as well to not have
764+ * the same lanes mapped twice.
765+ */
766+ for (; lane < 4; lane++) {
767+ unsigned int idx = find_first_zero_bit(&lanes_used, 4);
768+
769+ val |= idx << (lane * 2);
770+ lanes_used |= BIT(idx);
771+ }
772+
773+ cci_update_bits(priv->regmap, MAX96717_MIPI_RX3,
774+ MAX96717_PHY1_LANES_MAP,
775+ FIELD_PREP(MAX96717_PHY1_LANES_MAP, val), &ret);
776+
777+ return cci_update_bits(priv->regmap, MAX96717_MIPI_RX2,
778+ MAX96717_PHY2_LANES_MAP,
779+ FIELD_PREP(MAX96717_PHY2_LANES_MAP, val >> 4),
780+ &ret);
781+}
782+
783+static int max96717_hw_init(struct max96717_priv *priv)
784+{
785+ struct device *dev = &priv->client->dev;
786+ u64 dev_id, val;
787+ int ret;
788+
789+ ret = cci_read(priv->regmap, MAX96717_DEV_ID, &dev_id, NULL);
790+ if (ret)
791+ return dev_err_probe(dev, ret,
792+ "Fail to read the device id\n");
793+
794+ if (dev_id != MAX96717_DEVICE_ID && dev_id != MAX96717F_DEVICE_ID)
795+ return dev_err_probe(dev, -EOPNOTSUPP,
796+ "Unsupported device id got %x\n", (u8)dev_id);
797+
798+ ret = cci_read(priv->regmap, MAX96717_DEV_REV, &val, NULL);
799+ if (ret)
800+ return dev_err_probe(dev, ret,
801+ "Fail to read device revision");
802+
803+ dev_dbg(dev, "Found %x (rev %lx)\n", (u8)dev_id,
804+ (u8)val & MAX96717_DEV_REV_MASK);
805+
806+ ret = cci_read(priv->regmap, MAX96717_MIPI_RX_EXT11, &val, NULL);
807+ if (ret)
808+ return dev_err_probe(dev, ret,
809+ "Fail to read mipi rx extension");
810+
811+ if (!(val & MAX96717_TUN_MODE))
812+ return dev_err_probe(dev, -EOPNOTSUPP,
813+ "Only supporting tunnel mode");
814+
815+ return max96717_init_csi_lanes(priv);
816+}
817+
818+static int max96717_parse_dt(struct max96717_priv *priv)
819+{
820+ struct device *dev = &priv->client->dev;
821+ struct v4l2_fwnode_endpoint vep = {
822+ .bus_type = V4L2_MBUS_CSI2_DPHY
823+ };
824+ struct fwnode_handle *ep_fwnode;
825+ unsigned char num_data_lanes;
826+ int ret;
827+
828+ ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
829+ MAX96717_PAD_SINK, 0, 0);
830+ if (!ep_fwnode)
831+ return dev_err_probe(dev, -ENOENT, "no endpoint found\n");
832+
833+ ret = v4l2_fwnode_endpoint_parse(ep_fwnode, &vep);
834+
835+ fwnode_handle_put(ep_fwnode);
836+
837+ if (ret < 0)
838+ return dev_err_probe(dev, ret, "Failed to parse sink endpoint");
839+
840+ num_data_lanes = vep.bus.mipi_csi2.num_data_lanes;
841+ if (num_data_lanes < 1 || num_data_lanes > 4)
842+ return dev_err_probe(dev, -EINVAL,
843+ "Invalid data lanes must be 1 to 4\n");
844+
845+ memcpy(&priv->mipi_csi2, &vep.bus.mipi_csi2, sizeof(priv->mipi_csi2));
846+
847+ return 0;
848+}
849+
850+static int max96717_probe(struct i2c_client *client)
851+{
852+ struct device *dev = &client->dev;
853+ struct max96717_priv *priv;
854+ int ret;
855+
856+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
857+ if (!priv)
858+ return -ENOMEM;
859+
860+ priv->client = client;
861+ priv->regmap = devm_cci_regmap_init_i2c(client, 16);
862+ if (IS_ERR(priv->regmap)) {
863+ ret = PTR_ERR(priv->regmap);
864+ return dev_err_probe(dev, ret, "Failed to init regmap\n");
865+ }
866+
867+ ret = max96717_parse_dt(priv);
868+ if (ret)
869+ return dev_err_probe(dev, ret, "Failed to parse the dt\n");
870+
871+ ret = max96717_hw_init(priv);
872+ if (ret)
873+ return dev_err_probe(dev, ret,
874+ "Failed to initialize the hardware\n");
875+
876+ ret = max96717_gpiochip_probe(priv);
877+ if (ret)
878+ return dev_err_probe(&client->dev, ret,
879+ "Failed to init gpiochip\n");
880+
881+ ret = max96717_register_clkout(priv);
882+ if (ret)
883+ return dev_err_probe(dev, ret, "Failed to register clkout\n");
884+
885+ ret = max96717_subdev_init(priv);
886+ if (ret)
887+ return dev_err_probe(dev, ret,
888+ "Failed to initialize v4l2 subdev\n");
889+
890+ ret = max96717_i2c_mux_init(priv);
891+ if (ret) {
892+ dev_err_probe(dev, ret, "failed to add remote i2c adapter\n");
893+ max96717_subdev_uninit(priv);
894+ }
895+
896+ return ret;
897+}
898+
899+static void max96717_remove(struct i2c_client *client)
900+{
901+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
902+ struct max96717_priv *priv = sd_to_max96717(sd);
903+
904+ max96717_subdev_uninit(priv);
905+ i2c_mux_del_adapters(priv->mux);
906+}
907+
908+static const struct of_device_id max96717_of_ids[] = {
909+ { .compatible = "maxim,max96717f" },
910+ { }
911+};
912+MODULE_DEVICE_TABLE(of, max96717_of_ids);
913+
914+static struct i2c_driver max96717_i2c_driver = {
915+ .driver = {
916+ .name = "max96717",
917+ .of_match_table = max96717_of_ids,
918+ },
919+ .probe = max96717_probe,
920+ .remove = max96717_remove,
921+};
922+
923+module_i2c_driver(max96717_i2c_driver);
924+
925+MODULE_DESCRIPTION("Maxim GMSL2 MAX96717 Serializer Driver");
926+MODULE_AUTHOR("Julien Massot <julien.massot@collabora.com>");
927+MODULE_LICENSE("GPL");
drivers/media/i2c/ov2680.c+1−1
@@ -971,7 +971,7 @@ static int ov2680_v4l2_register(struct ov2680_dev *sensor) · 970 unmodified lines
971971 if (ret < 0)
972972 return ret;
973973
974− v4l2_ctrl_handler_init(hdl, 5);
974+ v4l2_ctrl_handler_init(hdl, 11);
975975
976976 hdl->lock = &sensor->lock;
977977
drivers/media/i2c/ov5647.c+4−7
@@ -1360,24 +1360,21 @@ static int ov5647_parse_dt(struct ov5647 *sensor, struct device_node *np) · 1359 unmodified lines
13601360 struct v4l2_fwnode_endpoint bus_cfg = {
13611361 .bus_type = V4L2_MBUS_CSI2_DPHY,
13621362 };
1363− struct device_node *ep;
1363+ struct device_node *ep __free(device_node) =
1364+ of_graph_get_endpoint_by_regs(np, 0, -1);
13641365 int ret;
13651366
1366− ep = of_graph_get_endpoint_by_regs(np, 0, -1);
13671367 if (!ep)
13681368 return -EINVAL;
13691369
13701370 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
13711371 if (ret)
1372− goto out;
1372+ return ret;
13731373
13741374 sensor->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
13751375 V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
13761376
1377−out:
1378− of_node_put(ep);
1379−
1380− return ret;
1377+ return 0;
13811378 }
13821379
13831380 static int ov5647_probe(struct i2c_client *client)
drivers/media/i2c/ov5693.c+0−10
@@ -141,7 +141,6 @@ struct ov5693_device { · 140 unmodified lines
141141
142142 struct gpio_desc *reset;
143143 struct gpio_desc *powerdown;
144− struct gpio_desc *privacy_led;
145144 struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
146145 struct clk *xvclk;
147146
@@ -657,7 +656,6 @@ static int ov5693_sensor_init(struct ov5693_device *ov5693) · 509 unmodified lines
657656
658657 static void ov5693_sensor_powerdown(struct ov5693_device *ov5693)
659658 {
660− gpiod_set_value_cansleep(ov5693->privacy_led, 0);
661659 gpiod_set_value_cansleep(ov5693->reset, 1);
662660 gpiod_set_value_cansleep(ov5693->powerdown, 1);
663661
@@ -687,7 +685,6 @@ static int ov5693_sensor_powerup(struct ov5693_device *ov5693) · 23 unmodified lines
687685
688686 gpiod_set_value_cansleep(ov5693->powerdown, 0);
689687 gpiod_set_value_cansleep(ov5693->reset, 0);
690− gpiod_set_value_cansleep(ov5693->privacy_led, 1);
691688
692689 usleep_range(5000, 7500);
693690
@@ -1201,13 +1198,6 @@ static int ov5693_configure_gpios(struct ov5693_device *ov5693) · 507 unmodified lines
12011198 return PTR_ERR(ov5693->powerdown);
12021199 }
12031200
1204− ov5693->privacy_led = devm_gpiod_get_optional(ov5693->dev, "privacy-led",
1205− GPIOD_OUT_LOW);
1206− if (IS_ERR(ov5693->privacy_led)) {
1207− dev_err(ov5693->dev, "Error fetching privacy-led GPIO\n");
1208− return PTR_ERR(ov5693->privacy_led);
1209− }
1210−
12111201 return 0;
12121202 }
12131203
drivers/media/i2c/tw9910.c+0−5
@@ -212,11 +212,6 @@ · 211 unmodified lines
212212 * structure
213213 */
214214
215−struct regval_list {
216− unsigned char reg_num;
217− unsigned char value;
218−};
219−
220215 struct tw9910_scale_ctrl {
221216 char *name;
222217 unsigned short width;
drivers/media/i2c/uda1342.c+1−0
@@ -95,4 +95,5 @@ static struct i2c_driver uda1342_driver = { · 94 unmodified lines
9595
9696 module_i2c_driver(uda1342_driver);
9797
98+MODULE_DESCRIPTION("Philips UDA1342 audio codec driver");
9899 MODULE_LICENSE("GPL v2");
drivers/media/i2c/vgxy61.crenamed from drivers/media/i2c/st-vgxy61.c+1−1
@@ -1878,7 +1878,7 @@ static const struct dev_pm_ops vgxy61_pm_ops = { · 1877 unmodified lines
18781878
18791879 static struct i2c_driver vgxy61_i2c_driver = {
18801880 .driver = {
1881− .name = "st-vgxy61",
1881+ .name = "vgxy61",
18821882 .of_match_table = vgxy61_dt_ids,
18831883 .pm = &vgxy61_pm_ops,
18841884 },
drivers/media/pci/bt8xx/bt878.c+5−4
@@ -300,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) · 299 unmodified lines
300300 }
301301 if (astat & BT878_ARISCI) {
302302 bt->finished_block = (stat & BT878_ARISCS) >> 28;
303− if (bt->tasklet.callback)
304− tasklet_schedule(&bt->tasklet);
303+ if (bt->bh_work.func)
304+ queue_work(system_bh_wq, &bt->bh_work);
305305 break;
306306 }
307307 count++;
@@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) · 170 unmodified lines
478478 btwrite(0, BT878_AINT_MASK);
479479 bt878_num++;
480480
481− if (!bt->tasklet.func)
482− tasklet_disable(&bt->tasklet);
481+ if (!bt->bh_work.func)
482+ disable_work_sync(&bt->bh_work);
483483
484484 return 0;
485485
@@ -563,4 +563,5 @@ static void __exit bt878_cleanup_module(void) · 77 unmodified lines
563563 module_init(bt878_init_module);
564564 module_exit(bt878_cleanup_module);
565565
566+MODULE_DESCRIPTION("DVB/ATSC Support for bt878 based TV cards");
566567 MODULE_LICENSE("GPL");
drivers/media/pci/bt8xx/bt878.h+2−1
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #include <linux/sched.h>
1515 #include <linux/spinlock.h>
1616 #include <linux/mutex.h>
17+#include <linux/workqueue.h>
1718
1819 #include "bt848.h"
1920 #include "bttv.h"
@@ -120,7 +121,7 @@ struct bt878 { · 100 unmodified lines
120121 dma_addr_t risc_dma;
121122 u32 risc_pos;
122123
123− struct tasklet_struct tasklet;
124+ struct work_struct bh_work;
124125 int shutdown;
125126 };
126127
drivers/media/pci/bt8xx/dvb-bt8xx.c+4−4
@@ -39,9 +39,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); · 38 unmodified lines
3939
4040 #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
4141
42−static void dvb_bt8xx_task(struct tasklet_struct *t)
42+static void dvb_bt8xx_work(struct work_struct *t)
4343 {
44− struct bt878 *bt = from_tasklet(bt, t, tasklet);
44+ struct bt878 *bt = from_work(bt, t, bh_work);
4545 struct dvb_bt8xx_card *card = dev_get_drvdata(&bt->adapter->dev);
4646
4747 dprintk("%d\n", card->bt->finished_block);
@@ -782,7 +782,7 @@ static int dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) · 734 unmodified lines
782782 goto err_disconnect_frontend;
783783 }
784784
785− tasklet_setup(&card->bt->tasklet, dvb_bt8xx_task);
785+ INIT_WORK(&card->bt->bh_work, dvb_bt8xx_work);
786786
787787 frontend_init(card, type);
788788
@@ -922,7 +922,7 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub) · 133 unmodified lines
922922 dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
923923
924924 bt878_stop(card->bt);
925− tasklet_kill(&card->bt->tasklet);
925+ cancel_work_sync(&card->bt->bh_work);
926926 dvb_net_release(&card->dvbnet);
927927 card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
928928 card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
drivers/media/pci/cx18/cx18-scb.h+1−1
@@ -258,7 +258,7 @@ struct cx18_scb { · 257 unmodified lines
258258 struct cx18_mailbox ppu2epu_mb;
259259
260260 struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS];
261− struct cx18_mdl_ent cpu_mdl[1];
261+ struct cx18_mdl_ent cpu_mdl[];
262262 };
263263
264264 void cx18_init_scb(struct cx18 *cx);
drivers/media/pci/ddbridge/ddbridge.h+1−1
@@ -298,7 +298,7 @@ struct ddb_link { · 297 unmodified lines
298298 spinlock_t lock; /* lock link access */
299299 struct mutex flash_mutex; /* lock flash access */
300300 struct ddb_lnb lnb;
301− struct tasklet_struct tasklet;
301+ struct work_struct bh_work;
302302 struct ddb_ids ids;
303303
304304 spinlock_t temp_lock; /* lock temp chip access */
drivers/media/pci/intel/ipu-bridge.c+29−11
@@ -43,28 +43,46 @@ · 42 unmodified lines
4343 * becoming apparent in the future.
4444 *
4545 * Do not add an entry for a sensor that is not actually supported.
46+ *
47+ * Please keep the list sorted by ACPI HID.
4648 */
4749 static const struct ipu_sensor_config ipu_supported_sensors[] = {
50+ /* Himax HM11B1 */
51+ IPU_SENSOR_CONFIG("HIMX11B1", 1, 384000000),
52+ /* Himax HM2170 */
53+ IPU_SENSOR_CONFIG("HIMX2170", 1, 384000000),
54+ /* Himax HM2172 */
55+ IPU_SENSOR_CONFIG("HIMX2172", 1, 384000000),
56+ /* GalaxyCore GC0310 */
57+ IPU_SENSOR_CONFIG("INT0310", 0),
4858 /* Omnivision OV5693 */
4959 IPU_SENSOR_CONFIG("INT33BE", 1, 419200000),
60+ /* Omnivision OV2740 */
61+ IPU_SENSOR_CONFIG("INT3474", 1, 180000000),
5062 /* Omnivision OV8865 */
5163 IPU_SENSOR_CONFIG("INT347A", 1, 360000000),
5264 /* Omnivision OV7251 */
5365 IPU_SENSOR_CONFIG("INT347E", 1, 319200000),
66+ /* Hynix Hi-556 */
67+ IPU_SENSOR_CONFIG("INT3537", 1, 437000000),
68+ /* Omnivision OV01A10 / OV01A1S */
69+ IPU_SENSOR_CONFIG("OVTI01A0", 1, 400000000),
70+ IPU_SENSOR_CONFIG("OVTI01AS", 1, 400000000),
71+ /* Omnivision OV02C10 */
72+ IPU_SENSOR_CONFIG("OVTI02C1", 1, 400000000),
73+ /* Omnivision OV02E10 */
74+ IPU_SENSOR_CONFIG("OVTI02E1", 1, 360000000),
75+ /* Omnivision OV08A10 */
76+ IPU_SENSOR_CONFIG("OVTI08A1", 1, 500000000),
77+ /* Omnivision OV08x40 */
78+ IPU_SENSOR_CONFIG("OVTI08F4", 1, 400000000),
79+ /* Omnivision OV13B10 */
80+ IPU_SENSOR_CONFIG("OVTI13B1", 1, 560000000),
81+ IPU_SENSOR_CONFIG("OVTIDB10", 1, 560000000),
5482 /* Omnivision OV2680 */
5583 IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000),
56− /* Omnivision ov8856 */
84+ /* Omnivision OV8856 */
5785 IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),
58− /* Omnivision ov2740 */
59− IPU_SENSOR_CONFIG("INT3474", 1, 180000000),
60− /* Hynix hi556 */
61− IPU_SENSOR_CONFIG("INT3537", 1, 437000000),
62− /* Omnivision ov13b10 */
63− IPU_SENSOR_CONFIG("OVTIDB10", 1, 560000000),
64− /* GalaxyCore GC0310 */
65− IPU_SENSOR_CONFIG("INT0310", 0),
66− /* Omnivision ov01a10 */
67− IPU_SENSOR_CONFIG("OVTI01A0", 1, 400000000),
6886 };
6987
7088 static const struct ipu_property_names prop_names = {
drivers/media/pci/intel/ipu6/ipu6-buttress.c+2−2
@@ -163,8 +163,8 @@ int ipu6_buttress_ipc_reset(struct ipu6_device *isp, · 162 unmodified lines
163163 writel(ENTRY, isp->base + ipc->csr_out);
164164 break;
165165 default:
166− dev_warn_ratelimited(&isp->pdev->dev,
167− "Unexpected CSR 0x%x\n", val);
166+ dev_dbg_ratelimited(&isp->pdev->dev,
167+ "Unexpected CSR 0x%x\n", val);
168168 break;
169169 }
170170 } while (retries--);
drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c+42−56
@@ -345,42 +345,61 @@ static int ipu6_isys_csi2_set_stream(struct v4l2_subdev *sd, · 344 unmodified lines
345345 return ret;
346346 }
347347
348−static int set_stream(struct v4l2_subdev *sd, int enable)
348+static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
349+ struct v4l2_subdev_state *state,
350+ u32 pad, u64 streams_mask)
349351 {
350352 struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
351353 struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd);
352− struct device *dev = &csi2->isys->adev->auxdev.dev;
353354 struct ipu6_isys_csi2_timing timing = { };
354− unsigned int nlanes;
355+ struct v4l2_subdev *remote_sd;
356+ struct media_pad *remote_pad;
357+ u64 sink_streams;
355358 int ret;
356359
357− dev_dbg(dev, "csi2 stream %s callback\n", enable ? "on" : "off");
358−
359− if (!enable) {
360− csi2->stream_count--;
361− if (csi2->stream_count)
362− return 0;
363−
364− ipu6_isys_csi2_set_stream(sd, &timing, 0, enable);
365− return 0;
366− }
367−
368− if (csi2->stream_count) {
369− csi2->stream_count++;
370− return 0;
371− }
360+ remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
361+ remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
372362
373− nlanes = csi2->nlanes;
363+ sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC,
364+ CSI2_PAD_SINK,
365+ &streams_mask);
374366
375367 ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV);
376368 if (ret)
377369 return ret;
378370
379− ret = ipu6_isys_csi2_set_stream(sd, &timing, nlanes, enable);
371+ ret = ipu6_isys_csi2_set_stream(sd, &timing, csi2->nlanes, true);
380372 if (ret)
381373 return ret;
382374
383− csi2->stream_count++;
375+ ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index,
376+ sink_streams);
377+ if (ret) {
378+ ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
379+ return ret;
380+ }
381+
382+ return 0;
383+}
384+
385+static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
386+ struct v4l2_subdev_state *state,
387+ u32 pad, u64 streams_mask)
388+{
389+ struct v4l2_subdev *remote_sd;
390+ struct media_pad *remote_pad;
391+ u64 sink_streams;
392+
393+ sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC,
394+ CSI2_PAD_SINK,
395+ &streams_mask);
396+
397+ remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
398+ remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
399+
400+ ipu6_isys_csi2_set_stream(sd, NULL, 0, false);
401+
402+ v4l2_subdev_disable_streams(remote_sd, remote_pad->index, sink_streams);
384403
385404 return 0;
386405 }
@@ -475,10 +494,6 @@ static int ipu6_isys_csi2_get_sel(struct v4l2_subdev *sd, · 88 unmodified lines
475494 return ret;
476495 }
477496
478−static const struct v4l2_subdev_video_ops csi2_sd_video_ops = {
479− .s_stream = set_stream,
480−};
481−
482497 static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = {
483498 .get_fmt = v4l2_subdev_get_fmt,
484499 .set_fmt = ipu6_isys_subdev_set_fmt,
@@ -486,11 +501,12 @@ static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = { · 1 unmodified line
486501 .set_selection = ipu6_isys_csi2_set_sel,
487502 .enum_mbus_code = ipu6_isys_subdev_enum_mbus_code,
488503 .set_routing = ipu6_isys_subdev_set_routing,
504+ .enable_streams = ipu6_isys_csi2_enable_streams,
505+ .disable_streams = ipu6_isys_csi2_disable_streams,
489506 };
490507
491508 static const struct v4l2_subdev_ops csi2_sd_ops = {
492509 .core = &csi2_sd_core_ops,
493− .video = &csi2_sd_video_ops,
494510 .pad = &csi2_sd_pad_ops,
495511 };
496512
@@ -631,33 +647,3 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream, · 134 unmodified lines
631647
632648 return 0;
633649 }
634−
635−void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status)
636−{
637− struct ipu6_isys_stream *stream = av->stream;
638− struct v4l2_subdev *sd = &stream->asd->sd;
639− struct v4l2_subdev_state *state;
640− struct media_pad *r_pad;
641− unsigned int i;
642− u32 r_stream;
643−
644− r_pad = media_pad_remote_pad_first(&av->pad);
645− r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index);
646−
647− state = v4l2_subdev_lock_and_get_active_state(sd);
648−
649− for (i = 0; i < state->stream_configs.num_configs; i++) {
650− struct v4l2_subdev_stream_config *cfg =
651− &state->stream_configs.configs[i];
652−
653− if (cfg->pad == r_pad->index && r_stream == cfg->stream) {
654− dev_dbg(&av->isys->adev->auxdev.dev,
655− "%s: pad:%u, stream:%u, status:%u\n",
656− sd->entity.name, r_pad->index, r_stream,
657− status);
658− cfg->enabled = status;
659− }
660− }
661−
662− v4l2_subdev_unlock_state(state);
663−}
drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h+0−2
@@ -45,7 +45,6 @@ struct ipu6_isys_csi2 { · 44 unmodified lines
4545 u32 receiver_errors;
4646 unsigned int nlanes;
4747 unsigned int port;
48− unsigned int stream_count;
4948 };
5049
5150 struct ipu6_isys_csi2_timing {
@@ -77,6 +76,5 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream, · 25 unmodified lines
7776 struct ipu6_isys_csi2 *csi2,
7877 struct media_entity *source_entity,
7978 struct v4l2_mbus_frame_desc_entry *entry);
80−void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status);
8179
8280 #endif /* IPU6_ISYS_CSI2_H */
drivers/media/pci/intel/ipu6/ipu6-isys-queue.c+0−3
@@ -551,7 +551,6 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) · 550 unmodified lines
551551 stream->nr_queues);
552552
553553 list_add(&aq->node, &stream->queues);
554− ipu6_isys_set_csi2_streams_status(av, true);
555554 ipu6_isys_configure_stream_watermark(av, true);
556555 ipu6_isys_update_stream_watermark(av, true);
557556
@@ -598,8 +597,6 @@ static void stop_streaming(struct vb2_queue *q) · 40 unmodified lines
598597 struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq);
599598 struct ipu6_isys_stream *stream = av->stream;
600599
601− ipu6_isys_set_csi2_streams_status(av, false);
602−
603600 mutex_lock(&stream->mutex);
604601
605602 ipu6_isys_update_stream_watermark(av, false);
drivers/media/pci/intel/ipu6/ipu6-isys-video.c+7−36
@@ -990,9 +990,7 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, · 989 unmodified lines
990990 struct v4l2_subdev_state *subdev_state;
991991 struct device *dev = &av->isys->adev->auxdev.dev;
992992 struct v4l2_subdev *sd;
993− struct v4l2_subdev *ssd;
994993 struct media_pad *r_pad;
995− struct media_pad *s_pad;
996994 u32 sink_pad, sink_stream;
997995 u64 r_stream;
998996 u64 stream_mask = 0;
@@ -1003,7 +1001,6 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, · 4 unmodified lines
10031001 if (WARN(!stream->source_entity, "No source entity for stream\n"))
10041002 return -ENODEV;
10051003
1006− ssd = media_entity_to_v4l2_subdev(stream->source_entity);
10071004 sd = &stream->asd->sd;
10081005 r_pad = media_pad_remote_pad_first(&av->pad);
10091006 r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index);
@@ -1017,27 +1014,15 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, · 7 unmodified lines
10171014 if (ret)
10181015 return ret;
10191016
1020− s_pad = media_pad_remote_pad_first(&stream->asd->pad[sink_pad]);
1021−
10221017 stream_mask = get_stream_mask_by_pipeline(av);
10231018 if (!state) {
10241019 stop_streaming_firmware(av);
10251020
1026− /* stop external sub-device now. */
1027− dev_dbg(dev, "disable streams 0x%llx of %s\n", stream_mask,
1028− ssd->name);
1029− ret = v4l2_subdev_disable_streams(ssd, s_pad->index,
1030− stream_mask);
1031− if (ret) {
1032− dev_err(dev, "disable streams of %s failed with %d\n",
1033− ssd->name, ret);
1034− return ret;
1035− }
1036−
10371021 /* stop sub-device which connects with video */
1038− dev_dbg(dev, "stream off entity %s pad:%d\n", sd->name,
1039− r_pad->index);
1040− ret = v4l2_subdev_call(sd, video, s_stream, state);
1022+ dev_dbg(dev, "stream off entity %s pad:%d mask:0x%llx\n",
1023+ sd->name, r_pad->index, stream_mask);
1024+ ret = v4l2_subdev_disable_streams(sd, r_pad->index,
1025+ stream_mask);
10411026 if (ret) {
10421027 dev_err(dev, "stream off %s failed with %d\n", sd->name,
10431028 ret);
@@ -1052,34 +1037,20 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, · 8 unmodified lines
10521037 }
10531038
10541039 /* start sub-device which connects with video */
1055− dev_dbg(dev, "stream on %s pad %d\n", sd->name, r_pad->index);
1056− ret = v4l2_subdev_call(sd, video, s_stream, state);
1040+ dev_dbg(dev, "stream on %s pad %d mask 0x%llx\n", sd->name,
1041+ r_pad->index, stream_mask);
1042+ ret = v4l2_subdev_enable_streams(sd, r_pad->index, stream_mask);
10571043 if (ret) {
10581044 dev_err(dev, "stream on %s failed with %d\n", sd->name,
10591045 ret);
10601046 goto out_media_entity_stop_streaming_firmware;
10611047 }
1062−
1063− /* start external sub-device now. */
1064− dev_dbg(dev, "enable streams 0x%llx of %s\n", stream_mask,
1065− ssd->name);
1066− ret = v4l2_subdev_enable_streams(ssd, s_pad->index,
1067− stream_mask);
1068− if (ret) {
1069− dev_err(dev,
1070− "enable streams 0x%llx of %s failed with %d\n",
1071− stream_mask, stream->source_entity->name, ret);
1072− goto out_media_entity_stop_streaming;
1073− }
10741048 }
10751049
10761050 av->streaming = state;
10771051
10781052 return 0;
10791053
1080−out_media_entity_stop_streaming:
1081− v4l2_subdev_disable_streams(sd, r_pad->index, BIT(r_stream));
1082−
10831054 out_media_entity_stop_streaming_firmware:
10841055 stop_streaming_firmware(av);
10851056
drivers/media/pci/intel/ivsc/mei_csi.c+15−9
@@ -126,6 +126,8 @@ struct mei_csi { · 125 unmodified lines
126126 struct v4l2_ctrl_handler ctrl_handler;
127127 struct v4l2_ctrl *freq_ctrl;
128128 struct v4l2_ctrl *privacy_ctrl;
129+ /* lock for v4l2 controls */
130+ struct mutex ctrl_lock;
129131 unsigned int remote_pad;
130132 /* start streaming or not */
131133 int streaming;
@@ -136,9 +138,6 @@ struct mei_csi { · 4 unmodified lines
136138 u32 nr_of_lanes;
137139 /* frequency of the CSI-2 link */
138140 u64 link_freq;
139−
140− /* privacy status */
141− enum ivsc_privacy_status status;
142141 };
143142
144143 static const struct v4l2_mbus_framefmt mei_csi_format_mbus_default = {
@@ -190,7 +189,11 @@ static int mei_csi_send(struct mei_csi *csi, u8 *buf, size_t len) · 45 unmodified lines
190189
191190 /* command response status */
192191 ret = csi->cmd_response.status;
193− if (ret) {
192+ if (ret == -1) {
193+ /* notify privacy on instead of reporting error */
194+ ret = 0;
195+ v4l2_ctrl_s_ctrl(csi->privacy_ctrl, 1);
196+ } else if (ret) {
194197 ret = -EINVAL;
195198 goto out;
196199 }
@@ -265,10 +268,9 @@ static void mei_csi_rx(struct mei_cl_device *cldev) · 68 unmodified lines
265268
266269 switch (notif.cmd_id) {
267270 case CSI_PRIVACY_NOTIF:
268− if (notif.cont.cont < CSI_PRIVACY_MAX) {
269− csi->status = notif.cont.cont;
270− v4l2_ctrl_s_ctrl(csi->privacy_ctrl, csi->status);
271− }
271+ if (notif.cont.cont < CSI_PRIVACY_MAX)
272+ v4l2_ctrl_s_ctrl(csi->privacy_ctrl,
273+ notif.cont.cont == CSI_PRIVACY_ON);
272274 break;
273275 case CSI_SET_OWNER:
274276 case CSI_SET_CONF:
@@ -559,11 +561,13 @@ static int mei_csi_init_controls(struct mei_csi *csi) · 284 unmodified lines
559561 u32 max;
560562 int ret;
561563
564+ mutex_init(&csi->ctrl_lock);
565+
562566 ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 2);
563567 if (ret)
564568 return ret;
565569
566− csi->ctrl_handler.lock = &csi->lock;
570+ csi->ctrl_handler.lock = &csi->ctrl_lock;
567571
568572 max = ARRAY_SIZE(link_freq_menu_items) - 1;
569573 csi->freq_ctrl = v4l2_ctrl_new_int_menu(&csi->ctrl_handler,
@@ -755,6 +759,7 @@ err_entity: · 185 unmodified lines
755759
756760 err_ctrl_handler:
757761 v4l2_ctrl_handler_free(&csi->ctrl_handler);
762+ mutex_destroy(&csi->ctrl_lock);
758763 v4l2_async_nf_unregister(&csi->notifier);
759764 v4l2_async_nf_cleanup(&csi->notifier);
760765
@@ -774,6 +779,7 @@ static void mei_csi_remove(struct mei_cl_device *cldev) · 13 unmodified lines
774779 v4l2_async_nf_unregister(&csi->notifier);
775780 v4l2_async_nf_cleanup(&csi->notifier);
776781 v4l2_ctrl_handler_free(&csi->ctrl_handler);
782+ mutex_destroy(&csi->ctrl_lock);
777783 v4l2_async_unregister_subdev(&csi->subdev);
778784 v4l2_subdev_cleanup(&csi->subdev);
779785 media_entity_cleanup(&csi->subdev.entity);
drivers/media/pci/ivtv/ivtv-driver.c+24−69
@@ -371,33 +371,6 @@ int ivtv_msleep_timeout(unsigned int msecs, int intr) · 370 unmodified lines
371371 return 0;
372372 }
373373
374−/* Release ioremapped memory */
375−static void ivtv_iounmap(struct ivtv *itv)
376−{
377− if (itv == NULL)
378− return;
379−
380− /* Release registers memory */
381− if (itv->reg_mem != NULL) {
382− IVTV_DEBUG_INFO("releasing reg_mem\n");
383− iounmap(itv->reg_mem);
384− itv->reg_mem = NULL;
385− }
386− /* Release io memory */
387− if (itv->has_cx23415 && itv->dec_mem != NULL) {
388− IVTV_DEBUG_INFO("releasing dec_mem\n");
389− iounmap(itv->dec_mem);
390− }
391− itv->dec_mem = NULL;
392−
393− /* Release io memory */
394− if (itv->enc_mem != NULL) {
395− IVTV_DEBUG_INFO("releasing enc_mem\n");
396− iounmap(itv->enc_mem);
397− itv->enc_mem = NULL;
398− }
399−}
400−
401374 /* Hauppauge card? get values from tveeprom */
402375 void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv)
403376 {
@@ -833,7 +806,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, · 429 unmodified lines
833806
834807 IVTV_DEBUG_INFO("Enabling pci device\n");
835808
836− if (pci_enable_device(pdev)) {
809+ if (pcim_enable_device(pdev)) {
837810 IVTV_ERR("Can't enable device!\n");
838811 return -EIO;
839812 }
@@ -841,24 +814,24 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, · 1 unmodified line
841814 IVTV_ERR("No suitable DMA available.\n");
842815 return -EIO;
843816 }
844− if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) {
817+ if (!devm_request_mem_region(&pdev->dev, itv->base_addr,
818+ IVTV_ENCODER_SIZE, "ivtv encoder")) {
845819 IVTV_ERR("Cannot request encoder memory region.\n");
846820 return -EIO;
847821 }
848822
849− if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET,
850− IVTV_REG_SIZE, "ivtv registers")) {
823+ if (!devm_request_mem_region(&pdev->dev,
824+ itv->base_addr + IVTV_REG_OFFSET,
825+ IVTV_REG_SIZE, "ivtv registers")) {
851826 IVTV_ERR("Cannot request register memory region.\n");
852− release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
853827 return -EIO;
854828 }
855829
856830 if (itv->has_cx23415 &&
857− !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,
858− IVTV_DECODER_SIZE, "ivtv decoder")) {
831+ !devm_request_mem_region(&pdev->dev,
832+ itv->base_addr + IVTV_DECODER_OFFSET,
833+ IVTV_DECODER_SIZE, "ivtv decoder")) {
859834 IVTV_ERR("Cannot request decoder memory region.\n");
860− release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
861− release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
862835 return -EIO;
863836 }
864837
@@ -870,11 +843,6 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, · 5 unmodified lines
870843 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
871844 if (!(cmd & PCI_COMMAND_MASTER)) {
872845 IVTV_ERR("Bus Mastering is not enabled\n");
873− if (itv->has_cx23415)
874− release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,
875− IVTV_DECODER_SIZE);
876− release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
877− release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
878846 return -ENXIO;
879847 }
880848 }
@@ -1033,37 +1001,37 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) · 152 unmodified lines
10331001
10341002 /* PCI Device Setup */
10351003 retval = ivtv_setup_pci(itv, pdev, pci_id);
1036− if (retval == -EIO)
1004+ if (retval == -EIO || retval == -ENXIO)
10371005 goto free_worker;
1038− if (retval == -ENXIO)
1039− goto free_mem;
10401006
10411007 /* map io memory */
10421008 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
10431009 (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE);
1044− itv->enc_mem = ioremap(itv->base_addr + IVTV_ENCODER_OFFSET,
1045− IVTV_ENCODER_SIZE);
1010+ itv->enc_mem = devm_ioremap(&pdev->dev,
1011+ itv->base_addr + IVTV_ENCODER_OFFSET,
1012+ IVTV_ENCODER_SIZE);
10461013 if (!itv->enc_mem) {
10471014 IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n");
10481015 IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of vmalloc address space for this window\n");
10491016 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
10501017 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
10511018 retval = -ENOMEM;
1052− goto free_mem;
1019+ goto free_worker;
10531020 }
10541021
10551022 if (itv->has_cx23415) {
10561023 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
10571024 (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
1058− itv->dec_mem = ioremap(itv->base_addr + IVTV_DECODER_OFFSET,
1059− IVTV_DECODER_SIZE);
1025+ itv->dec_mem = devm_ioremap(&pdev->dev,
1026+ itv->base_addr + IVTV_DECODER_OFFSET,
1027+ IVTV_DECODER_SIZE);
10601028 if (!itv->dec_mem) {
10611029 IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n");
10621030 IVTV_ERR("Each capture card with a CX23415 needs 8 MB of vmalloc address space for this window\n");
10631031 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
10641032 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
10651033 retval = -ENOMEM;
1066− goto free_mem;
1034+ goto free_worker;
10671035 }
10681036 }
10691037 else {
@@ -1073,26 +1041,27 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) · 3 unmodified lines
10731041 /* map registers memory */
10741042 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
10751043 (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
1076− itv->reg_mem =
1077− ioremap(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
1044+ itv->reg_mem = devm_ioremap(&pdev->dev,
1045+ itv->base_addr + IVTV_REG_OFFSET,
1046+ IVTV_REG_SIZE);
10781047 if (!itv->reg_mem) {
10791048 IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n");
10801049 IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n");
10811050 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
10821051 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
10831052 retval = -ENOMEM;
1084− goto free_io;
1053+ goto free_worker;
10851054 }
10861055
10871056 retval = ivtv_gpio_init(itv);
10881057 if (retval)
1089− goto free_io;
1058+ goto free_worker;
10901059
10911060 /* active i2c */
10921061 IVTV_DEBUG_INFO("activating i2c...\n");
10931062 if (init_ivtv_i2c(itv)) {
10941063 IVTV_ERR("Could not initialize i2c\n");
1095− goto free_io;
1064+ goto free_worker;
10961065 }
10971066
10981067 if (itv->card->hw_all & IVTV_HW_TVEEPROM) {
@@ -1277,13 +1246,6 @@ free_irq: · 178 unmodified lines
12771246 free_i2c:
12781247 v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
12791248 exit_ivtv_i2c(itv);
1280−free_io:
1281− ivtv_iounmap(itv);
1282−free_mem:
1283− release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
1284− release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
1285− if (itv->has_cx23415)
1286− release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
12871249 free_worker:
12881250 kthread_stop(itv->irq_worker_task);
12891251 err:
@@ -1439,14 +1401,7 @@ static void ivtv_remove(struct pci_dev *pdev) · 149 unmodified lines
14391401 exit_ivtv_i2c(itv);
14401402
14411403 free_irq(itv->pdev->irq, (void *)itv);
1442− ivtv_iounmap(itv);
1443−
1444− release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
1445− release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
1446− if (itv->has_cx23415)
1447− release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
14481404
1449− pci_disable_device(itv->pdev);
14501405 for (i = 0; i < IVTV_VBI_FRAMES; i++)
14511406 kfree(itv->vbi.sliced_mpeg_data[i]);
14521407
drivers/media/pci/ivtv/ivtv-fileops.c+39−27
@@ -21,6 +21,7 @@ · 20 unmodified lines
2121 #include "ivtv-ioctl.h"
2222 #include "ivtv-cards.h"
2323 #include "ivtv-firmware.h"
24+#include <linux/lockdep.h>
2425 #include <media/v4l2-event.h>
2526 #include <media/i2c/saa7115.h>
2627
@@ -190,12 +191,27 @@ static void ivtv_update_pgm_info(struct ivtv *itv) · 163 unmodified lines
190191 itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
191192 }
192193
194+static void ivtv_schedule(struct ivtv_stream *s)
195+{
196+ struct ivtv *itv = s->itv;
197+ DEFINE_WAIT(wait);
198+
199+ lockdep_assert_held(&itv->serialize_lock);
200+
201+ mutex_unlock(&itv->serialize_lock);
202+ prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
203+ /* New buffers might have become free before we were added to the waitqueue */
204+ if (!s->q_free.buffers)
205+ schedule();
206+ finish_wait(&s->waitq, &wait);
207+ mutex_lock(&itv->serialize_lock);
208+}
209+
193210 static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err)
194211 {
195212 struct ivtv *itv = s->itv;
196213 struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
197214 struct ivtv_buffer *buf;
198− DEFINE_WAIT(wait);
199215
200216 *err = 0;
201217 while (1) {
@@ -258,13 +274,7 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, · 56 unmodified lines
258274 }
259275
260276 /* wait for more data to arrive */
261− mutex_unlock(&itv->serialize_lock);
262− prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
263− /* New buffers might have become available before we were added to the waitqueue */
264− if (!s->q_full.buffers)
265− schedule();
266− finish_wait(&s->waitq, &wait);
267− mutex_lock(&itv->serialize_lock);
277+ ivtv_schedule(s);
268278 if (signal_pending(current)) {
269279 /* return if a signal was received */
270280 IVTV_DEBUG_INFO("User stopped %s\n", s->name);
@@ -533,6 +543,25 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed) · 262 unmodified lines
533543 return 0;
534544 }
535545
546+static int ivtv_schedule_dma(struct ivtv_stream *s)
547+{
548+ struct ivtv *itv = s->itv;
549+ int got_sig;
550+ DEFINE_WAIT(wait);
551+
552+ lockdep_assert_held(&itv->serialize_lock);
553+
554+ mutex_unlock(&itv->serialize_lock);
555+ prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
556+ while (!(got_sig = signal_pending(current)) &&
557+ test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags))
558+ schedule();
559+ finish_wait(&itv->dma_waitq, &wait);
560+ mutex_lock(&itv->serialize_lock);
561+
562+ return got_sig;
563+}
564+
536565 static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
537566 {
538567 struct ivtv_open_id *id = fh2id(filp->private_data);
@@ -544,7 +573,6 @@ static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t · 5 unmodified lines
544573 int bytes_written = 0;
545574 int mode;
546575 int rc;
547− DEFINE_WAIT(wait);
548576
549577 IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name);
550578
@@ -618,13 +646,7 @@ retry: · 67 unmodified lines
618646 break;
619647 if (filp->f_flags & O_NONBLOCK)
620648 return -EAGAIN;
621− mutex_unlock(&itv->serialize_lock);
622− prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
623− /* New buffers might have become free before we were added to the waitqueue */
624− if (!s->q_free.buffers)
625− schedule();
626− finish_wait(&s->waitq, &wait);
627− mutex_lock(&itv->serialize_lock);
649+ ivtv_schedule(s);
628650 if (signal_pending(current)) {
629651 IVTV_DEBUG_INFO("User stopped %s\n", s->name);
630652 return -EINTR;
@@ -674,20 +696,10 @@ retry: · 43 unmodified lines
674696
675697 if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) {
676698 if (s->q_full.length >= itv->dma_data_req_size) {
677− int got_sig;
678−
679699 if (mode == OUT_YUV)
680700 ivtv_yuv_setup_stream_frame(itv);
681701
682− mutex_unlock(&itv->serialize_lock);
683− prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
684− while (!(got_sig = signal_pending(current)) &&
685− test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
686− schedule();
687− }
688− finish_wait(&itv->dma_waitq, &wait);
689− mutex_lock(&itv->serialize_lock);
690− if (got_sig) {
702+ if (ivtv_schedule_dma(s)) {
691703 IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
692704 return -EINTR;
693705 }
drivers/media/pci/ivtv/ivtv-udma.c+8−0
@@ -131,6 +131,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, · 130 unmodified lines
131131
132132 /* Fill SG List with new values */
133133 if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) {
134+ IVTV_DEBUG_WARN("%s: could not allocate bounce buffers for highmem userspace buffers\n",
135+ __func__);
134136 unpin_user_pages(dma->map, dma->page_count);
135137 dma->page_count = 0;
136138 return -ENOMEM;
@@ -139,6 +141,12 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, · 2 unmodified lines
139141 /* Map SG List */
140142 dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
141143 dma->page_count, DMA_TO_DEVICE);
144+ if (!dma->SG_length) {
145+ IVTV_DEBUG_WARN("%s: DMA map error, SG_length is 0\n", __func__);
146+ unpin_user_pages(dma->map, dma->page_count);
147+ dma->page_count = 0;
148+ return -EINVAL;
149+ }
142150
143151 /* Fill SG Array with new values */
144152 ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1);
drivers/media/pci/ivtv/ivtv-yuv.c+6−0
@@ -114,6 +114,12 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, · 113 unmodified lines
114114 }
115115 dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
116116 dma->page_count, DMA_TO_DEVICE);
117+ if (!dma->SG_length) {
118+ IVTV_DEBUG_WARN("%s: DMA map error, SG_length is 0\n", __func__);
119+ unpin_user_pages(dma->map, dma->page_count);
120+ dma->page_count = 0;
121+ return -EINVAL;
122+ }
117123
118124 /* Fill SG Array with new values */
119125 ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
drivers/media/pci/ivtv/ivtvfb.c+4−3
@@ -104,6 +104,7 @@ MODULE_PARM_DESC(osd_xres, · 103 unmodified lines
104104 "\t\t\tdefault 640");
105105
106106 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
107+MODULE_DESCRIPTION("Conexant cx23415 framebuffer support");
107108 MODULE_LICENSE("GPL");
108109
109110 /* --------------------------------------------------------------------- */
@@ -281,10 +282,10 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, · 171 unmodified lines
281282 /* Map User DMA */
282283 if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
283284 mutex_unlock(&itv->udma.lock);
284− IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with pin_user_pages: %d bytes, %d pages returned\n",
285− size_in_bytes, itv->udma.page_count);
285+ IVTVFB_WARN("%s, Error in ivtv_udma_setup: %d bytes, %d pages returned\n",
286+ __func__, size_in_bytes, itv->udma.page_count);
286287
287− /* pin_user_pages must have failed completely */
288+ /* pin_user_pages or DMA must have failed completely */
288289 return -EIO;
289290 }
290291
drivers/media/pci/mantis/hopper_cards.c+1−1
@@ -116,7 +116,7 @@ static irqreturn_t hopper_irq_handler(int irq, void *dev_id) · 115 unmodified lines
116116 if (stat & MANTIS_INT_RISCI) {
117117 dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
118118 mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
119− tasklet_schedule(&mantis->tasklet);
119+ queue_work(system_bh_wq, &mantis->bh_work);
120120 }
121121 if (stat & MANTIS_INT_I2CDONE) {
122122 dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
drivers/media/pci/mantis/mantis_cards.c+1−1
@@ -125,7 +125,7 @@ static irqreturn_t mantis_irq_handler(int irq, void *dev_id) · 124 unmodified lines
125125 if (stat & MANTIS_INT_RISCI) {
126126 dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
127127 mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
128− tasklet_schedule(&mantis->tasklet);
128+ queue_work(system_bh_wq, &mantis->bh_work);
129129 }
130130 if (stat & MANTIS_INT_I2CDONE) {
131131 dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
drivers/media/pci/mantis/mantis_common.h+1−1
@@ -125,7 +125,7 @@ struct mantis_pci { · 124 unmodified lines
125125 __le32 *risc_cpu;
126126 dma_addr_t risc_dma;
127127
128− struct tasklet_struct tasklet;
128+ struct work_struct bh_work;
129129 spinlock_t intmask_lock;
130130
131131 struct i2c_adapter adapter;
drivers/media/pci/mantis/mantis_dma.c+2−2
@@ -200,9 +200,9 @@ void mantis_dma_stop(struct mantis_pci *mantis) · 199 unmodified lines
200200 }
201201
202202
203−void mantis_dma_xfer(struct tasklet_struct *t)
203+void mantis_dma_xfer(struct work_struct *t)
204204 {
205− struct mantis_pci *mantis = from_tasklet(mantis, t, tasklet);
205+ struct mantis_pci *mantis = from_work(mantis, t, bh_work);
206206 struct mantis_hwconfig *config = mantis->hwconfig;
207207
208208 while (mantis->last_block != mantis->busy_block) {
drivers/media/pci/mantis/mantis_dma.h+1−1
@@ -13,6 +13,6 @@ extern int mantis_dma_init(struct mantis_pci *mantis); · 12 unmodified lines
1313 extern int mantis_dma_exit(struct mantis_pci *mantis);
1414 extern void mantis_dma_start(struct mantis_pci *mantis);
1515 extern void mantis_dma_stop(struct mantis_pci *mantis);
16−extern void mantis_dma_xfer(struct tasklet_struct *t);
16+extern void mantis_dma_xfer(struct work_struct *t);
1717
1818 #endif /* __MANTIS_DMA_H */
drivers/media/pci/mantis/mantis_dvb.c+6−6
@@ -105,7 +105,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) · 104 unmodified lines
105105 if (mantis->feeds == 1) {
106106 dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
107107 mantis_dma_start(mantis);
108− tasklet_enable(&mantis->tasklet);
108+ enable_and_queue_work(system_bh_wq, &mantis->bh_work);
109109 }
110110
111111 return mantis->feeds;
@@ -125,7 +125,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) · 13 unmodified lines
125125 mantis->feeds--;
126126 if (mantis->feeds == 0) {
127127 dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
128− tasklet_disable(&mantis->tasklet);
128+ disable_work_sync(&mantis->bh_work);
129129 mantis_dma_stop(mantis);
130130 }
131131
@@ -205,8 +205,8 @@ int mantis_dvb_init(struct mantis_pci *mantis) · 73 unmodified lines
205205 }
206206
207207 dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
208− tasklet_setup(&mantis->tasklet, mantis_dma_xfer);
209− tasklet_disable(&mantis->tasklet);
208+ INIT_WORK(&mantis->bh_work, mantis_dma_xfer);
209+ disable_work_sync(&mantis->bh_work);
210210 if (mantis->hwconfig) {
211211 result = config->frontend_init(mantis, mantis->fe);
212212 if (result < 0) {
@@ -235,7 +235,7 @@ int mantis_dvb_init(struct mantis_pci *mantis) · 22 unmodified lines
235235
236236 /* Error conditions .. */
237237 err5:
238− tasklet_kill(&mantis->tasklet);
238+ cancel_work_sync(&mantis->bh_work);
239239 dvb_net_release(&mantis->dvbnet);
240240 if (mantis->fe) {
241241 dvb_unregister_frontend(mantis->fe);
@@ -273,7 +273,7 @@ int mantis_dvb_exit(struct mantis_pci *mantis) · 31 unmodified lines
273273 dvb_frontend_detach(mantis->fe);
274274 }
275275
276− tasklet_kill(&mantis->tasklet);
276+ cancel_work_sync(&mantis->bh_work);
277277 dvb_net_release(&mantis->dvbnet);
278278
279279 mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
drivers/media/pci/ngene/ngene-core.c+11−11
@@ -50,9 +50,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); · 49 unmodified lines
5050 /* nGene interrupt handler **************************************************/
5151 /****************************************************************************/
5252
53−static void event_tasklet(struct tasklet_struct *t)
53+static void event_bh_work(struct work_struct *t)
5454 {
55− struct ngene *dev = from_tasklet(dev, t, event_tasklet);
55+ struct ngene *dev = from_work(dev, t, event_bh_work);
5656
5757 while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) {
5858 struct EVENT_BUFFER Event =
@@ -68,9 +68,9 @@ static void event_tasklet(struct tasklet_struct *t) · 9 unmodified lines
6868 }
6969 }
7070
71−static void demux_tasklet(struct tasklet_struct *t)
71+static void demux_bh_work(struct work_struct *t)
7272 {
73− struct ngene_channel *chan = from_tasklet(chan, t, demux_tasklet);
73+ struct ngene_channel *chan = from_work(chan, t, demux_bh_work);
7474 struct device *pdev = &chan->dev->pci_dev->dev;
7575 struct SBufferHeader *Cur = chan->nextBuffer;
7676
@@ -204,7 +204,7 @@ static irqreturn_t irq_handler(int irq, void *dev_id) · 127 unmodified lines
204204 dev->EventQueueOverflowFlag = 1;
205205 }
206206 dev->EventBuffer->EventStatus &= ~0x80;
207− tasklet_schedule(&dev->event_tasklet);
207+ queue_work(system_bh_wq, &dev->event_bh_work);
208208 rc = IRQ_HANDLED;
209209 }
210210
@@ -217,8 +217,8 @@ static irqreturn_t irq_handler(int irq, void *dev_id) · 6 unmodified lines
217217 ngeneBuffer.SR.Flags & 0xC0) == 0x80) {
218218 dev->channel[i].nextBuffer->
219219 ngeneBuffer.SR.Flags |= 0x40;
220− tasklet_schedule(
221− &dev->channel[i].demux_tasklet);
220+ queue_work(system_bh_wq,
221+ &dev->channel[i].demux_bh_work);
222222 rc = IRQ_HANDLED;
223223 }
224224 }
@@ -1181,7 +1181,7 @@ static void ngene_init(struct ngene *dev) · 956 unmodified lines
11811181 struct device *pdev = &dev->pci_dev->dev;
11821182 int i;
11831183
1184− tasklet_setup(&dev->event_tasklet, event_tasklet);
1184+ INIT_WORK(&dev->event_bh_work, event_bh_work);
11851185
11861186 memset_io(dev->iomem + 0xc000, 0x00, 0x220);
11871187 memset_io(dev->iomem + 0xc400, 0x00, 0x100);
@@ -1395,7 +1395,7 @@ static void release_channel(struct ngene_channel *chan) · 207 unmodified lines
13951395 if (chan->running)
13961396 set_transfer(chan, 0);
13971397
1398− tasklet_kill(&chan->demux_tasklet);
1398+ cancel_work_sync(&chan->demux_bh_work);
13991399
14001400 if (chan->ci_dev) {
14011401 dvb_unregister_device(chan->ci_dev);
@@ -1445,7 +1445,7 @@ static int init_channel(struct ngene_channel *chan) · 43 unmodified lines
14451445 struct ngene_info *ni = dev->card_info;
14461446 int io = ni->io_type[nr];
14471447
1448− tasklet_setup(&chan->demux_tasklet, demux_tasklet);
1448+ INIT_WORK(&chan->demux_bh_work, demux_bh_work);
14491449 chan->users = 0;
14501450 chan->type = io;
14511451 chan->mode = chan->type; /* for now only one mode */
@@ -1649,7 +1649,7 @@ void ngene_remove(struct pci_dev *pdev) · 197 unmodified lines
16491649 struct ngene *dev = pci_get_drvdata(pdev);
16501650 int i;
16511651
1652− tasklet_kill(&dev->event_tasklet);
1652+ cancel_work_sync(&dev->event_bh_work);
16531653 for (i = MAX_STREAM - 1; i >= 0; i--)
16541654 release_channel(&dev->channel[i]);
16551655 if (dev->ci.en)
drivers/media/pci/ngene/ngene.h+3−2
@@ -16,6 +16,7 @@ · 15 unmodified lines
1616 #include <linux/scatterlist.h>
1717
1818 #include <linux/dvb/frontend.h>
19+#include <linux/workqueue.h>
1920
2021 #include <media/dmxdev.h>
2122 #include <media/dvbdev.h>
@@ -621,7 +622,7 @@ struct ngene_channel { · 599 unmodified lines
621622 int users;
622623 struct video_device *v4l_dev;
623624 struct dvb_device *ci_dev;
624− struct tasklet_struct demux_tasklet;
625+ struct work_struct demux_bh_work;
625626
626627 struct SBufferHeader *nextBuffer;
627628 enum KSSTATE State;
@@ -717,7 +718,7 @@ struct ngene { · 89 unmodified lines
717718 struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE];
718719 int EventQueueOverflowCount;
719720 int EventQueueOverflowFlag;
720− struct tasklet_struct event_tasklet;
721+ struct work_struct event_bh_work;
721722 struct EVENT_BUFFER *EventBuffer;
722723 int EventQueueWriteIndex;
723724 int EventQueueReadIndex;
drivers/media/pci/saa7134/saa7134-alsa.c+1−0
@@ -1254,5 +1254,6 @@ static void saa7134_alsa_exit(void) · 1253 unmodified lines
12541254 /* We initialize this late, to make sure the sound system is up and running */
12551255 late_initcall(saa7134_alsa_init);
12561256 module_exit(saa7134_alsa_exit);
1257+MODULE_DESCRIPTION("Philips SAA7134 DMA audio support");
12571258 MODULE_LICENSE("GPL");
12581259 MODULE_AUTHOR("Ricardo Cerqueira");
drivers/media/pci/saa7134/saa7134-dvb.c+7−2
@@ -52,6 +52,7 @@ · 51 unmodified lines
5252 #include "s5h1411.h"
5353
5454 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
55+MODULE_DESCRIPTION("DVB/ATSC Support for saa7134 based TV cards");
5556 MODULE_LICENSE("GPL");
5657
5758 static unsigned int antenna_pwr;
@@ -466,7 +467,9 @@ static int philips_europa_tuner_sleep(struct dvb_frontend *fe) · 408 unmodified lines
466467 /* switch the board to analog mode */
467468 if (fe->ops.i2c_gate_ctrl)
468469 fe->ops.i2c_gate_ctrl(fe, 1);
469− i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
470+ if (i2c_transfer(&dev->i2c_adap, &analog_msg, 1) != 1)
471+ return -EIO;
472+
470473 return 0;
471474 }
472475
@@ -1018,7 +1021,9 @@ static int md8800_set_voltage2(struct dvb_frontend *fe, · 545 unmodified lines
10181021 else
10191022 wbuf[1] = rbuf & 0xef;
10201023 msg[0].len = 2;
1021− i2c_transfer(&dev->i2c_adap, msg, 1);
1024+ if (i2c_transfer(&dev->i2c_adap, msg, 1) != 1)
1025+ return -EIO;
1026+
10221027 return 0;
10231028 }
10241029
drivers/media/pci/saa7134/saa7134-empress.c+1−0
@@ -19,6 +19,7 @@ · 18 unmodified lines
1919 /* ------------------------------------------------------------------ */
2020
2121 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
22+MODULE_DESCRIPTION("Philips SAA7134 empress support");
2223 MODULE_LICENSE("GPL");
2324
2425 static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
drivers/media/pci/saa7134/saa7134-go7007.c+1−0
@@ -516,4 +516,5 @@ static void __exit saa7134_go7007_mod_cleanup(void) · 515 unmodified lines
516516 module_init(saa7134_go7007_mod_init);
517517 module_exit(saa7134_go7007_mod_cleanup);
518518
519+MODULE_DESCRIPTION("go7007 support for saa7134 based TV cards");
519520 MODULE_LICENSE("GPL v2");
drivers/media/pci/smipcie/smipcie-main.c+9−9
@@ -279,10 +279,10 @@ static void smi_port_clearInterrupt(struct smi_port *port) · 278 unmodified lines
279279 (port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
280280 }
281281
282−/* tasklet handler: DMA data to dmx.*/
283−static void smi_dma_xfer(struct tasklet_struct *t)
282+/* BH work handler: DMA data to dmx.*/
283+static void smi_dma_xfer(struct work_struct *t)
284284 {
285− struct smi_port *port = from_tasklet(port, t, tasklet);
285+ struct smi_port *port = from_work(port, t, bh_work);
286286 struct smi_dev *dev = port->dev;
287287 u32 intr_status, finishedData, dmaManagement;
288288 u8 dmaChan0State, dmaChan1State;
@@ -426,8 +426,8 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) · 137 unmodified lines
426426 }
427427
428428 smi_port_disableInterrupt(port);
429− tasklet_setup(&port->tasklet, smi_dma_xfer);
430− tasklet_disable(&port->tasklet);
429+ INIT_WORK(&port->bh_work, smi_dma_xfer);
430+ disable_work_sync(&port->bh_work);
431431 port->enable = 1;
432432 return 0;
433433 err:
@@ -438,7 +438,7 @@ err: · 4 unmodified lines
438438 static void smi_port_exit(struct smi_port *port)
439439 {
440440 smi_port_disableInterrupt(port);
441− tasklet_kill(&port->tasklet);
441+ cancel_work_sync(&port->bh_work);
442442 smi_port_dma_free(port);
443443 port->enable = 0;
444444 }
@@ -452,7 +452,7 @@ static int smi_port_irq(struct smi_port *port, u32 int_status) · 7 unmodified lines
452452 smi_port_disableInterrupt(port);
453453 port->_int_status = int_status;
454454 smi_port_clearInterrupt(port);
455− tasklet_schedule(&port->tasklet);
455+ queue_work(system_bh_wq, &port->bh_work);
456456 handled = 1;
457457 }
458458 return handled;
@@ -823,7 +823,7 @@ static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed) · 364 unmodified lines
823823 smi_port_clearInterrupt(port);
824824 smi_port_enableInterrupt(port);
825825 smi_write(port->DMA_MANAGEMENT, dmaManagement);
826− tasklet_enable(&port->tasklet);
826+ enable_and_queue_work(system_bh_wq, &port->bh_work);
827827 }
828828 return port->users;
829829 }
@@ -837,7 +837,7 @@ static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed) · 7 unmodified lines
837837 if (--port->users)
838838 return port->users;
839839
840− tasklet_disable(&port->tasklet);
840+ disable_work_sync(&port->bh_work);
841841 smi_port_disableInterrupt(port);
842842 smi_clear(port->DMA_MANAGEMENT, 0x30003);
843843 return 0;
drivers/media/pci/smipcie/smipcie.h+2−1
@@ -17,6 +17,7 @@ · 16 unmodified lines
1717 #include <linux/pci.h>
1818 #include <linux/dma-mapping.h>
1919 #include <linux/slab.h>
20+#include <linux/workqueue.h>
2021 #include <media/rc-core.h>
2122
2223 #include <media/demux.h>
@@ -257,7 +258,7 @@ struct smi_port { · 234 unmodified lines
257258 u32 _dmaInterruptCH0;
258259 u32 _dmaInterruptCH1;
259260 u32 _int_status;
260− struct tasklet_struct tasklet;
261+ struct work_struct bh_work;
261262 /* dvb */
262263 struct dmx_frontend hw_frontend;
263264 struct dmx_frontend mem_frontend;
drivers/media/pci/ttpci/budget-av.c+2−1
@@ -36,6 +36,7 @@ · 35 unmodified lines
3636 #include <linux/interrupt.h>
3737 #include <linux/input.h>
3838 #include <linux/spinlock.h>
39+#include <linux/workqueue.h>
3940
4041 #include <media/dvb_ca_en50221.h>
4142
@@ -54,7 +55,7 @@ struct budget_av { · 12 unmodified lines
5455 struct video_device vd;
5556 int cur_input;
5657 int has_saa7113;
57− struct tasklet_struct ciintf_irq_tasklet;
58+ struct work_struct ciintf_irq_bh_work;
5859 int slot_status;
5960 struct dvb_ca_en50221 ca;
6061 u8 reinitialise_demod:1;
drivers/media/pci/ttpci/budget-ci.c+14−13
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818 #include <linux/slab.h>
1919 #include <linux/interrupt.h>
2020 #include <linux/spinlock.h>
21+#include <linux/workqueue.h>
2122 #include <media/rc-core.h>
2223
2324 #include "budget.h"
@@ -81,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); · 57 unmodified lines
8182
8283 struct budget_ci_ir {
8384 struct rc_dev *dev;
84− struct tasklet_struct msp430_irq_tasklet;
85+ struct work_struct msp430_irq_bh_work;
8586 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
8687 char phys[32];
8788 int rc5_device;
@@ -92,7 +93,7 @@ struct budget_ci_ir { · 4 unmodified lines
9293
9394 struct budget_ci {
9495 struct budget budget;
95− struct tasklet_struct ciintf_irq_tasklet;
96+ struct work_struct ciintf_irq_bh_work;
9697 int slot_status;
9798 int ci_irq;
9899 struct dvb_ca_en50221 ca;
@@ -100,9 +101,9 @@ struct budget_ci { · 1 unmodified line
100101 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
101102 };
102103
103−static void msp430_ir_interrupt(struct tasklet_struct *t)
104+static void msp430_ir_interrupt(struct work_struct *t)
104105 {
105− struct budget_ci_ir *ir = from_tasklet(ir, t, msp430_irq_tasklet);
106+ struct budget_ci_ir *ir = from_work(ir, t, msp430_irq_bh_work);
106107 struct budget_ci *budget_ci = container_of(ir, typeof(*budget_ci), ir);
107108 struct rc_dev *dev = budget_ci->ir.dev;
108109 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
@@ -231,7 +232,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) · 122 unmodified lines
231232
232233 budget_ci->ir.dev = dev;
233234
234− tasklet_setup(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt);
235+ INIT_WORK(&budget_ci->ir.msp430_irq_bh_work, msp430_ir_interrupt);
235236
236237 SAA7146_IER_ENABLE(saa, MASK_06);
237238 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
@@ -245,7 +246,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) · 7 unmodified lines
245246
246247 SAA7146_IER_DISABLE(saa, MASK_06);
247248 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
248− tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
249+ cancel_work_sync(&budget_ci->ir.msp430_irq_bh_work);
249250
250251 rc_unregister_device(budget_ci->ir.dev);
251252 }
@@ -349,10 +350,10 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) · 97 unmodified lines
349350 return 0;
350351 }
351352
352−static void ciintf_interrupt(struct tasklet_struct *t)
353+static void ciintf_interrupt(struct work_struct *t)
353354 {
354− struct budget_ci *budget_ci = from_tasklet(budget_ci, t,
355− ciintf_irq_tasklet);
355+ struct budget_ci *budget_ci = from_work(budget_ci, t,
356+ ciintf_irq_bh_work);
356357 struct saa7146_dev *saa = budget_ci->budget.dev;
357358 unsigned int flags;
358359
@@ -491,7 +492,7 @@ static int ciintf_init(struct budget_ci *budget_ci) · 132 unmodified lines
491492
492493 // Setup CI slot IRQ
493494 if (budget_ci->ci_irq) {
494− tasklet_setup(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt);
495+ INIT_WORK(&budget_ci->ciintf_irq_bh_work, ciintf_interrupt);
495496 if (budget_ci->slot_status != SLOTSTATUS_NONE)
496497 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
497498 else
@@ -530,7 +531,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) · 32 unmodified lines
530531 if (budget_ci->ci_irq) {
531532 SAA7146_IER_DISABLE(saa, MASK_03);
532533 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
533− tasklet_kill(&budget_ci->ciintf_irq_tasklet);
534+ cancel_work_sync(&budget_ci->ciintf_irq_bh_work);
534535 }
535536
536537 // reset interface
@@ -556,13 +557,13 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 *isr) · 19 unmodified lines
556557 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
557558
558559 if (*isr & MASK_06)
559− tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
560+ queue_work(system_bh_wq, &budget_ci->ir.msp430_irq_bh_work);
560561
561562 if (*isr & MASK_10)
562563 ttpci_budget_irq10_handler(dev, isr);
563564
564565 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
565− tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
566+ queue_work(system_bh_wq, &budget_ci->ciintf_irq_bh_work);
566567 }
567568
568569 static u8 philips_su1278_tt_inittab[] = {
drivers/media/pci/ttpci/budget-core.c+6−5
@@ -172,9 +172,9 @@ static int budget_read_fe_status(struct dvb_frontend *fe, · 171 unmodified lines
172172 return ret;
173173 }
174174
175−static void vpeirq(struct tasklet_struct *t)
175+static void vpeirq(struct work_struct *t)
176176 {
177− struct budget *budget = from_tasklet(budget, t, vpe_tasklet);
177+ struct budget *budget = from_work(budget, t, vpe_bh_work);
178178 u8 *mem = (u8 *) (budget->grabbing);
179179 u32 olddma = budget->ttbp;
180180 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
@@ -525,7 +525,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, · 344 unmodified lines
525525 /* upload all */
526526 saa7146_write(dev, GPIO_CTRL, 0x000000);
527527
528− tasklet_setup(&budget->vpe_tasklet, vpeirq);
528+ INIT_WORK(&budget->vpe_bh_work, vpeirq);
529529
530530 /* frontend power on */
531531 if (bi->type != BUDGET_FS_ACTIVY)
@@ -565,7 +565,7 @@ int ttpci_budget_deinit(struct budget *budget) · 33 unmodified lines
565565
566566 budget_unregister(budget);
567567
568− tasklet_kill(&budget->vpe_tasklet);
568+ cancel_work_sync(&budget->vpe_bh_work);
569569
570570 saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
571571
@@ -584,7 +584,7 @@ void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 *isr) · 12 unmodified lines
584584 dprintk(8, "dev: %p, budget: %p\n", dev, budget);
585585
586586 if (*isr & MASK_10)
587− tasklet_schedule(&budget->vpe_tasklet);
587+ queue_work(system_bh_wq, &budget->vpe_bh_work);
588588 }
589589 EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
590590
@@ -602,4 +602,5 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) · 11 unmodified lines
602602 }
603603 EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
604604
605+MODULE_DESCRIPTION("base driver for the SAA7146 based Budget DVB cards");
605606 MODULE_LICENSE("GPL");
drivers/media/pci/ttpci/budget.h+3−2
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818
1919 #include <linux/module.h>
2020 #include <linux/mutex.h>
21+#include <linux/workqueue.h>
2122
2223 #include <media/drv-intf/saa7146.h>
2324
@@ -54,8 +55,8 @@ struct budget { · 30 unmodified lines
5455 unsigned char *grabbing;
5556 struct saa7146_pgtable pt;
5657
57− struct tasklet_struct fidb_tasklet;
58− struct tasklet_struct vpe_tasklet;
58+ struct work_struct fidb_bh_work;
59+ struct work_struct vpe_bh_work;
5960
6061 struct dmxdev dmxdev;
6162 struct dvb_demux demux;
drivers/media/pci/tw5864/tw5864-core.c+1−1
@@ -144,7 +144,7 @@ static void tw5864_h264_isr(struct tw5864_dev *dev) · 143 unmodified lines
144144 cur_frame->gop_seqno = input->frame_gop_seqno;
145145
146146 dev->h264_buf_w_index = next_frame_index;
147− tasklet_schedule(&dev->tasklet);
147+ queue_work(system_bh_wq, &dev->bh_work);
148148
149149 cur_frame = next_frame;
150150
drivers/media/pci/tw5864/tw5864-video.c+7−6
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 */
77
88 #include <linux/module.h>
9+#include <linux/workqueue.h>
910 #include <media/v4l2-common.h>
1011 #include <media/v4l2-event.h>
1112 #include <media/videobuf2-dma-contig.h>
@@ -175,7 +176,7 @@ static const unsigned int intra4x4_lambda3[] = { · 163 unmodified lines
175176 static v4l2_std_id tw5864_get_v4l2_std(enum tw5864_vid_std std);
176177 static enum tw5864_vid_std tw5864_from_v4l2_std(v4l2_std_id v4l2_std);
177178
178−static void tw5864_handle_frame_task(struct tasklet_struct *t);
179+static void tw5864_handle_frame_work(struct work_struct *t);
179180 static void tw5864_handle_frame(struct tw5864_h264_frame *frame);
180181 static void tw5864_frame_interval_set(struct tw5864_input *input);
181182
@@ -1062,7 +1063,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) · 880 unmodified lines
10621063 dev->irqmask |= TW5864_INTR_VLC_DONE | TW5864_INTR_TIMER;
10631064 tw5864_irqmask_apply(dev);
10641065
1065− tasklet_setup(&dev->tasklet, tw5864_handle_frame_task);
1066+ INIT_WORK(&dev->bh_work, tw5864_handle_frame_work);
10661067
10671068 for (i = 0; i < TW5864_INPUTS; i++) {
10681069 dev->inputs[i].root = dev;
@@ -1079,7 +1080,7 @@ fini_video_inputs: · 10 unmodified lines
10791080 for (i = last_input_nr_registered; i >= 0; i--)
10801081 tw5864_video_input_fini(&dev->inputs[i]);
10811082
1082− tasklet_kill(&dev->tasklet);
1083+ cancel_work_sync(&dev->bh_work);
10831084
10841085 free_dma:
10851086 for (i = last_dma_allocated; i >= 0; i--) {
@@ -1198,7 +1199,7 @@ void tw5864_video_fini(struct tw5864_dev *dev) · 112 unmodified lines
11981199 {
11991200 int i;
12001201
1201− tasklet_kill(&dev->tasklet);
1202+ cancel_work_sync(&dev->bh_work);
12021203
12031204 for (i = 0; i < TW5864_INPUTS; i++)
12041205 tw5864_video_input_fini(&dev->inputs[i]);
@@ -1315,9 +1316,9 @@ static int tw5864_is_motion_triggered(struct tw5864_h264_frame *frame) · 110 unmodified lines
13151316 return detected;
13161317 }
13171318
1318−static void tw5864_handle_frame_task(struct tasklet_struct *t)
1319+static void tw5864_handle_frame_work(struct work_struct *t)
13191320 {
1320− struct tw5864_dev *dev = from_tasklet(dev, t, tasklet);
1321+ struct tw5864_dev *dev = from_work(dev, t, bh_work);
13211322 unsigned long flags;
13221323 int batch_size = H264_BUF_CNT;
13231324
drivers/media/pci/tw5864/tw5864.h+4−3
@@ -12,6 +12,7 @@ · 11 unmodified lines
1212 #include <linux/mutex.h>
1313 #include <linux/io.h>
1414 #include <linux/interrupt.h>
15+#include <linux/workqueue.h>
1516
1617 #include <media/v4l2-common.h>
1718 #include <media/v4l2-ioctl.h>
@@ -85,7 +86,7 @@ struct tw5864_input { · 67 unmodified lines
8586 int nr; /* input number */
8687 struct tw5864_dev *root;
8788 struct mutex lock; /* used for vidq and vdev */
88− spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */
89+ spinlock_t slock; /* used for sync between ISR, bh_work & V4L2 API */
8990 struct video_device vdev;
9091 struct v4l2_ctrl_handler hdl;
9192 struct vb2_queue vidq;
@@ -142,7 +143,7 @@ struct tw5864_h264_frame { · 50 unmodified lines
142143
143144 /* global device status */
144145 struct tw5864_dev {
145− spinlock_t slock; /* used for sync between ISR, tasklet & V4L2 API */
146+ spinlock_t slock; /* used for sync between ISR, bh_work & V4L2 API */
146147 struct v4l2_device v4l2_dev;
147148 struct tw5864_input inputs[TW5864_INPUTS];
148149 #define H264_BUF_CNT 4
@@ -150,7 +151,7 @@ struct tw5864_dev { · 1 unmodified line
150151 int h264_buf_r_index;
151152 int h264_buf_w_index;
152153
153− struct tasklet_struct tasklet;
154+ struct work_struct bh_work;
154155
155156 int encoder_busy;
156157 /* Input number to check next for ready raw picture (in RR fashion) */
drivers/media/platform/Kconfig+2−0
@@ -70,6 +70,7 @@ source "drivers/media/platform/atmel/Kconfig" · 69 unmodified lines
7070 source "drivers/media/platform/broadcom/Kconfig"
7171 source "drivers/media/platform/cadence/Kconfig"
7272 source "drivers/media/platform/chips-media/Kconfig"
73+source "drivers/media/platform/imagination/Kconfig"
7374 source "drivers/media/platform/intel/Kconfig"
7475 source "drivers/media/platform/marvell/Kconfig"
7576 source "drivers/media/platform/mediatek/Kconfig"
@@ -78,6 +79,7 @@ source "drivers/media/platform/nuvoton/Kconfig" · 2 unmodified lines
7879 source "drivers/media/platform/nvidia/Kconfig"
7980 source "drivers/media/platform/nxp/Kconfig"
8081 source "drivers/media/platform/qcom/Kconfig"
82+source "drivers/media/platform/raspberrypi/Kconfig"
8183 source "drivers/media/platform/renesas/Kconfig"
8284 source "drivers/media/platform/rockchip/Kconfig"
8385 source "drivers/media/platform/samsung/Kconfig"
drivers/media/platform/Makefile+2−0
@@ -13,6 +13,7 @@ obj-y += atmel/ · 12 unmodified lines
1313 obj-y += broadcom/
1414 obj-y += cadence/
1515 obj-y += chips-media/
16+obj-y += imagination/
1617 obj-y += intel/
1718 obj-y += marvell/
1819 obj-y += mediatek/
@@ -21,6 +22,7 @@ obj-y += nuvoton/ · 2 unmodified lines
2122 obj-y += nvidia/
2223 obj-y += nxp/
2324 obj-y += qcom/
25+obj-y += raspberrypi/
2426 obj-y += renesas/
2527 obj-y += rockchip/
2628 obj-y += samsung/
drivers/media/platform/allegro-dvt/nal-hevc.h+4−3
@@ -96,10 +96,11 @@ struct nal_hevc_vps { · 95 unmodified lines
9696 unsigned int extension_data_flag;
9797 };
9898
99+#define N_HRD_PARAMS 1
99100 struct nal_hevc_sub_layer_hrd_parameters {
100− unsigned int bit_rate_value_minus1[1];
101− unsigned int cpb_size_value_minus1[1];
102− unsigned int cbr_flag[1];
101+ unsigned int bit_rate_value_minus1[N_HRD_PARAMS];
102+ unsigned int cpb_size_value_minus1[N_HRD_PARAMS];
103+ unsigned int cbr_flag[N_HRD_PARAMS];
103104 };
104105
105106 struct nal_hevc_hrd_parameters {
drivers/media/platform/amphion/vdec.c+0−2
@@ -195,7 +195,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) · 194 unmodified lines
195195 struct vdec_t *vdec = inst->priv;
196196 int ret = 0;
197197
198− vpu_inst_lock(inst);
199198 switch (ctrl->id) {
200199 case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
201200 vdec->params.display_delay_enable = ctrl->val;
@@ -207,7 +206,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) · 5 unmodified lines
207206 ret = -EINVAL;
208207 break;
209208 }
210− vpu_inst_unlock(inst);
211209
212210 return ret;
213211 }
drivers/media/platform/amphion/venc.c+4−2
@@ -518,7 +518,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) · 517 unmodified lines
518518 struct venc_t *venc = inst->priv;
519519 int ret = 0;
520520
521− vpu_inst_lock(inst);
522521 switch (ctrl->id) {
523522 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
524523 venc->params.profile = ctrl->val;
@@ -579,7 +578,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) · 54 unmodified lines
579578 ret = -EINVAL;
580579 break;
581580 }
582− vpu_inst_unlock(inst);
583581
584582 return ret;
585583 }
@@ -680,6 +678,9 @@ static int venc_ctrl_init(struct vpu_inst *inst) · 94 unmodified lines
680678 ~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
681679 V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
682680
681+ v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
682+ V4L2_CID_MPEG_VIDEO_AVERAGE_QP, 0, 51, 1, 0);
683+
683684 if (inst->ctrl_handler.error) {
684685 ret = inst->ctrl_handler.error;
685686 v4l2_ctrl_handler_free(&inst->ctrl_handler);
@@ -819,6 +820,7 @@ static int venc_get_one_encoded_frame(struct vpu_inst *inst, · 133 unmodified lines
819820 vbuf->field = inst->cap_format.field;
820821 vbuf->flags |= frame->info.pic_type;
821822 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
823+ vpu_set_buffer_average_qp(vbuf, frame->info.average_qp);
822824 dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);
823825 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
824826 venc->ready_count++;
drivers/media/platform/amphion/vpu.h+1−0
@@ -306,6 +306,7 @@ struct vpu_vb2_buffer { · 305 unmodified lines
306306 dma_addr_t chroma_v;
307307 unsigned int state;
308308 u32 tag;
309+ u32 average_qp;
309310 };
310311
311312 void vpu_writel(struct vpu_dev *vpu, u32 reg, u32 val);
drivers/media/platform/amphion/vpu_defs.h+1−0
@@ -114,6 +114,7 @@ struct vpu_enc_pic_info { · 113 unmodified lines
114114 u32 wptr;
115115 u32 crc;
116116 s64 timestamp;
117+ u32 average_qp;
117118 };
118119
119120 struct vpu_dec_codec_info {
drivers/media/platform/amphion/vpu_malone.c+0−5
@@ -207,11 +207,6 @@ struct vpu_malone_dbglog_desc { · 206 unmodified lines
207207 u32 reserved;
208208 };
209209
210−struct vpu_malone_frame_buffer {
211− u32 addr;
212− u32 size;
213−};
214−
215210 struct vpu_malone_udata {
216211 u32 base;
217212 u32 total_size;
drivers/media/platform/amphion/vpu_v4l2.c+16−0
@@ -63,6 +63,13 @@ unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf) · 62 unmodified lines
6363 return vpu_buf->state;
6464 }
6565
66+void vpu_set_buffer_average_qp(struct vb2_v4l2_buffer *vbuf, u32 qp)
67+{
68+ struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf);
69+
70+ vpu_buf->average_qp = qp;
71+}
72+
6673 void vpu_v4l2_set_error(struct vpu_inst *inst)
6774 {
6875 vpu_inst_lock(inst);
@@ -539,6 +546,15 @@ static void vpu_vb2_buf_finish(struct vb2_buffer *vb) · 470 unmodified lines
539546 struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
540547 struct vb2_queue *q = vb->vb2_queue;
541548
549+ if (V4L2_TYPE_IS_CAPTURE(vb->type)) {
550+ struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf);
551+ struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
552+ V4L2_CID_MPEG_VIDEO_AVERAGE_QP);
553+
554+ if (ctrl)
555+ v4l2_ctrl_s_ctrl(ctrl, vpu_buf->average_qp);
556+ }
557+
542558 if (vbuf->flags & V4L2_BUF_FLAG_LAST)
543559 vpu_notify_eos(inst);
544560
drivers/media/platform/amphion/vpu_v4l2.h+1−0
@@ -12,6 +12,7 @@ void vpu_inst_lock(struct vpu_inst *inst); · 11 unmodified lines
1212 void vpu_inst_unlock(struct vpu_inst *inst);
1313 void vpu_set_buffer_state(struct vb2_v4l2_buffer *vbuf, unsigned int state);
1414 unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf);
15+void vpu_set_buffer_average_qp(struct vb2_v4l2_buffer *vbuf, u32 qp);
1516
1617 int vpu_v4l2_open(struct file *file, struct vpu_inst *inst);
1718 int vpu_v4l2_close(struct file *file);
drivers/media/platform/amphion/vpu_windsor.c+2−0
@@ -499,6 +499,7 @@ struct windsor_pic_info { · 498 unmodified lines
499499 u32 proc_dacc_rng_wr_cnt;
500500 s32 tv_s;
501501 u32 tv_ns;
502+ u32 average_qp;
502503 };
503504
504505 u32 vpu_windsor_get_data_size(void)
@@ -734,6 +735,7 @@ static void vpu_windsor_unpack_pic_info(struct vpu_rpc_event *pkt, void *data) · 229 unmodified lines
734735 info->wptr = get_ptr(windsor->str_buff_wptr);
735736 info->crc = windsor->frame_crc;
736737 info->timestamp = timespec64_to_ns(&ts);
738+ info->average_qp = windsor->average_qp;
737739 }
738740
739741 static void vpu_windsor_unpack_mem_req(struct vpu_rpc_event *pkt, void *data)
drivers/media/platform/chips-media/wave5/wave5-helper.c+7−1
@@ -29,7 +29,13 @@ void wave5_cleanup_instance(struct vpu_instance *inst) · 28 unmodified lines
2929 {
3030 int i;
3131
32− if (list_is_singular(&inst->list))
32+ /*
33+ * For Wave515 SRAM memory is allocated at
34+ * wave5_vpu_dec_register_device() and freed at
35+ * wave5_vpu_dec_unregister_device().
36+ */
37+ if (list_is_singular(&inst->list) &&
38+ inst->dev->product_code != WAVE515_CODE)
3339 wave5_vdi_free_sram(inst->dev);
3440
3541 for (i = 0; i < inst->fbc_buf_count; i++)
drivers/media/platform/chips-media/wave5/wave5-hw.c+295−100
@@ -18,18 +18,20 @@ · 17 unmodified lines
1818 #define QUEUE_REPORT_MASK 0xffff
1919
2020 /* Encoder support fields */
21−#define FEATURE_HEVC10BIT_ENC BIT(3)
22−#define FEATURE_AVC10BIT_ENC BIT(11)
23−#define FEATURE_AVC_ENCODER BIT(1)
24−#define FEATURE_HEVC_ENCODER BIT(0)
21+#define W521_FEATURE_HEVC10BIT_ENC BIT(3)
22+#define W521_FEATURE_AVC10BIT_ENC BIT(11)
23+#define W521_FEATURE_AVC_ENCODER BIT(1)
24+#define W521_FEATURE_HEVC_ENCODER BIT(0)
2525
2626 /* Decoder support fields */
27−#define FEATURE_AVC_DECODER BIT(3)
28−#define FEATURE_HEVC_DECODER BIT(2)
27+#define W521_FEATURE_AVC_DECODER BIT(3)
28+#define W521_FEATURE_HEVC_DECODER BIT(2)
29+#define W515_FEATURE_HEVC10BIT_DEC BIT(1)
30+#define W515_FEATURE_HEVC_DECODER BIT(0)
2931
30−#define FEATURE_BACKBONE BIT(16)
31−#define FEATURE_VCORE_BACKBONE BIT(22)
32−#define FEATURE_VCPU_BACKBONE BIT(28)
32+#define W521_FEATURE_BACKBONE BIT(16)
33+#define W521_FEATURE_VCORE_BACKBONE BIT(22)
34+#define W521_FEATURE_VCPU_BACKBONE BIT(28)
3335
3436 #define REMAP_CTRL_MAX_SIZE_BITS ((W5_REMAP_MAX_SIZE >> 12) & 0x1ff)
3537 #define REMAP_CTRL_REGISTER_VALUE(index) ( \
@@ -155,6 +157,8 @@ static int wave5_wait_bus_busy(struct vpu_device *vpu_dev, unsigned int addr) · 119 unmodified lines
155157 {
156158 u32 gdi_status_check_value = 0x3f;
157159
160+ if (vpu_dev->product_code == WAVE515_CODE)
161+ gdi_status_check_value = 0x0738;
158162 if (vpu_dev->product_code == WAVE521C_CODE ||
159163 vpu_dev->product_code == WAVE521_CODE ||
160164 vpu_dev->product_code == WAVE521E1_CODE)
@@ -186,6 +190,8 @@ unsigned int wave5_vpu_get_product_id(struct vpu_device *vpu_dev) · 25 unmodified lines
186190 u32 val = vpu_read_reg(vpu_dev, W5_PRODUCT_NUMBER);
187191
188192 switch (val) {
193+ case WAVE515_CODE:
194+ return PRODUCT_ID_515;
189195 case WAVE521C_CODE:
190196 return PRODUCT_ID_521;
191197 case WAVE521_CODE:
@@ -299,6 +305,27 @@ static int wave5_send_query(struct vpu_device *vpu_dev, struct vpu_instance *ins · 107 unmodified lines
299305 return wave5_vpu_firmware_command_queue_error_check(vpu_dev, NULL);
300306 }
301307
308+static void setup_wave5_interrupts(struct vpu_device *vpu_dev)
309+{
310+ u32 reg_val = 0;
311+
312+ if (vpu_dev->attr.support_encoders) {
313+ /* Encoder interrupt */
314+ reg_val |= BIT(INT_WAVE5_ENC_SET_PARAM);
315+ reg_val |= BIT(INT_WAVE5_ENC_PIC);
316+ reg_val |= BIT(INT_WAVE5_BSBUF_FULL);
317+ }
318+
319+ if (vpu_dev->attr.support_decoders) {
320+ /* Decoder interrupt */
321+ reg_val |= BIT(INT_WAVE5_INIT_SEQ);
322+ reg_val |= BIT(INT_WAVE5_DEC_PIC);
323+ reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);
324+ }
325+
326+ return vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);
327+}
328+
302329 static int setup_wave5_properties(struct device *dev)
303330 {
304331 struct vpu_device *vpu_dev = dev_get_drvdata(dev);
@@ -328,17 +355,35 @@ static int setup_wave5_properties(struct device *dev) · 23 unmodified lines
328355 hw_config_def1 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF1);
329356 hw_config_feature = vpu_read_reg(vpu_dev, W5_RET_CONF_FEATURE);
330357
331− p_attr->support_hevc10bit_enc = FIELD_GET(FEATURE_HEVC10BIT_ENC, hw_config_feature);
332− p_attr->support_avc10bit_enc = FIELD_GET(FEATURE_AVC10BIT_ENC, hw_config_feature);
333−
334− p_attr->support_decoders = FIELD_GET(FEATURE_AVC_DECODER, hw_config_def1) << STD_AVC;
335− p_attr->support_decoders |= FIELD_GET(FEATURE_HEVC_DECODER, hw_config_def1) << STD_HEVC;
336− p_attr->support_encoders = FIELD_GET(FEATURE_AVC_ENCODER, hw_config_def1) << STD_AVC;
337− p_attr->support_encoders |= FIELD_GET(FEATURE_HEVC_ENCODER, hw_config_def1) << STD_HEVC;
338−
339− p_attr->support_backbone = FIELD_GET(FEATURE_BACKBONE, hw_config_def0);
340− p_attr->support_vcpu_backbone = FIELD_GET(FEATURE_VCPU_BACKBONE, hw_config_def0);
341− p_attr->support_vcore_backbone = FIELD_GET(FEATURE_VCORE_BACKBONE, hw_config_def0);
358+ if (vpu_dev->product_code == WAVE515_CODE) {
359+ p_attr->support_hevc10bit_dec = FIELD_GET(W515_FEATURE_HEVC10BIT_DEC,
360+ hw_config_feature);
361+ p_attr->support_decoders = FIELD_GET(W515_FEATURE_HEVC_DECODER,
362+ hw_config_def1) << STD_HEVC;
363+ } else {
364+ p_attr->support_hevc10bit_enc = FIELD_GET(W521_FEATURE_HEVC10BIT_ENC,
365+ hw_config_feature);
366+ p_attr->support_avc10bit_enc = FIELD_GET(W521_FEATURE_AVC10BIT_ENC,
367+ hw_config_feature);
368+
369+ p_attr->support_decoders = FIELD_GET(W521_FEATURE_AVC_DECODER,
370+ hw_config_def1) << STD_AVC;
371+ p_attr->support_decoders |= FIELD_GET(W521_FEATURE_HEVC_DECODER,
372+ hw_config_def1) << STD_HEVC;
373+ p_attr->support_encoders = FIELD_GET(W521_FEATURE_AVC_ENCODER,
374+ hw_config_def1) << STD_AVC;
375+ p_attr->support_encoders |= FIELD_GET(W521_FEATURE_HEVC_ENCODER,
376+ hw_config_def1) << STD_HEVC;
377+
378+ p_attr->support_backbone = FIELD_GET(W521_FEATURE_BACKBONE,
379+ hw_config_def0);
380+ p_attr->support_vcpu_backbone = FIELD_GET(W521_FEATURE_VCPU_BACKBONE,
381+ hw_config_def0);
382+ p_attr->support_vcore_backbone = FIELD_GET(W521_FEATURE_VCORE_BACKBONE,
383+ hw_config_def0);
384+ }
385+
386+ setup_wave5_interrupts(vpu_dev);
342387
343388 return 0;
344389 }
@@ -380,12 +425,18 @@ int wave5_vpu_init(struct device *dev, u8 *fw, size_t size) · 35 unmodified lines
380425 common_vb = &vpu_dev->common_mem;
381426
382427 code_base = common_vb->daddr;
428+
429+ if (vpu_dev->product_code == WAVE515_CODE)
430+ code_size = WAVE515_MAX_CODE_BUF_SIZE;
431+ else
432+ code_size = WAVE521_MAX_CODE_BUF_SIZE;
433+
383434 /* ALIGN TO 4KB */
384− code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
435+ code_size &= ~0xfff;
385436 if (code_size < size * 2)
386437 return -EINVAL;
387438
388− temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET;
439+ temp_base = code_base + code_size;
389440 temp_size = WAVE5_TEMPBUF_SIZE;
390441
391442 ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size);
@@ -413,22 +464,15 @@ int wave5_vpu_init(struct device *dev, u8 *fw, size_t size) · 21 unmodified lines
413464
414465 /* These register must be reset explicitly */
415466 vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
416− wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
417− wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
418− vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
419−
420− /* Encoder interrupt */
421− reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);
422− reg_val |= BIT(INT_WAVE5_ENC_PIC);
423− reg_val |= BIT(INT_WAVE5_BSBUF_FULL);
424− /* Decoder interrupt */
425− reg_val |= BIT(INT_WAVE5_INIT_SEQ);
426− reg_val |= BIT(INT_WAVE5_DEC_PIC);
427− reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);
428− vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);
467+
468+ if (vpu_dev->product_code != WAVE515_CODE) {
469+ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
470+ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
471+ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
472+ }
429473
430474 reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
431− if (FIELD_GET(FEATURE_BACKBONE, reg_val)) {
475+ if (FIELD_GET(W521_FEATURE_BACKBONE, reg_val)) {
432476 reg_val = ((WAVE5_PROC_AXI_ID << 28) |
433477 (WAVE5_PRP_AXI_ID << 24) |
434478 (WAVE5_FBD_Y_AXI_ID << 20) |
@@ -440,6 +484,24 @@ int wave5_vpu_init(struct device *dev, u8 *fw, size_t size) · 5 unmodified lines
440484 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
441485 }
442486
487+ if (vpu_dev->product_code == WAVE515_CODE) {
488+ dma_addr_t task_buf_base;
489+
490+ vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF, WAVE515_COMMAND_QUEUE_DEPTH);
491+ vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE, WAVE515_ONE_TASKBUF_SIZE);
492+
493+ for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {
494+ task_buf_base = temp_base + temp_size +
495+ (i * WAVE515_ONE_TASKBUF_SIZE);
496+ vpu_write_reg(vpu_dev,
497+ W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),
498+ task_buf_base);
499+ }
500+
501+ vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);
502+ vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);
503+ }
504+
443505 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
444506 vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);
445507 vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);
@@ -480,29 +542,40 @@ int wave5_vpu_build_up_dec_param(struct vpu_instance *inst, · 34 unmodified lines
480542 return -EINVAL;
481543 }
482544
483− p_dec_info->vb_work.size = WAVE521DEC_WORKBUF_SIZE;
545+ if (vpu_dev->product == PRODUCT_ID_515)
546+ p_dec_info->vb_work.size = WAVE515DEC_WORKBUF_SIZE;
547+ else
548+ p_dec_info->vb_work.size = WAVE521DEC_WORKBUF_SIZE;
549+
484550 ret = wave5_vdi_allocate_dma_memory(inst->dev, &p_dec_info->vb_work);
485551 if (ret)
486552 return ret;
487553
488− vpu_write_reg(inst->dev, W5_CMD_DEC_VCORE_INFO, 1);
554+ if (inst->dev->product_code != WAVE515_CODE)
555+ vpu_write_reg(inst->dev, W5_CMD_DEC_VCORE_INFO, 1);
489556
490557 wave5_vdi_clear_memory(inst->dev, &p_dec_info->vb_work);
491558
492559 vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_dec_info->vb_work.daddr);
493560 vpu_write_reg(inst->dev, W5_WORK_SIZE, p_dec_info->vb_work.size);
494561
495− vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);
496− vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);
562+ if (inst->dev->product_code != WAVE515_CODE) {
563+ vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);
564+ vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);
565+ }
497566
498567 vpu_write_reg(inst->dev, W5_CMD_DEC_BS_START_ADDR, p_dec_info->stream_buf_start_addr);
499568 vpu_write_reg(inst->dev, W5_CMD_DEC_BS_SIZE, p_dec_info->stream_buf_size);
500569
501570 /* NOTE: SDMA reads MSB first */
502571 vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, BITSTREAM_ENDIANNESS_BIG_ENDIAN);
503− /* This register must be reset explicitly */
504− vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);
505− vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, (COMMAND_QUEUE_DEPTH - 1));
572+
573+ if (inst->dev->product_code != WAVE515_CODE) {
574+ /* This register must be reset explicitly */
575+ vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);
576+ vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1,
577+ WAVE521_COMMAND_QUEUE_DEPTH - 1);
578+ }
506579
507580 ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL);
508581 if (ret) {
@@ -553,7 +626,7 @@ static u32 get_bitstream_options(struct dec_info *info) · 44 unmodified lines
553626 int wave5_vpu_dec_init_seq(struct vpu_instance *inst)
554627 {
555628 struct dec_info *p_dec_info = &inst->codec_info->dec_info;
556− u32 cmd_option = INIT_SEQ_NORMAL;
629+ u32 bs_option, cmd_option = INIT_SEQ_NORMAL;
557630 u32 reg_val, fail_res;
558631 int ret;
559632
@@ -563,7 +636,13 @@ int wave5_vpu_dec_init_seq(struct vpu_instance *inst) · 3 unmodified lines
563636 vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr);
564637 vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);
565638
566− vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info));
639+ bs_option = get_bitstream_options(p_dec_info);
640+
641+ /* Without RD_PTR_VALID_FLAG Wave515 ignores RD_PTR value */
642+ if (inst->dev->product_code == WAVE515_CODE)
643+ bs_option |= BSOPTION_RD_PTR_VALID_FLAG;
644+
645+ vpu_write_reg(inst->dev, W5_BS_OPTION, bs_option);
567646
568647 vpu_write_reg(inst->dev, W5_COMMAND_OPTION, cmd_option);
569648 vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info->user_data_enable);
@@ -629,10 +708,12 @@ static void wave5_get_dec_seq_result(struct vpu_instance *inst, struct dec_initi · 59 unmodified lines
629708 info->profile = FIELD_GET(SEQ_PARAM_PROFILE_MASK, reg_val);
630709 }
631710
632− info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);
633− info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE);
634− p_dec_info->vlc_buf_size = info->vlc_buf_size;
635− p_dec_info->param_buf_size = info->param_buf_size;
711+ if (inst->dev->product_code != WAVE515_CODE) {
712+ info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);
713+ info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE);
714+ p_dec_info->vlc_buf_size = info->vlc_buf_size;
715+ p_dec_info->param_buf_size = info->param_buf_size;
716+ }
636717 }
637718
638719 int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct dec_initial_info *info)
@@ -734,22 +815,27 @@ int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_b · 95 unmodified lines
734815
735816 pic_size = (init_info->pic_width << 16) | (init_info->pic_height);
736817
737− vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) +
738− (p_dec_info->param_buf_size * COMMAND_QUEUE_DEPTH);
739− vb_buf.daddr = 0;
818+ if (inst->dev->product_code != WAVE515_CODE) {
819+ vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) +
820+ (p_dec_info->param_buf_size * WAVE521_COMMAND_QUEUE_DEPTH);
821+ vb_buf.daddr = 0;
740822
741− if (vb_buf.size != p_dec_info->vb_task.size) {
742− wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task);
743− ret = wave5_vdi_allocate_dma_memory(inst->dev, &vb_buf);
744− if (ret)
745− goto free_fbc_c_tbl_buffers;
823+ if (vb_buf.size != p_dec_info->vb_task.size) {
824+ wave5_vdi_free_dma_memory(inst->dev,
825+ &p_dec_info->vb_task);
826+ ret = wave5_vdi_allocate_dma_memory(inst->dev,
827+ &vb_buf);
828+ if (ret)
829+ goto free_fbc_c_tbl_buffers;
746830
747− p_dec_info->vb_task = vb_buf;
748− }
831+ p_dec_info->vb_task = vb_buf;
832+ }
749833
750− vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,
751− p_dec_info->vb_task.daddr);
752− vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_buf.size);
834+ vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,
835+ p_dec_info->vb_task.daddr);
836+ vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE,
837+ vb_buf.size);
838+ }
753839 } else {
754840 pic_size = (init_info->pic_width << 16) | (init_info->pic_height);
755841
@@ -830,6 +916,43 @@ free_mv_buffers: · 74 unmodified lines
830916 return ret;
831917 }
832918
919+static u32 wave5_vpu_dec_validate_sec_axi(struct vpu_instance *inst)
920+{
921+ u32 bitdepth = inst->codec_info->dec_info.initial_info.luma_bitdepth;
922+ struct dec_info *p_dec_info = &inst->codec_info->dec_info;
923+ u32 bit_size = 0, ip_size = 0, lf_size = 0, ret = 0;
924+ u32 sram_size = inst->dev->sram_size;
925+ u32 width = inst->src_fmt.width;
926+
927+ if (!sram_size)
928+ return 0;
929+
930+ /*
931+ * TODO: calculate bit_size, ip_size, lf_size from width and bitdepth
932+ * for Wave521.
933+ */
934+ if (inst->dev->product_code == WAVE515_CODE) {
935+ bit_size = DIV_ROUND_UP(width, 16) * 5 * 8;
936+ ip_size = ALIGN(width, 16) * 2 * bitdepth / 8;
937+ lf_size = ALIGN(width, 16) * 10 * bitdepth / 8;
938+ }
939+
940+ if (p_dec_info->sec_axi_info.use_bit_enable && sram_size >= bit_size) {
941+ ret |= BIT(0);
942+ sram_size -= bit_size;
943+ }
944+
945+ if (p_dec_info->sec_axi_info.use_ip_enable && sram_size >= ip_size) {
946+ ret |= BIT(9);
947+ sram_size -= ip_size;
948+ }
949+
950+ if (p_dec_info->sec_axi_info.use_lf_row_enable && sram_size >= lf_size)
951+ ret |= BIT(15);
952+
953+ return ret;
954+}
955+
833956 int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res)
834957 {
835958 u32 reg_val;
@@ -842,9 +965,7 @@ int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res) · 6 unmodified lines
842965 vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info));
843966
844967 /* secondary AXI */
845− reg_val = p_dec_info->sec_axi_info.use_bit_enable |
846− (p_dec_info->sec_axi_info.use_ip_enable << 9) |
847− (p_dec_info->sec_axi_info.use_lf_row_enable << 15);
968+ reg_val = wave5_vpu_dec_validate_sec_axi(inst);
848969 vpu_write_reg(inst->dev, W5_USE_SEC_AXI, reg_val);
849970
850971 /* set attributes of user buffer */
@@ -992,11 +1113,18 @@ int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size) · 141 unmodified lines
9921113 common_vb = &vpu_dev->common_mem;
9931114
9941115 code_base = common_vb->daddr;
1116+
1117+ if (vpu_dev->product_code == WAVE515_CODE)
1118+ code_size = WAVE515_MAX_CODE_BUF_SIZE;
1119+ else
1120+ code_size = WAVE521_MAX_CODE_BUF_SIZE;
1121+
9951122 /* ALIGN TO 4KB */
996− code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
1123+ code_size &= ~0xfff;
9971124 if (code_size < size * 2)
9981125 return -EINVAL;
999− temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET;
1126+
1127+ temp_base = code_base + code_size;
10001128 temp_size = WAVE5_TEMPBUF_SIZE;
10011129
10021130 old_code_base = vpu_read_reg(vpu_dev, W5_VPU_REMAP_PADDR);
@@ -1030,22 +1158,15 @@ int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size) · 27 unmodified lines
10301158
10311159 /* These register must be reset explicitly */
10321160 vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
1033− wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
1034− wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
1035− vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
10361161
1037− /* Encoder interrupt */
1038− reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);
1039− reg_val |= BIT(INT_WAVE5_ENC_PIC);
1040− reg_val |= BIT(INT_WAVE5_BSBUF_FULL);
1041− /* Decoder interrupt */
1042− reg_val |= BIT(INT_WAVE5_INIT_SEQ);
1043− reg_val |= BIT(INT_WAVE5_DEC_PIC);
1044− reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);
1045− vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);
1162+ if (vpu_dev->product_code != WAVE515_CODE) {
1163+ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
1164+ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
1165+ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
1166+ }
10461167
10471168 reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
1048− if (FIELD_GET(FEATURE_BACKBONE, reg_val)) {
1169+ if (FIELD_GET(W521_FEATURE_BACKBONE, reg_val)) {
10491170 reg_val = ((WAVE5_PROC_AXI_ID << 28) |
10501171 (WAVE5_PRP_AXI_ID << 24) |
10511172 (WAVE5_FBD_Y_AXI_ID << 20) |
@@ -1057,6 +1178,29 @@ int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size) · 5 unmodified lines
10571178 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
10581179 }
10591180
1181+ if (vpu_dev->product_code == WAVE515_CODE) {
1182+ dma_addr_t task_buf_base;
1183+ u32 i;
1184+
1185+ vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF,
1186+ WAVE515_COMMAND_QUEUE_DEPTH);
1187+ vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE,
1188+ WAVE515_ONE_TASKBUF_SIZE);
1189+
1190+ for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {
1191+ task_buf_base = temp_base + temp_size +
1192+ (i * WAVE515_ONE_TASKBUF_SIZE);
1193+ vpu_write_reg(vpu_dev,
1194+ W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),
1195+ task_buf_base);
1196+ }
1197+
1198+ vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI,
1199+ vpu_dev->sram_buf.daddr);
1200+ vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE,
1201+ vpu_dev->sram_buf.size);
1202+ }
1203+
10601204 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
10611205 vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);
10621206 vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);
@@ -1080,8 +1224,8 @@ static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uin · 17 unmodified lines
10801224 {
10811225 u32 reg_val;
10821226 struct vpu_buf *common_vb;
1083− dma_addr_t code_base;
1084− u32 code_size, reason_code;
1227+ dma_addr_t code_base, temp_base;
1228+ u32 code_size, temp_size, reason_code;
10851229 struct vpu_device *vpu_dev = dev_get_drvdata(dev);
10861230 int ret;
10871231
@@ -1111,13 +1255,22 @@ static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uin · 23 unmodified lines
11111255 common_vb = &vpu_dev->common_mem;
11121256
11131257 code_base = common_vb->daddr;
1258+
1259+ if (vpu_dev->product_code == WAVE515_CODE)
1260+ code_size = WAVE515_MAX_CODE_BUF_SIZE;
1261+ else
1262+ code_size = WAVE521_MAX_CODE_BUF_SIZE;
1263+
11141264 /* ALIGN TO 4KB */
1115− code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
1265+ code_size &= ~0xfff;
11161266 if (code_size < size * 2) {
11171267 dev_err(dev, "size too small\n");
11181268 return -EINVAL;
11191269 }
11201270
1271+ temp_base = code_base + code_size;
1272+ temp_size = WAVE5_TEMPBUF_SIZE;
1273+
11211274 /* Power on without DEBUG mode */
11221275 vpu_write_reg(vpu_dev, W5_PO_CONF, 0);
11231276
@@ -1130,22 +1283,17 @@ static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uin · 6 unmodified lines
11301283
11311284 /* These register must be reset explicitly */
11321285 vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
1133− wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
1134− wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
1135− vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
11361286
1137− /* Encoder interrupt */
1138− reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);
1139− reg_val |= BIT(INT_WAVE5_ENC_PIC);
1140− reg_val |= BIT(INT_WAVE5_BSBUF_FULL);
1141− /* Decoder interrupt */
1142− reg_val |= BIT(INT_WAVE5_INIT_SEQ);
1143− reg_val |= BIT(INT_WAVE5_DEC_PIC);
1144− reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);
1145− vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);
1287+ if (vpu_dev->product_code != WAVE515_CODE) {
1288+ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
1289+ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
1290+ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
1291+ }
1292+
1293+ setup_wave5_interrupts(vpu_dev);
11461294
11471295 reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
1148− if (FIELD_GET(FEATURE_BACKBONE, reg_val)) {
1296+ if (FIELD_GET(W521_FEATURE_BACKBONE, reg_val)) {
11491297 reg_val = ((WAVE5_PROC_AXI_ID << 28) |
11501298 (WAVE5_PRP_AXI_ID << 24) |
11511299 (WAVE5_FBD_Y_AXI_ID << 20) |
@@ -1157,6 +1305,29 @@ static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uin · 5 unmodified lines
11571305 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
11581306 }
11591307
1308+ if (vpu_dev->product_code == WAVE515_CODE) {
1309+ dma_addr_t task_buf_base;
1310+ u32 i;
1311+
1312+ vpu_write_reg(vpu_dev, W5_CMD_INIT_NUM_TASK_BUF,
1313+ WAVE515_COMMAND_QUEUE_DEPTH);
1314+ vpu_write_reg(vpu_dev, W5_CMD_INIT_TASK_BUF_SIZE,
1315+ WAVE515_ONE_TASKBUF_SIZE);
1316+
1317+ for (i = 0; i < WAVE515_COMMAND_QUEUE_DEPTH; i++) {
1318+ task_buf_base = temp_base + temp_size +
1319+ (i * WAVE515_ONE_TASKBUF_SIZE);
1320+ vpu_write_reg(vpu_dev,
1321+ W5_CMD_INIT_ADDR_TASK_BUF0 + (i * 4),
1322+ task_buf_base);
1323+ }
1324+
1325+ vpu_write_reg(vpu_dev, W515_CMD_ADDR_SEC_AXI,
1326+ vpu_dev->sram_buf.daddr);
1327+ vpu_write_reg(vpu_dev, W515_CMD_SEC_AXI_SIZE,
1328+ vpu_dev->sram_buf.size);
1329+ }
1330+
11601331 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
11611332 vpu_write_reg(vpu_dev, W5_COMMAND, W5_WAKEUP_VPU);
11621333 /* Start VPU after settings */
@@ -1401,7 +1572,7 @@ int wave5_vpu_build_up_enc_param(struct device *dev, struct vpu_instance *inst, · 238 unmodified lines
14011572 reg_val = (open_param->line_buf_int_en << 6) | BITSTREAM_ENDIANNESS_BIG_ENDIAN;
14021573 vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, reg_val);
14031574 vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);
1404− vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, (COMMAND_QUEUE_DEPTH - 1));
1575+ vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, WAVE521_COMMAND_QUEUE_DEPTH - 1);
14051576
14061577 /* This register must be reset explicitly */
14071578 vpu_write_reg(inst->dev, W5_CMD_ENC_SRC_OPTIONS, 0);
@@ -1855,7 +2026,7 @@ int wave5_vpu_enc_register_framebuffer(struct device *dev, struct vpu_instance * · 447 unmodified lines
18552026 p_enc_info->vb_sub_sam_buf = vb_sub_sam_buf;
18562027
18572028 vb_task.size = (p_enc_info->vlc_buf_size * VLC_BUF_NUM) +
1858− (p_enc_info->param_buf_size * COMMAND_QUEUE_DEPTH);
2029+ (p_enc_info->param_buf_size * WAVE521_COMMAND_QUEUE_DEPTH);
18592030 vb_task.daddr = 0;
18602031 if (p_enc_info->vb_task.size == 0) {
18612032 ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_task);
@@ -1943,6 +2114,31 @@ free_vb_fbc_y_tbl: · 81 unmodified lines
19432114 return ret;
19442115 }
19452116
2117+static u32 wave5_vpu_enc_validate_sec_axi(struct vpu_instance *inst)
2118+{
2119+ struct enc_info *p_enc_info = &inst->codec_info->enc_info;
2120+ u32 rdo_size = 0, lf_size = 0, ret = 0;
2121+ u32 sram_size = inst->dev->sram_size;
2122+
2123+ if (!sram_size)
2124+ return 0;
2125+
2126+ /*
2127+ * TODO: calculate rdo_size and lf_size from inst->src_fmt.width and
2128+ * inst->codec_info->enc_info.open_param.wave_param.internal_bit_depth
2129+ */
2130+
2131+ if (p_enc_info->sec_axi_info.use_enc_rdo_enable && sram_size >= rdo_size) {
2132+ ret |= BIT(11);
2133+ sram_size -= rdo_size;
2134+ }
2135+
2136+ if (p_enc_info->sec_axi_info.use_enc_lf_enable && sram_size >= lf_size)
2137+ ret |= BIT(15);
2138+
2139+ return ret;
2140+}
2141+
19462142 int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res)
19472143 {
19482144 u32 src_frame_format;
@@ -1964,8 +2160,7 @@ int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *f · 15 unmodified lines
19642160
19652161 vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_AXI_SEL, DEFAULT_SRC_AXI);
19662162 /* secondary AXI */
1967− reg_val = (p_enc_info->sec_axi_info.use_enc_rdo_enable << 11) |
1968− (p_enc_info->sec_axi_info.use_enc_lf_enable << 15);
2163+ reg_val = wave5_vpu_enc_validate_sec_axi(inst);
19692164 vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_USE_SEC_AXI, reg_val);
19702165
19712166 vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_REPORT_PARAM, 0);
drivers/media/platform/chips-media/wave5/wave5-regdefine.h+5−0
@@ -205,6 +205,9 @@ enum query_opt { · 204 unmodified lines
205205 #define W5_ADDR_TEMP_BASE (W5_REG_BASE + 0x011C)
206206 #define W5_TEMP_SIZE (W5_REG_BASE + 0x0120)
207207 #define W5_HW_OPTION (W5_REG_BASE + 0x012C)
208+#define W5_CMD_INIT_NUM_TASK_BUF (W5_REG_BASE + 0x0134)
209+#define W5_CMD_INIT_ADDR_TASK_BUF0 (W5_REG_BASE + 0x0138)
210+#define W5_CMD_INIT_TASK_BUF_SIZE (W5_REG_BASE + 0x0178)
208211 #define W5_SEC_AXI_PARAM (W5_REG_BASE + 0x0180)
209212
210213 /************************************************************************/
@@ -216,7 +219,9 @@ enum query_opt { · 5 unmodified lines
216219 #define W5_CMD_DEC_BS_SIZE (W5_REG_BASE + 0x0120)
217220 #define W5_CMD_BS_PARAM (W5_REG_BASE + 0x0124)
218221 #define W5_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0130)
222+#define W515_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0124)
219223 #define W5_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0134)
224+#define W515_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0128)
220225 #define W5_CMD_EXT_ADDR (W5_REG_BASE + 0x0138)
221226 #define W5_CMD_NUM_CQ_DEPTH_M1 (W5_REG_BASE + 0x013C)
222227 #define W5_CMD_ERR_CONCEAL (W5_REG_BASE + 0x0140)
drivers/media/platform/chips-media/wave5/wave5-vdi.c+16−11
@@ -18,7 +18,11 @@ static int wave5_vdi_allocate_common_memory(struct device *dev) · 17 unmodified lines
1818 if (!vpu_dev->common_mem.vaddr) {
1919 int ret;
2020
21− vpu_dev->common_mem.size = SIZE_COMMON;
21+ if (vpu_dev->product_code == WAVE515_CODE)
22+ vpu_dev->common_mem.size = WAVE515_SIZE_COMMON;
23+ else
24+ vpu_dev->common_mem.size = WAVE521_SIZE_COMMON;
25+
2226 ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev->common_mem);
2327 if (ret) {
2428 dev_err(dev, "unable to allocate common buffer\n");
@@ -174,16 +178,19 @@ int wave5_vdi_allocate_array(struct vpu_device *vpu_dev, struct vpu_buf *array, · 149 unmodified lines
174178 void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev)
175179 {
176180 struct vpu_buf *vb = &vpu_dev->sram_buf;
181+ dma_addr_t daddr;
182+ void *vaddr;
183+ size_t size;
177184
178− if (!vpu_dev->sram_pool || !vpu_dev->sram_size)
185+ if (!vpu_dev->sram_pool || vb->vaddr)
179186 return;
180187
181− if (!vb->vaddr) {
182− vb->size = vpu_dev->sram_size;
183− vb->vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, vb->size,
184− &vb->daddr);
185− if (!vb->vaddr)
186− vb->size = 0;
188+ size = min_t(size_t, vpu_dev->sram_size, gen_pool_avail(vpu_dev->sram_pool));
189+ vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, size, &daddr);
190+ if (vaddr) {
191+ vb->vaddr = vaddr;
192+ vb->daddr = daddr;
193+ vb->size = size;
187194 }
188195
189196 dev_dbg(vpu_dev->dev, "%s: sram daddr: %pad, size: %zu, vaddr: 0x%p\n",
@@ -197,9 +204,7 @@ void wave5_vdi_free_sram(struct vpu_device *vpu_dev) · 7 unmodified lines
197204 if (!vb->size || !vb->vaddr)
198205 return;
199206
200− if (vb->vaddr)
201− gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr,
202− vb->size);
207+ gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr, vb->size);
203208
204209 memset(vb, 0, sizeof(*vb));
205210 }
drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c+37−14
@@ -1055,6 +1055,22 @@ static int wave5_prepare_fb(struct vpu_instance *inst) · 1054 unmodified lines
10551055 int ret, i;
10561056 struct v4l2_m2m_buffer *buf, *n;
10571057 struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx;
1058+ u32 bitdepth = inst->codec_info->dec_info.initial_info.luma_bitdepth;
1059+
1060+ switch (bitdepth) {
1061+ case 8:
1062+ break;
1063+ case 10:
1064+ if (inst->std == W_HEVC_DEC &&
1065+ inst->dev->attr.support_hevc10bit_dec)
1066+ break;
1067+
1068+ fallthrough;
1069+ default:
1070+ dev_err(inst->dev->dev, "no support for %d bit depth\n", bitdepth);
1071+
1072+ return -EINVAL;
1073+ }
10581074
10591075 linear_num = v4l2_m2m_num_dst_bufs_ready(m2m_ctx);
10601076 non_linear_num = inst->fbc_buf_count;
@@ -1063,7 +1079,7 @@ static int wave5_prepare_fb(struct vpu_instance *inst) · 2 unmodified lines
10631079 struct frame_buffer *frame = &inst->frame_buf[i];
10641080 struct vpu_buf *vframe = &inst->frame_vbuf[i];
10651081
1066− fb_stride = inst->dst_fmt.width;
1082+ fb_stride = ALIGN(inst->dst_fmt.width * bitdepth / 8, 32);
10671083 fb_height = ALIGN(inst->dst_fmt.height, 32);
10681084 luma_size = fb_stride * fb_height;
10691085
@@ -1408,22 +1424,10 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count · 338 unmodified lines
14081424 if (ret)
14091425 goto free_bitstream_vbuf;
14101426 } else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1411− struct dec_initial_info *initial_info =
1412− &inst->codec_info->dec_info.initial_info;
1413−
14141427 if (inst->state == VPU_INST_STATE_STOP)
14151428 ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ);
14161429 if (ret)
14171430 goto return_buffers;
1418−
1419− if (inst->state == VPU_INST_STATE_INIT_SEQ) {
1420− if (initial_info->luma_bitdepth != 8) {
1421− dev_info(inst->dev->dev, "%s: no support for %d bit depth",
1422− __func__, initial_info->luma_bitdepth);
1423− ret = -EINVAL;
1424− goto return_buffers;
1425− }
1426− }
14271431 }
14281432
14291433 return ret;
@@ -1864,7 +1868,12 @@ static int wave5_vpu_open_dec(struct file *filp) · 434 unmodified lines
18641868 goto cleanup_inst;
18651869 }
18661870
1867− wave5_vdi_allocate_sram(inst->dev);
1871+ /*
1872+ * For Wave515 SRAM memory was already allocated
1873+ * at wave5_vpu_dec_register_device()
1874+ */
1875+ if (inst->dev->product_code != WAVE515_CODE)
1876+ wave5_vdi_allocate_sram(inst->dev);
18681877
18691878 ret = mutex_lock_interruptible(&dev->dev_lock);
18701879 if (ret)
@@ -1904,6 +1913,13 @@ int wave5_vpu_dec_register_device(struct vpu_device *dev) · 33 unmodified lines
19041913 struct video_device *vdev_dec;
19051914 int ret;
19061915
1916+ /*
1917+ * Secondary AXI setup for Wave515 is done by INIT_VPU command,
1918+ * i.e. wave5_vpu_init(), that's why we allocate SRAM memory early.
1919+ */
1920+ if (dev->product_code == WAVE515_CODE)
1921+ wave5_vdi_allocate_sram(dev);
1922+
19071923 vdev_dec = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_dec), GFP_KERNEL);
19081924 if (!vdev_dec)
19091925 return -ENOMEM;
@@ -1937,6 +1953,13 @@ int wave5_vpu_dec_register_device(struct vpu_device *dev) · 27 unmodified lines
19371953
19381954 void wave5_vpu_dec_unregister_device(struct vpu_device *dev)
19391955 {
1956+ /*
1957+ * Here is a freeing pair for Wave515 SRAM memory allocation
1958+ * happened at wave5_vpu_dec_register_device().
1959+ */
1960+ if (dev->product_code == WAVE515_CODE)
1961+ wave5_vdi_free_sram(dev);
1962+
19401963 video_unregister_device(dev->video_dev_dec);
19411964 if (dev->v4l2_m2m_dec_dev)
19421965 v4l2_m2m_release(dev->v4l2_m2m_dec_dev);
drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c+1−1
@@ -1247,7 +1247,7 @@ static int initialize_sequence(struct vpu_instance *inst) · 1246 unmodified lines
12471247 __func__, initial_info.min_frame_buffer_count,
12481248 initial_info.min_src_frame_count);
12491249 inst->min_src_buf_count = initial_info.min_src_frame_count +
1250− COMMAND_QUEUE_DEPTH;
1250+ WAVE521_COMMAND_QUEUE_DEPTH;
12511251
12521252 ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl,
12531253 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT);
drivers/media/platform/chips-media/wave5/wave5-vpu.c+26−9
@@ -10,6 +10,7 @@ · 9 unmodified lines
1010 #include <linux/clk.h>
1111 #include <linux/firmware.h>
1212 #include <linux/interrupt.h>
13+#include <linux/reset.h>
1314 #include "wave5-vpu.h"
1415 #include "wave5-regdefine.h"
1516 #include "wave5-vpuconfig.h"
@@ -24,6 +25,7 @@ · 8 unmodified lines
2425 struct wave5_match_data {
2526 int flags;
2627 const char *fw_name;
28+ u32 sram_size;
2729 };
2830
2931 static int vpu_poll_interval = 5;
@@ -61,7 +63,13 @@ static void wave5_vpu_handle_irq(void *dev_id) · 31 unmodified lines
6163
6264 if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) ||
6365 irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) {
64− if (seq_done & BIT(inst->id)) {
66+ if (dev->product_code == WAVE515_CODE &&
67+ (cmd_done & BIT(inst->id))) {
68+ cmd_done &= ~BIT(inst->id);
69+ wave5_vdi_write_register(dev, W5_RET_QUEUE_CMD_DONE_INST,
70+ cmd_done);
71+ complete(&inst->irq_done);
72+ } else if (seq_done & BIT(inst->id)) {
6573 seq_done &= ~BIT(inst->id);
6674 wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO,
6775 seq_done);
@@ -179,6 +187,16 @@ static int wave5_vpu_probe(struct platform_device *pdev) · 111 unmodified lines
179187 dev_set_drvdata(&pdev->dev, dev);
180188 dev->dev = &pdev->dev;
181189
190+ dev->resets = devm_reset_control_array_get_optional_exclusive(&pdev->dev);
191+ if (IS_ERR(dev->resets)) {
192+ return dev_err_probe(&pdev->dev, PTR_ERR(dev->resets),
193+ "Failed to get reset control\n");
194+ }
195+
196+ ret = reset_control_deassert(dev->resets);
197+ if (ret)
198+ return dev_err_probe(&pdev->dev, ret, "Failed to deassert resets\n");
199+
182200 ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks);
183201
184202 /* continue without clock, assume externally managed */
@@ -191,20 +209,15 @@ static int wave5_vpu_probe(struct platform_device *pdev) · 6 unmodified lines
191209 ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks);
192210 if (ret) {
193211 dev_err(&pdev->dev, "Enabling clocks, fail: %d\n", ret);
194− return ret;
195− }
196−
197− ret = of_property_read_u32(pdev->dev.of_node, "sram-size",
198− &dev->sram_size);
199− if (ret) {
200− dev_warn(&pdev->dev, "sram-size not found\n");
201− dev->sram_size = 0;
212+ goto err_reset_assert;
202213 }
203214
204215 dev->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
205216 if (!dev->sram_pool)
206217 dev_warn(&pdev->dev, "sram node not found\n");
207218
219+ dev->sram_size = match_data->sram_size;
220+
208221 dev->product_code = wave5_vdi_read_register(dev, VPU_PRODUCT_CODE_REGISTER);
209222 ret = wave5_vdi_init(&pdev->dev);
210223 if (ret < 0) {
@@ -282,6 +295,8 @@ err_vdi_release: · 71 unmodified lines
282295 wave5_vdi_release(&pdev->dev);
283296 err_clk_dis:
284297 clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
298+err_reset_assert:
299+ reset_control_assert(dev->resets);
285300
286301 return ret;
287302 }
@@ -297,6 +312,7 @@ static void wave5_vpu_remove(struct platform_device *pdev) · 9 unmodified lines
297312
298313 mutex_destroy(&dev->dev_lock);
299314 mutex_destroy(&dev->hw_lock);
315+ reset_control_assert(dev->resets);
300316 clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
301317 wave5_vpu_enc_unregister_device(dev);
302318 wave5_vpu_dec_unregister_device(dev);
@@ -308,6 +324,7 @@ static void wave5_vpu_remove(struct platform_device *pdev) · 5 unmodified lines
308324 static const struct wave5_match_data ti_wave521c_data = {
309325 .flags = WAVE5_IS_ENC | WAVE5_IS_DEC,
310326 .fw_name = "cnm/wave521c_k3_codec_fw.bin",
327+ .sram_size = (64 * 1024),
311328 };
312329
313330 static const struct of_device_id wave5_dt_ids[] = {
drivers/media/platform/chips-media/wave5/wave5-vpuapi.h+3−0
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818 #include "wave5-vdi.h"
1919
2020 enum product_id {
21+ PRODUCT_ID_515,
2122 PRODUCT_ID_521,
2223 PRODUCT_ID_511,
2324 PRODUCT_ID_517,
@@ -327,6 +328,7 @@ struct vpu_attr { · 303 unmodified lines
327328 u32 support_backbone: 1;
328329 u32 support_avc10bit_enc: 1;
329330 u32 support_hevc10bit_enc: 1;
331+ u32 support_hevc10bit_dec: 1;
330332 u32 support_vcore_backbone: 1;
331333 u32 support_vcpu_backbone: 1;
332334 };
@@ -761,6 +763,7 @@ struct vpu_device { · 428 unmodified lines
761763 struct kthread_worker *worker;
762764 int vpu_poll_interval;
763765 int num_clks;
766+ struct reset_control *resets;
764767 };
765768
766769 struct vpu_instance;
drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h+11−5
@@ -8,6 +8,7 @@ · 7 unmodified lines
88 #ifndef _VPU_CONFIG_H_
99 #define _VPU_CONFIG_H_
1010
11+#define WAVE515_CODE 0x5150
1112 #define WAVE517_CODE 0x5170
1213 #define WAVE537_CODE 0x5370
1314 #define WAVE511_CODE 0x5110
@@ -21,12 +22,13 @@ · 7 unmodified lines
2122 ((c) == WAVE517_CODE || (c) == WAVE537_CODE || \
2223 (c) == WAVE511_CODE || (c) == WAVE521_CODE || \
2324 (c) == WAVE521E1_CODE || (c) == WAVE521C_CODE || \
24− (c) == WAVE521C_DUAL_CODE); \
25+ (c) == WAVE521C_DUAL_CODE) || (c) == WAVE515_CODE; \
2526 })
2627
2728 #define WAVE517_WORKBUF_SIZE (2 * 1024 * 1024)
2829 #define WAVE521ENC_WORKBUF_SIZE (128 * 1024) //HEVC 128K, AVC 40K
2930 #define WAVE521DEC_WORKBUF_SIZE (1784 * 1024)
31+#define WAVE515DEC_WORKBUF_SIZE (2 * 1024 * 1024)
3032
3133 #define MAX_NUM_INSTANCE 32
3234
@@ -49,17 +51,21 @@ · 16 unmodified lines
4951 /************************************************************************/
5052 #define VLC_BUF_NUM (2)
5153
52−#define COMMAND_QUEUE_DEPTH (2)
54+#define WAVE521_COMMAND_QUEUE_DEPTH (2)
55+#define WAVE515_COMMAND_QUEUE_DEPTH (4)
5356
5457 #define W5_REMAP_INDEX0 0
5558 #define W5_REMAP_INDEX1 1
5659 #define W5_REMAP_MAX_SIZE (1024 * 1024)
5760
58−#define WAVE5_MAX_CODE_BUF_SIZE (2 * 1024 * 1024)
59−#define WAVE5_TEMPBUF_OFFSET WAVE5_MAX_CODE_BUF_SIZE
61+#define WAVE521_MAX_CODE_BUF_SIZE (2 * 1024 * 1024)
62+#define WAVE515_MAX_CODE_BUF_SIZE (1024 * 1024)
6063 #define WAVE5_TEMPBUF_SIZE (1024 * 1024)
6164
62−#define SIZE_COMMON (WAVE5_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE)
65+#define WAVE521_SIZE_COMMON (WAVE521_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE)
66+#define WAVE515_ONE_TASKBUF_SIZE (8 * 1024 * 1024)
67+#define WAVE515_SIZE_COMMON (WAVE515_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE + \
68+ WAVE515_COMMAND_QUEUE_DEPTH * WAVE515_ONE_TASKBUF_SIZE)
6369
6470 //=====4. VPU REPORT MEMORY ======================//
6571
drivers/media/platform/chips-media/wave5/wave5.h+6−0
@@ -22,6 +22,12 @@ · 21 unmodified lines
2222 */
2323 #define BSOPTION_ENABLE_EXPLICIT_END BIT(0)
2424 #define BSOPTION_HIGHLIGHT_STREAM_END BIT(1)
25+/*
26+ * When RD_PTR_VALID_FLAG is 0 Wave515 ignores RD_PTR value and starts to
27+ * decode from the access unit end position of the last decoded picture in
28+ * bitstream buffer.
29+ */
30+#define BSOPTION_RD_PTR_VALID_FLAG BIT(31)
2531
2632 /*
2733 * Currently the driver only supports hardware with little endian but for source
drivers/media/platform/imagination/Kconfig+13−0
@@ -0,0 +1,13 @@
1+# SPDX-License-Identifier: GPL-2.0
2+config VIDEO_E5010_JPEG_ENC
3+ tristate "Imagination E5010 JPEG Encoder Driver"
4+ depends on VIDEO_DEV
5+ select VIDEOBUF2_DMA_CONTIG
6+ select VIDEOBUF2_VMALLOC
7+ select V4L2_MEM2MEM_DEV
8+ select V4L2_JPEG_HELPER
9+ help
10+ This is a video4linux2 M2M driver for Imagination E5010 JPEG encoder,
11+ which supports JPEG and MJPEG baseline encoding of YUV422 and YUV420
12+ semiplanar video formats, with resolution ranging from 64x64 to 8K x 8K
13+ pixels. The module will be named as e5010_jpeg_enc.
drivers/media/platform/imagination/Makefile+3−0
@@ -0,0 +1,3 @@
1+# SPDX-License-Identifier: GPL-2.0
2+e5010_jpeg_enc-objs := e5010-jpeg-enc-hw.o e5010-jpeg-enc.o
3+obj-$(CONFIG_VIDEO_E5010_JPEG_ENC) += e5010_jpeg_enc.o
drivers/media/platform/imagination/e5010-core-regs.h+585−0
@@ -0,0 +1,585 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * Imagination E5010 JPEG Encoder driver.
4+ *
5+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
6+ *
7+ * Author: David Huang <d-huang@ti.com>
8+ * Author: Devarsh Thakkar <devarsht@ti.com>
9+ */
10+
11+#ifndef _E5010_CORE_REGS_H
12+#define _E5010_CORE_REGS_H
13+
14+#define JASPER_CORE_ID_OFFSET (0x0000)
15+#define JASPER_CORE_ID_CR_GROUP_ID_MASK (0xFF000000)
16+#define JASPER_CORE_ID_CR_GROUP_ID_SHIFT (24)
17+#define JASPER_CORE_ID_CR_CORE_ID_MASK (0x00FF0000)
18+#define JASPER_CORE_ID_CR_CORE_ID_SHIFT (16)
19+#define JASPER_CORE_ID_CR_UNIQUE_NUM_MASK (0x0000FFF8)
20+#define JASPER_CORE_ID_CR_UNIQUE_NUM_SHIFT (3)
21+#define JASPER_CORE_ID_CR_PELS_PER_CYCLE_MASK (0x00000007)
22+#define JASPER_CORE_ID_CR_PELS_PER_CYCLE_SHIFT (0)
23+
24+#define JASPER_CORE_REV_OFFSET (0x0004)
25+#define JASPER_CORE_REV_CR_JASPER_DESIGNER_MASK (0xFF000000)
26+#define JASPER_CORE_REV_CR_JASPER_DESIGNER_SHIFT (24)
27+#define JASPER_CORE_REV_CR_JASPER_MAJOR_REV_MASK (0x00FF0000)
28+#define JASPER_CORE_REV_CR_JASPER_MAJOR_REV_SHIFT (16)
29+#define JASPER_CORE_REV_CR_JASPER_MINOR_REV_MASK (0x0000FF00)
30+#define JASPER_CORE_REV_CR_JASPER_MINOR_REV_SHIFT (8)
31+#define JASPER_CORE_REV_CR_JASPER_MAINT_REV_MASK (0x000000FF)
32+#define JASPER_CORE_REV_CR_JASPER_MAINT_REV_SHIFT (0)
33+
34+#define JASPER_INTERRUPT_MASK_OFFSET (0x0008)
35+#define JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_MASK (0x00000002)
36+#define JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_SHIFT (1)
37+#define JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_MASK (0x00000001)
38+#define JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_SHIFT (0)
39+
40+#define JASPER_INTERRUPT_STATUS_OFFSET (0x000C)
41+#define JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK (0x00000002)
42+#define JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_SHIFT (1)
43+#define JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK (0x00000001)
44+#define JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_SHIFT (0)
45+
46+#define JASPER_INTERRUPT_CLEAR_OFFSET (0x0010)
47+#define JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_MASK (0x00000002)
48+#define JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_SHIFT (1)
49+#define JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_MASK (0x00000001)
50+#define JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_SHIFT (0)
51+
52+#define JASPER_CLK_CONTROL_OFFSET (0x0014)
53+#define JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_MASK (0x00000002)
54+#define JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_SHIFT (1)
55+#define JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_MASK (0x00000001)
56+#define JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_SHIFT (0)
57+
58+#define JASPER_CLK_STATUS_OFFSET (0x0018)
59+#define JASPER_CLK_STATUS_CR_JASPER_CLKG_STATUS_MASK (0x00000001)
60+#define JASPER_CLK_STATUS_CR_JASPER_CLKG_STATUS_SHIFT (0)
61+
62+#define JASPER_RESET_OFFSET (0x001C)
63+#define JASPER_RESET_CR_SYS_RESET_MASK (0x00000002)
64+#define JASPER_RESET_CR_SYS_RESET_SHIFT (1)
65+#define JASPER_RESET_CR_CORE_RESET_MASK (0x00000001)
66+#define JASPER_RESET_CR_CORE_RESET_SHIFT (0)
67+
68+#define JASPER_CORE_CTRL_OFFSET (0x0020)
69+#define JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_MASK (0x00000001)
70+#define JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_SHIFT (0)
71+
72+#define JASPER_STATUS_OFFSET (0x0024)
73+#define JASPER_STATUS_CR_FLUSH_MODE_MASK (0x00000002)
74+#define JASPER_STATUS_CR_FLUSH_MODE_SHIFT (1)
75+#define JASPER_STATUS_CR_JASPER_BUSY_MASK (0x00000001)
76+#define JASPER_STATUS_CR_JASPER_BUSY_SHIFT (0)
77+
78+#define JASPER_CRC_CLEAR_OFFSET (0x0028)
79+#define JASPER_CRC_CLEAR_CR_FRONT_END_CRC_CLEAR_MASK (0x00000001)
80+#define JASPER_CRC_CLEAR_CR_FRONT_END_CRC_CLEAR_SHIFT (0)
81+#define JASPER_CRC_CLEAR_CR_DCT_CRC_CLEAR_MASK (0x00000002)
82+#define JASPER_CRC_CLEAR_CR_DCT_CRC_CLEAR_SHIFT (1)
83+#define JASPER_CRC_CLEAR_CR_ZZ_CRC_CLEAR_MASK (0x00000004)
84+#define JASPER_CRC_CLEAR_CR_ZZ_CRC_CLEAR_SHIFT (2)
85+#define JASPER_CRC_CLEAR_CR_QUANT_CRC_CLEAR_MASK (0x00000008)
86+#define JASPER_CRC_CLEAR_CR_QUANT_CRC_CLEAR_SHIFT (3)
87+#define JASPER_CRC_CLEAR_CR_ENTROPY_ENCODER_CRC_CLEAR_MASK (0x00000010)
88+#define JASPER_CRC_CLEAR_CR_ENTROPY_ENCODER_CRC_CLEAR_SHIFT (4)
89+#define JASPER_CRC_CLEAR_CR_PACKING_BUFFER_CRC_CLEAR_MASK (0x00000020)
90+#define JASPER_CRC_CLEAR_CR_PACKING_BUFFER_CRC_CLEAR_SHIFT (5)
91+
92+#define JASPER_INPUT_CTRL0_OFFSET (0x002C)
93+#define JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_MASK (0x01000000)
94+#define JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_SHIFT (24)
95+#define JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_MASK (0x00030000)
96+#define JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_SHIFT (16)
97+#define JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_MASK (0x00000004)
98+#define JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_SHIFT (2)
99+
100+#define JASPER_INPUT_CTRL1_OFFSET (0x0030)
101+#define JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_MASK (0x1FC00000)
102+#define JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_SHIFT (22)
103+#define JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_MASK (0x00001FC0)
104+#define JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_SHIFT (6)
105+
106+#define JASPER_MMU_CTRL_OFFSET (0x0034)
107+#define JASPER_MMU_CTRL_CR_JASPER_TILING_SCHEME_MASK (0x00000002)
108+#define JASPER_MMU_CTRL_CR_JASPER_TILING_SCHEME_SHIFT (1)
109+#define JASPER_MMU_CTRL_CR_JASPER_TILING_ENABLE_MASK (0x00000001)
110+#define JASPER_MMU_CTRL_CR_JASPER_TILING_ENABLE_SHIFT (0)
111+
112+#define JASPER_IMAGE_SIZE_OFFSET (0x0038)
113+#define JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_MASK (0x1FFF0000)
114+#define JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_SHIFT (16)
115+#define JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_MASK (0x00001FFF)
116+#define JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_SHIFT (0)
117+
118+#define INPUT_LUMA_BASE_OFFSET (0x003C)
119+#define INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_MASK (0xFFFFFFC0)
120+#define INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_SHIFT (6)
121+
122+#define INPUT_CHROMA_BASE_OFFSET (0x0040)
123+#define INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_MASK (0xFFFFFFC0)
124+#define INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_SHIFT (6)
125+
126+#define JASPER_OUTPUT_BASE_OFFSET (0x0044)
127+#define JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_MASK (0xFFFFFFFF)
128+#define JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_SHIFT (0)
129+
130+#define JASPER_OUTPUT_SIZE_OFFSET (0x0048)
131+#define JASPER_OUTPUT_SIZE_CR_OUTPUT_SIZE_MASK (0xFFFFFFFF)
132+#define JASPER_OUTPUT_SIZE_CR_OUTPUT_SIZE_SHIFT (0)
133+#define JASPER_OUTPUT_MAX_SIZE_OFFSET (0x004C)
134+#define JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_MASK (0xFFFFFFFF)
135+#define JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_SHIFT (0)
136+
137+#define JASPER_LUMA_QUANTIZATION_TABLE0_OFFSET (0x0050)
138+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_03_MASK (0xFF000000)
139+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_03_SHIFT (24)
140+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_02_MASK (0x00FF0000)
141+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_02_SHIFT (16)
142+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_01_MASK (0x0000FF00)
143+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_01_SHIFT (8)
144+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_00_MASK (0x000000FF)
145+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_00_SHIFT (0)
146+#define JASPER_LUMA_QUANTIZATION_TABLE1_OFFSET (0x0054)
147+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_07_MASK (0xFF000000)
148+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_07_SHIFT (24)
149+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_06_MASK (0x00FF0000)
150+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_06_SHIFT (16)
151+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_05_MASK (0x0000FF00)
152+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_05_SHIFT (8)
153+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_04_MASK (0x000000FF)
154+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_04_SHIFT (0)
155+#define JASPER_LUMA_QUANTIZATION_TABLE2_OFFSET (0x0058)
156+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_13_MASK (0xFF000000)
157+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_13_SHIFT (24)
158+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_12_MASK (0x00FF0000)
159+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_12_SHIFT (16)
160+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_11_MASK (0x0000FF00)
161+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_11_SHIFT (8)
162+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_10_MASK (0x000000FF)
163+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_10_SHIFT (0)
164+#define JASPER_LUMA_QUANTIZATION_TABLE3_OFFSET (0x005C)
165+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_17_MASK (0xFF000000)
166+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_17_SHIFT (24)
167+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_16_MASK (0x00FF0000)
168+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_16_SHIFT (16)
169+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_15_MASK (0x0000FF00)
170+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_15_SHIFT (8)
171+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_14_MASK (0x000000FF)
172+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_14_SHIFT (0)
173+#define JASPER_LUMA_QUANTIZATION_TABLE4_OFFSET (0x0060)
174+#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_21_MASK (0x0000FF00)
175+#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_21_SHIFT (8)
176+#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_20_MASK (0x000000FF)
177+#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_20_SHIFT (0)
178+
179+#define JASPER_LUMA_QUANTIZATION_TABLE5_OFFSET (0x0064)
180+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_27_MASK (0xFF000000)
181+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_27_SHIFT (24)
182+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_26_MASK (0x00FF0000)
183+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_26_SHIFT (16)
184+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_25_MASK (0x0000FF00)
185+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_25_SHIFT (8)
186+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_24_MASK (0x000000FF)
187+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_24_SHIFT (0)
188+
189+#define JASPER_LUMA_QUANTIZATION_TABLE6_OFFSET (0x0068)
190+
191+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_33_MASK (0xFF000000)
192+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_33_SHIFT (24)
193+
194+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_32_MASK (0x00FF0000)
195+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_32_SHIFT (16)
196+
197+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_31_MASK (0x0000FF00)
198+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_31_SHIFT (8)
199+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_30_MASK (0x000000FF)
200+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_30_SHIFT (0)
201+
202+#define JASPER_LUMA_QUANTIZATION_TABLE7_OFFSET (0x006C)
203+
204+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_37_MASK (0xFF000000)
205+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_37_SHIFT (24)
206+
207+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_36_MASK (0x00FF0000)
208+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_36_SHIFT (16)
209+
210+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_35_MASK (0x0000FF00)
211+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_35_SHIFT (8)
212+
213+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_34_MASK (0x000000FF)
214+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_34_SHIFT (0)
215+
216+#define JASPER_LUMA_QUANTIZATION_TABLE8_OFFSET (0x0070)
217+
218+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_43_MASK (0xFF000000)
219+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_43_SHIFT (24)
220+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_42_MASK (0x00FF0000)
221+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_42_SHIFT (16)
222+
223+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_41_MASK (0x0000FF00)
224+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_41_SHIFT (8)
225+
226+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_40_MASK (0x000000FF)
227+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_40_SHIFT (0)
228+
229+#define JASPER_LUMA_QUANTIZATION_TABLE9_OFFSET (0x0074)
230+
231+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_47_MASK (0xFF000000)
232+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_47_SHIFT (24)
233+
234+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_46_MASK (0x00FF0000)
235+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_46_SHIFT (16)
236+
237+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_45_MASK (0x0000FF00)
238+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_45_SHIFT (8)
239+
240+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_44_MASK (0x000000FF)
241+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_44_SHIFT (0)
242+
243+#define JASPER_LUMA_QUANTIZATION_TABLE10_OFFSET (0x0078)
244+
245+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_53_MASK (0xFF000000)
246+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_53_SHIFT (24)
247+
248+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_52_MASK (0x00FF0000)
249+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_52_SHIFT (16)
250+
251+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_51_MASK (0x0000FF00)
252+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_51_SHIFT (8)
253+
254+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_50_MASK (0x000000FF)
255+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_50_SHIFT (0)
256+
257+#define JASPER_LUMA_QUANTIZATION_TABLE11_OFFSET (0x007C)
258+
259+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_57_MASK (0xFF000000)
260+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_57_SHIFT (24)
261+
262+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_56_MASK (0x00FF0000)
263+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_56_SHIFT (16)
264+
265+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_55_MASK (0x0000FF00)
266+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_55_SHIFT (8)
267+
268+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_54_MASK (0x000000FF)
269+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_54_SHIFT (0)
270+
271+#define JASPER_LUMA_QUANTIZATION_TABLE12_OFFSET (0x0080)
272+
273+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_63_MASK (0xFF000000)
274+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_63_SHIFT (24)
275+
276+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_62_MASK (0x00FF0000)
277+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_62_SHIFT (16)
278+
279+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_61_MASK (0x0000FF00)
280+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_61_SHIFT (8)
281+
282+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_60_MASK (0x000000FF)
283+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_60_SHIFT (0)
284+
285+#define JASPER_LUMA_QUANTIZATION_TABLE13_OFFSET (0x0084)
286+
287+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_67_MASK (0xFF000000)
288+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_67_SHIFT (24)
289+
290+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_66_MASK (0x00FF0000)
291+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_66_SHIFT (16)
292+
293+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_65_MASK (0x0000FF00)
294+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_65_SHIFT (8)
295+
296+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_64_MASK (0x000000FF)
297+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_64_SHIFT (0)
298+
299+#define JASPER_LUMA_QUANTIZATION_TABLE14_OFFSET (0x0088)
300+
301+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_73_MASK (0xFF000000)
302+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_73_SHIFT (24)
303+
304+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_72_MASK (0x00FF0000)
305+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_72_SHIFT (16)
306+
307+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_71_MASK (0x0000FF00)
308+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_71_SHIFT (8)
309+
310+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_70_MASK (0x000000FF)
311+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_70_SHIFT (0)
312+
313+#define JASPER_LUMA_QUANTIZATION_TABLE15_OFFSET (0x008C)
314+
315+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_77_MASK (0xFF000000)
316+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_77_SHIFT (24)
317+
318+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_76_MASK (0x00FF0000)
319+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_76_SHIFT (16)
320+
321+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_75_MASK (0x0000FF00)
322+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_75_SHIFT (8)
323+
324+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_74_MASK (0x000000FF)
325+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_74_SHIFT (0)
326+
327+#define JASPER_CHROMA_QUANTIZATION_TABLE0_OFFSET (0x0090)
328+
329+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_03_MASK (0xFF000000)
330+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_03_SHIFT (24)
331+
332+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_02_MASK (0x00FF0000)
333+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_02_SHIFT (16)
334+
335+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_01_MASK (0x0000FF00)
336+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_01_SHIFT (8)
337+
338+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_00_MASK (0x000000FF)
339+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_00_SHIFT (0)
340+
341+#define JASPER_CHROMA_QUANTIZATION_TABLE1_OFFSET (0x0094)
342+
343+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_07_MASK (0xFF000000)
344+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_07_SHIFT (24)
345+
346+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_06_MASK (0x00FF0000)
347+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_06_SHIFT (16)
348+
349+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_05_MASK (0x0000FF00)
350+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_05_SHIFT (8)
351+
352+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_04_MASK (0x000000FF)
353+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_04_SHIFT (0)
354+
355+#define JASPER_CHROMA_QUANTIZATION_TABLE2_OFFSET (0x0098)
356+
357+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_13_MASK (0xFF000000)
358+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_13_SHIFT (24)
359+
360+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_12_MASK (0x00FF0000)
361+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_12_SHIFT (16)
362+
363+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_11_MASK (0x0000FF00)
364+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_11_SHIFT (8)
365+
366+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_10_MASK (0x000000FF)
367+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_10_SHIFT (0)
368+
369+#define JASPER_CHROMA_QUANTIZATION_TABLE3_OFFSET (0x009C)
370+
371+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_17_MASK (0xFF000000)
372+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_17_SHIFT (24)
373+
374+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_16_MASK (0x00FF0000)
375+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_16_SHIFT (16)
376+
377+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_15_MASK (0x0000FF00)
378+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_15_SHIFT (8)
379+
380+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_14_MASK (0x000000FF)
381+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_14_SHIFT (0)
382+
383+#define JASPER_CHROMA_QUANTIZATION_TABLE4_OFFSET (0x00A0)
384+
385+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_23_MASK (0xFF000000)
386+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_23_SHIFT (24)
387+
388+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_22_MASK (0x00FF0000)
389+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_22_SHIFT (16)
390+
391+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_21_MASK (0x0000FF00)
392+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_21_SHIFT (8)
393+
394+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_20_MASK (0x000000FF)
395+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_20_SHIFT (0)
396+
397+#define JASPER_CHROMA_QUANTIZATION_TABLE5_OFFSET (0x00A4)
398+
399+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_27_MASK (0xFF000000)
400+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_27_SHIFT (24)
401+
402+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_26_MASK (0x00FF0000)
403+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_26_SHIFT (16)
404+
405+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_25_MASK (0x0000FF00)
406+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_25_SHIFT (8)
407+
408+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_24_MASK (0x000000FF)
409+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_24_SHIFT (0)
410+
411+#define JASPER_CHROMA_QUANTIZATION_TABLE6_OFFSET (0x00A8)
412+
413+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_33_MASK (0xFF000000)
414+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_33_SHIFT (24)
415+
416+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_32_MASK (0x00FF0000)
417+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_32_SHIFT (16)
418+
419+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_31_MASK (0x0000FF00)
420+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_31_SHIFT (8)
421+
422+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_30_MASK (0x000000FF)
423+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_30_SHIFT (0)
424+
425+#define JASPER_CHROMA_QUANTIZATION_TABLE7_OFFSET (0x00AC)
426+
427+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_37_MASK (0xFF000000)
428+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_37_SHIFT (24)
429+
430+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_36_MASK (0x00FF0000)
431+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_36_SHIFT (16)
432+
433+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_35_MASK (0x0000FF00)
434+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_35_SHIFT (8)
435+
436+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_34_MASK (0x000000FF)
437+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_34_SHIFT (0)
438+
439+#define JASPER_CHROMA_QUANTIZATION_TABLE8_OFFSET (0x00B0)
440+
441+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_43_MASK (0xFF000000)
442+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_43_SHIFT (24)
443+
444+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_42_MASK (0x00FF0000)
445+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_42_SHIFT (16)
446+
447+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_41_MASK (0x0000FF00)
448+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_41_SHIFT (8)
449+
450+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_40_MASK (0x000000FF)
451+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_40_SHIFT (0)
452+
453+#define JASPER_CHROMA_QUANTIZATION_TABLE9_OFFSET (0x00B4)
454+
455+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_47_MASK (0xFF000000)
456+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_47_SHIFT (24)
457+
458+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_46_MASK (0x00FF0000)
459+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_46_SHIFT (16)
460+
461+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_45_MASK (0x0000FF00)
462+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_45_SHIFT (8)
463+
464+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_44_MASK (0x000000FF)
465+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_44_SHIFT (0)
466+
467+#define JASPER_CHROMA_QUANTIZATION_TABLE10_OFFSET (0x00B8)
468+
469+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_53_MASK (0xFF000000)
470+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_53_SHIFT (24)
471+
472+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_52_MASK (0x00FF0000)
473+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_52_SHIFT (16)
474+
475+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_51_MASK (0x0000FF00)
476+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_51_SHIFT (8)
477+
478+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_50_MASK (0x000000FF)
479+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_50_SHIFT (0)
480+
481+#define JASPER_CHROMA_QUANTIZATION_TABLE11_OFFSET (0x00BC)
482+
483+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_57_MASK (0xFF000000)
484+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_57_SHIFT (24)
485+
486+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_56_MASK (0x00FF0000)
487+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_56_SHIFT (16)
488+
489+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_55_MASK (0x0000FF00)
490+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_55_SHIFT (8)
491+
492+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_54_MASK (0x000000FF)
493+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_54_SHIFT (0)
494+
495+#define JASPER_CHROMA_QUANTIZATION_TABLE12_OFFSET (0x00C0)
496+
497+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_63_MASK (0xFF000000)
498+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_63_SHIFT (24)
499+
500+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_62_MASK (0x00FF0000)
501+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_62_SHIFT (16)
502+
503+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_61_MASK (0x0000FF00)
504+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_61_SHIFT (8)
505+
506+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_60_MASK (0x000000FF)
507+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_60_SHIFT (0)
508+
509+#define JASPER_CHROMA_QUANTIZATION_TABLE13_OFFSET (0x00C4)
510+
511+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_67_MASK (0xFF000000)
512+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_67_SHIFT (24)
513+
514+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_66_MASK (0x00FF0000)
515+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_66_SHIFT (16)
516+
517+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_65_MASK (0x0000FF00)
518+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_65_SHIFT (8)
519+
520+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_64_MASK (0x000000FF)
521+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_64_SHIFT (0)
522+
523+#define JASPER_CHROMA_QUANTIZATION_TABLE14_OFFSET (0x00C8)
524+
525+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_73_MASK (0xFF000000)
526+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_73_SHIFT (24)
527+
528+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_72_MASK (0x00FF0000)
529+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_72_SHIFT (16)
530+
531+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_71_MASK (0x0000FF00)
532+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_71_SHIFT (8)
533+
534+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_70_MASK (0x000000FF)
535+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_70_SHIFT (0)
536+
537+#define JASPER_CHROMA_QUANTIZATION_TABLE15_OFFSET (0x00CC)
538+
539+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_77_MASK (0xFF000000)
540+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_77_SHIFT (24)
541+
542+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_76_MASK (0x00FF0000)
543+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_76_SHIFT (16)
544+
545+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_75_MASK (0x0000FF00)
546+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_75_SHIFT (8)
547+
548+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_74_MASK (0x000000FF)
549+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_74_SHIFT (0)
550+
551+#define JASPER_CRC_CTRL_OFFSET (0x00D0)
552+#define JASPER_CRC_CTRL_JASPER_CRC_ENABLE_MASK (0x00000001)
553+#define JASPER_CRC_CTRL_JASPER_CRC_ENABLE_SHIFT (0)
554+
555+#define JASPER_FRONT_END_CRC_OFFSET (0x00D4)
556+#define JASPER_FRONT_END_CRC_CR_JASPER_FRONT_END_CRC_OUT_MASK (0xFFFFFFFF)
557+#define JASPER_FRONT_END_CRC_CR_JASPER_FRONT_END_CRC_OUT_SHIFT (0)
558+
559+#define JASPER_DCT_CRC_OFFSET (0x00D8)
560+#define JASPER_DCT_CRC_CR_JASPER_DCT_CRC_OUT_MASK (0xFFFFFFFF)
561+#define JASPER_DCT_CRC_CR_JASPER_DCT_CRC_OUT_SHIFT (0)
562+
563+#define JASPER_ZZ_CRC_OFFSET (0x00DC)
564+#define JASPER_ZZ_CRC_CR_JASPER_ZZ_CRC_OUT_MASK (0xFFFFFFFF)
565+#define JASPER_ZZ_CRC_CR_JASPER_ZZ_CRC_OUT_SHIFT (0)
566+
567+#define JASPER_QUANT_CRC_OFFSET (0x00E0)
568+#define JASPER_QUANT_CRC_CR_JASPER_QUANT_CRC_OUT_MASK (0xFFFFFFFF)
569+#define JASPER_QUANT_CRC_CR_JASPER_QUANT_CRC_OUT_SHIFT (0)
570+
571+#define JASPER_ENTROPY_ENCODER_CRC_OFFSET (0x00E4)
572+#define JASPER_ENTROPY_ENCODER_CRC_CR_JASPER_ENTROPY_CRC_OUT_MASK (0xFFFFFFFF)
573+#define JASPER_ENTROPY_ENCODER_CRC_CR_JASPER_ENTROPY_CRC_OUT_SHIFT (0)
574+
575+#define JASPER_PACKING_BUFFER_DATA_CRC_OFFSET (0x00E8)
576+#define JASPER_PACKING_BUFFER_DATA_CRC_CR_JASPER_PACKING_DATA_CRC_OUT_MASK (0xFFFFFFFF)
577+#define JASPER_PACKING_BUFFER_DATA_CRC_CR_JASPER_PACKING_DATA_CRC_OUT_SHIFT (0)
578+
579+#define JASPER_PACKING_BUFFER_ADDR_CRC_OFFSET (0x00EC)
580+#define JASPER_PACKING_BUFFER_ADDR_CRC_CR_JASPER_PACKING_ADDR_OUT_CRC_MASK (0xFFFFFFFF)
581+#define JASPER_PACKING_BUFFER_ADDR_CRC_CR_JASPER_PACKING_ADDR_OUT_CRC_SHIFT (0)
582+
583+#define JASPER_CORE_BYTE_SIZE (0x00F0)
584+
585+#endif
drivers/media/platform/imagination/e5010-jpeg-enc-hw.c+267−0
@@ -0,0 +1,267 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Imagination E5010 JPEG Encoder driver.
4+ *
5+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
6+ *
7+ * Author: David Huang <d-huang@ti.com>
8+ * Author: Devarsh Thakkar <devarsht@ti.com>
9+ */
10+
11+#include <linux/io.h>
12+#include <linux/iopoll.h>
13+#include <linux/dev_printk.h>
14+#include "e5010-jpeg-enc-hw.h"
15+
16+static void write_reg_field(void __iomem *base, unsigned int offset, u32 mask,
17+ unsigned int shift, u32 value)
18+{
19+ u32 reg;
20+
21+ value <<= shift;
22+ if (mask != 0xffffffff) {
23+ reg = readl(base + offset);
24+ value = (value & mask) | (reg & ~mask);
25+ }
26+ writel(value, (base + offset));
27+}
28+
29+static int write_reg_field_not_busy(void __iomem *jasper_base, void __iomem *wr_base,
30+ unsigned int offset, u32 mask, unsigned int shift,
31+ u32 value)
32+{
33+ int ret;
34+ u32 val;
35+
36+ ret = readl_poll_timeout_atomic(jasper_base + JASPER_STATUS_OFFSET, val,
37+ (val & JASPER_STATUS_CR_JASPER_BUSY_MASK) == 0,
38+ 2000, 50000);
39+ if (ret)
40+ return ret;
41+
42+ write_reg_field(wr_base, offset, mask, shift, value);
43+
44+ return 0;
45+}
46+
47+void e5010_reset(struct device *dev, void __iomem *core_base, void __iomem *mmu_base)
48+{
49+ int ret = 0;
50+ u32 val;
51+
52+ write_reg_field(core_base, JASPER_RESET_OFFSET,
53+ JASPER_RESET_CR_CORE_RESET_MASK,
54+ JASPER_RESET_CR_CORE_RESET_SHIFT, 1);
55+
56+ write_reg_field(mmu_base, MMU_MMU_CONTROL1_OFFSET,
57+ MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK,
58+ MMU_MMU_CONTROL1_MMU_SOFT_RESET_SHIFT, 1);
59+
60+ ret = readl_poll_timeout_atomic(mmu_base + MMU_MMU_CONTROL1_OFFSET, val,
61+ (val & MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK) == 0,
62+ 2000, 50000);
63+ if (ret)
64+ dev_warn(dev, "MMU soft reset timed out, forcing system soft reset\n");
65+
66+ write_reg_field(core_base, JASPER_RESET_OFFSET,
67+ JASPER_RESET_CR_SYS_RESET_MASK,
68+ JASPER_RESET_CR_SYS_RESET_SHIFT, 1);
69+}
70+
71+void e5010_hw_bypass_mmu(void __iomem *mmu_base, u32 enable)
72+{
73+ /* Bypass MMU */
74+ write_reg_field(mmu_base,
75+ MMU_MMU_ADDRESS_CONTROL_OFFSET,
76+ MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_MASK,
77+ MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_SHIFT,
78+ enable);
79+}
80+
81+int e5010_hw_enable_output_address_error_irq(void __iomem *core_base, u32 enable)
82+{
83+ return write_reg_field_not_busy(core_base, core_base,
84+ JASPER_INTERRUPT_MASK_OFFSET,
85+ JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_MASK,
86+ JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_SHIFT,
87+ enable);
88+}
89+
90+bool e5010_hw_pic_done_irq(void __iomem *core_base)
91+{
92+ u32 reg;
93+
94+ reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET);
95+ return reg & JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK;
96+}
97+
98+bool e5010_hw_output_address_irq(void __iomem *core_base)
99+{
100+ u32 reg;
101+
102+ reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET);
103+ return reg & JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK;
104+}
105+
106+int e5010_hw_enable_picture_done_irq(void __iomem *core_base, u32 enable)
107+{
108+ return write_reg_field_not_busy(core_base, core_base,
109+ JASPER_INTERRUPT_MASK_OFFSET,
110+ JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_MASK,
111+ JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_SHIFT,
112+ enable);
113+}
114+
115+int e5010_hw_enable_auto_clock_gating(void __iomem *core_base, u32 enable)
116+{
117+ return write_reg_field_not_busy(core_base, core_base,
118+ JASPER_CLK_CONTROL_OFFSET,
119+ JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_MASK,
120+ JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_SHIFT,
121+ enable);
122+}
123+
124+int e5010_hw_enable_manual_clock_gating(void __iomem *core_base, u32 enable)
125+{
126+ return write_reg_field_not_busy(core_base, core_base,
127+ JASPER_CLK_CONTROL_OFFSET,
128+ JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_MASK,
129+ JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_SHIFT, 0);
130+}
131+
132+int e5010_hw_enable_crc_check(void __iomem *core_base, u32 enable)
133+{
134+ return write_reg_field_not_busy(core_base, core_base,
135+ JASPER_CRC_CTRL_OFFSET,
136+ JASPER_CRC_CTRL_JASPER_CRC_ENABLE_MASK,
137+ JASPER_CRC_CTRL_JASPER_CRC_ENABLE_SHIFT, enable);
138+}
139+
140+int e5010_hw_set_input_source_to_memory(void __iomem *core_base, u32 set)
141+{
142+ return write_reg_field_not_busy(core_base, core_base,
143+ JASPER_INPUT_CTRL0_OFFSET,
144+ JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_MASK,
145+ JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_SHIFT, set);
146+}
147+
148+int e5010_hw_set_input_luma_addr(void __iomem *core_base, u32 val)
149+{
150+ return write_reg_field_not_busy(core_base, core_base,
151+ INPUT_LUMA_BASE_OFFSET,
152+ INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_MASK, 0, val);
153+}
154+
155+int e5010_hw_set_input_chroma_addr(void __iomem *core_base, u32 val)
156+{
157+ return write_reg_field_not_busy(core_base, core_base,
158+ INPUT_CHROMA_BASE_OFFSET,
159+ INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_MASK, 0, val);
160+}
161+
162+int e5010_hw_set_output_base_addr(void __iomem *core_base, u32 val)
163+{
164+ return write_reg_field_not_busy(core_base, core_base,
165+ JASPER_OUTPUT_BASE_OFFSET,
166+ JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_MASK,
167+ JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_SHIFT, val);
168+}
169+
170+int e5010_hw_set_horizontal_size(void __iomem *core_base, u32 val)
171+{
172+ return write_reg_field_not_busy(core_base, core_base,
173+ JASPER_IMAGE_SIZE_OFFSET,
174+ JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_MASK,
175+ JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_SHIFT,
176+ val);
177+}
178+
179+int e5010_hw_set_vertical_size(void __iomem *core_base, u32 val)
180+{
181+ return write_reg_field_not_busy(core_base, core_base,
182+ JASPER_IMAGE_SIZE_OFFSET,
183+ JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_MASK,
184+ JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_SHIFT,
185+ val);
186+}
187+
188+int e5010_hw_set_luma_stride(void __iomem *core_base, u32 bytesperline)
189+{
190+ u32 val = bytesperline / 64;
191+
192+ return write_reg_field_not_busy(core_base, core_base,
193+ JASPER_INPUT_CTRL1_OFFSET,
194+ JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_MASK,
195+ JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_SHIFT,
196+ val);
197+}
198+
199+int e5010_hw_set_chroma_stride(void __iomem *core_base, u32 bytesperline)
200+{
201+ u32 val = bytesperline / 64;
202+
203+ return write_reg_field_not_busy(core_base, core_base,
204+ JASPER_INPUT_CTRL1_OFFSET,
205+ JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_MASK,
206+ JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_SHIFT,
207+ val);
208+}
209+
210+int e5010_hw_set_input_subsampling(void __iomem *core_base, u32 val)
211+{
212+ return write_reg_field_not_busy(core_base, core_base,
213+ JASPER_INPUT_CTRL0_OFFSET,
214+ JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_MASK,
215+ JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_SHIFT,
216+ val);
217+}
218+
219+int e5010_hw_set_chroma_order(void __iomem *core_base, u32 val)
220+{
221+ return write_reg_field_not_busy(core_base, core_base,
222+ JASPER_INPUT_CTRL0_OFFSET,
223+ JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_MASK,
224+ JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_SHIFT,
225+ val);
226+}
227+
228+void e5010_hw_set_output_max_size(void __iomem *core_base, u32 val)
229+{
230+ write_reg_field(core_base, JASPER_OUTPUT_MAX_SIZE_OFFSET,
231+ JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_MASK,
232+ JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_SHIFT,
233+ val);
234+}
235+
236+int e5010_hw_set_qpvalue(void __iomem *core_base, u32 offset, u32 val)
237+{
238+ return write_reg_field_not_busy(core_base, core_base, offset, 0xffffffff, 0, val);
239+}
240+
241+void e5010_hw_clear_output_error(void __iomem *core_base, u32 clear)
242+{
243+ /* Make sure interrupts are clear */
244+ write_reg_field(core_base, JASPER_INTERRUPT_CLEAR_OFFSET,
245+ JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_MASK,
246+ JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_SHIFT, clear);
247+}
248+
249+void e5010_hw_clear_picture_done(void __iomem *core_base, u32 clear)
250+{
251+ write_reg_field(core_base,
252+ JASPER_INTERRUPT_CLEAR_OFFSET,
253+ JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_MASK,
254+ JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_SHIFT, clear);
255+}
256+
257+int e5010_hw_get_output_size(void __iomem *core_base)
258+{
259+ return readl(core_base + JASPER_OUTPUT_SIZE_OFFSET);
260+}
261+
262+void e5010_hw_encode_start(void __iomem *core_base, u32 start)
263+{
264+ write_reg_field(core_base, JASPER_CORE_CTRL_OFFSET,
265+ JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_MASK,
266+ JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_SHIFT, start);
267+}
drivers/media/platform/imagination/e5010-jpeg-enc-hw.h+42−0
@@ -0,0 +1,42 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * Imagination E5010 JPEG Encoder driver.
4+ *
5+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
6+ *
7+ * Author: David Huang <d-huang@ti.com>
8+ * Author: Devarsh Thakkar <devarsht@ti.com>
9+ */
10+
11+#ifndef _E5010_JPEG_ENC_HW_H
12+#define _E5010_JPEG_ENC_HW_H
13+
14+#include "e5010-core-regs.h"
15+#include "e5010-mmu-regs.h"
16+
17+int e5010_hw_enable_output_address_error_irq(void __iomem *core_offset, u32 enable);
18+int e5010_hw_enable_picture_done_irq(void __iomem *core_offset, u32 enable);
19+int e5010_hw_enable_auto_clock_gating(void __iomem *core_offset, u32 enable);
20+int e5010_hw_enable_manual_clock_gating(void __iomem *core_offset, u32 enable);
21+int e5010_hw_enable_crc_check(void __iomem *core_offset, u32 enable);
22+int e5010_hw_set_input_source_to_memory(void __iomem *core_offset, u32 set);
23+int e5010_hw_set_input_luma_addr(void __iomem *core_offset, u32 val);
24+int e5010_hw_set_input_chroma_addr(void __iomem *core_offset, u32 val);
25+int e5010_hw_set_output_base_addr(void __iomem *core_offset, u32 val);
26+int e5010_hw_get_output_size(void __iomem *core_offset);
27+int e5010_hw_set_horizontal_size(void __iomem *core_offset, u32 val);
28+int e5010_hw_set_vertical_size(void __iomem *core_offset, u32 val);
29+int e5010_hw_set_luma_stride(void __iomem *core_offset, u32 bytesperline);
30+int e5010_hw_set_chroma_stride(void __iomem *core_offset, u32 bytesperline);
31+int e5010_hw_set_input_subsampling(void __iomem *core_offset, u32 val);
32+int e5010_hw_set_chroma_order(void __iomem *core_offset, u32 val);
33+int e5010_hw_set_qpvalue(void __iomem *core_offset, u32 offset, u32 value);
34+void e5010_reset(struct device *dev, void __iomem *core_offset, void __iomem *mmu_offset);
35+void e5010_hw_set_output_max_size(void __iomem *core_offset, u32 val);
36+void e5010_hw_clear_picture_done(void __iomem *core_offset, u32 clear);
37+void e5010_hw_encode_start(void __iomem *core_offset, u32 start);
38+void e5010_hw_clear_output_error(void __iomem *core_offset, u32 clear);
39+void e5010_hw_bypass_mmu(void __iomem *mmu_base, u32 enable);
40+bool e5010_hw_pic_done_irq(void __iomem *core_base);
41+bool e5010_hw_output_address_irq(void __iomem *core_base);
42+#endif
drivers/media/platform/imagination/e5010-jpeg-enc.c+1632−0
@@ -0,0 +1,1632 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Imagination E5010 JPEG Encoder driver.
4+ *
5+ * TODO: Add MMU and memory tiling support
6+ *
7+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
8+ *
9+ * Author: David Huang <d-huang@ti.com>
10+ * Author: Devarsh Thakkar <devarsht@ti.com>
11+ */
12+
13+#include <linux/clk.h>
14+#include <linux/dma-mapping.h>
15+#include <linux/err.h>
16+#include <linux/interrupt.h>
17+#include <linux/ioctl.h>
18+#include <linux/module.h>
19+#include <linux/of_device.h>
20+#include <linux/pm_runtime.h>
21+#include <media/jpeg.h>
22+#include <media/v4l2-common.h>
23+#include <media/v4l2-ctrls.h>
24+#include <media/v4l2-device.h>
25+#include <media/v4l2-event.h>
26+#include <media/v4l2-ioctl.h>
27+#include <media/v4l2-jpeg.h>
28+#include <media/v4l2-rect.h>
29+#include <media/v4l2-mem2mem.h>
30+#include <media/videobuf2-dma-contig.h>
31+#include <media/videobuf2-v4l2.h>
32+#include "e5010-jpeg-enc.h"
33+#include "e5010-jpeg-enc-hw.h"
34+
35+/* forward declarations */
36+static const struct of_device_id e5010_of_match[];
37+
38+static const struct v4l2_file_operations e5010_fops;
39+
40+static const struct v4l2_ioctl_ops e5010_ioctl_ops;
41+
42+static const struct vb2_ops e5010_video_ops;
43+
44+static const struct v4l2_m2m_ops e5010_m2m_ops;
45+
46+static struct e5010_fmt e5010_formats[] = {
47+ {
48+ .fourcc = V4L2_PIX_FMT_NV12,
49+ .num_planes = 1,
50+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
51+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
52+ .chroma_order = CHROMA_ORDER_CB_CR,
53+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
54+ MIN_DIMENSION, MAX_DIMENSION, 8 },
55+ },
56+ {
57+ .fourcc = V4L2_PIX_FMT_NV12M,
58+ .num_planes = 2,
59+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
60+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
61+ .chroma_order = CHROMA_ORDER_CB_CR,
62+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
63+ MIN_DIMENSION, MAX_DIMENSION, 8 },
64+ },
65+ {
66+ .fourcc = V4L2_PIX_FMT_NV21,
67+ .num_planes = 1,
68+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
69+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
70+ .chroma_order = CHROMA_ORDER_CR_CB,
71+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
72+ MIN_DIMENSION, MAX_DIMENSION, 8 },
73+ },
74+ {
75+ .fourcc = V4L2_PIX_FMT_NV21M,
76+ .num_planes = 2,
77+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
78+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
79+ .chroma_order = CHROMA_ORDER_CR_CB,
80+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
81+ MIN_DIMENSION, MAX_DIMENSION, 8 },
82+ },
83+ {
84+ .fourcc = V4L2_PIX_FMT_NV16,
85+ .num_planes = 1,
86+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
87+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
88+ .chroma_order = CHROMA_ORDER_CB_CR,
89+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
90+ MIN_DIMENSION, MAX_DIMENSION, 8 },
91+ },
92+ {
93+ .fourcc = V4L2_PIX_FMT_NV16M,
94+ .num_planes = 2,
95+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
96+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
97+ .chroma_order = CHROMA_ORDER_CB_CR,
98+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
99+ MIN_DIMENSION, MAX_DIMENSION, 8 },
100+
101+ },
102+ {
103+ .fourcc = V4L2_PIX_FMT_NV61,
104+ .num_planes = 1,
105+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
106+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
107+ .chroma_order = CHROMA_ORDER_CR_CB,
108+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
109+ MIN_DIMENSION, MAX_DIMENSION, 8 },
110+ },
111+ {
112+ .fourcc = V4L2_PIX_FMT_NV61M,
113+ .num_planes = 2,
114+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
115+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
116+ .chroma_order = CHROMA_ORDER_CR_CB,
117+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
118+ MIN_DIMENSION, MAX_DIMENSION, 8 },
119+ },
120+ {
121+ .fourcc = V4L2_PIX_FMT_JPEG,
122+ .num_planes = 1,
123+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
124+ .subsampling = 0,
125+ .chroma_order = 0,
126+ .frmsize = { MIN_DIMENSION, MAX_DIMENSION, 16,
127+ MIN_DIMENSION, MAX_DIMENSION, 8 },
128+ },
129+};
130+
131+static unsigned int debug;
132+module_param(debug, uint, 0644);
133+MODULE_PARM_DESC(debug, "debug level");
134+
135+#define dprintk(dev, lvl, fmt, arg...) \
136+ v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
137+
138+static const struct v4l2_event e5010_eos_event = {
139+ .type = V4L2_EVENT_EOS
140+};
141+
142+static const char *type_name(enum v4l2_buf_type type)
143+{
144+ switch (type) {
145+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
146+ return "Output";
147+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
148+ return "Capture";
149+ default:
150+ return "Invalid";
151+ }
152+}
153+
154+static struct e5010_q_data *get_queue(struct e5010_context *ctx, enum v4l2_buf_type type)
155+{
156+ return (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? &ctx->out_queue : &ctx->cap_queue;
157+}
158+
159+static void calculate_qp_tables(struct e5010_context *ctx)
160+{
161+ long long luminosity, contrast;
162+ int quality, i;
163+
164+ quality = 50 - ctx->quality;
165+
166+ luminosity = LUMINOSITY * quality / 50;
167+ contrast = CONTRAST * quality / 50;
168+
169+ if (quality > 0) {
170+ luminosity *= INCREASE;
171+ contrast *= INCREASE;
172+ }
173+
174+ for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++) {
175+ long long delta = v4l2_jpeg_ref_table_chroma_qt[i] * contrast + luminosity;
176+ int val = (int)(v4l2_jpeg_ref_table_chroma_qt[i] + delta);
177+
178+ clamp(val, 1, 255);
179+ ctx->chroma_qp[i] = quality == -50 ? 1 : val;
180+
181+ delta = v4l2_jpeg_ref_table_luma_qt[i] * contrast + luminosity;
182+ val = (int)(v4l2_jpeg_ref_table_luma_qt[i] + delta);
183+ clamp(val, 1, 255);
184+ ctx->luma_qp[i] = quality == -50 ? 1 : val;
185+ }
186+
187+ ctx->update_qp = true;
188+}
189+
190+static int update_qp_tables(struct e5010_context *ctx)
191+{
192+ struct e5010_dev *e5010 = ctx->e5010;
193+ int i, ret = 0;
194+ u32 lvalue, cvalue;
195+
196+ lvalue = 0;
197+ cvalue = 0;
198+
199+ for (i = 0; i < QP_TABLE_SIZE; i++) {
200+ lvalue |= ctx->luma_qp[i] << (8 * (i % 4));
201+ cvalue |= ctx->chroma_qp[i] << (8 * (i % 4));
202+ if (i % 4 == 3) {
203+ ret |= e5010_hw_set_qpvalue(e5010->core_base,
204+ JASPER_LUMA_QUANTIZATION_TABLE0_OFFSET
205+ + QP_TABLE_FIELD_OFFSET * ((i - 3) / 4),
206+ lvalue);
207+ ret |= e5010_hw_set_qpvalue(e5010->core_base,
208+ JASPER_CHROMA_QUANTIZATION_TABLE0_OFFSET
209+ + QP_TABLE_FIELD_OFFSET * ((i - 3) / 4),
210+ cvalue);
211+ lvalue = 0;
212+ cvalue = 0;
213+ }
214+ }
215+
216+ return ret;
217+}
218+
219+static int e5010_set_input_subsampling(void __iomem *core_base, int subsampling)
220+{
221+ switch (subsampling) {
222+ case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
223+ return e5010_hw_set_input_subsampling(core_base, SUBSAMPLING_420);
224+ case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
225+ return e5010_hw_set_input_subsampling(core_base, SUBSAMPLING_422);
226+ default:
227+ return -EINVAL;
228+ };
229+}
230+
231+static int e5010_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
232+{
233+ strscpy(cap->driver, E5010_MODULE_NAME, sizeof(cap->driver));
234+ strscpy(cap->card, E5010_MODULE_NAME, sizeof(cap->card));
235+
236+ return 0;
237+}
238+
239+static struct e5010_fmt *find_format(struct v4l2_format *f)
240+{
241+ int i;
242+
243+ for (i = 0; i < ARRAY_SIZE(e5010_formats); ++i) {
244+ if (e5010_formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
245+ e5010_formats[i].type == f->type)
246+ return &e5010_formats[i];
247+ }
248+
249+ return NULL;
250+}
251+
252+static int e5010_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
253+{
254+ int i, index = 0;
255+ struct e5010_fmt *fmt = NULL;
256+ struct e5010_context *ctx = file->private_data;
257+
258+ if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
259+ v4l2_err(&ctx->e5010->v4l2_dev, "ENUMFMT with Invalid type: %d\n", f->type);
260+ return -EINVAL;
261+ }
262+
263+ for (i = 0; i < ARRAY_SIZE(e5010_formats); ++i) {
264+ if (e5010_formats[i].type == f->type) {
265+ if (index == f->index) {
266+ fmt = &e5010_formats[i];
267+ break;
268+ }
269+ index++;
270+ }
271+ }
272+
273+ if (!fmt)
274+ return -EINVAL;
275+
276+ f->pixelformat = fmt->fourcc;
277+ return 0;
278+}
279+
280+static int e5010_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
281+{
282+ struct e5010_context *ctx = file->private_data;
283+ struct e5010_q_data *queue;
284+ int i;
285+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
286+ struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
287+
288+ queue = get_queue(ctx, f->type);
289+
290+ pix_mp->flags = 0;
291+ pix_mp->field = V4L2_FIELD_NONE;
292+ pix_mp->pixelformat = queue->fmt->fourcc;
293+ pix_mp->width = queue->width_adjusted;
294+ pix_mp->height = queue->height_adjusted;
295+ pix_mp->num_planes = queue->fmt->num_planes;
296+
297+ if (V4L2_TYPE_IS_OUTPUT(f->type)) {
298+ if (!pix_mp->colorspace)
299+ pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
300+
301+ for (i = 0; i < queue->fmt->num_planes; i++) {
302+ plane_fmt[i].sizeimage = queue->sizeimage[i];
303+ plane_fmt[i].bytesperline = queue->bytesperline[i];
304+ }
305+
306+ } else {
307+ pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
308+ plane_fmt[0].bytesperline = 0;
309+ plane_fmt[0].sizeimage = queue->sizeimage[0];
310+ }
311+ pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
312+ pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
313+ pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
314+
315+ return 0;
316+}
317+
318+static int e5010_jpeg_try_fmt(struct v4l2_format *f, struct e5010_context *ctx)
319+{
320+ struct e5010_fmt *fmt;
321+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
322+ struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
323+
324+ fmt = find_format(f);
325+ if (!fmt) {
326+ if (V4L2_TYPE_IS_OUTPUT(f->type))
327+ pix_mp->pixelformat = V4L2_PIX_FMT_NV12;
328+ else
329+ pix_mp->pixelformat = V4L2_PIX_FMT_JPEG;
330+ fmt = find_format(f);
331+ if (!fmt)
332+ return -EINVAL;
333+ }
334+
335+ if (V4L2_TYPE_IS_OUTPUT(f->type)) {
336+ if (!pix_mp->colorspace)
337+ pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
338+ if (!pix_mp->ycbcr_enc)
339+ pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
340+ if (!pix_mp->quantization)
341+ pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
342+ if (!pix_mp->xfer_func)
343+ pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
344+
345+ v4l2_apply_frmsize_constraints(&pix_mp->width,
346+ &pix_mp->height,
347+ &fmt->frmsize);
348+
349+ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
350+ pix_mp->width, pix_mp->height);
351+
352+ } else {
353+ pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
354+ pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
355+ pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
356+ pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
357+ v4l2_apply_frmsize_constraints(&pix_mp->width,
358+ &pix_mp->height,
359+ &fmt->frmsize);
360+ plane_fmt[0].sizeimage = pix_mp->width * pix_mp->height * JPEG_MAX_BYTES_PER_PIXEL;
361+ plane_fmt[0].sizeimage += HEADER_SIZE;
362+ plane_fmt[0].bytesperline = 0;
363+ pix_mp->pixelformat = fmt->fourcc;
364+ pix_mp->num_planes = fmt->num_planes;
365+ }
366+ pix_mp->flags = 0;
367+ pix_mp->field = V4L2_FIELD_NONE;
368+
369+ dprintk(ctx->e5010, 2,
370+ "ctx: 0x%p: format type %s:, wxh: %dx%d (plane0 : %d bytes, plane1 : %d bytes),fmt: %c%c%c%c\n",
371+ ctx, type_name(f->type), pix_mp->width, pix_mp->height,
372+ plane_fmt[0].sizeimage, plane_fmt[1].sizeimage,
373+ (fmt->fourcc & 0xff),
374+ (fmt->fourcc >> 8) & 0xff,
375+ (fmt->fourcc >> 16) & 0xff,
376+ (fmt->fourcc >> 24) & 0xff);
377+
378+ return 0;
379+}
380+
381+static int e5010_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
382+{
383+ struct e5010_context *ctx = file->private_data;
384+
385+ return e5010_jpeg_try_fmt(f, ctx);
386+}
387+
388+static int e5010_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
389+{
390+ struct e5010_context *ctx = file->private_data;
391+ struct vb2_queue *vq;
392+ int ret = 0, i = 0;
393+ struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
394+ struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
395+ struct e5010_q_data *queue;
396+ struct e5010_fmt *fmt;
397+
398+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
399+ if (!vq)
400+ return -EINVAL;
401+
402+ if (vb2_is_busy(vq)) {
403+ v4l2_err(&ctx->e5010->v4l2_dev, "queue busy\n");
404+ return -EBUSY;
405+ }
406+
407+ ret = e5010_jpeg_try_fmt(f, ctx);
408+ if (ret)
409+ return ret;
410+
411+ fmt = find_format(f);
412+ queue = get_queue(ctx, f->type);
413+
414+ queue->fmt = fmt;
415+ queue->width = pix_mp->width;
416+ queue->height = pix_mp->height;
417+
418+ if (V4L2_TYPE_IS_OUTPUT(f->type)) {
419+ for (i = 0; i < fmt->num_planes; i++) {
420+ queue->bytesperline[i] = plane_fmt[i].bytesperline;
421+ queue->sizeimage[i] = plane_fmt[i].sizeimage;
422+ }
423+ queue->crop.left = 0;
424+ queue->crop.top = 0;
425+ queue->crop.width = queue->width;
426+ queue->crop.height = queue->height;
427+ } else {
428+ queue->sizeimage[0] = plane_fmt[0].sizeimage;
429+ queue->sizeimage[1] = 0;
430+ queue->bytesperline[0] = 0;
431+ queue->bytesperline[1] = 0;
432+ }
433+
434+ return 0;
435+}
436+
437+static int e5010_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize)
438+{
439+ struct v4l2_format f;
440+ struct e5010_fmt *fmt;
441+
442+ if (fsize->index != 0)
443+ return -EINVAL;
444+
445+ f.fmt.pix_mp.pixelformat = fsize->pixel_format;
446+ if (f.fmt.pix_mp.pixelformat == V4L2_PIX_FMT_JPEG)
447+ f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
448+ else
449+ f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
450+
451+ fmt = find_format(&f);
452+ if (!fmt)
453+ return -EINVAL;
454+
455+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
456+ fsize->stepwise = fmt->frmsize;
457+ fsize->reserved[0] = 0;
458+ fsize->reserved[1] = 0;
459+
460+ return 0;
461+}
462+
463+static int e5010_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
464+{
465+ struct e5010_context *ctx = file->private_data;
466+ struct e5010_q_data *queue;
467+
468+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
469+ return -EINVAL;
470+
471+ queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
472+
473+ switch (s->target) {
474+ case V4L2_SEL_TGT_CROP_DEFAULT:
475+ case V4L2_SEL_TGT_CROP_BOUNDS:
476+ s->r.left = 0;
477+ s->r.top = 0;
478+ s->r.width = queue->width;
479+ s->r.height = queue->height;
480+ break;
481+ case V4L2_SEL_TGT_CROP:
482+ memcpy(&s->r, &queue->crop, sizeof(s->r));
483+ break;
484+ default:
485+ return -EINVAL;
486+ }
487+
488+ return 0;
489+}
490+
491+static int e5010_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
492+{
493+ struct e5010_context *ctx = file->private_data;
494+ struct e5010_q_data *queue;
495+ struct vb2_queue *vq;
496+ struct v4l2_rect base_rect;
497+
498+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, s->type);
499+ if (!vq)
500+ return -EINVAL;
501+
502+ if (vb2_is_streaming(vq))
503+ return -EBUSY;
504+
505+ if (s->target != V4L2_SEL_TGT_CROP ||
506+ s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
507+ return -EINVAL;
508+
509+ queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
510+ base_rect.top = 0;
511+ base_rect.left = 0;
512+ base_rect.width = queue->width;
513+ base_rect.height = queue->height;
514+
515+ switch (s->flags) {
516+ case 0:
517+ s->r.width = round_down(s->r.width, queue->fmt->frmsize.step_width);
518+ s->r.height = round_down(s->r.height, queue->fmt->frmsize.step_height);
519+ s->r.left = round_down(s->r.left, queue->fmt->frmsize.step_width);
520+ s->r.top = round_down(s->r.top, 2);
521+
522+ if (s->r.left + s->r.width > queue->width)
523+ s->r.width = round_down(s->r.width + s->r.left - queue->width,
524+ queue->fmt->frmsize.step_width);
525+ if (s->r.top + s->r.height > queue->height)
526+ s->r.top = round_down(s->r.top + s->r.height - queue->height, 2);
527+ break;
528+ case V4L2_SEL_FLAG_GE:
529+ s->r.width = round_up(s->r.width, queue->fmt->frmsize.step_width);
530+ s->r.height = round_up(s->r.height, queue->fmt->frmsize.step_height);
531+ s->r.left = round_up(s->r.left, queue->fmt->frmsize.step_width);
532+ s->r.top = round_up(s->r.top, 2);
533+ break;
534+ case V4L2_SEL_FLAG_LE:
535+ s->r.width = round_down(s->r.width, queue->fmt->frmsize.step_width);
536+ s->r.height = round_down(s->r.height, queue->fmt->frmsize.step_height);
537+ s->r.left = round_down(s->r.left, queue->fmt->frmsize.step_width);
538+ s->r.top = round_down(s->r.top, 2);
539+ break;
540+ case V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE:
541+ if (!IS_ALIGNED(s->r.width, queue->fmt->frmsize.step_width) ||
542+ !IS_ALIGNED(s->r.height, queue->fmt->frmsize.step_height) ||
543+ !IS_ALIGNED(s->r.left, queue->fmt->frmsize.step_width) ||
544+ !IS_ALIGNED(s->r.top, 2))
545+ return -ERANGE;
546+ break;
547+ default:
548+ return -EINVAL;
549+ }
550+
551+ if (!v4l2_rect_enclosed(&s->r, &base_rect))
552+ return -ERANGE;
553+
554+ memcpy(&queue->crop, &s->r, sizeof(s->r));
555+
556+ if (!v4l2_rect_equal(&s->r, &base_rect))
557+ queue->crop_set = true;
558+
559+ dprintk(ctx->e5010, 2, "ctx: 0x%p: crop rectangle: w: %d, h : %d, l : %d, t : %d\n",
560+ ctx, queue->crop.width, queue->crop.height, queue->crop.left, queue->crop.top);
561+
562+ return 0;
563+}
564+
565+static int e5010_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
566+{
567+ switch (sub->type) {
568+ case V4L2_EVENT_EOS:
569+ return v4l2_event_subscribe(fh, sub, 0, NULL);
570+ case V4L2_EVENT_CTRL:
571+ return v4l2_ctrl_subscribe_event(fh, sub);
572+ default:
573+ return -EINVAL;
574+ }
575+
576+ return 0;
577+}
578+
579+static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
580+{
581+ struct e5010_context *ctx = priv;
582+ struct e5010_dev *e5010 = ctx->e5010;
583+ int ret = 0;
584+
585+ /* src_vq */
586+ memset(src_vq, 0, sizeof(*src_vq));
587+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
588+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
589+ src_vq->drv_priv = ctx;
590+ src_vq->buf_struct_size = sizeof(struct e5010_buffer);
591+ src_vq->ops = &e5010_video_ops;
592+ src_vq->mem_ops = &vb2_dma_contig_memops;
593+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
594+ src_vq->lock = &e5010->mutex;
595+ src_vq->dev = e5010->v4l2_dev.dev;
596+
597+ ret = vb2_queue_init(src_vq);
598+ if (ret)
599+ return ret;
600+
601+ /* dst_vq */
602+ memset(dst_vq, 0, sizeof(*dst_vq));
603+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
604+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
605+ dst_vq->drv_priv = ctx;
606+ dst_vq->buf_struct_size = sizeof(struct e5010_buffer);
607+ dst_vq->ops = &e5010_video_ops;
608+ dst_vq->mem_ops = &vb2_dma_contig_memops;
609+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
610+ dst_vq->lock = &e5010->mutex;
611+ dst_vq->dev = e5010->v4l2_dev.dev;
612+
613+ ret = vb2_queue_init(dst_vq);
614+ if (ret) {
615+ vb2_queue_release(src_vq);
616+ return ret;
617+ }
618+
619+ return 0;
620+}
621+
622+static int e5010_s_ctrl(struct v4l2_ctrl *ctrl)
623+{
624+ struct e5010_context *ctx =
625+ container_of(ctrl->handler, struct e5010_context, ctrl_handler);
626+
627+ switch (ctrl->id) {
628+ case V4L2_CID_JPEG_COMPRESSION_QUALITY:
629+ ctx->quality = ctrl->val;
630+ calculate_qp_tables(ctx);
631+ dprintk(ctx->e5010, 2, "ctx: 0x%p compression quality set to : %d\n", ctx,
632+ ctx->quality);
633+ break;
634+ default:
635+ return -EINVAL;
636+ }
637+
638+ return 0;
639+}
640+
641+static const struct v4l2_ctrl_ops e5010_ctrl_ops = {
642+ .s_ctrl = e5010_s_ctrl,
643+};
644+
645+static void e5010_encode_ctrls(struct e5010_context *ctx)
646+{
647+ v4l2_ctrl_new_std(&ctx->ctrl_handler, &e5010_ctrl_ops,
648+ V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 75);
649+}
650+
651+static int e5010_ctrls_setup(struct e5010_context *ctx)
652+{
653+ int err;
654+
655+ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1);
656+
657+ e5010_encode_ctrls(ctx);
658+
659+ if (ctx->ctrl_handler.error) {
660+ err = ctx->ctrl_handler.error;
661+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
662+
663+ return err;
664+ }
665+
666+ err = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
667+ if (err)
668+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
669+
670+ return err;
671+}
672+
673+static void e5010_jpeg_set_default_params(struct e5010_context *ctx)
674+{
675+ struct e5010_q_data *queue;
676+ struct v4l2_format f;
677+ struct e5010_fmt *fmt;
678+ struct v4l2_pix_format_mplane *pix_mp = &f.fmt.pix_mp;
679+ struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
680+ int i = 0;
681+
682+ f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
683+ f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
684+ fmt = find_format(&f);
685+ queue = &ctx->out_queue;
686+ queue->fmt = fmt;
687+ queue->width = DEFAULT_WIDTH;
688+ queue->height = DEFAULT_HEIGHT;
689+ pix_mp->width = queue->width;
690+ pix_mp->height = queue->height;
691+ queue->crop.left = 0;
692+ queue->crop.top = 0;
693+ queue->crop.width = queue->width;
694+ queue->crop.height = queue->height;
695+ v4l2_apply_frmsize_constraints(&pix_mp->width,
696+ &pix_mp->height,
697+ &fmt->frmsize);
698+ v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
699+ pix_mp->width, pix_mp->height);
700+ for (i = 0; i < fmt->num_planes; i++) {
701+ queue->bytesperline[i] = plane_fmt[i].bytesperline;
702+ queue->sizeimage[i] = plane_fmt[i].sizeimage;
703+ }
704+ queue->width_adjusted = pix_mp->width;
705+ queue->height_adjusted = pix_mp->height;
706+
707+ f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
708+ f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_JPEG;
709+ fmt = find_format(&f);
710+ queue = &ctx->cap_queue;
711+ queue->fmt = fmt;
712+ queue->width = DEFAULT_WIDTH;
713+ queue->height = DEFAULT_HEIGHT;
714+ pix_mp->width = queue->width;
715+ pix_mp->height = queue->height;
716+ v4l2_apply_frmsize_constraints(&pix_mp->width,
717+ &pix_mp->height,
718+ &fmt->frmsize);
719+ queue->sizeimage[0] = pix_mp->width * pix_mp->height * JPEG_MAX_BYTES_PER_PIXEL;
720+ queue->sizeimage[0] += HEADER_SIZE;
721+ queue->sizeimage[1] = 0;
722+ queue->bytesperline[0] = 0;
723+ queue->bytesperline[1] = 0;
724+ queue->width_adjusted = pix_mp->width;
725+ queue->height_adjusted = pix_mp->height;
726+}
727+
728+static int e5010_open(struct file *file)
729+{
730+ struct e5010_dev *e5010 = video_drvdata(file);
731+ struct video_device *vdev = video_devdata(file);
732+ struct e5010_context *ctx;
733+ int ret = 0;
734+
735+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
736+ if (!ctx)
737+ return -ENOMEM;
738+
739+ if (mutex_lock_interruptible(&e5010->mutex)) {
740+ ret = -ERESTARTSYS;
741+ goto free;
742+ }
743+
744+ v4l2_fh_init(&ctx->fh, vdev);
745+ file->private_data = ctx;
746+ v4l2_fh_add(&ctx->fh);
747+
748+ ctx->e5010 = e5010;
749+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(e5010->m2m_dev, ctx, queue_init);
750+ if (IS_ERR(ctx->fh.m2m_ctx)) {
751+ v4l2_err(&e5010->v4l2_dev, "failed to init m2m ctx\n");
752+ ret = PTR_ERR(ctx->fh.m2m_ctx);
753+ goto exit;
754+ }
755+
756+ ret = e5010_ctrls_setup(ctx);
757+ if (ret) {
758+ v4l2_err(&e5010->v4l2_dev, "failed to setup e5010 jpeg controls\n");
759+ goto err_ctrls_setup;
760+ }
761+ ctx->fh.ctrl_handler = &ctx->ctrl_handler;
762+
763+ e5010_jpeg_set_default_params(ctx);
764+
765+ dprintk(e5010, 1, "Created instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx);
766+
767+ mutex_unlock(&e5010->mutex);
768+ return 0;
769+
770+err_ctrls_setup:
771+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
772+exit:
773+ v4l2_fh_del(&ctx->fh);
774+ v4l2_fh_exit(&ctx->fh);
775+ mutex_unlock(&e5010->mutex);
776+free:
777+ kfree(ctx);
778+ return ret;
779+}
780+
781+static int e5010_release(struct file *file)
782+{
783+ struct e5010_dev *e5010 = video_drvdata(file);
784+ struct e5010_context *ctx = file->private_data;
785+
786+ dprintk(e5010, 1, "Releasing instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx);
787+ mutex_lock(&e5010->mutex);
788+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
789+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
790+ v4l2_fh_del(&ctx->fh);
791+ v4l2_fh_exit(&ctx->fh);
792+ kfree(ctx);
793+ mutex_unlock(&e5010->mutex);
794+
795+ return 0;
796+}
797+
798+static void header_write(struct e5010_context *ctx, u8 *addr, unsigned int *offset,
799+ unsigned int no_bytes, unsigned long bits)
800+{
801+ u8 *w_addr = addr + *offset;
802+ int i;
803+
804+ if ((*offset + no_bytes) > HEADER_SIZE) {
805+ v4l2_warn(&ctx->e5010->v4l2_dev, "%s: %s: %d: Problem writing header. %d > HEADER_SIZE %d\n",
806+ __FILE__, __func__, __LINE__, *offset + no_bytes, HEADER_SIZE);
807+ return;
808+ }
809+
810+ for (i = no_bytes - 1; i >= 0; i--)
811+ *(w_addr++) = ((u8 *)&bits)[i];
812+
813+ *offset += no_bytes;
814+}
815+
816+static void encode_marker_segment(struct e5010_context *ctx, void *addr, unsigned int *offset)
817+{
818+ u8 *buffer = (u8 *)addr;
819+ int i;
820+
821+ header_write(ctx, buffer, offset, 2, START_OF_IMAGE);
822+ header_write(ctx, buffer, offset, 2, DQT_MARKER);
823+ header_write(ctx, buffer, offset, 3, LQPQ << 4);
824+ for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++)
825+ header_write(ctx, buffer, offset, 1, ctx->luma_qp[v4l2_jpeg_zigzag_scan_index[i]]);
826+
827+ header_write(ctx, buffer, offset, 2, DQT_MARKER);
828+ header_write(ctx, buffer, offset, 3, (LQPQ << 4) | 1);
829+ for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++)
830+ header_write(ctx, buffer, offset, 1,
831+ ctx->chroma_qp[v4l2_jpeg_zigzag_scan_index[i]]);
832+
833+ /* Huffman tables */
834+ header_write(ctx, buffer, offset, 2, DHT_MARKER);
835+ header_write(ctx, buffer, offset, 2, LH_DC);
836+ header_write(ctx, buffer, offset, 1, V4L2_JPEG_LUM_HT | V4L2_JPEG_DC_HT);
837+ for (i = 0 ; i < V4L2_JPEG_REF_HT_DC_LEN; i++)
838+ header_write(ctx, buffer, offset, 1, v4l2_jpeg_ref_table_luma_dc_ht[i]);
839+
840+ header_write(ctx, buffer, offset, 2, DHT_MARKER);
841+ header_write(ctx, buffer, offset, 2, LH_AC);
842+ header_write(ctx, buffer, offset, 1, V4L2_JPEG_LUM_HT | V4L2_JPEG_AC_HT);
843+ for (i = 0 ; i < V4L2_JPEG_REF_HT_AC_LEN; i++)
844+ header_write(ctx, buffer, offset, 1, v4l2_jpeg_ref_table_luma_ac_ht[i]);
845+
846+ header_write(ctx, buffer, offset, 2, DHT_MARKER);
847+ header_write(ctx, buffer, offset, 2, LH_DC);
848+ header_write(ctx, buffer, offset, 1, V4L2_JPEG_CHR_HT | V4L2_JPEG_DC_HT);
849+ for (i = 0 ; i < V4L2_JPEG_REF_HT_DC_LEN; i++)
850+ header_write(ctx, buffer, offset, 1, v4l2_jpeg_ref_table_chroma_dc_ht[i]);
851+
852+ header_write(ctx, buffer, offset, 2, DHT_MARKER);
853+ header_write(ctx, buffer, offset, 2, LH_AC);
854+ header_write(ctx, buffer, offset, 1, V4L2_JPEG_CHR_HT | V4L2_JPEG_AC_HT);
855+ for (i = 0 ; i < V4L2_JPEG_REF_HT_AC_LEN; i++)
856+ header_write(ctx, buffer, offset, 1, v4l2_jpeg_ref_table_chroma_ac_ht[i]);
857+}
858+
859+static void encode_frame_header(struct e5010_context *ctx, void *addr, unsigned int *offset)
860+{
861+ u8 *buffer = (u8 *)addr;
862+
863+ header_write(ctx, buffer, offset, 2, SOF_BASELINE_DCT);
864+ header_write(ctx, buffer, offset, 2, 8 + (3 * UC_NUM_COMP));
865+ header_write(ctx, buffer, offset, 1, PRECISION);
866+ header_write(ctx, buffer, offset, 2, ctx->out_queue.crop.height);
867+ header_write(ctx, buffer, offset, 2, ctx->out_queue.crop.width);
868+ header_write(ctx, buffer, offset, 1, UC_NUM_COMP);
869+
870+ /* Luma details */
871+ header_write(ctx, buffer, offset, 1, 1);
872+ if (ctx->out_queue.fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422)
873+ header_write(ctx, buffer, offset, 1,
874+ HORZ_SAMPLING_FACTOR | (VERT_SAMPLING_FACTOR_422));
875+ else
876+ header_write(ctx, buffer, offset, 1,
877+ HORZ_SAMPLING_FACTOR | (VERT_SAMPLING_FACTOR_420));
878+ header_write(ctx, buffer, offset, 1, 0);
879+ /* Chroma details */
880+ header_write(ctx, buffer, offset, 1, 2);
881+ header_write(ctx, buffer, offset, 1, (HORZ_SAMPLING_FACTOR >> 1) | 1);
882+ header_write(ctx, buffer, offset, 1, 1);
883+ header_write(ctx, buffer, offset, 1, 3);
884+ header_write(ctx, buffer, offset, 1, (HORZ_SAMPLING_FACTOR >> 1) | 1);
885+ header_write(ctx, buffer, offset, 1, 1);
886+}
887+
888+static void jpg_encode_sos_header(struct e5010_context *ctx, void *addr, unsigned int *offset)
889+{
890+ u8 *buffer = (u8 *)addr;
891+ int i;
892+
893+ header_write(ctx, buffer, offset, 2, START_OF_SCAN);
894+ header_write(ctx, buffer, offset, 2, 6 + (COMPONENTS_IN_SCAN << 1));
895+ header_write(ctx, buffer, offset, 1, COMPONENTS_IN_SCAN);
896+
897+ for (i = 0; i < COMPONENTS_IN_SCAN; i++) {
898+ header_write(ctx, buffer, offset, 1, i + 1);
899+ if (i == 0)
900+ header_write(ctx, buffer, offset, 1, 0);
901+ else
902+ header_write(ctx, buffer, offset, 1, 17);
903+ }
904+
905+ header_write(ctx, buffer, offset, 1, 0);
906+ header_write(ctx, buffer, offset, 1, 63);
907+ header_write(ctx, buffer, offset, 1, 0);
908+}
909+
910+static void write_header(struct e5010_context *ctx, void *addr)
911+{
912+ unsigned int offset = 0;
913+
914+ encode_marker_segment(ctx, addr, &offset);
915+ encode_frame_header(ctx, addr, &offset);
916+ jpg_encode_sos_header(ctx, addr, &offset);
917+}
918+
919+static irqreturn_t e5010_irq(int irq, void *data)
920+{
921+ struct e5010_dev *e5010 = data;
922+ struct e5010_context *ctx;
923+ int output_size;
924+ struct vb2_v4l2_buffer *src_buf, *dst_buf;
925+ bool pic_done, out_addr_err;
926+
927+ spin_lock(&e5010->hw_lock);
928+ pic_done = e5010_hw_pic_done_irq(e5010->core_base);
929+ out_addr_err = e5010_hw_output_address_irq(e5010->core_base);
930+
931+ if (!pic_done && !out_addr_err) {
932+ spin_unlock(&e5010->hw_lock);
933+ return IRQ_NONE;
934+ }
935+
936+ ctx = v4l2_m2m_get_curr_priv(e5010->m2m_dev);
937+ if (WARN_ON(!ctx))
938+ goto job_unlock;
939+
940+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
941+ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
942+ if (!dst_buf || !src_buf) {
943+ v4l2_err(&e5010->v4l2_dev, "ctx: 0x%p No source or destination buffer\n", ctx);
944+ goto job_unlock;
945+ }
946+
947+ if (out_addr_err) {
948+ e5010_hw_clear_output_error(e5010->core_base, 1);
949+ v4l2_warn(&e5010->v4l2_dev,
950+ "ctx: 0x%p Output bitstream size exceeded max size\n", ctx);
951+ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
952+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, dst_buf->planes[0].length);
953+ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
954+ if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
955+ dst_buf->flags |= V4L2_BUF_FLAG_LAST;
956+ v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
957+ v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
958+ dprintk(e5010, 2, "ctx: 0x%p Sending EOS\n", ctx);
959+ }
960+ }
961+
962+ if (pic_done) {
963+ e5010_hw_clear_picture_done(e5010->core_base, 1);
964+ dprintk(e5010, 3, "ctx: 0x%p Got output bitstream of size %d bytes\n",
965+ ctx, readl(e5010->core_base + JASPER_OUTPUT_SIZE_OFFSET));
966+
967+ if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
968+ dst_buf->flags |= V4L2_BUF_FLAG_LAST;
969+ v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
970+ v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
971+ dprintk(e5010, 2, "ctx: 0x%p Sending EOS\n", ctx);
972+ }
973+ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
974+ output_size = e5010_hw_get_output_size(e5010->core_base);
975+ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, output_size + HEADER_SIZE);
976+ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
977+ dprintk(e5010, 3,
978+ "ctx: 0x%p frame done for dst_buf->sequence: %d src_buf->sequence: %d\n",
979+ ctx, dst_buf->sequence, src_buf->sequence);
980+ }
981+
982+ v4l2_m2m_job_finish(e5010->m2m_dev, ctx->fh.m2m_ctx);
983+ dprintk(e5010, 3, "ctx: 0x%p Finish job\n", ctx);
984+
985+job_unlock:
986+ spin_unlock(&e5010->hw_lock);
987+ return IRQ_HANDLED;
988+}
989+
990+static int e5010_init_device(struct e5010_dev *e5010)
991+{
992+ int ret = 0;
993+
994+ /*TODO: Set MMU in bypass mode until support for the same is added in driver*/
995+ e5010_hw_bypass_mmu(e5010->mmu_base, 1);
996+
997+ if (e5010_hw_enable_auto_clock_gating(e5010->core_base, 1))
998+ v4l2_warn(&e5010->v4l2_dev, "failed to enable auto clock gating\n");
999+
1000+ if (e5010_hw_enable_manual_clock_gating(e5010->core_base, 0))
1001+ v4l2_warn(&e5010->v4l2_dev, "failed to disable manual clock gating\n");
1002+
1003+ if (e5010_hw_enable_crc_check(e5010->core_base, 0))
1004+ v4l2_warn(&e5010->v4l2_dev, "failed to disable CRC check\n");
1005+
1006+ if (e5010_hw_enable_output_address_error_irq(e5010->core_base, 1))
1007+ v4l2_err(&e5010->v4l2_dev, "failed to enable Output Address Error interrupts\n");
1008+
1009+ ret = e5010_hw_set_input_source_to_memory(e5010->core_base, 1);
1010+ if (ret) {
1011+ v4l2_err(&e5010->v4l2_dev, "failed to set input source to memory\n");
1012+ return ret;
1013+ }
1014+
1015+ ret = e5010_hw_enable_picture_done_irq(e5010->core_base, 1);
1016+ if (ret)
1017+ v4l2_err(&e5010->v4l2_dev, "failed to enable Picture Done interrupts\n");
1018+
1019+ return ret;
1020+}
1021+
1022+static int e5010_probe(struct platform_device *pdev)
1023+{
1024+ struct e5010_dev *e5010;
1025+ int irq, ret = 0;
1026+ struct device *dev = &pdev->dev;
1027+
1028+ ret = dma_set_mask(dev, DMA_BIT_MASK(32));
1029+ if (ret)
1030+ return dev_err_probe(dev, ret, "32-bit consistent DMA enable failed\n");
1031+
1032+ e5010 = devm_kzalloc(dev, sizeof(*e5010), GFP_KERNEL);
1033+ if (!e5010)
1034+ return -ENOMEM;
1035+
1036+ platform_set_drvdata(pdev, e5010);
1037+
1038+ e5010->dev = dev;
1039+
1040+ mutex_init(&e5010->mutex);
1041+ spin_lock_init(&e5010->hw_lock);
1042+
1043+ e5010->vdev = video_device_alloc();
1044+ if (!e5010->vdev) {
1045+ dev_err(dev, "failed to allocate video device\n");
1046+ return -ENOMEM;
1047+ }
1048+
1049+ snprintf(e5010->vdev->name, sizeof(e5010->vdev->name), "%s", E5010_MODULE_NAME);
1050+ e5010->vdev->fops = &e5010_fops;
1051+ e5010->vdev->ioctl_ops = &e5010_ioctl_ops;
1052+ e5010->vdev->minor = -1;
1053+ e5010->vdev->release = video_device_release;
1054+ e5010->vdev->vfl_dir = VFL_DIR_M2M;
1055+ e5010->vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1056+ e5010->vdev->v4l2_dev = &e5010->v4l2_dev;
1057+ e5010->vdev->lock = &e5010->mutex;
1058+
1059+ ret = v4l2_device_register(dev, &e5010->v4l2_dev);
1060+ if (ret)
1061+ return dev_err_probe(dev, ret, "failed to register v4l2 device\n");
1062+
1063+ e5010->m2m_dev = v4l2_m2m_init(&e5010_m2m_ops);
1064+ if (IS_ERR(e5010->m2m_dev)) {
1065+ ret = PTR_ERR(e5010->m2m_dev);
1066+ e5010->m2m_dev = NULL;
1067+ dev_err_probe(dev, ret, "failed to init mem2mem device\n");
1068+ goto fail_after_v4l2_register;
1069+ }
1070+
1071+ video_set_drvdata(e5010->vdev, e5010);
1072+
1073+ e5010->core_base = devm_platform_ioremap_resource_byname(pdev, "core");
1074+ if (IS_ERR(e5010->core_base)) {
1075+ ret = PTR_ERR(e5010->core_base);
1076+ dev_err_probe(dev, ret, "Missing 'core' resources area\n");
1077+ goto fail_after_v4l2_register;
1078+ }
1079+
1080+ e5010->mmu_base = devm_platform_ioremap_resource_byname(pdev, "mmu");
1081+ if (IS_ERR(e5010->mmu_base)) {
1082+ ret = PTR_ERR(e5010->mmu_base);
1083+ dev_err_probe(dev, ret, "Missing 'mmu' resources area\n");
1084+ goto fail_after_v4l2_register;
1085+ }
1086+
1087+ e5010->last_context_run = NULL;
1088+
1089+ irq = platform_get_irq(pdev, 0);
1090+ ret = devm_request_irq(dev, irq, e5010_irq, 0,
1091+ E5010_MODULE_NAME, e5010);
1092+ if (ret) {
1093+ dev_err_probe(dev, ret, "failed to register IRQ %d\n", irq);
1094+ goto fail_after_v4l2_register;
1095+ }
1096+
1097+ e5010->clk = devm_clk_get(dev, NULL);
1098+ if (IS_ERR(e5010->clk)) {
1099+ ret = PTR_ERR(e5010->clk);
1100+ dev_err_probe(dev, ret, "failed to get clock\n");
1101+ goto fail_after_v4l2_register;
1102+ }
1103+
1104+ pm_runtime_enable(dev);
1105+
1106+ ret = video_register_device(e5010->vdev, VFL_TYPE_VIDEO, 0);
1107+ if (ret) {
1108+ dev_err_probe(dev, ret, "failed to register video device\n");
1109+ goto fail_after_video_register_device;
1110+ }
1111+
1112+ v4l2_info(&e5010->v4l2_dev, "Device registered as /dev/video%d\n",
1113+ e5010->vdev->num);
1114+
1115+ return 0;
1116+
1117+fail_after_video_register_device:
1118+ v4l2_m2m_release(e5010->m2m_dev);
1119+fail_after_v4l2_register:
1120+ v4l2_device_unregister(&e5010->v4l2_dev);
1121+ return ret;
1122+}
1123+
1124+static void e5010_remove(struct platform_device *pdev)
1125+{
1126+ struct e5010_dev *e5010 = platform_get_drvdata(pdev);
1127+
1128+ pm_runtime_disable(e5010->dev);
1129+ video_unregister_device(e5010->vdev);
1130+ v4l2_m2m_release(e5010->m2m_dev);
1131+ v4l2_device_unregister(&e5010->v4l2_dev);
1132+}
1133+
1134+static void e5010_vb2_buffers_return(struct vb2_queue *q, enum vb2_buffer_state state)
1135+{
1136+ struct vb2_v4l2_buffer *vbuf;
1137+ struct e5010_context *ctx = vb2_get_drv_priv(q);
1138+
1139+ if (V4L2_TYPE_IS_OUTPUT(q->type)) {
1140+ while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) {
1141+ dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n",
1142+ ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index);
1143+ v4l2_m2m_buf_done(vbuf, state);
1144+ }
1145+ } else {
1146+ while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) {
1147+ dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n",
1148+ ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index);
1149+ vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0);
1150+ v4l2_m2m_buf_done(vbuf, state);
1151+ }
1152+ }
1153+}
1154+
1155+static int e5010_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes,
1156+ unsigned int sizes[], struct device *alloc_devs[])
1157+{
1158+ struct e5010_context *ctx = vb2_get_drv_priv(vq);
1159+ struct e5010_q_data *queue;
1160+ int i;
1161+
1162+ queue = get_queue(ctx, vq->type);
1163+
1164+ if (*nplanes) {
1165+ if (*nplanes != queue->fmt->num_planes)
1166+ return -EINVAL;
1167+ for (i = 0; i < *nplanes; i++) {
1168+ if (sizes[i] < queue->sizeimage[i])
1169+ return -EINVAL;
1170+ }
1171+ return 0;
1172+ }
1173+
1174+ *nplanes = queue->fmt->num_planes;
1175+ for (i = 0; i < *nplanes; i++)
1176+ sizes[i] = queue->sizeimage[i];
1177+
1178+ dprintk(ctx->e5010, 2,
1179+ "ctx: 0x%p, type %s, buffer(s): %d, planes %d, plane1: bytes %d plane2: %d bytes\n",
1180+ ctx, type_name(vq->type), *nbuffers, *nplanes, sizes[0], sizes[1]);
1181+
1182+ return 0;
1183+}
1184+
1185+static void e5010_buf_finish(struct vb2_buffer *vb)
1186+{
1187+ struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
1188+ void *d_addr;
1189+
1190+ if (vb->state != VB2_BUF_STATE_DONE || V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
1191+ return;
1192+
1193+ d_addr = vb2_plane_vaddr(vb, 0);
1194+ write_header(ctx, d_addr);
1195+}
1196+
1197+static int e5010_buf_out_validate(struct vb2_buffer *vb)
1198+{
1199+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1200+ struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
1201+
1202+ if (vbuf->field != V4L2_FIELD_NONE)
1203+ dprintk(ctx->e5010, 1, "ctx: 0x%p, field isn't supported\n", ctx);
1204+
1205+ vbuf->field = V4L2_FIELD_NONE;
1206+
1207+ return 0;
1208+}
1209+
1210+static int e5010_buf_prepare(struct vb2_buffer *vb)
1211+{
1212+ struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
1213+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1214+ struct e5010_q_data *queue;
1215+ int i;
1216+
1217+ vbuf->field = V4L2_FIELD_NONE;
1218+
1219+ queue = get_queue(ctx, vb->vb2_queue->type);
1220+
1221+ for (i = 0; i < queue->fmt->num_planes; i++) {
1222+ if (vb2_plane_size(vb, i) < (unsigned long)queue->sizeimage[i]) {
1223+ v4l2_err(&ctx->e5010->v4l2_dev, "plane %d too small (%lu < %lu)", i,
1224+ vb2_plane_size(vb, i), (unsigned long)queue->sizeimage[i]);
1225+
1226+ return -EINVAL;
1227+ }
1228+ }
1229+
1230+ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) {
1231+ vb2_set_plane_payload(vb, 0, 0);
1232+ vb2_set_plane_payload(vb, 1, 0);
1233+ }
1234+
1235+ return 0;
1236+}
1237+
1238+static void e5010_buf_queue(struct vb2_buffer *vb)
1239+{
1240+ struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
1241+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1242+
1243+ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
1244+ vb2_is_streaming(vb->vb2_queue) &&
1245+ v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
1246+ struct e5010_q_data *queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1247+
1248+ vbuf->sequence = queue->sequence++;
1249+ v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
1250+ v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
1251+ return;
1252+ }
1253+
1254+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1255+}
1256+
1257+static int e5010_encoder_cmd(struct file *file, void *priv,
1258+ struct v4l2_encoder_cmd *cmd)
1259+{
1260+ struct e5010_context *ctx = file->private_data;
1261+ int ret;
1262+ struct vb2_queue *cap_vq;
1263+
1264+ cap_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1265+
1266+ ret = v4l2_m2m_ioctl_try_encoder_cmd(file, &ctx->fh, cmd);
1267+ if (ret < 0)
1268+ return ret;
1269+
1270+ if (!vb2_is_streaming(v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx)) ||
1271+ !vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx)))
1272+ return 0;
1273+
1274+ ret = v4l2_m2m_ioctl_encoder_cmd(file, &ctx->fh, cmd);
1275+ if (ret < 0)
1276+ return ret;
1277+
1278+ if (cmd->cmd == V4L2_ENC_CMD_STOP &&
1279+ v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
1280+ v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
1281+
1282+ if (cmd->cmd == V4L2_ENC_CMD_START &&
1283+ v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
1284+ vb2_clear_last_buffer_dequeued(cap_vq);
1285+
1286+ return 0;
1287+}
1288+
1289+static int e5010_start_streaming(struct vb2_queue *q, unsigned int count)
1290+{
1291+ struct e5010_context *ctx = vb2_get_drv_priv(q);
1292+ int ret;
1293+
1294+ struct e5010_q_data *queue = get_queue(ctx, q->type);
1295+
1296+ v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
1297+ queue->sequence = 0;
1298+
1299+ ret = pm_runtime_resume_and_get(ctx->e5010->dev);
1300+ if (ret < 0) {
1301+ v4l2_err(&ctx->e5010->v4l2_dev, "failed to power up jpeg\n");
1302+ goto fail;
1303+ }
1304+
1305+ ret = e5010_init_device(ctx->e5010);
1306+ if (ret) {
1307+ v4l2_err(&ctx->e5010->v4l2_dev, "failed to Enable e5010 device\n");
1308+ goto fail;
1309+ }
1310+
1311+ return 0;
1312+
1313+fail:
1314+ e5010_vb2_buffers_return(q, VB2_BUF_STATE_QUEUED);
1315+
1316+ return ret;
1317+}
1318+
1319+static void e5010_stop_streaming(struct vb2_queue *q)
1320+{
1321+ struct e5010_context *ctx = vb2_get_drv_priv(q);
1322+
1323+ e5010_vb2_buffers_return(q, VB2_BUF_STATE_ERROR);
1324+
1325+ if (V4L2_TYPE_IS_OUTPUT(q->type))
1326+ v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
1327+
1328+ if (V4L2_TYPE_IS_OUTPUT(q->type) &&
1329+ v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) {
1330+ v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
1331+ }
1332+
1333+ pm_runtime_put_sync(ctx->e5010->dev);
1334+}
1335+
1336+static void e5010_device_run(void *priv)
1337+{
1338+ struct e5010_context *ctx = priv;
1339+ struct e5010_dev *e5010 = ctx->e5010;
1340+ struct vb2_v4l2_buffer *s_vb, *d_vb;
1341+ u32 reg = 0;
1342+ int ret = 0, luma_crop_offset = 0, chroma_crop_offset = 0;
1343+ unsigned long flags;
1344+ int num_planes = ctx->out_queue.fmt->num_planes;
1345+
1346+ spin_lock_irqsave(&e5010->hw_lock, flags);
1347+ s_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1348+ WARN_ON(!s_vb);
1349+ d_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1350+ WARN_ON(!d_vb);
1351+ if (!s_vb || !d_vb)
1352+ goto no_ready_buf_err;
1353+
1354+ s_vb->sequence = ctx->out_queue.sequence++;
1355+ d_vb->sequence = ctx->cap_queue.sequence++;
1356+
1357+ v4l2_m2m_buf_copy_metadata(s_vb, d_vb, false);
1358+
1359+ if (ctx != e5010->last_context_run || ctx->update_qp) {
1360+ dprintk(e5010, 1, "ctx updated: 0x%p -> 0x%p, updating qp tables\n",
1361+ e5010->last_context_run, ctx);
1362+ ret = update_qp_tables(ctx);
1363+ }
1364+
1365+ if (ret) {
1366+ ctx->update_qp = true;
1367+ v4l2_err(&e5010->v4l2_dev, "failed to update QP tables\n");
1368+ goto device_busy_err;
1369+ } else {
1370+ e5010->last_context_run = ctx;
1371+ ctx->update_qp = false;
1372+ }
1373+
1374+ /* Set I/O Buffer addresses */
1375+ reg = (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 0);
1376+
1377+ if (ctx->out_queue.crop_set) {
1378+ luma_crop_offset = ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top +
1379+ ctx->out_queue.crop.left;
1380+
1381+ if (ctx->out_queue.fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422) {
1382+ chroma_crop_offset =
1383+ ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top
1384+ + ctx->out_queue.crop.left;
1385+ } else {
1386+ chroma_crop_offset =
1387+ ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top / 2
1388+ + ctx->out_queue.crop.left;
1389+ }
1390+
1391+ dprintk(e5010, 1, "Luma crop offset : %x, chroma crop offset : %x\n",
1392+ luma_crop_offset, chroma_crop_offset);
1393+ }
1394+
1395+ ret = e5010_hw_set_input_luma_addr(e5010->core_base, reg + luma_crop_offset);
1396+ if (ret || !reg) {
1397+ v4l2_err(&e5010->v4l2_dev, "failed to set input luma address\n");
1398+ goto device_busy_err;
1399+ }
1400+
1401+ if (num_planes == 1)
1402+ reg += (ctx->out_queue.bytesperline[0]) * (ctx->out_queue.height);
1403+ else
1404+ reg = (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 1);
1405+
1406+ dprintk(e5010, 3,
1407+ "ctx: 0x%p, luma_addr: 0x%x, chroma_addr: 0x%x, out_addr: 0x%x\n",
1408+ ctx, (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 0) + luma_crop_offset,
1409+ reg + chroma_crop_offset, (u32)vb2_dma_contig_plane_dma_addr(&d_vb->vb2_buf, 0));
1410+
1411+ dprintk(e5010, 3,
1412+ "ctx: 0x%p, buf indices: src_index: %d, dst_index: %d\n",
1413+ ctx, s_vb->vb2_buf.index, d_vb->vb2_buf.index);
1414+
1415+ ret = e5010_hw_set_input_chroma_addr(e5010->core_base, reg + chroma_crop_offset);
1416+ if (ret || !reg) {
1417+ v4l2_err(&e5010->v4l2_dev, "failed to set input chroma address\n");
1418+ goto device_busy_err;
1419+ }
1420+
1421+ reg = (u32)vb2_dma_contig_plane_dma_addr(&d_vb->vb2_buf, 0);
1422+ reg += HEADER_SIZE;
1423+ ret = e5010_hw_set_output_base_addr(e5010->core_base, reg);
1424+ if (ret || !reg) {
1425+ v4l2_err(&e5010->v4l2_dev, "failed to set output base address\n");
1426+ goto device_busy_err;
1427+ }
1428+
1429+ /* Set input settings */
1430+ ret = e5010_hw_set_horizontal_size(e5010->core_base, ctx->out_queue.crop.width - 1);
1431+ if (ret) {
1432+ v4l2_err(&e5010->v4l2_dev, "failed to set input width\n");
1433+ goto device_busy_err;
1434+ }
1435+
1436+ ret = e5010_hw_set_vertical_size(e5010->core_base, ctx->out_queue.crop.height - 1);
1437+ if (ret) {
1438+ v4l2_err(&e5010->v4l2_dev, "failed to set input width\n");
1439+ goto device_busy_err;
1440+ }
1441+
1442+ ret = e5010_hw_set_luma_stride(e5010->core_base, ctx->out_queue.bytesperline[0]);
1443+ if (ret) {
1444+ v4l2_err(&e5010->v4l2_dev, "failed to set luma stride\n");
1445+ goto device_busy_err;
1446+ }
1447+
1448+ ret = e5010_hw_set_chroma_stride(e5010->core_base, ctx->out_queue.bytesperline[0]);
1449+ if (ret) {
1450+ v4l2_err(&e5010->v4l2_dev, "failed to set chroma stride\n");
1451+ goto device_busy_err;
1452+ }
1453+
1454+ ret = e5010_set_input_subsampling(e5010->core_base, ctx->out_queue.fmt->subsampling);
1455+ if (ret) {
1456+ v4l2_err(&e5010->v4l2_dev, "failed to set input subsampling\n");
1457+ goto device_busy_err;
1458+ }
1459+
1460+ ret = e5010_hw_set_chroma_order(e5010->core_base, ctx->out_queue.fmt->chroma_order);
1461+ if (ret) {
1462+ v4l2_err(&e5010->v4l2_dev, "failed to set chroma order\n");
1463+ goto device_busy_err;
1464+ }
1465+
1466+ e5010_hw_set_output_max_size(e5010->core_base, d_vb->planes[0].length);
1467+ e5010_hw_encode_start(e5010->core_base, 1);
1468+
1469+ spin_unlock_irqrestore(&e5010->hw_lock, flags);
1470+
1471+ return;
1472+
1473+device_busy_err:
1474+ e5010_reset(e5010->dev, e5010->core_base, e5010->mmu_base);
1475+
1476+no_ready_buf_err:
1477+ if (s_vb) {
1478+ v4l2_m2m_src_buf_remove_by_buf(ctx->fh.m2m_ctx, s_vb);
1479+ v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_ERROR);
1480+ }
1481+
1482+ if (d_vb) {
1483+ v4l2_m2m_dst_buf_remove_by_buf(ctx->fh.m2m_ctx, d_vb);
1484+ /* Payload set to 1 since 0 payload can trigger EOS */
1485+ vb2_set_plane_payload(&d_vb->vb2_buf, 0, 1);
1486+ v4l2_m2m_buf_done(d_vb, VB2_BUF_STATE_ERROR);
1487+ }
1488+ v4l2_m2m_job_finish(e5010->m2m_dev, ctx->fh.m2m_ctx);
1489+ spin_unlock_irqrestore(&e5010->hw_lock, flags);
1490+}
1491+
1492+#ifdef CONFIG_PM
1493+static int e5010_runtime_resume(struct device *dev)
1494+{
1495+ struct e5010_dev *e5010 = dev_get_drvdata(dev);
1496+ int ret;
1497+
1498+ ret = clk_prepare_enable(e5010->clk);
1499+ if (ret < 0) {
1500+ v4l2_err(&e5010->v4l2_dev, "failed to enable clock\n");
1501+ return ret;
1502+ }
1503+
1504+ return 0;
1505+}
1506+
1507+static int e5010_runtime_suspend(struct device *dev)
1508+{
1509+ struct e5010_dev *e5010 = dev_get_drvdata(dev);
1510+
1511+ clk_disable_unprepare(e5010->clk);
1512+
1513+ return 0;
1514+}
1515+#endif
1516+
1517+#ifdef CONFIG_PM_SLEEP
1518+static int e5010_suspend(struct device *dev)
1519+{
1520+ struct e5010_dev *e5010 = dev_get_drvdata(dev);
1521+
1522+ v4l2_m2m_suspend(e5010->m2m_dev);
1523+
1524+ return pm_runtime_force_suspend(dev);
1525+}
1526+
1527+static int e5010_resume(struct device *dev)
1528+{
1529+ struct e5010_dev *e5010 = dev_get_drvdata(dev);
1530+ int ret;
1531+
1532+ ret = pm_runtime_force_resume(dev);
1533+ if (ret < 0)
1534+ return ret;
1535+
1536+ ret = e5010_init_device(e5010);
1537+ if (ret) {
1538+ dev_err(dev, "Failed to re-enable e5010 device\n");
1539+ return ret;
1540+ }
1541+
1542+ v4l2_m2m_resume(e5010->m2m_dev);
1543+
1544+ return ret;
1545+}
1546+#endif
1547+
1548+static const struct dev_pm_ops e5010_pm_ops = {
1549+ SET_RUNTIME_PM_OPS(e5010_runtime_suspend,
1550+ e5010_runtime_resume, NULL)
1551+ SET_SYSTEM_SLEEP_PM_OPS(e5010_suspend, e5010_resume)
1552+};
1553+
1554+static const struct v4l2_ioctl_ops e5010_ioctl_ops = {
1555+ .vidioc_querycap = e5010_querycap,
1556+
1557+ .vidioc_enum_fmt_vid_cap = e5010_enum_fmt,
1558+ .vidioc_g_fmt_vid_cap_mplane = e5010_g_fmt,
1559+ .vidioc_try_fmt_vid_cap_mplane = e5010_try_fmt,
1560+ .vidioc_s_fmt_vid_cap_mplane = e5010_s_fmt,
1561+
1562+ .vidioc_enum_fmt_vid_out = e5010_enum_fmt,
1563+ .vidioc_g_fmt_vid_out_mplane = e5010_g_fmt,
1564+ .vidioc_try_fmt_vid_out_mplane = e5010_try_fmt,
1565+ .vidioc_s_fmt_vid_out_mplane = e5010_s_fmt,
1566+
1567+ .vidioc_g_selection = e5010_g_selection,
1568+ .vidioc_s_selection = e5010_s_selection,
1569+
1570+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1571+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1572+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1573+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
1574+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
1575+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
1576+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
1577+
1578+ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
1579+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
1580+ .vidioc_log_status = v4l2_ctrl_log_status,
1581+
1582+ .vidioc_subscribe_event = e5010_subscribe_event,
1583+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1584+ .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
1585+ .vidioc_encoder_cmd = e5010_encoder_cmd,
1586+
1587+ .vidioc_enum_framesizes = e5010_enum_framesizes,
1588+};
1589+
1590+static const struct vb2_ops e5010_video_ops = {
1591+ .queue_setup = e5010_queue_setup,
1592+ .buf_queue = e5010_buf_queue,
1593+ .buf_finish = e5010_buf_finish,
1594+ .buf_prepare = e5010_buf_prepare,
1595+ .buf_out_validate = e5010_buf_out_validate,
1596+ .wait_prepare = vb2_ops_wait_prepare,
1597+ .wait_finish = vb2_ops_wait_finish,
1598+ .start_streaming = e5010_start_streaming,
1599+ .stop_streaming = e5010_stop_streaming,
1600+};
1601+
1602+static const struct v4l2_file_operations e5010_fops = {
1603+ .owner = THIS_MODULE,
1604+ .open = e5010_open,
1605+ .release = e5010_release,
1606+ .poll = v4l2_m2m_fop_poll,
1607+ .unlocked_ioctl = video_ioctl2,
1608+ .mmap = v4l2_m2m_fop_mmap,
1609+};
1610+
1611+static const struct v4l2_m2m_ops e5010_m2m_ops = {
1612+ .device_run = e5010_device_run,
1613+};
1614+
1615+static const struct of_device_id e5010_of_match[] = {
1616+ {.compatible = "img,e5010-jpeg-enc"}, { /* end */},
1617+};
1618+MODULE_DEVICE_TABLE(of, e5010_of_match);
1619+
1620+static struct platform_driver e5010_driver = {
1621+ .probe = e5010_probe,
1622+ .remove_new = e5010_remove,
1623+ .driver = {
1624+ .name = E5010_MODULE_NAME,
1625+ .of_match_table = e5010_of_match,
1626+ .pm = &e5010_pm_ops,
1627+ },
1628+};
1629+module_platform_driver(e5010_driver);
1630+
1631+MODULE_LICENSE("GPL");
1632+MODULE_DESCRIPTION("Imagination E5010 JPEG encoder driver");
drivers/media/platform/imagination/e5010-jpeg-enc.h+168−0
@@ -0,0 +1,168 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * Imagination E5010 JPEG Encoder driver.
4+ *
5+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
6+ *
7+ * Author: David Huang <d-huang@ti.com>
8+ * Author: Devarsh Thakkar <devarsht@ti.com>
9+ */
10+
11+#include <media/v4l2-ctrls.h>
12+#include <media/v4l2-device.h>
13+#include <media/v4l2-fh.h>
14+
15+#ifndef _E5010_JPEG_ENC_H
16+#define _E5010_JPEG_ENC_H
17+
18+#define MAX_PLANES 2
19+#define HEADER_SIZE 0x025D
20+#define MIN_DIMENSION 64
21+#define MAX_DIMENSION 8192
22+#define DEFAULT_WIDTH 640
23+#define DEFAULT_HEIGHT 480
24+#define E5010_MODULE_NAME "e5010"
25+#define JPEG_MAX_BYTES_PER_PIXEL 2
26+
27+/* JPEG marker definitions */
28+#define START_OF_IMAGE 0xFFD8
29+#define SOF_BASELINE_DCT 0xFFC0
30+#define END_OF_IMAGE 0xFFD9
31+#define START_OF_SCAN 0xFFDA
32+
33+/* Definitions for the huffman table specification in the Marker segment */
34+#define DHT_MARKER 0xFFC4
35+#define LH_DC 0x001F
36+#define LH_AC 0x00B5
37+
38+/* Definitions for the quantization table specification in the Marker segment */
39+#define DQT_MARKER 0xFFDB
40+#define ACMAX 0x03FF
41+#define DCMAX 0x07FF
42+
43+/* Length and precision of the quantization table parameters */
44+#define LQPQ 0x00430
45+#define QMAX 255
46+
47+/* Misc JPEG header definitions */
48+#define UC_NUM_COMP 3
49+#define PRECISION 8
50+#define HORZ_SAMPLING_FACTOR (2 << 4)
51+#define VERT_SAMPLING_FACTOR_422 1
52+#define VERT_SAMPLING_FACTOR_420 2
53+#define COMPONENTS_IN_SCAN 3
54+#define PELS_IN_BLOCK 64
55+
56+/* Used for Qp table generation */
57+#define LUMINOSITY 10
58+#define CONTRAST 1
59+#define INCREASE 2
60+#define QP_TABLE_SIZE (8 * 8)
61+#define QP_TABLE_FIELD_OFFSET 0x04
62+
63+/*
64+ * vb2 queue structure
65+ * contains queue data information
66+ *
67+ * @fmt: format info
68+ * @width: frame width
69+ * @height: frame height
70+ * @bytesperline: bytes per line in memory
71+ * @size_image: image size in memory
72+ */
73+struct e5010_q_data {
74+ struct e5010_fmt *fmt;
75+ u32 width;
76+ u32 height;
77+ u32 width_adjusted;
78+ u32 height_adjusted;
79+ u32 sizeimage[MAX_PLANES];
80+ u32 bytesperline[MAX_PLANES];
81+ u32 sequence;
82+ struct v4l2_rect crop;
83+ bool crop_set;
84+};
85+
86+/*
87+ * Driver device structure
88+ * Holds all memory handles and global parameters
89+ * Shared by all instances
90+ */
91+struct e5010_dev {
92+ struct device *dev;
93+ struct v4l2_device v4l2_dev;
94+ struct v4l2_m2m_dev *m2m_dev;
95+ struct video_device *vdev;
96+ void __iomem *core_base;
97+ void __iomem *mmu_base;
98+ struct clk *clk;
99+ struct e5010_context *last_context_run;
100+ /* Protect access to device data */
101+ struct mutex mutex;
102+ /* Protect access to hardware*/
103+ spinlock_t hw_lock;
104+};
105+
106+/*
107+ * Driver context structure
108+ * One of these exists for every m2m context
109+ * Holds context specific data
110+ */
111+struct e5010_context {
112+ struct v4l2_fh fh;
113+ struct e5010_dev *e5010;
114+ struct e5010_q_data out_queue;
115+ struct e5010_q_data cap_queue;
116+ int quality;
117+ bool update_qp;
118+ struct v4l2_ctrl_handler ctrl_handler;
119+ u8 luma_qp[QP_TABLE_SIZE];
120+ u8 chroma_qp[QP_TABLE_SIZE];
121+};
122+
123+/*
124+ * Buffer structure
125+ * Contains info for all buffers
126+ */
127+struct e5010_buffer {
128+ struct v4l2_m2m_buffer buffer;
129+};
130+
131+enum {
132+ CHROMA_ORDER_CB_CR = 0, //UV ordering
133+ CHROMA_ORDER_CR_CB = 1, //VU ordering
134+};
135+
136+enum {
137+ SUBSAMPLING_420 = 1,
138+ SUBSAMPLING_422 = 2,
139+};
140+
141+/*
142+ * e5010 format structure
143+ * contains format information
144+ */
145+struct e5010_fmt {
146+ u32 fourcc;
147+ unsigned int num_planes;
148+ unsigned int type;
149+ u32 subsampling;
150+ u32 chroma_order;
151+ const struct v4l2_frmsize_stepwise frmsize;
152+};
153+
154+/*
155+ * struct e5010_ctrl - contains info for each supported v4l2 control
156+ */
157+struct e5010_ctrl {
158+ unsigned int cid;
159+ enum v4l2_ctrl_type type;
160+ unsigned char name[32];
161+ int minimum;
162+ int maximum;
163+ int step;
164+ int default_value;
165+ unsigned char compound;
166+};
167+
168+#endif
drivers/media/platform/imagination/e5010-mmu-regs.h+311−0
@@ -0,0 +1,311 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * Imagination E5010 JPEG Encoder driver.
4+ *
5+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
6+ *
7+ * Author: David Huang <d-huang@ti.com>
8+ * Author: Devarsh Thakkar <devarsht@ti.com>
9+ */
10+
11+#ifndef _E5010_MMU_REGS_H
12+#define _E5010_MMU_REGS_H
13+
14+#define MMU_MMU_DIR_BASE_ADDR_OFFSET (0x0020)
15+#define MMU_MMU_DIR_BASE_ADDR_STRIDE (4)
16+#define MMU_MMU_DIR_BASE_ADDR_NO_ENTRIES (4)
17+
18+#define MMU_MMU_DIR_BASE_ADDR_MMU_DIR_BASE_ADDR_MASK (0xFFFFFFFF)
19+#define MMU_MMU_DIR_BASE_ADDR_MMU_DIR_BASE_ADDR_SHIFT (0)
20+
21+#define MMU_MMU_TILE_CFG_OFFSET (0x0040)
22+#define MMU_MMU_TILE_CFG_STRIDE (4)
23+#define MMU_MMU_TILE_CFG_NO_ENTRIES (4)
24+
25+#define MMU_MMU_TILE_CFG_TILE_128INTERLEAVE_MASK (0x00000010)
26+#define MMU_MMU_TILE_CFG_TILE_128INTERLEAVE_SHIFT (4)
27+
28+#define MMU_MMU_TILE_CFG_TILE_ENABLE_MASK (0x00000008)
29+#define MMU_MMU_TILE_CFG_TILE_ENABLE_SHIFT (3)
30+
31+#define MMU_MMU_TILE_CFG_TILE_STRIDE_MASK (0x00000007)
32+#define MMU_MMU_TILE_CFG_TILE_STRIDE_SHIFT (0)
33+
34+#define MMU_MMU_TILE_MIN_ADDR_OFFSET (0x0050)
35+#define MMU_MMU_TILE_MIN_ADDR_STRIDE (4)
36+#define MMU_MMU_TILE_MIN_ADDR_NO_ENTRIES (4)
37+
38+#define MMU_MMU_TILE_MIN_ADDR_TILE_MIN_ADDR_MASK (0xFFFFFFFF)
39+#define MMU_MMU_TILE_MIN_ADDR_TILE_MIN_ADDR_SHIFT (0)
40+
41+#define MMU_MMU_TILE_MAX_ADDR_OFFSET (0x0060)
42+#define MMU_MMU_TILE_MAX_ADDR_STRIDE (4)
43+#define MMU_MMU_TILE_MAX_ADDR_NO_ENTRIES (4)
44+
45+#define MMU_MMU_TILE_MAX_ADDR_TILE_MAX_ADDR_MASK (0xFFFFFFFF)
46+#define MMU_MMU_TILE_MAX_ADDR_TILE_MAX_ADDR_SHIFT (0)
47+
48+#define MMU_MMU_CONTROL0_OFFSET (0x0000)
49+
50+#define MMU_MMU_CONTROL0_MMU_TILING_SCHEME_MASK (0x00000001)
51+#define MMU_MMU_CONTROL0_MMU_TILING_SCHEME_SHIFT (0)
52+
53+#define MMU_MMU_CONTROL0_MMU_CACHE_POLICY_MASK (0x00000100)
54+#define MMU_MMU_CONTROL0_MMU_CACHE_POLICY_SHIFT (8)
55+
56+#define MMU_MMU_CONTROL0_FORCE_CACHE_POLICY_BYPASS_MASK (0x00000200)
57+#define MMU_MMU_CONTROL0_FORCE_CACHE_POLICY_BYPASS_SHIFT (9)
58+
59+#define MMU_MMU_CONTROL0_STALL_ON_PROTOCOL_FAULT_MASK (0x00001000)
60+#define MMU_MMU_CONTROL0_STALL_ON_PROTOCOL_FAULT_SHIFT (12)
61+
62+#define MMU_MMU_CONTROL1_OFFSET (0x0008)
63+
64+#define MMU_MMU_CONTROL1_MMU_FLUSH_MASK (0x00000008)
65+#define MMU_MMU_CONTROL1_MMU_FLUSH_SHIFT (3)
66+#define MMU_MMU_CONTROL1_MMU_FLUSH_NO_REPS (4)
67+#define MMU_MMU_CONTROL1_MMU_FLUSH_SIZE (1)
68+
69+#define MMU_MMU_CONTROL1_MMU_INVALDC_MASK (0x00000800)
70+#define MMU_MMU_CONTROL1_MMU_INVALDC_SHIFT (11)
71+#define MMU_MMU_CONTROL1_MMU_INVALDC_NO_REPS (4)
72+#define MMU_MMU_CONTROL1_MMU_INVALDC_SIZE (1)
73+
74+#define MMU_MMU_CONTROL1_MMU_FAULT_CLEAR_MASK (0x00010000)
75+#define MMU_MMU_CONTROL1_MMU_FAULT_CLEAR_SHIFT (16)
76+
77+#define MMU_MMU_CONTROL1_PROTOCOL_FAULT_CLEAR_MASK (0x00100000)
78+#define MMU_MMU_CONTROL1_PROTOCOL_FAULT_CLEAR_SHIFT (20)
79+
80+#define MMU_MMU_CONTROL1_MMU_PAUSE_SET_MASK (0x01000000)
81+#define MMU_MMU_CONTROL1_MMU_PAUSE_SET_SHIFT (24)
82+
83+#define MMU_MMU_CONTROL1_MMU_PAUSE_CLEAR_MASK (0x02000000)
84+#define MMU_MMU_CONTROL1_MMU_PAUSE_CLEAR_SHIFT (25)
85+
86+#define MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK (0x10000000)
87+#define MMU_MMU_CONTROL1_MMU_SOFT_RESET_SHIFT (28)
88+
89+#define MMU_MMU_BANK_INDEX_OFFSET (0x0010)
90+
91+#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_MASK (0xC0000000)
92+#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_SHIFT (30)
93+#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_NO_REPS (16)
94+#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_SIZE (2)
95+
96+#define MMU_REQUEST_PRIORITY_ENABLE_OFFSET (0x0018)
97+
98+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_MASK (0x00008000)
99+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_SHIFT (15)
100+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_NO_REPS (16)
101+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_SIZE (1)
102+
103+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_MMU_PRIORITY_ENABLE_MASK (0x00010000)
104+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_MMU_PRIORITY_ENABLE_SHIFT (16)
105+
106+#define MMU_REQUEST_LIMITED_THROUGHPUT_OFFSET (0x001C)
107+
108+#define MMU_REQUEST_LIMITED_THROUGHPUT_LIMITED_WORDS_MASK (0x000003FF)
109+#define MMU_REQUEST_LIMITED_THROUGHPUT_LIMITED_WORDS_SHIFT (0)
110+
111+#define MMU_REQUEST_LIMITED_THROUGHPUT_REQUEST_GAP_MASK (0x0FFF0000)
112+#define MMU_REQUEST_LIMITED_THROUGHPUT_REQUEST_GAP_SHIFT (16)
113+
114+#define MMU_MMU_ADDRESS_CONTROL_OFFSET (0x0070)
115+#define MMU_MMU_ADDRESS_CONTROL_TRUSTED (IMG_TRUE)
116+
117+#define MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_MASK (0x00000001)
118+#define MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_SHIFT (0)
119+
120+#define MMU_MMU_ADDRESS_CONTROL_MMU_ENABLE_EXT_ADDRESSING_MASK (0x00000010)
121+#define MMU_MMU_ADDRESS_CONTROL_MMU_ENABLE_EXT_ADDRESSING_SHIFT (4)
122+
123+#define MMU_MMU_ADDRESS_CONTROL_UPPER_ADDRESS_FIXED_MASK (0x00FF0000)
124+#define MMU_MMU_ADDRESS_CONTROL_UPPER_ADDRESS_FIXED_SHIFT (16)
125+
126+#define MMU_MMU_CONFIG0_OFFSET (0x0080)
127+
128+#define MMU_MMU_CONFIG0_NUM_REQUESTORS_MASK (0x0000000F)
129+#define MMU_MMU_CONFIG0_NUM_REQUESTORS_SHIFT (0)
130+
131+#define MMU_MMU_CONFIG0_EXTENDED_ADDR_RANGE_MASK (0x000000F0)
132+#define MMU_MMU_CONFIG0_EXTENDED_ADDR_RANGE_SHIFT (4)
133+
134+#define MMU_MMU_CONFIG0_GROUP_OVERRIDE_SIZE_MASK (0x00000700)
135+#define MMU_MMU_CONFIG0_GROUP_OVERRIDE_SIZE_SHIFT (8)
136+
137+#define MMU_MMU_CONFIG0_ADDR_COHERENCY_SUPPORTED_MASK (0x00001000)
138+#define MMU_MMU_CONFIG0_ADDR_COHERENCY_SUPPORTED_SHIFT (12)
139+
140+#define MMU_MMU_CONFIG0_MMU_SUPPORTED_MASK (0x00002000)
141+#define MMU_MMU_CONFIG0_MMU_SUPPORTED_SHIFT (13)
142+
143+#define MMU_MMU_CONFIG0_TILE_ADDR_GRANULARITY_MASK (0x001F0000)
144+#define MMU_MMU_CONFIG0_TILE_ADDR_GRANULARITY_SHIFT (16)
145+
146+#define MMU_MMU_CONFIG0_NO_READ_REORDER_MASK (0x00200000)
147+#define MMU_MMU_CONFIG0_NO_READ_REORDER_SHIFT (21)
148+
149+#define MMU_MMU_CONFIG0_TAGS_SUPPORTED_MASK (0xFFC00000)
150+#define MMU_MMU_CONFIG0_TAGS_SUPPORTED_SHIFT (22)
151+
152+#define MMU_MMU_CONFIG1_OFFSET (0x0084)
153+
154+#define MMU_MMU_CONFIG1_PAGE_SIZE_MASK (0x0000000F)
155+#define MMU_MMU_CONFIG1_PAGE_SIZE_SHIFT (0)
156+
157+#define MMU_MMU_CONFIG1_PAGE_CACHE_ENTRIES_MASK (0x0000FF00)
158+#define MMU_MMU_CONFIG1_PAGE_CACHE_ENTRIES_SHIFT (8)
159+
160+#define MMU_MMU_CONFIG1_DIR_CACHE_ENTRIES_MASK (0x001F0000)
161+#define MMU_MMU_CONFIG1_DIR_CACHE_ENTRIES_SHIFT (16)
162+
163+#define MMU_MMU_CONFIG1_BANDWIDTH_COUNT_SUPPORTED_MASK (0x01000000)
164+#define MMU_MMU_CONFIG1_BANDWIDTH_COUNT_SUPPORTED_SHIFT (24)
165+
166+#define MMU_MMU_CONFIG1_STALL_COUNT_SUPPORTED_MASK (0x02000000)
167+#define MMU_MMU_CONFIG1_STALL_COUNT_SUPPORTED_SHIFT (25)
168+
169+#define MMU_MMU_CONFIG1_LATENCY_COUNT_SUPPORTED_MASK (0x04000000)
170+#define MMU_MMU_CONFIG1_LATENCY_COUNT_SUPPORTED_SHIFT (26)
171+
172+#define MMU_MMU_STATUS0_OFFSET (0x0088)
173+
174+#define MMU_MMU_STATUS0_MMU_PF_N_RW_MASK (0x00000001)
175+#define MMU_MMU_STATUS0_MMU_PF_N_RW_SHIFT (0)
176+
177+#define MMU_MMU_STATUS0_MMU_FAULT_ADDR_MASK (0xFFFFF000)
178+#define MMU_MMU_STATUS0_MMU_FAULT_ADDR_SHIFT (12)
179+
180+#define MMU_MMU_STATUS1_OFFSET (0x008C)
181+
182+#define MMU_MMU_STATUS1_MMU_FAULT_REQ_STAT_MASK (0x0000FFFF)
183+#define MMU_MMU_STATUS1_MMU_FAULT_REQ_STAT_SHIFT (0)
184+
185+#define MMU_MMU_STATUS1_MMU_FAULT_REQ_ID_MASK (0x000F0000)
186+#define MMU_MMU_STATUS1_MMU_FAULT_REQ_ID_SHIFT (16)
187+
188+#define MMU_MMU_STATUS1_MMU_FAULT_INDEX_MASK (0x03000000)
189+#define MMU_MMU_STATUS1_MMU_FAULT_INDEX_SHIFT (24)
190+
191+#define MMU_MMU_STATUS1_MMU_FAULT_RNW_MASK (0x10000000)
192+#define MMU_MMU_STATUS1_MMU_FAULT_RNW_SHIFT (28)
193+
194+#define MMU_MMU_MEM_REQ_OFFSET (0x0090)
195+
196+#define MMU_MMU_MEM_REQ_TAG_OUTSTANDING_MASK (0x000003FF)
197+#define MMU_MMU_MEM_REQ_TAG_OUTSTANDING_SHIFT (0)
198+
199+#define MMU_MMU_MEM_REQ_EXT_WRRESP_FAULT_MASK (0x00001000)
200+#define MMU_MMU_MEM_REQ_EXT_WRRESP_FAULT_SHIFT (12)
201+
202+#define MMU_MMU_MEM_REQ_EXT_RDRESP_FAULT_MASK (0x00002000)
203+#define MMU_MMU_MEM_REQ_EXT_RDRESP_FAULT_SHIFT (13)
204+
205+#define MMU_MMU_MEM_REQ_EXT_READ_BURST_FAULT_MASK (0x00004000)
206+#define MMU_MMU_MEM_REQ_EXT_READ_BURST_FAULT_SHIFT (14)
207+
208+#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_MASK (0x80000000)
209+#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_SHIFT (31)
210+#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_NO_REPS (16)
211+#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_SIZE (1)
212+
213+#define MMU_MMU_FAULT_SELECT_OFFSET (0x00A0)
214+
215+#define MMU_MMU_FAULT_SELECT_MMU_FAULT_SELECT_MASK (0x0000000F)
216+#define MMU_MMU_FAULT_SELECT_MMU_FAULT_SELECT_SHIFT (0)
217+
218+#define MMU_PROTOCOL_FAULT_OFFSET (0x00A8)
219+
220+#define MMU_PROTOCOL_FAULT_FAULT_PAGE_BREAK_MASK (0x00000001)
221+#define MMU_PROTOCOL_FAULT_FAULT_PAGE_BREAK_SHIFT (0)
222+
223+#define MMU_PROTOCOL_FAULT_FAULT_WRITE_MASK (0x00000010)
224+#define MMU_PROTOCOL_FAULT_FAULT_WRITE_SHIFT (4)
225+
226+#define MMU_PROTOCOL_FAULT_FAULT_READ_MASK (0x00000020)
227+#define MMU_PROTOCOL_FAULT_FAULT_READ_SHIFT (5)
228+
229+#define MMU_TOTAL_READ_REQ_OFFSET (0x0100)
230+
231+#define MMU_TOTAL_READ_REQ_TOTAL_READ_REQ_MASK (0xFFFFFFFF)
232+#define MMU_TOTAL_READ_REQ_TOTAL_READ_REQ_SHIFT (0)
233+
234+#define MMU_TOTAL_WRITE_REQ_OFFSET (0x0104)
235+
236+#define MMU_TOTAL_WRITE_REQ_TOTAL_WRITE_REQ_MASK (0xFFFFFFFF)
237+#define MMU_TOTAL_WRITE_REQ_TOTAL_WRITE_REQ_SHIFT (0)
238+
239+#define MMU_READS_LESS_64_REQ_OFFSET (0x0108)
240+
241+#define MMU_READS_LESS_64_REQ_READS_LESS_64_REQ_MASK (0xFFFFFFFF)
242+#define MMU_READS_LESS_64_REQ_READS_LESS_64_REQ_SHIFT (0)
243+
244+#define MMU_WRITES_LESS_64_REQ_OFFSET (0x010C)
245+
246+#define MMU_WRITES_LESS_64_REQ_WRITES_LESS_64_REQ_MASK (0xFFFFFFFF)
247+#define MMU_WRITES_LESS_64_REQ_WRITES_LESS_64_REQ_SHIFT (0)
248+
249+#define MMU_EXT_CMD_STALL_OFFSET (0x0120)
250+
251+#define MMU_EXT_CMD_STALL_EXT_CMD_STALL_MASK (0xFFFFFFFF)
252+#define MMU_EXT_CMD_STALL_EXT_CMD_STALL_SHIFT (0)
253+
254+#define MMU_WRITE_REQ_STALL_OFFSET (0x0124)
255+
256+#define MMU_WRITE_REQ_STALL_WRITE_REQ_STALL_MASK (0xFFFFFFFF)
257+#define MMU_WRITE_REQ_STALL_WRITE_REQ_STALL_SHIFT (0)
258+
259+#define MMU_MMU_MISS_STALL_OFFSET (0x0128)
260+
261+#define MMU_MMU_MISS_STALL_MMU_MISS_STALL_MASK (0xFFFFFFFF)
262+#define MMU_MMU_MISS_STALL_MMU_MISS_STALL_SHIFT (0)
263+
264+#define MMU_ADDRESS_STALL_OFFSET (0x012C)
265+
266+#define MMU_ADDRESS_STALL_ADDRESS_STALL_MASK (0xFFFFFFFF)
267+#define MMU_ADDRESS_STALL_ADDRESS_STALL_SHIFT (0)
268+
269+#define MMU_TAG_STALL_OFFSET (0x0130)
270+
271+#define MMU_TAG_STALL_TAG_STALL_MASK (0xFFFFFFFF)
272+#define MMU_TAG_STALL_TAG_STALL_SHIFT (0)
273+
274+#define MMU_PEAK_READ_OUTSTANDING_OFFSET (0x0140)
275+
276+#define MMU_PEAK_READ_OUTSTANDING_PEAK_TAG_OUTSTANDING_MASK (0x000003FF)
277+#define MMU_PEAK_READ_OUTSTANDING_PEAK_TAG_OUTSTANDING_SHIFT (0)
278+
279+#define MMU_PEAK_READ_OUTSTANDING_PEAK_READ_LATENCY_MASK (0xFFFF0000)
280+#define MMU_PEAK_READ_OUTSTANDING_PEAK_READ_LATENCY_SHIFT (16)
281+
282+#define MMU_AVERAGE_READ_LATENCY_OFFSET (0x0144)
283+
284+#define MMU_AVERAGE_READ_LATENCY_AVERAGE_READ_LATENCY_MASK (0xFFFFFFFF)
285+#define MMU_AVERAGE_READ_LATENCY_AVERAGE_READ_LATENCY_SHIFT (0)
286+
287+#define MMU_STATISTICS_CONTROL_OFFSET (0x0160)
288+
289+#define MMU_STATISTICS_CONTROL_BANDWIDTH_STATS_INIT_MASK (0x00000001)
290+#define MMU_STATISTICS_CONTROL_BANDWIDTH_STATS_INIT_SHIFT (0)
291+
292+#define MMU_STATISTICS_CONTROL_STALL_STATS_INIT_MASK (0x00000002)
293+#define MMU_STATISTICS_CONTROL_STALL_STATS_INIT_SHIFT (1)
294+
295+#define MMU_STATISTICS_CONTROL_LATENCY_STATS_INIT_MASK (0x00000004)
296+#define MMU_STATISTICS_CONTROL_LATENCY_STATS_INIT_SHIFT (2)
297+
298+#define MMU_MMU_VERSION_OFFSET (0x01D0)
299+
300+#define MMU_MMU_VERSION_MMU_MAJOR_REV_MASK (0x00FF0000)
301+#define MMU_MMU_VERSION_MMU_MAJOR_REV_SHIFT (16)
302+
303+#define MMU_MMU_VERSION_MMU_MINOR_REV_MASK (0x0000FF00)
304+#define MMU_MMU_VERSION_MMU_MINOR_REV_SHIFT (8)
305+
306+#define MMU_MMU_VERSION_MMU_MAINT_REV_MASK (0x000000FF)
307+#define MMU_MMU_VERSION_MMU_MAINT_REV_SHIFT (0)
308+
309+#define MMU_BYTE_SIZE (0x01D4)
310+
311+#endif
drivers/media/platform/intel/pxa_camera.c+8−7
@@ -43,6 +43,7 @@ · 42 unmodified lines
4343 #include <linux/videodev2.h>
4444
4545 #include <linux/platform_data/media/camera-pxa.h>
46+#include <linux/workqueue.h>
4647
4748 #define PXA_CAM_VERSION "0.0.6"
4849 #define PXA_CAM_DRV_NAME "pxa27x-camera"
@@ -683,7 +684,7 @@ struct pxa_camera_dev { · 634 unmodified lines
683684 unsigned int buf_sequence;
684685
685686 struct pxa_buffer *active;
686− struct tasklet_struct task_eof;
687+ struct work_struct eof_bh_work;
687688
688689 u32 save_cicr[5];
689690 };
@@ -1146,9 +1147,9 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) · 456 unmodified lines
11461147 clk_disable_unprepare(pcdev->clk);
11471148 }
11481149
1149−static void pxa_camera_eof(struct tasklet_struct *t)
1150+static void pxa_camera_eof_bh_work(struct work_struct *t)
11501151 {
1151− struct pxa_camera_dev *pcdev = from_tasklet(pcdev, t, task_eof);
1152+ struct pxa_camera_dev *pcdev = from_work(pcdev, t, eof_bh_work);
11521153 unsigned long cifr;
11531154 struct pxa_buffer *buf;
11541155
@@ -1185,7 +1186,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) · 30 unmodified lines
11851186 if (status & CISR_EOF) {
11861187 cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM;
11871188 __raw_writel(cicr0, pcdev->base + CICR0);
1188− tasklet_schedule(&pcdev->task_eof);
1189+ queue_work(system_bh_wq, &pcdev->eof_bh_work);
11891190 }
11901191
11911192 return IRQ_HANDLED;
@@ -2383,7 +2384,7 @@ static int pxa_camera_probe(struct platform_device *pdev) · 1191 unmodified lines
23832384 }
23842385 }
23852386
2386− tasklet_setup(&pcdev->task_eof, pxa_camera_eof);
2387+ INIT_WORK(&pcdev->eof_bh_work, pxa_camera_eof_bh_work);
23872388
23882389 pxa_camera_activate(pcdev);
23892390
@@ -2409,7 +2410,7 @@ static int pxa_camera_probe(struct platform_device *pdev) · 19 unmodified lines
24092410 return 0;
24102411 exit_deactivate:
24112412 pxa_camera_deactivate(pcdev);
2412− tasklet_kill(&pcdev->task_eof);
2413+ cancel_work_sync(&pcdev->eof_bh_work);
24132414 exit_free_dma:
24142415 dma_release_channel(pcdev->dma_chans[2]);
24152416 exit_free_dma_u:
@@ -2428,7 +2429,7 @@ static void pxa_camera_remove(struct platform_device *pdev) · 12 unmodified lines
24282429 struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
24292430
24302431 pxa_camera_deactivate(pcdev);
2431− tasklet_kill(&pcdev->task_eof);
2432+ cancel_work_sync(&pcdev->eof_bh_work);
24322433 dma_release_channel(pcdev->dma_chans[0]);
24332434 dma_release_channel(pcdev->dma_chans[1]);
24342435 dma_release_channel(pcdev->dma_chans[2]);
drivers/media/platform/m2m-deinterlace.c+0−4
@@ -724,10 +724,6 @@ static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = { · 723 unmodified lines
724724 /*
725725 * Queue operations
726726 */
727−struct vb2_dc_conf {
728− struct device *dev;
729−};
730−
731727 static int deinterlace_queue_setup(struct vb2_queue *vq,
732728 unsigned int *nbuffers, unsigned int *nplanes,
733729 unsigned int sizes[], struct device *alloc_devs[])
drivers/media/platform/marvell/mcam-core.c+5−4
@@ -439,9 +439,9 @@ static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam) · 438 unmodified lines
439439 /*
440440 * Copy data out to user space in the vmalloc case
441441 */
442−static void mcam_frame_tasklet(struct tasklet_struct *t)
442+static void mcam_frame_work(struct work_struct *t)
443443 {
444− struct mcam_camera *cam = from_tasklet(cam, t, s_tasklet);
444+ struct mcam_camera *cam = from_work(cam, t, s_bh_work);
445445 int i;
446446 unsigned long flags;
447447 struct mcam_vb_buffer *buf;
@@ -493,7 +493,7 @@ static int mcam_check_dma_buffers(struct mcam_camera *cam) · 45 unmodified lines
493493
494494 static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
495495 {
496− tasklet_schedule(&cam->s_tasklet);
496+ queue_work(system_bh_wq, &cam->s_bh_work);
497497 }
498498
499499 #else /* MCAM_MODE_VMALLOC */
@@ -1305,7 +1305,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) · 805 unmodified lines
13051305 break;
13061306 case B_vmalloc:
13071307 #ifdef MCAM_MODE_VMALLOC
1308− tasklet_setup(&cam->s_tasklet, mcam_frame_tasklet);
1308+ INIT_WORK(&cam->s_bh_work, mcam_frame_work);
13091309 vq->ops = &mcam_vb2_ops;
13101310 vq->mem_ops = &vb2_vmalloc_memops;
13111311 cam->dma_setup = mcam_ctlr_dma_vmalloc;
@@ -1981,5 +1981,6 @@ int mccic_resume(struct mcam_camera *cam) · 669 unmodified lines
19811981 }
19821982 EXPORT_SYMBOL_GPL(mccic_resume);
19831983
1984+MODULE_DESCRIPTION("Marvell camera core driver");
19841985 MODULE_LICENSE("GPL v2");
19851986 MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
drivers/media/platform/marvell/mcam-core.h+2−1
@@ -9,6 +9,7 @@ · 8 unmodified lines
99
1010 #include <linux/list.h>
1111 #include <linux/clk-provider.h>
12+#include <linux/workqueue.h>
1213 #include <media/v4l2-common.h>
1314 #include <media/v4l2-ctrls.h>
1415 #include <media/v4l2-dev.h>
@@ -167,7 +168,7 @@ struct mcam_camera { · 152 unmodified lines
167168 unsigned int dma_buf_size; /* allocated size */
168169 void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */
169170 dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
170− struct tasklet_struct s_tasklet;
171+ struct work_struct s_bh_work;
171172 #endif
172173 unsigned int sequence; /* Frame sequence number */
173174 unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */
drivers/media/platform/marvell/mmp-driver.c+1−0
@@ -30,6 +30,7 @@ · 29 unmodified lines
3030
3131 MODULE_ALIAS("platform:mmp-camera");
3232 MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
33+MODULE_DESCRIPTION("Support for the camera device found on Marvell MMP processors");
3334 MODULE_LICENSE("GPL");
3435
3536 static char *mcam_clks[] = {"axi", "func", "phy"};
drivers/media/platform/mediatek/mdp3/mdp_cfg_data.c+280−0
@@ -46,6 +46,53 @@ enum mt8183_mdp_comp_id { · 45 unmodified lines
4646 MT8183_MDP_COMP_WROT1, /* 25 */
4747 };
4848
49+enum mt8188_mdp_comp_id {
50+ /* MT8188 Comp id */
51+ /* ISP */
52+ MT8188_MDP_COMP_WPEI = 0,
53+ MT8188_MDP_COMP_WPEO, /* 1 */
54+
55+ /* MDP */
56+ MT8188_MDP_COMP_CAMIN, /* 2 */
57+ MT8188_MDP_COMP_RDMA0, /* 3 */
58+ MT8188_MDP_COMP_RDMA2, /* 4 */
59+ MT8188_MDP_COMP_RDMA3, /* 5 */
60+ MT8188_MDP_COMP_FG0, /* 6 */
61+ MT8188_MDP_COMP_FG2, /* 7 */
62+ MT8188_MDP_COMP_FG3, /* 8 */
63+ MT8188_MDP_COMP_TO_SVPP2MOUT, /* 9 */
64+ MT8188_MDP_COMP_TO_SVPP3MOUT, /* 10 */
65+ MT8188_MDP_COMP_TO_WARP0MOUT, /* 11 */
66+ MT8188_MDP_COMP_VPP0_SOUT, /* 12 */
67+ MT8188_MDP_COMP_VPP1_SOUT, /* 13 */
68+ MT8188_MDP_COMP_PQ0_SOUT, /* 14 */
69+ MT8188_MDP_COMP_HDR0, /* 15 */
70+ MT8188_MDP_COMP_HDR2, /* 16 */
71+ MT8188_MDP_COMP_HDR3, /* 17 */
72+ MT8188_MDP_COMP_AAL0, /* 18 */
73+ MT8188_MDP_COMP_AAL2, /* 19 */
74+ MT8188_MDP_COMP_AAL3, /* 20 */
75+ MT8188_MDP_COMP_RSZ0, /* 21 */
76+ MT8188_MDP_COMP_RSZ2, /* 22 */
77+ MT8188_MDP_COMP_RSZ3, /* 23 */
78+ MT8188_MDP_COMP_TDSHP0, /* 24 */
79+ MT8188_MDP_COMP_TDSHP2, /* 25 */
80+ MT8188_MDP_COMP_TDSHP3, /* 26 */
81+ MT8188_MDP_COMP_COLOR0, /* 27 */
82+ MT8188_MDP_COMP_COLOR2, /* 28 */
83+ MT8188_MDP_COMP_COLOR3, /* 29 */
84+ MT8188_MDP_COMP_OVL0, /* 30 */
85+ MT8188_MDP_COMP_PAD0, /* 31 */
86+ MT8188_MDP_COMP_PAD2, /* 32 */
87+ MT8188_MDP_COMP_PAD3, /* 33 */
88+ MT8188_MDP_COMP_TCC0, /* 34 */
89+ MT8188_MDP_COMP_WROT0, /* 35 */
90+ MT8188_MDP_COMP_WROT2, /* 36 */
91+ MT8188_MDP_COMP_WROT3, /* 37 */
92+ MT8188_MDP_COMP_MERGE2, /* 38 */
93+ MT8188_MDP_COMP_MERGE3, /* 39 */
94+};
95+
4996 enum mt8195_mdp_comp_id {
5097 /* MT8195 Comp id */
5198 /* ISP */
@@ -123,6 +170,13 @@ static const struct of_device_id mt8183_mdp_probe_infra[MDP_INFRA_MAX] = { · 71 unmodified lines
123170 [MDP_INFRA_SCP] = { .compatible = "mediatek,mt8183-scp" }
124171 };
125172
173+static const struct of_device_id mt8188_mdp_probe_infra[MDP_INFRA_MAX] = {
174+ [MDP_INFRA_MMSYS] = { .compatible = "mediatek,mt8188-vppsys0" },
175+ [MDP_INFRA_MMSYS2] = { .compatible = "mediatek,mt8188-vppsys1" },
176+ [MDP_INFRA_MUTEX] = { .compatible = "mediatek,mt8188-vpp-mutex" },
177+ [MDP_INFRA_MUTEX2] = { .compatible = "mediatek,mt8188-vpp-mutex" },
178+};
179+
126180 static const struct of_device_id mt8195_mdp_probe_infra[MDP_INFRA_MAX] = {
127181 [MDP_INFRA_MMSYS] = { .compatible = "mediatek,mt8195-vppsys0" },
128182 [MDP_INFRA_MMSYS2] = { .compatible = "mediatek,mt8195-vppsys1" },
@@ -167,6 +221,40 @@ static const u32 mt8183_mutex_idx[MDP_MAX_COMP_COUNT] = { · 38 unmodified lines
167221 [MDP_COMP_CCORR0] = MUTEX_MOD_IDX_MDP_CCORR0,
168222 };
169223
224+static const u32 mt8188_mutex_idx[MDP_MAX_COMP_COUNT] = {
225+ [MDP_COMP_RDMA0] = MUTEX_MOD_IDX_MDP_RDMA0,
226+ [MDP_COMP_RDMA2] = MUTEX_MOD_IDX_MDP_RDMA2,
227+ [MDP_COMP_RDMA3] = MUTEX_MOD_IDX_MDP_RDMA3,
228+ [MDP_COMP_FG0] = MUTEX_MOD_IDX_MDP_FG0,
229+ [MDP_COMP_FG2] = MUTEX_MOD_IDX_MDP_FG2,
230+ [MDP_COMP_FG3] = MUTEX_MOD_IDX_MDP_FG3,
231+ [MDP_COMP_HDR0] = MUTEX_MOD_IDX_MDP_HDR0,
232+ [MDP_COMP_HDR2] = MUTEX_MOD_IDX_MDP_HDR2,
233+ [MDP_COMP_HDR3] = MUTEX_MOD_IDX_MDP_HDR3,
234+ [MDP_COMP_AAL0] = MUTEX_MOD_IDX_MDP_AAL0,
235+ [MDP_COMP_AAL2] = MUTEX_MOD_IDX_MDP_AAL2,
236+ [MDP_COMP_AAL3] = MUTEX_MOD_IDX_MDP_AAL3,
237+ [MDP_COMP_RSZ0] = MUTEX_MOD_IDX_MDP_RSZ0,
238+ [MDP_COMP_RSZ2] = MUTEX_MOD_IDX_MDP_RSZ2,
239+ [MDP_COMP_RSZ3] = MUTEX_MOD_IDX_MDP_RSZ3,
240+ [MDP_COMP_MERGE2] = MUTEX_MOD_IDX_MDP_MERGE2,
241+ [MDP_COMP_MERGE3] = MUTEX_MOD_IDX_MDP_MERGE3,
242+ [MDP_COMP_TDSHP0] = MUTEX_MOD_IDX_MDP_TDSHP0,
243+ [MDP_COMP_TDSHP2] = MUTEX_MOD_IDX_MDP_TDSHP2,
244+ [MDP_COMP_TDSHP3] = MUTEX_MOD_IDX_MDP_TDSHP3,
245+ [MDP_COMP_COLOR0] = MUTEX_MOD_IDX_MDP_COLOR0,
246+ [MDP_COMP_COLOR2] = MUTEX_MOD_IDX_MDP_COLOR2,
247+ [MDP_COMP_COLOR3] = MUTEX_MOD_IDX_MDP_COLOR3,
248+ [MDP_COMP_OVL0] = MUTEX_MOD_IDX_MDP_OVL0,
249+ [MDP_COMP_PAD0] = MUTEX_MOD_IDX_MDP_PAD0,
250+ [MDP_COMP_PAD2] = MUTEX_MOD_IDX_MDP_PAD2,
251+ [MDP_COMP_PAD3] = MUTEX_MOD_IDX_MDP_PAD3,
252+ [MDP_COMP_TCC0] = MUTEX_MOD_IDX_MDP_TCC0,
253+ [MDP_COMP_WROT0] = MUTEX_MOD_IDX_MDP_WROT0,
254+ [MDP_COMP_WROT2] = MUTEX_MOD_IDX_MDP_WROT2,
255+ [MDP_COMP_WROT3] = MUTEX_MOD_IDX_MDP_WROT3,
256+};
257+
170258 static const u32 mt8195_mutex_idx[MDP_MAX_COMP_COUNT] = {
171259 [MDP_COMP_RDMA0] = MUTEX_MOD_IDX_MDP_RDMA0,
172260 [MDP_COMP_RDMA1] = MUTEX_MOD_IDX_MDP_RDMA1,
@@ -288,6 +376,171 @@ static const struct mdp_comp_data mt8183_mdp_comp_data[MDP_MAX_COMP_COUNT] = { · 115 unmodified lines
288376 },
289377 };
290378
379+static const struct mdp_comp_data mt8188_mdp_comp_data[MDP_MAX_COMP_COUNT] = {
380+ [MDP_COMP_WPEI] = {
381+ {MDP_COMP_TYPE_WPEI, 0, MT8188_MDP_COMP_WPEI, MDP_MM_SUBSYS_0},
382+ {0, 0, 0}
383+ },
384+ [MDP_COMP_WPEO] = {
385+ {MDP_COMP_TYPE_EXTO, 0, MT8188_MDP_COMP_WPEO, MDP_MM_SUBSYS_0},
386+ {0, 0, 0}
387+ },
388+ [MDP_COMP_CAMIN] = {
389+ {MDP_COMP_TYPE_DL_PATH, 0, MT8188_MDP_COMP_CAMIN, MDP_MM_SUBSYS_0},
390+ {3, 3, 0}
391+ },
392+ [MDP_COMP_RDMA0] = {
393+ {MDP_COMP_TYPE_RDMA, 0, MT8188_MDP_COMP_RDMA0, MDP_MM_SUBSYS_0},
394+ {3, 0, 0}
395+ },
396+ [MDP_COMP_RDMA2] = {
397+ {MDP_COMP_TYPE_RDMA, 1, MT8188_MDP_COMP_RDMA2, MDP_MM_SUBSYS_1},
398+ {3, 0, 0}
399+ },
400+ [MDP_COMP_RDMA3] = {
401+ {MDP_COMP_TYPE_RDMA, 2, MT8188_MDP_COMP_RDMA3, MDP_MM_SUBSYS_1},
402+ {3, 0, 0}
403+ },
404+ [MDP_COMP_FG0] = {
405+ {MDP_COMP_TYPE_FG, 0, MT8188_MDP_COMP_FG0, MDP_MM_SUBSYS_0},
406+ {1, 0, 0}
407+ },
408+ [MDP_COMP_FG2] = {
409+ {MDP_COMP_TYPE_FG, 1, MT8188_MDP_COMP_FG2, MDP_MM_SUBSYS_1},
410+ {1, 0, 0}
411+ },
412+ [MDP_COMP_FG3] = {
413+ {MDP_COMP_TYPE_FG, 2, MT8188_MDP_COMP_FG3, MDP_MM_SUBSYS_1},
414+ {1, 0, 0}
415+ },
416+ [MDP_COMP_HDR0] = {
417+ {MDP_COMP_TYPE_HDR, 0, MT8188_MDP_COMP_HDR0, MDP_MM_SUBSYS_0},
418+ {1, 0, 0}
419+ },
420+ [MDP_COMP_HDR2] = {
421+ {MDP_COMP_TYPE_HDR, 1, MT8188_MDP_COMP_HDR2, MDP_MM_SUBSYS_1},
422+ {1, 0, 0}
423+ },
424+ [MDP_COMP_HDR3] = {
425+ {MDP_COMP_TYPE_HDR, 2, MT8188_MDP_COMP_HDR3, MDP_MM_SUBSYS_1},
426+ {1, 0, 0}
427+ },
428+ [MDP_COMP_AAL0] = {
429+ {MDP_COMP_TYPE_AAL, 0, MT8188_MDP_COMP_AAL0, MDP_MM_SUBSYS_0},
430+ {1, 0, 0}
431+ },
432+ [MDP_COMP_AAL2] = {
433+ {MDP_COMP_TYPE_AAL, 1, MT8188_MDP_COMP_AAL2, MDP_MM_SUBSYS_1},
434+ {1, 0, 0}
435+ },
436+ [MDP_COMP_AAL3] = {
437+ {MDP_COMP_TYPE_AAL, 2, MT8188_MDP_COMP_AAL3, MDP_MM_SUBSYS_1},
438+ {1, 0, 0}
439+ },
440+ [MDP_COMP_RSZ0] = {
441+ {MDP_COMP_TYPE_RSZ, 0, MT8188_MDP_COMP_RSZ0, MDP_MM_SUBSYS_0},
442+ {1, 0, 0}
443+ },
444+ [MDP_COMP_RSZ2] = {
445+ {MDP_COMP_TYPE_RSZ, 1, MT8188_MDP_COMP_RSZ2, MDP_MM_SUBSYS_1},
446+ {2, 0, 0},
447+ {MDP_COMP_MERGE2, true, true}
448+ },
449+ [MDP_COMP_RSZ3] = {
450+ {MDP_COMP_TYPE_RSZ, 2, MT8188_MDP_COMP_RSZ3, MDP_MM_SUBSYS_1},
451+ {2, 0, 0},
452+ {MDP_COMP_MERGE3, true, true}
453+ },
454+ [MDP_COMP_TDSHP0] = {
455+ {MDP_COMP_TYPE_TDSHP, 0, MT8188_MDP_COMP_TDSHP0, MDP_MM_SUBSYS_0},
456+ {1, 0, 0}
457+ },
458+ [MDP_COMP_TDSHP2] = {
459+ {MDP_COMP_TYPE_TDSHP, 1, MT8188_MDP_COMP_TDSHP2, MDP_MM_SUBSYS_1},
460+ {1, 0, 0}
461+ },
462+ [MDP_COMP_TDSHP3] = {
463+ {MDP_COMP_TYPE_TDSHP, 2, MT8188_MDP_COMP_TDSHP3, MDP_MM_SUBSYS_1},
464+ {1, 0, 0}
465+ },
466+ [MDP_COMP_COLOR0] = {
467+ {MDP_COMP_TYPE_COLOR, 0, MT8188_MDP_COMP_COLOR0, MDP_MM_SUBSYS_0},
468+ {1, 0, 0}
469+ },
470+ [MDP_COMP_COLOR2] = {
471+ {MDP_COMP_TYPE_COLOR, 1, MT8188_MDP_COMP_COLOR2, MDP_MM_SUBSYS_1},
472+ {1, 0, 0}
473+ },
474+ [MDP_COMP_COLOR3] = {
475+ {MDP_COMP_TYPE_COLOR, 2, MT8188_MDP_COMP_COLOR3, MDP_MM_SUBSYS_1},
476+ {1, 0, 0}
477+ },
478+ [MDP_COMP_OVL0] = {
479+ {MDP_COMP_TYPE_OVL, 0, MT8188_MDP_COMP_OVL0, MDP_MM_SUBSYS_0},
480+ {1, 0, 0}
481+ },
482+ [MDP_COMP_PAD0] = {
483+ {MDP_COMP_TYPE_PAD, 0, MT8188_MDP_COMP_PAD0, MDP_MM_SUBSYS_0},
484+ {1, 0, 0}
485+ },
486+ [MDP_COMP_PAD2] = {
487+ {MDP_COMP_TYPE_PAD, 1, MT8188_MDP_COMP_PAD2, MDP_MM_SUBSYS_1},
488+ {1, 0, 0}
489+ },
490+ [MDP_COMP_PAD3] = {
491+ {MDP_COMP_TYPE_PAD, 2, MT8188_MDP_COMP_PAD3, MDP_MM_SUBSYS_1},
492+ {1, 0, 0}
493+ },
494+ [MDP_COMP_TCC0] = {
495+ {MDP_COMP_TYPE_TCC, 0, MT8188_MDP_COMP_TCC0, MDP_MM_SUBSYS_0},
496+ {1, 0, 0}
497+ },
498+ [MDP_COMP_WROT0] = {
499+ {MDP_COMP_TYPE_WROT, 0, MT8188_MDP_COMP_WROT0, MDP_MM_SUBSYS_0},
500+ {1, 0, 0}
501+ },
502+ [MDP_COMP_WROT2] = {
503+ {MDP_COMP_TYPE_WROT, 1, MT8188_MDP_COMP_WROT2, MDP_MM_SUBSYS_1},
504+ {1, 0, 0}
505+ },
506+ [MDP_COMP_WROT3] = {
507+ {MDP_COMP_TYPE_WROT, 2, MT8188_MDP_COMP_WROT3, MDP_MM_SUBSYS_1},
508+ {1, 0, 0}
509+ },
510+ [MDP_COMP_MERGE2] = {
511+ {MDP_COMP_TYPE_MERGE, 0, MT8188_MDP_COMP_MERGE2, MDP_MM_SUBSYS_1},
512+ {1, 0, 0}
513+ },
514+ [MDP_COMP_MERGE3] = {
515+ {MDP_COMP_TYPE_MERGE, 1, MT8188_MDP_COMP_MERGE3, MDP_MM_SUBSYS_1},
516+ {1, 0, 0}
517+ },
518+ [MDP_COMP_PQ0_SOUT] = {
519+ {MDP_COMP_TYPE_DUMMY, 0, MT8188_MDP_COMP_PQ0_SOUT, MDP_MM_SUBSYS_0},
520+ {0, 0, 0}
521+ },
522+ [MDP_COMP_TO_WARP0MOUT] = {
523+ {MDP_COMP_TYPE_DUMMY, 1, MT8188_MDP_COMP_TO_WARP0MOUT, MDP_MM_SUBSYS_0},
524+ {0, 0, 0}
525+ },
526+ [MDP_COMP_TO_SVPP2MOUT] = {
527+ {MDP_COMP_TYPE_DUMMY, 2, MT8188_MDP_COMP_TO_SVPP2MOUT, MDP_MM_SUBSYS_1},
528+ {0, 0, 0}
529+ },
530+ [MDP_COMP_TO_SVPP3MOUT] = {
531+ {MDP_COMP_TYPE_DUMMY, 3, MT8188_MDP_COMP_TO_SVPP3MOUT, MDP_MM_SUBSYS_1},
532+ {0, 0, 0}
533+ },
534+ [MDP_COMP_VPP0_SOUT] = {
535+ {MDP_COMP_TYPE_PATH, 0, MT8188_MDP_COMP_VPP0_SOUT, MDP_MM_SUBSYS_1},
536+ {2, 6, 0}
537+ },
538+ [MDP_COMP_VPP1_SOUT] = {
539+ {MDP_COMP_TYPE_PATH, 1, MT8188_MDP_COMP_VPP1_SOUT, MDP_MM_SUBSYS_0},
540+ {2, 8, 0}
541+ },
542+};
543+
291544 static const struct mdp_comp_data mt8195_mdp_comp_data[MDP_MAX_COMP_COUNT] = {
292545 [MDP_COMP_WPEI] = {
293546 {MDP_COMP_TYPE_WPEI, 0, MT8195_MDP_COMP_WPEI, MDP_MM_SUBSYS_0},
@@ -1046,6 +1299,15 @@ static const struct mdp_pipe_info mt8183_pipe_info[] = { · 752 unmodified lines
10461299 [MDP_PIPE_RDMA0] = {MDP_PIPE_RDMA0, MDP_MM_SUBSYS_0, 3}
10471300 };
10481301
1302+static const struct mdp_pipe_info mt8188_pipe_info[] = {
1303+ [MDP_PIPE_WPEI] = {MDP_PIPE_WPEI, MDP_MM_SUBSYS_0, 0},
1304+ [MDP_PIPE_RDMA0] = {MDP_PIPE_RDMA0, MDP_MM_SUBSYS_0, 1},
1305+ [MDP_PIPE_RDMA2] = {MDP_PIPE_RDMA2, MDP_MM_SUBSYS_1, 0},
1306+ [MDP_PIPE_RDMA3] = {MDP_PIPE_RDMA3, MDP_MM_SUBSYS_1, 1},
1307+ [MDP_PIPE_VPP1_SOUT] = {MDP_PIPE_VPP1_SOUT, MDP_MM_SUBSYS_0, 2},
1308+ [MDP_PIPE_VPP0_SOUT] = {MDP_PIPE_VPP0_SOUT, MDP_MM_SUBSYS_1, 2},
1309+};
1310+
10491311 static const struct mdp_pipe_info mt8195_pipe_info[] = {
10501312 [MDP_PIPE_WPEI] = {MDP_PIPE_WPEI, MDP_MM_SUBSYS_0, 0},
10511313 [MDP_PIPE_WPEI2] = {MDP_PIPE_WPEI2, MDP_MM_SUBSYS_0, 1},
@@ -1082,6 +1344,24 @@ const struct mtk_mdp_driver_data mt8183_mdp_driver_data = { · 30 unmodified lines
10821344 .pp_used = MDP_PP_USED_1,
10831345 };
10841346
1347+const struct mtk_mdp_driver_data mt8188_mdp_driver_data = {
1348+ .mdp_plat_id = MT8188,
1349+ .mdp_con_res = 0x14001000,
1350+ .mdp_probe_infra = mt8188_mdp_probe_infra,
1351+ .mdp_sub_comp_dt_ids = mt8195_sub_comp_dt_ids,
1352+ .mdp_cfg = &mt8195_plat_cfg,
1353+ .mdp_mutex_table_idx = mt8188_mutex_idx,
1354+ .comp_data = mt8188_mdp_comp_data,
1355+ .comp_data_len = ARRAY_SIZE(mt8188_mdp_comp_data),
1356+ .format = mt8195_formats,
1357+ .format_len = ARRAY_SIZE(mt8195_formats),
1358+ .def_limit = &mt8195_mdp_def_limit,
1359+ .pipe_info = mt8188_pipe_info,
1360+ .pipe_info_len = ARRAY_SIZE(mt8188_pipe_info),
1361+ .pp_criteria = &mt8195_mdp_pp_criteria,
1362+ .pp_used = MDP_PP_USED_2,
1363+};
1364+
10851365 const struct mtk_mdp_driver_data mt8195_mdp_driver_data = {
10861366 .mdp_plat_id = MT8195,
10871367 .mdp_con_res = 0x14001000,
drivers/media/platform/mediatek/mdp3/mtk-img-ipi.h+1−0
@@ -116,6 +116,7 @@ struct img_frameparam { · 115 unmodified lines
116116
117117 /* Platform config indicator */
118118 #define MT8183 8183
119+#define MT8188 8195
119120 #define MT8195 8195
120121
121122 #define CFG_CHECK(plat, p_id) ((plat) == (p_id))
drivers/media/platform/mediatek/mdp3/mtk-mdp3-cfg.h+1−0
@@ -10,6 +10,7 @@ · 9 unmodified lines
1010 #include <linux/types.h>
1111
1212 extern const struct mtk_mdp_driver_data mt8183_mdp_driver_data;
13+extern const struct mtk_mdp_driver_data mt8188_mdp_driver_data;
1314 extern const struct mtk_mdp_driver_data mt8195_mdp_driver_data;
1415
1516 struct mdp_dev;
drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c+3−0
@@ -21,6 +21,9 @@ static const struct of_device_id mdp_of_ids[] = { · 20 unmodified lines
2121 { .compatible = "mediatek,mt8183-mdp3-rdma",
2222 .data = &mt8183_mdp_driver_data,
2323 },
24+ { .compatible = "mediatek,mt8188-mdp3-rdma",
25+ .data = &mt8188_mdp_driver_data,
26+ },
2427 { .compatible = "mediatek,mt8195-mdp3-rdma",
2528 .data = &mt8195_mdp_driver_data,
2629 },
drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_util.c+2−1
@@ -63,7 +63,8 @@ int mtk_vcodec_mem_alloc(void *priv, struct mtk_vcodec_mem *mem) · 62 unmodified lines
6363 id = dec_ctx->id;
6464 }
6565
66− mem->va = dma_alloc_coherent(&plat_dev->dev, mem->size, &mem->dma_addr, GFP_KERNEL);
66+ mem->va = dma_alloc_attrs(&plat_dev->dev, mem->size, &mem->dma_addr,
67+ GFP_KERNEL, DMA_ATTR_ALLOC_SINGLE_PAGES);
6768 if (!mem->va) {
6869 mtk_v4l2_err(plat_dev, "%s dma_alloc size=0x%zx failed!",
6970 __func__, mem->size);
drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c+54−6
@@ -80,21 +80,18 @@ static struct mtk_q_data *mtk_vdec_get_q_data(struct mtk_vcodec_dec_ctx *ctx, · 79 unmodified lines
8080 return &ctx->q_data[MTK_Q_DATA_DST];
8181 }
8282
83−static int vidioc_try_decoder_cmd(struct file *file, void *priv,
84− struct v4l2_decoder_cmd *cmd)
83+static int stateful_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd)
8584 {
8685 return v4l2_m2m_ioctl_try_decoder_cmd(file, priv, cmd);
8786 }
8887
89−
90−static int vidioc_decoder_cmd(struct file *file, void *priv,
91− struct v4l2_decoder_cmd *cmd)
88+static int stateful_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd)
9289 {
9390 struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv);
9491 struct vb2_queue *src_vq, *dst_vq;
9592 int ret;
9693
97− ret = vidioc_try_decoder_cmd(file, priv, cmd);
94+ ret = stateful_try_decoder_cmd(file, priv, cmd);
9895 if (ret)
9996 return ret;
10097
@@ -128,6 +125,57 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, · 27 unmodified lines
128125 return 0;
129126 }
130127
128+static int stateless_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd)
129+{
130+ return v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv, cmd);
131+}
132+
133+static int stateless_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd)
134+{
135+ struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv);
136+ int ret;
137+
138+ ret = v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv, cmd);
139+ if (ret)
140+ return ret;
141+
142+ mtk_v4l2_vdec_dbg(3, ctx, "decoder cmd=%u", cmd->cmd);
143+ switch (cmd->cmd) {
144+ case V4L2_DEC_CMD_FLUSH:
145+ /*
146+ * If the flag of the output buffer is equals V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF,
147+ * this command will prevent dequeueing the capture buffer containing the last
148+ * decoded frame. Or do nothing
149+ */
150+ break;
151+ default:
152+ mtk_v4l2_vdec_err(ctx, "invalid stateless decoder cmd=%u", cmd->cmd);
153+ return -EINVAL;
154+ }
155+
156+ return 0;
157+}
158+
159+static int vidioc_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd)
160+{
161+ struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv);
162+
163+ if (ctx->dev->vdec_pdata->uses_stateless_api)
164+ return stateless_try_decoder_cmd(file, priv, cmd);
165+
166+ return stateful_try_decoder_cmd(file, priv, cmd);
167+}
168+
169+static int vidioc_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd)
170+{
171+ struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv);
172+
173+ if (ctx->dev->vdec_pdata->uses_stateless_api)
174+ return stateless_decoder_cmd(file, priv, cmd);
175+
176+ return stateful_decoder_cmd(file, priv, cmd);
177+}
178+
131179 void mtk_vdec_unlock(struct mtk_vcodec_dec_ctx *ctx)
132180 {
133181 mutex_unlock(&ctx->dev->dec_mutex[ctx->hw_id]);
drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c+1−1
@@ -449,7 +449,7 @@ static int vdec_vp8_decode(void *h_vdec, struct mtk_vcodec_mem *bs, · 448 unmodified lines
449449 inst->frm_cnt, y_fb_dma, c_fb_dma, fb);
450450
451451 inst->cur_fb = fb;
452− dec->bs_dma = (uint64_t)bs->dma_addr;
452+ dec->bs_dma = bs->dma_addr;
453453 dec->bs_sz = bs->size;
454454 dec->cur_y_fb_dma = y_fb_dma;
455455 dec->cur_c_fb_dma = c_fb_dma;
drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c+6−0
@@ -233,6 +233,12 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu) · 232 unmodified lines
233233 mtk_vdec_debug(vpu->ctx, "vdec_inst=%p", vpu);
234234
235235 err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg));
236+
237+ if (IS_ERR_OR_NULL(vpu->vsi)) {
238+ mtk_vdec_err(vpu->ctx, "invalid vdec vsi, status=%d", err);
239+ return -EINVAL;
240+ }
241+
236242 mtk_vdec_debug(vpu->ctx, "- ret=%d", err);
237243 return err;
238244 }
drivers/media/platform/nvidia/tegra-vde/h264.c+0−5
@@ -19,11 +19,6 @@ · 18 unmodified lines
1919 #define FLAG_B_FRAME 0x1
2020 #define FLAG_REFERENCE 0x2
2121
22−struct tegra_vde_h264_frame {
23− unsigned int frame_num;
24− unsigned int flags;
25−};
26−
2722 struct tegra_vde_h264_decoder_ctx {
2823 unsigned int dpb_frames_nb;
2924 unsigned int dpb_ref_frames_with_earlier_poc_nb;
drivers/media/platform/nvidia/tegra-vde/vde.h+0−1
@@ -47,7 +47,6 @@ struct iommu_group; · 46 unmodified lines
4747 struct iommu_domain;
4848 struct reset_control;
4949 struct dma_buf_attachment;
50−struct tegra_vde_h264_frame;
5150 struct tegra_vde_h264_decoder_ctx;
5251
5352 struct tegra_video_frame {
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c+3−11
@@ -1634,6 +1634,9 @@ static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count) · 1633 unmodified lines
16341634 dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
16351635 q_data->sequence = 0;
16361636
1637+ if (V4L2_TYPE_IS_CAPTURE(q->type))
1638+ ctx->need_initial_source_change_evt = false;
1639+
16371640 ret = pm_runtime_resume_and_get(ctx->mxc_jpeg->dev);
16381641 if (ret < 0) {
16391642 dev_err(ctx->mxc_jpeg->dev, "Failed to power up jpeg\n");
@@ -1840,17 +1843,6 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb) · 200 unmodified lines
18401843
18411844 q_data_out = mxc_jpeg_get_q_data(ctx,
18421845 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
1843− if (q_data_out->w == 0 && q_data_out->h == 0) {
1844− dev_warn(dev, "Invalid user resolution 0x0");
1845− dev_warn(dev, "Keeping resolution from JPEG: %dx%d",
1846− header.frame.width, header.frame.height);
1847− } else if (header.frame.width != q_data_out->w ||
1848− header.frame.height != q_data_out->h) {
1849− dev_err(dev,
1850− "Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)",
1851− header.frame.width, header.frame.height,
1852− q_data_out->w, q_data_out->h);
1853− }
18541846 q_data_out->w = header.frame.width;
18551847 q_data_out->h = header.frame.height;
18561848 if (header.frame.width > MXC_JPEG_MAX_WIDTH ||
drivers/media/platform/nxp/imx-mipi-csis.c+15−7
@@ -320,7 +320,11 @@ struct mipi_csis_device { · 319 unmodified lines
320320 struct v4l2_subdev sd;
321321 struct media_pad pads[CSIS_PADS_NUM];
322322 struct v4l2_async_notifier notifier;
323− struct v4l2_subdev *src_sd;
323+
324+ struct {
325+ struct v4l2_subdev *sd;
326+ const struct media_pad *pad;
327+ } source;
324328
325329 struct v4l2_mbus_config_mipi_csi2 bus;
326330 u32 clk_frequency;
@@ -597,7 +601,7 @@ static int mipi_csis_calculate_params(struct mipi_csis_device *csis, · 270 unmodified lines
597601 u32 lane_rate;
598602
599603 /* Calculate the line rate from the pixel rate. */
600− link_freq = v4l2_get_link_freq(csis->src_sd->ctrl_handler,
604+ link_freq = v4l2_get_link_freq(csis->source.sd->ctrl_handler,
601605 csis_fmt->width,
602606 csis->bus.num_data_lanes * 2);
603607 if (link_freq < 0) {
@@ -958,7 +962,8 @@ static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable) · 354 unmodified lines
958962 int ret;
959963
960964 if (!enable) {
961− v4l2_subdev_call(csis->src_sd, video, s_stream, 0);
965+ v4l2_subdev_disable_streams(csis->source.sd,
966+ csis->source.pad->index, BIT(0));
962967
963968 mipi_csis_stop_stream(csis);
964969 if (csis->debug.enable)
@@ -986,7 +991,8 @@ static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable) · 21 unmodified lines
986991
987992 mipi_csis_start_stream(csis, format, csis_fmt);
988993
989− ret = v4l2_subdev_call(csis->src_sd, video, s_stream, 1);
994+ ret = v4l2_subdev_enable_streams(csis->source.sd,
995+ csis->source.pad->index, BIT(0));
990996 if (ret < 0)
991997 goto err_stop;
992998
@@ -1233,12 +1239,14 @@ static int mipi_csis_link_setup(struct media_entity *entity, · 240 unmodified lines
12331239 remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
12341240
12351241 if (flags & MEDIA_LNK_FL_ENABLED) {
1236− if (csis->src_sd)
1242+ if (csis->source.sd)
12371243 return -EBUSY;
12381244
1239− csis->src_sd = remote_sd;
1245+ csis->source.sd = remote_sd;
1246+ csis->source.pad = remote_pad;
12401247 } else {
1241− csis->src_sd = NULL;
1248+ csis->source.sd = NULL;
1249+ csis->source.pad = NULL;
12421250 }
12431251
12441252 return 0;
drivers/media/platform/nxp/imx-pxp.c+3−0
@@ -1805,6 +1805,9 @@ static int pxp_probe(struct platform_device *pdev) · 1804 unmodified lines
18051805 return PTR_ERR(mmio);
18061806 dev->regmap = devm_regmap_init_mmio(&pdev->dev, mmio,
18071807 &pxp_regmap_config);
1808+ if (IS_ERR(dev->regmap))
1809+ return dev_err_probe(&pdev->dev, PTR_ERR(dev->regmap),
1810+ "Failed to init regmap\n");
18081811
18091812 irq = platform_get_irq(pdev, 0);
18101813 if (irq < 0)
drivers/media/platform/qcom/camss/Makefile+1−0
@@ -19,5 +19,6 @@ qcom-camss-objs += \ · 18 unmodified lines
1919 camss-vfe-gen1.o \
2020 camss-vfe.o \
2121 camss-video.o \
22+ camss-format.o \
2223
2324 obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom-camss.o
drivers/media/platform/qcom/camss/camss-csid-4-1.c+5−127
@@ -45,128 +45,6 @@ · 44 unmodified lines
4545 #define CAMSS_CSID_TG_DT_n_CGG_1(n) (0x0b0 + 0xc * (n))
4646 #define CAMSS_CSID_TG_DT_n_CGG_2(n) (0x0b4 + 0xc * (n))
4747
48−static const struct csid_format csid_formats[] = {
49− {
50− MEDIA_BUS_FMT_UYVY8_1X16,
51− DATA_TYPE_YUV422_8BIT,
52− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
53− 8,
54− 2,
55− },
56− {
57− MEDIA_BUS_FMT_VYUY8_1X16,
58− DATA_TYPE_YUV422_8BIT,
59− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
60− 8,
61− 2,
62− },
63− {
64− MEDIA_BUS_FMT_YUYV8_1X16,
65− DATA_TYPE_YUV422_8BIT,
66− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
67− 8,
68− 2,
69− },
70− {
71− MEDIA_BUS_FMT_YVYU8_1X16,
72− DATA_TYPE_YUV422_8BIT,
73− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
74− 8,
75− 2,
76− },
77− {
78− MEDIA_BUS_FMT_SBGGR8_1X8,
79− DATA_TYPE_RAW_8BIT,
80− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
81− 8,
82− 1,
83− },
84− {
85− MEDIA_BUS_FMT_SGBRG8_1X8,
86− DATA_TYPE_RAW_8BIT,
87− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
88− 8,
89− 1,
90− },
91− {
92− MEDIA_BUS_FMT_SGRBG8_1X8,
93− DATA_TYPE_RAW_8BIT,
94− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
95− 8,
96− 1,
97− },
98− {
99− MEDIA_BUS_FMT_SRGGB8_1X8,
100− DATA_TYPE_RAW_8BIT,
101− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
102− 8,
103− 1,
104− },
105− {
106− MEDIA_BUS_FMT_SBGGR10_1X10,
107− DATA_TYPE_RAW_10BIT,
108− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
109− 10,
110− 1,
111− },
112− {
113− MEDIA_BUS_FMT_SGBRG10_1X10,
114− DATA_TYPE_RAW_10BIT,
115− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
116− 10,
117− 1,
118− },
119− {
120− MEDIA_BUS_FMT_SGRBG10_1X10,
121− DATA_TYPE_RAW_10BIT,
122− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
123− 10,
124− 1,
125− },
126− {
127− MEDIA_BUS_FMT_SRGGB10_1X10,
128− DATA_TYPE_RAW_10BIT,
129− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
130− 10,
131− 1,
132− },
133− {
134− MEDIA_BUS_FMT_SBGGR12_1X12,
135− DATA_TYPE_RAW_12BIT,
136− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
137− 12,
138− 1,
139− },
140− {
141− MEDIA_BUS_FMT_SGBRG12_1X12,
142− DATA_TYPE_RAW_12BIT,
143− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
144− 12,
145− 1,
146− },
147− {
148− MEDIA_BUS_FMT_SGRBG12_1X12,
149− DATA_TYPE_RAW_12BIT,
150− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
151− 12,
152− 1,
153− },
154− {
155− MEDIA_BUS_FMT_SRGGB12_1X12,
156− DATA_TYPE_RAW_12BIT,
157− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
158− 12,
159− 1,
160− },
161− {
162− MEDIA_BUS_FMT_Y10_1X10,
163− DATA_TYPE_RAW_10BIT,
164− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
165− 10,
166− 1,
167− },
168−};
169−
17048 static void csid_configure_stream(struct csid_device *csid, u8 enable)
17149 {
17250 struct csid_testgen_config *tg = &csid->testgen;
@@ -174,7 +52,7 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 1 unmodified line
17452
17553 if (enable) {
17654 struct v4l2_mbus_framefmt *input_format;
177− const struct csid_format *format;
55+ const struct csid_format_info *format;
17856 u8 vc = 0; /* Virtual Channel 0 */
17957 u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */
18058 u8 dt_shift;
@@ -184,7 +62,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 3 unmodified lines
18462 u32 num_lines, num_bytes_per_line;
18563
18664 input_format = &csid->fmt[MSM_CSID_PAD_SRC];
187− format = csid_get_fmt_entry(csid->formats, csid->nformats,
65+ format = csid_get_fmt_entry(csid->res->formats->formats,
66+ csid->res->formats->nformats,
18867 input_format->code);
18968 num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;
19069 num_lines = input_format->height;
@@ -211,7 +90,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 20 unmodified lines
21190 struct csid_phy_config *phy = &csid->phy;
21291
21392 input_format = &csid->fmt[MSM_CSID_PAD_SINK];
214− format = csid_get_fmt_entry(csid->formats, csid->nformats,
93+ format = csid_get_fmt_entry(csid->res->formats->formats,
94+ csid->res->formats->nformats,
21595 input_format->code);
21696
21797 val = phy->lane_cnt - 1;
@@ -311,8 +191,6 @@ static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code, · 93 unmodified lines
311191
312192 static void csid_subdev_init(struct csid_device *csid)
313193 {
314− csid->formats = csid_formats;
315− csid->nformats = ARRAY_SIZE(csid_formats);
316194 csid->testgen.modes = csid_testgen_modes;
317195 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1;
318196 }
drivers/media/platform/qcom/camss/camss-csid-4-7.c+5−155
@@ -44,156 +44,6 @@ · 43 unmodified lines
4444 #define CAMSS_CSID_TG_DT_n_CGG_1(n) (0x0b8 + 0xc * (n))
4545 #define CAMSS_CSID_TG_DT_n_CGG_2(n) (0x0bc + 0xc * (n))
4646
47−static const struct csid_format csid_formats[] = {
48− {
49− MEDIA_BUS_FMT_UYVY8_1X16,
50− DATA_TYPE_YUV422_8BIT,
51− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
52− 8,
53− 2,
54− },
55− {
56− MEDIA_BUS_FMT_VYUY8_1X16,
57− DATA_TYPE_YUV422_8BIT,
58− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
59− 8,
60− 2,
61− },
62− {
63− MEDIA_BUS_FMT_YUYV8_1X16,
64− DATA_TYPE_YUV422_8BIT,
65− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
66− 8,
67− 2,
68− },
69− {
70− MEDIA_BUS_FMT_YVYU8_1X16,
71− DATA_TYPE_YUV422_8BIT,
72− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
73− 8,
74− 2,
75− },
76− {
77− MEDIA_BUS_FMT_SBGGR8_1X8,
78− DATA_TYPE_RAW_8BIT,
79− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
80− 8,
81− 1,
82− },
83− {
84− MEDIA_BUS_FMT_SGBRG8_1X8,
85− DATA_TYPE_RAW_8BIT,
86− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
87− 8,
88− 1,
89− },
90− {
91− MEDIA_BUS_FMT_SGRBG8_1X8,
92− DATA_TYPE_RAW_8BIT,
93− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
94− 8,
95− 1,
96− },
97− {
98− MEDIA_BUS_FMT_SRGGB8_1X8,
99− DATA_TYPE_RAW_8BIT,
100− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
101− 8,
102− 1,
103− },
104− {
105− MEDIA_BUS_FMT_SBGGR10_1X10,
106− DATA_TYPE_RAW_10BIT,
107− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
108− 10,
109− 1,
110− },
111− {
112− MEDIA_BUS_FMT_SGBRG10_1X10,
113− DATA_TYPE_RAW_10BIT,
114− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
115− 10,
116− 1,
117− },
118− {
119− MEDIA_BUS_FMT_SGRBG10_1X10,
120− DATA_TYPE_RAW_10BIT,
121− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
122− 10,
123− 1,
124− },
125− {
126− MEDIA_BUS_FMT_SRGGB10_1X10,
127− DATA_TYPE_RAW_10BIT,
128− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
129− 10,
130− 1,
131− },
132− {
133− MEDIA_BUS_FMT_SBGGR12_1X12,
134− DATA_TYPE_RAW_12BIT,
135− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
136− 12,
137− 1,
138− },
139− {
140− MEDIA_BUS_FMT_SGBRG12_1X12,
141− DATA_TYPE_RAW_12BIT,
142− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
143− 12,
144− 1,
145− },
146− {
147− MEDIA_BUS_FMT_SGRBG12_1X12,
148− DATA_TYPE_RAW_12BIT,
149− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
150− 12,
151− 1,
152− },
153− {
154− MEDIA_BUS_FMT_SRGGB12_1X12,
155− DATA_TYPE_RAW_12BIT,
156− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
157− 12,
158− 1,
159− },
160− {
161− MEDIA_BUS_FMT_SBGGR14_1X14,
162− DATA_TYPE_RAW_14BIT,
163− DECODE_FORMAT_UNCOMPRESSED_14_BIT,
164− 14,
165− 1,
166− },
167− {
168− MEDIA_BUS_FMT_SGBRG14_1X14,
169− DATA_TYPE_RAW_14BIT,
170− DECODE_FORMAT_UNCOMPRESSED_14_BIT,
171− 14,
172− 1,
173− },
174− {
175− MEDIA_BUS_FMT_SGRBG14_1X14,
176− DATA_TYPE_RAW_14BIT,
177− DECODE_FORMAT_UNCOMPRESSED_14_BIT,
178− 14,
179− 1,
180− },
181− {
182− MEDIA_BUS_FMT_SRGGB14_1X14,
183− DATA_TYPE_RAW_14BIT,
184− DECODE_FORMAT_UNCOMPRESSED_14_BIT,
185− 14,
186− 1,
187− },
188− {
189− MEDIA_BUS_FMT_Y10_1X10,
190− DATA_TYPE_RAW_10BIT,
191− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
192− 10,
193− 1,
194− },
195−};
196−
19747 static void csid_configure_stream(struct csid_device *csid, u8 enable)
19848 {
19949 struct csid_testgen_config *tg = &csid->testgen;
@@ -203,7 +53,7 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 3 unmodified lines
20353
20454 if (enable) {
20555 struct v4l2_mbus_framefmt *input_format;
206− const struct csid_format *format;
56+ const struct csid_format_info *format;
20757 u8 vc = 0; /* Virtual Channel 0 */
20858 u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */
20959 u8 dt_shift;
@@ -213,7 +63,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 3 unmodified lines
21363 u32 num_bytes_per_line, num_lines;
21464
21565 input_format = &csid->fmt[MSM_CSID_PAD_SRC];
216− format = csid_get_fmt_entry(csid->formats, csid->nformats,
66+ format = csid_get_fmt_entry(csid->res->formats->formats,
67+ csid->res->formats->nformats,
21768 input_format->code);
21869 num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;
21970 num_lines = input_format->height;
@@ -240,7 +91,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 20 unmodified lines
24091 struct csid_phy_config *phy = &csid->phy;
24192
24293 input_format = &csid->fmt[MSM_CSID_PAD_SINK];
243− format = csid_get_fmt_entry(csid->formats, csid->nformats,
94+ format = csid_get_fmt_entry(csid->res->formats->formats,
95+ csid->res->formats->nformats,
24496 input_format->code);
24597
24698 val = phy->lane_cnt - 1;
@@ -387,8 +239,6 @@ static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code, · 140 unmodified lines
387239
388240 static void csid_subdev_init(struct csid_device *csid)
389241 {
390− csid->formats = csid_formats;
391− csid->nformats = ARRAY_SIZE(csid_formats);
392242 csid->testgen.modes = csid_testgen_modes;
393243 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1;
394244 }
drivers/media/platform/qcom/camss/camss-csid-gen2.c+135−272
@@ -176,306 +176,171 @@ · 175 unmodified lines
176176 #define TPG_COLOR_BOX_CFG_MODE 0
177177 #define TPG_COLOR_BOX_PATTERN_SEL 2
178178
179−static const struct csid_format csid_formats[] = {
180− {
181− MEDIA_BUS_FMT_UYVY8_1X16,
182− DATA_TYPE_YUV422_8BIT,
183− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
184− 8,
185− 2,
186− },
187− {
188− MEDIA_BUS_FMT_VYUY8_1X16,
189− DATA_TYPE_YUV422_8BIT,
190− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
191− 8,
192− 2,
193− },
194− {
195− MEDIA_BUS_FMT_YUYV8_1X16,
196− DATA_TYPE_YUV422_8BIT,
197− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
198− 8,
199− 2,
200− },
201− {
202− MEDIA_BUS_FMT_YVYU8_1X16,
203− DATA_TYPE_YUV422_8BIT,
204− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
205− 8,
206− 2,
207− },
208− {
209− MEDIA_BUS_FMT_SBGGR8_1X8,
210− DATA_TYPE_RAW_8BIT,
211− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
212− 8,
213− 1,
214− },
215− {
216− MEDIA_BUS_FMT_SGBRG8_1X8,
217− DATA_TYPE_RAW_8BIT,
218− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
219− 8,
220− 1,
221− },
222− {
223− MEDIA_BUS_FMT_SGRBG8_1X8,
224− DATA_TYPE_RAW_8BIT,
225− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
226− 8,
227− 1,
228− },
229− {
230− MEDIA_BUS_FMT_SRGGB8_1X8,
231− DATA_TYPE_RAW_8BIT,
232− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
233− 8,
234− 1,
235− },
236− {
237− MEDIA_BUS_FMT_SBGGR10_1X10,
238− DATA_TYPE_RAW_10BIT,
239− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
240− 10,
241− 1,
242− },
243− {
244− MEDIA_BUS_FMT_SGBRG10_1X10,
245− DATA_TYPE_RAW_10BIT,
246− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
247− 10,
248− 1,
249− },
250− {
251− MEDIA_BUS_FMT_SGRBG10_1X10,
252− DATA_TYPE_RAW_10BIT,
253− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
254− 10,
255− 1,
256− },
257− {
258− MEDIA_BUS_FMT_SRGGB10_1X10,
259− DATA_TYPE_RAW_10BIT,
260− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
261− 10,
262− 1,
263− },
264− {
265− MEDIA_BUS_FMT_Y8_1X8,
266− DATA_TYPE_RAW_8BIT,
267− DECODE_FORMAT_UNCOMPRESSED_8_BIT,
268− 8,
269− 1,
270− },
271− {
272− MEDIA_BUS_FMT_Y10_1X10,
273− DATA_TYPE_RAW_10BIT,
274− DECODE_FORMAT_UNCOMPRESSED_10_BIT,
275− 10,
276− 1,
277− },
278− {
279− MEDIA_BUS_FMT_SBGGR12_1X12,
280− DATA_TYPE_RAW_12BIT,
281− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
282− 12,
283− 1,
284− },
285− {
286− MEDIA_BUS_FMT_SGBRG12_1X12,
287− DATA_TYPE_RAW_12BIT,
288− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
289− 12,
290− 1,
291− },
292− {
293− MEDIA_BUS_FMT_SGRBG12_1X12,
294− DATA_TYPE_RAW_12BIT,
295− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
296− 12,
297− 1,
298− },
299− {
300− MEDIA_BUS_FMT_SRGGB12_1X12,
301− DATA_TYPE_RAW_12BIT,
302− DECODE_FORMAT_UNCOMPRESSED_12_BIT,
303− 12,
304− 1,
305− },
306− {
307− MEDIA_BUS_FMT_SBGGR14_1X14,
308− DATA_TYPE_RAW_14BIT,
309− DECODE_FORMAT_UNCOMPRESSED_14_BIT,
310− 14,
311− 1,
312− },
313− {
314− MEDIA_BUS_FMT_SGBRG14_1X14,
315− DATA_TYPE_RAW_14BIT,
316− DECODE_FORMAT_UNCOMPRESSED_14_BIT,
317− 14,
318− 1,
319− },
320− {
321− MEDIA_BUS_FMT_SGRBG14_1X14,
322− DATA_TYPE_RAW_14BIT,
323− DECODE_FORMAT_UNCOMPRESSED_14_BIT,
324− 14,
325− 1,
326− },
327− {
328− MEDIA_BUS_FMT_SRGGB14_1X14,
329− DATA_TYPE_RAW_14BIT,
330− DECODE_FORMAT_UNCOMPRESSED_14_BIT,
331− 14,
332− 1,
333− },
334−};
335−
336−static void __csid_configure_stream(struct csid_device *csid, u8 enable, u8 vc)
179+static void __csid_configure_rx(struct csid_device *csid,
180+ struct csid_phy_config *phy, int vc)
337181 {
338− struct csid_testgen_config *tg = &csid->testgen;
339− u32 val;
340− u32 phy_sel = 0;
341182 u8 lane_cnt = csid->phy.lane_cnt;
342− /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
343− struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
344− const struct csid_format *format = csid_get_fmt_entry(csid->formats, csid->nformats,
345− input_format->code);
183+ int val;
346184
347185 if (!lane_cnt)
348186 lane_cnt = 4;
349187
350− if (!tg->enabled)
351− phy_sel = csid->phy.csiphy_id;
352−
353− if (enable) {
354− /*
355− * DT_ID is a two bit bitfield that is concatenated with
356− * the four least significant bits of the five bit VC
357− * bitfield to generate an internal CID value.
358− *
359− * CSID_RDI_CFG0(vc)
360− * DT_ID : 28:27
361− * VC : 26:22
362− * DT : 21:16
363− *
364− * CID : VC 3:0 << 2 | DT_ID 1:0
365− */
366− u8 dt_id = vc & 0x03;
367−
368− if (tg->enabled) {
369− /* configure one DT, infinite frames */
370− val = vc << TPG_VC_CFG0_VC_NUM;
371− val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE;
372− val |= 0 << TPG_VC_CFG0_NUM_FRAMES;
373− writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0);
374−
375− val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT;
376− val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT;
377− writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1);
378−
379− writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
380−
381− val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT;
382− val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH;
383− writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
384−
385− val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
386− writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
387−
388− val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE;
389− val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD;
390− val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT;
391− writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0));
392−
393− writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
394−
395− writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
396− }
188+ val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
189+ val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
190+ val |= phy->csiphy_id << CSI2_RX_CFG0_PHY_NUM_SEL;
191+ writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
397192
398− val = 1 << RDI_CFG0_BYTE_CNTR_EN;
399− val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
400− val |= 1 << RDI_CFG0_TIMESTAMP_EN;
401− /* note: for non-RDI path, this should be format->decode_format */
402− val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
403− val |= format->data_type << RDI_CFG0_DATA_TYPE;
404− val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
405− val |= dt_id << RDI_CFG0_DT_ID;
406− writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
193+ val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
194+ if (vc > 3)
195+ val |= 1 << CSI2_RX_CFG1_VC_MODE;
196+ val |= 1 << CSI2_RX_CFG1_MISR_EN;
197+ writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);
198+}
407199
408− /* CSID_TIMESTAMP_STB_POST_IRQ */
409− val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
410− writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));
200+static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi)
201+{
202+ int val;
411203
412− val = 1;
413− writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
204+ if (enable)
205+ val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
206+ else
207+ val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
208+ writel_relaxed(val, csid->base + CSID_RDI_CTRL(rdi));
209+}
414210
415− val = 0;
416− writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc));
211+static void __csid_configure_testgen(struct csid_device *csid, u8 enable, u8 vc)
212+{
213+ struct csid_testgen_config *tg = &csid->testgen;
214+ struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
215+ const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
216+ csid->res->formats->nformats,
217+ input_format->code);
218+ u8 lane_cnt = csid->phy.lane_cnt;
219+ u32 val;
417220
418− val = 1;
419− writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
221+ if (!lane_cnt)
222+ lane_cnt = 4;
420223
421− val = 0;
422− writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
224+ /* configure one DT, infinite frames */
225+ val = vc << TPG_VC_CFG0_VC_NUM;
226+ val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE;
227+ val |= 0 << TPG_VC_CFG0_NUM_FRAMES;
228+ writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0);
423229
424− val = 1;
425− writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));
230+ val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT;
231+ val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT;
232+ writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1);
426233
427− val = 0;
428− writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
234+ writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
429235
430− val = 1;
431− writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));
236+ val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT;
237+ val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH;
238+ writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
432239
433− val = 0;
434− writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));
240+ val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
241+ writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
435242
436− val = 0;
437− writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
243+ val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE;
244+ val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD;
245+ val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT;
246+ writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0));
438247
439− val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));
440− val |= 1 << RDI_CFG0_ENABLE;
441− writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
442− }
248+ writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
443249
444− if (tg->enabled) {
445− val = enable << TPG_CTRL_TEST_EN;
446− val |= 1 << TPG_CTRL_FS_PKT_EN;
447− val |= 1 << TPG_CTRL_FE_PKT_EN;
448− val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES;
449− val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS;
450− val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES;
451− writel_relaxed(val, csid->base + CSID_TPG_CTRL);
452− }
250+ writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
453251
454− val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
455− val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
456− val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL;
457− writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
252+ val = enable << TPG_CTRL_TEST_EN;
253+ val |= 1 << TPG_CTRL_FS_PKT_EN;
254+ val |= 1 << TPG_CTRL_FE_PKT_EN;
255+ val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES;
256+ val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS;
257+ val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES;
258+ writel_relaxed(val, csid->base + CSID_TPG_CTRL);
259+}
458260
459− val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
460− if (vc > 3)
461− val |= 1 << CSI2_RX_CFG1_VC_MODE;
462− val |= 1 << CSI2_RX_CFG1_MISR_EN;
463− writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);
261+static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc)
262+{
263+ /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
264+ struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
265+ const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
266+ csid->res->formats->nformats,
267+ input_format->code);
268+ u32 val;
464269
465− if (enable)
466− val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
467− else
468− val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;
270+ /*
271+ * DT_ID is a two bit bitfield that is concatenated with
272+ * the four least significant bits of the five bit VC
273+ * bitfield to generate an internal CID value.
274+ *
275+ * CSID_RDI_CFG0(vc)
276+ * DT_ID : 28:27
277+ * VC : 26:22
278+ * DT : 21:16
279+ *
280+ * CID : VC 3:0 << 2 | DT_ID 1:0
281+ */
282+ u8 dt_id = vc & 0x03;
283+
284+ val = 1 << RDI_CFG0_BYTE_CNTR_EN;
285+ val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
286+ val |= 1 << RDI_CFG0_TIMESTAMP_EN;
287+ /* note: for non-RDI path, this should be format->decode_format */
288+ val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
289+ val |= format->data_type << RDI_CFG0_DATA_TYPE;
290+ val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
291+ val |= dt_id << RDI_CFG0_DT_ID;
292+ writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
293+
294+ /* CSID_TIMESTAMP_STB_POST_IRQ */
295+ val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
296+ writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));
297+
298+ val = 1;
299+ writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
300+
301+ val = 0;
302+ writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc));
303+
304+ val = 1;
305+ writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
306+
307+ val = 0;
308+ writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
309+
310+ val = 1;
311+ writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));
312+
313+ val = 0;
314+ writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
315+
316+ val = 1;
317+ writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));
318+
319+ val = 0;
320+ writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));
321+
322+ val = 0;
469323 writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
324+
325+ val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));
326+ val |= enable << RDI_CFG0_ENABLE;
327+ writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
470328 }
471329
472330 static void csid_configure_stream(struct csid_device *csid, u8 enable)
473331 {
332+ struct csid_testgen_config *tg = &csid->testgen;
474333 u8 i;
475334 /* Loop through all enabled VCs and configure stream for each */
476335 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
477− if (csid->phy.en_vc & BIT(i))
478− __csid_configure_stream(csid, enable, i);
336+ if (csid->phy.en_vc & BIT(i)) {
337+ if (tg->enabled)
338+ __csid_configure_testgen(csid, enable, i);
339+
340+ __csid_configure_rdi_stream(csid, enable, i);
341+ __csid_configure_rx(csid, &csid->phy, i);
342+ __csid_ctrl_rdi(csid, enable, i);
343+ }
479344 }
480345
481346 static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)
@@ -612,8 +477,6 @@ static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code, · 130 unmodified lines
612477
613478 static void csid_subdev_init(struct csid_device *csid)
614479 {
615− csid->formats = csid_formats;
616− csid->nformats = ARRAY_SIZE(csid_formats);
617480 csid->testgen.modes = csid_testgen_modes;
618481 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2;
619482 }
drivers/media/platform/qcom/camss/camss-csid.c+481−31
@@ -45,6 +45,450 @@ const char * const csid_testgen_modes[] = { · 44 unmodified lines
4545 NULL
4646 };
4747
48+static const struct csid_format_info formats_4_1[] = {
49+ {
50+ MEDIA_BUS_FMT_UYVY8_1X16,
51+ DATA_TYPE_YUV422_8BIT,
52+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
53+ 8,
54+ 2,
55+ },
56+ {
57+ MEDIA_BUS_FMT_VYUY8_1X16,
58+ DATA_TYPE_YUV422_8BIT,
59+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
60+ 8,
61+ 2,
62+ },
63+ {
64+ MEDIA_BUS_FMT_YUYV8_1X16,
65+ DATA_TYPE_YUV422_8BIT,
66+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
67+ 8,
68+ 2,
69+ },
70+ {
71+ MEDIA_BUS_FMT_YVYU8_1X16,
72+ DATA_TYPE_YUV422_8BIT,
73+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
74+ 8,
75+ 2,
76+ },
77+ {
78+ MEDIA_BUS_FMT_SBGGR8_1X8,
79+ DATA_TYPE_RAW_8BIT,
80+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
81+ 8,
82+ 1,
83+ },
84+ {
85+ MEDIA_BUS_FMT_SGBRG8_1X8,
86+ DATA_TYPE_RAW_8BIT,
87+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
88+ 8,
89+ 1,
90+ },
91+ {
92+ MEDIA_BUS_FMT_SGRBG8_1X8,
93+ DATA_TYPE_RAW_8BIT,
94+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
95+ 8,
96+ 1,
97+ },
98+ {
99+ MEDIA_BUS_FMT_SRGGB8_1X8,
100+ DATA_TYPE_RAW_8BIT,
101+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
102+ 8,
103+ 1,
104+ },
105+ {
106+ MEDIA_BUS_FMT_SBGGR10_1X10,
107+ DATA_TYPE_RAW_10BIT,
108+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
109+ 10,
110+ 1,
111+ },
112+ {
113+ MEDIA_BUS_FMT_SGBRG10_1X10,
114+ DATA_TYPE_RAW_10BIT,
115+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
116+ 10,
117+ 1,
118+ },
119+ {
120+ MEDIA_BUS_FMT_SGRBG10_1X10,
121+ DATA_TYPE_RAW_10BIT,
122+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
123+ 10,
124+ 1,
125+ },
126+ {
127+ MEDIA_BUS_FMT_SRGGB10_1X10,
128+ DATA_TYPE_RAW_10BIT,
129+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
130+ 10,
131+ 1,
132+ },
133+ {
134+ MEDIA_BUS_FMT_SBGGR12_1X12,
135+ DATA_TYPE_RAW_12BIT,
136+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
137+ 12,
138+ 1,
139+ },
140+ {
141+ MEDIA_BUS_FMT_SGBRG12_1X12,
142+ DATA_TYPE_RAW_12BIT,
143+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
144+ 12,
145+ 1,
146+ },
147+ {
148+ MEDIA_BUS_FMT_SGRBG12_1X12,
149+ DATA_TYPE_RAW_12BIT,
150+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
151+ 12,
152+ 1,
153+ },
154+ {
155+ MEDIA_BUS_FMT_SRGGB12_1X12,
156+ DATA_TYPE_RAW_12BIT,
157+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
158+ 12,
159+ 1,
160+ },
161+ {
162+ MEDIA_BUS_FMT_Y10_1X10,
163+ DATA_TYPE_RAW_10BIT,
164+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
165+ 10,
166+ 1,
167+ },
168+};
169+
170+static const struct csid_format_info formats_4_7[] = {
171+ {
172+ MEDIA_BUS_FMT_UYVY8_1X16,
173+ DATA_TYPE_YUV422_8BIT,
174+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
175+ 8,
176+ 2,
177+ },
178+ {
179+ MEDIA_BUS_FMT_VYUY8_1X16,
180+ DATA_TYPE_YUV422_8BIT,
181+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
182+ 8,
183+ 2,
184+ },
185+ {
186+ MEDIA_BUS_FMT_YUYV8_1X16,
187+ DATA_TYPE_YUV422_8BIT,
188+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
189+ 8,
190+ 2,
191+ },
192+ {
193+ MEDIA_BUS_FMT_YVYU8_1X16,
194+ DATA_TYPE_YUV422_8BIT,
195+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
196+ 8,
197+ 2,
198+ },
199+ {
200+ MEDIA_BUS_FMT_SBGGR8_1X8,
201+ DATA_TYPE_RAW_8BIT,
202+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
203+ 8,
204+ 1,
205+ },
206+ {
207+ MEDIA_BUS_FMT_SGBRG8_1X8,
208+ DATA_TYPE_RAW_8BIT,
209+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
210+ 8,
211+ 1,
212+ },
213+ {
214+ MEDIA_BUS_FMT_SGRBG8_1X8,
215+ DATA_TYPE_RAW_8BIT,
216+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
217+ 8,
218+ 1,
219+ },
220+ {
221+ MEDIA_BUS_FMT_SRGGB8_1X8,
222+ DATA_TYPE_RAW_8BIT,
223+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
224+ 8,
225+ 1,
226+ },
227+ {
228+ MEDIA_BUS_FMT_SBGGR10_1X10,
229+ DATA_TYPE_RAW_10BIT,
230+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
231+ 10,
232+ 1,
233+ },
234+ {
235+ MEDIA_BUS_FMT_SGBRG10_1X10,
236+ DATA_TYPE_RAW_10BIT,
237+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
238+ 10,
239+ 1,
240+ },
241+ {
242+ MEDIA_BUS_FMT_SGRBG10_1X10,
243+ DATA_TYPE_RAW_10BIT,
244+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
245+ 10,
246+ 1,
247+ },
248+ {
249+ MEDIA_BUS_FMT_SRGGB10_1X10,
250+ DATA_TYPE_RAW_10BIT,
251+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
252+ 10,
253+ 1,
254+ },
255+ {
256+ MEDIA_BUS_FMT_SBGGR12_1X12,
257+ DATA_TYPE_RAW_12BIT,
258+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
259+ 12,
260+ 1,
261+ },
262+ {
263+ MEDIA_BUS_FMT_SGBRG12_1X12,
264+ DATA_TYPE_RAW_12BIT,
265+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
266+ 12,
267+ 1,
268+ },
269+ {
270+ MEDIA_BUS_FMT_SGRBG12_1X12,
271+ DATA_TYPE_RAW_12BIT,
272+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
273+ 12,
274+ 1,
275+ },
276+ {
277+ MEDIA_BUS_FMT_SRGGB12_1X12,
278+ DATA_TYPE_RAW_12BIT,
279+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
280+ 12,
281+ 1,
282+ },
283+ {
284+ MEDIA_BUS_FMT_SBGGR14_1X14,
285+ DATA_TYPE_RAW_14BIT,
286+ DECODE_FORMAT_UNCOMPRESSED_14_BIT,
287+ 14,
288+ 1,
289+ },
290+ {
291+ MEDIA_BUS_FMT_SGBRG14_1X14,
292+ DATA_TYPE_RAW_14BIT,
293+ DECODE_FORMAT_UNCOMPRESSED_14_BIT,
294+ 14,
295+ 1,
296+ },
297+ {
298+ MEDIA_BUS_FMT_SGRBG14_1X14,
299+ DATA_TYPE_RAW_14BIT,
300+ DECODE_FORMAT_UNCOMPRESSED_14_BIT,
301+ 14,
302+ 1,
303+ },
304+ {
305+ MEDIA_BUS_FMT_SRGGB14_1X14,
306+ DATA_TYPE_RAW_14BIT,
307+ DECODE_FORMAT_UNCOMPRESSED_14_BIT,
308+ 14,
309+ 1,
310+ },
311+ {
312+ MEDIA_BUS_FMT_Y10_1X10,
313+ DATA_TYPE_RAW_10BIT,
314+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
315+ 10,
316+ 1,
317+ },
318+};
319+
320+static const struct csid_format_info formats_gen2[] = {
321+ {
322+ MEDIA_BUS_FMT_UYVY8_1X16,
323+ DATA_TYPE_YUV422_8BIT,
324+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
325+ 8,
326+ 2,
327+ },
328+ {
329+ MEDIA_BUS_FMT_VYUY8_1X16,
330+ DATA_TYPE_YUV422_8BIT,
331+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
332+ 8,
333+ 2,
334+ },
335+ {
336+ MEDIA_BUS_FMT_YUYV8_1X16,
337+ DATA_TYPE_YUV422_8BIT,
338+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
339+ 8,
340+ 2,
341+ },
342+ {
343+ MEDIA_BUS_FMT_YVYU8_1X16,
344+ DATA_TYPE_YUV422_8BIT,
345+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
346+ 8,
347+ 2,
348+ },
349+ {
350+ MEDIA_BUS_FMT_SBGGR8_1X8,
351+ DATA_TYPE_RAW_8BIT,
352+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
353+ 8,
354+ 1,
355+ },
356+ {
357+ MEDIA_BUS_FMT_SGBRG8_1X8,
358+ DATA_TYPE_RAW_8BIT,
359+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
360+ 8,
361+ 1,
362+ },
363+ {
364+ MEDIA_BUS_FMT_SGRBG8_1X8,
365+ DATA_TYPE_RAW_8BIT,
366+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
367+ 8,
368+ 1,
369+ },
370+ {
371+ MEDIA_BUS_FMT_SRGGB8_1X8,
372+ DATA_TYPE_RAW_8BIT,
373+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
374+ 8,
375+ 1,
376+ },
377+ {
378+ MEDIA_BUS_FMT_SBGGR10_1X10,
379+ DATA_TYPE_RAW_10BIT,
380+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
381+ 10,
382+ 1,
383+ },
384+ {
385+ MEDIA_BUS_FMT_SGBRG10_1X10,
386+ DATA_TYPE_RAW_10BIT,
387+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
388+ 10,
389+ 1,
390+ },
391+ {
392+ MEDIA_BUS_FMT_SGRBG10_1X10,
393+ DATA_TYPE_RAW_10BIT,
394+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
395+ 10,
396+ 1,
397+ },
398+ {
399+ MEDIA_BUS_FMT_SRGGB10_1X10,
400+ DATA_TYPE_RAW_10BIT,
401+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
402+ 10,
403+ 1,
404+ },
405+ {
406+ MEDIA_BUS_FMT_Y8_1X8,
407+ DATA_TYPE_RAW_8BIT,
408+ DECODE_FORMAT_UNCOMPRESSED_8_BIT,
409+ 8,
410+ 1,
411+ },
412+ {
413+ MEDIA_BUS_FMT_Y10_1X10,
414+ DATA_TYPE_RAW_10BIT,
415+ DECODE_FORMAT_UNCOMPRESSED_10_BIT,
416+ 10,
417+ 1,
418+ },
419+ {
420+ MEDIA_BUS_FMT_SBGGR12_1X12,
421+ DATA_TYPE_RAW_12BIT,
422+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
423+ 12,
424+ 1,
425+ },
426+ {
427+ MEDIA_BUS_FMT_SGBRG12_1X12,
428+ DATA_TYPE_RAW_12BIT,
429+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
430+ 12,
431+ 1,
432+ },
433+ {
434+ MEDIA_BUS_FMT_SGRBG12_1X12,
435+ DATA_TYPE_RAW_12BIT,
436+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
437+ 12,
438+ 1,
439+ },
440+ {
441+ MEDIA_BUS_FMT_SRGGB12_1X12,
442+ DATA_TYPE_RAW_12BIT,
443+ DECODE_FORMAT_UNCOMPRESSED_12_BIT,
444+ 12,
445+ 1,
446+ },
447+ {
448+ MEDIA_BUS_FMT_SBGGR14_1X14,
449+ DATA_TYPE_RAW_14BIT,
450+ DECODE_FORMAT_UNCOMPRESSED_14_BIT,
451+ 14,
452+ 1,
453+ },
454+ {
455+ MEDIA_BUS_FMT_SGBRG14_1X14,
456+ DATA_TYPE_RAW_14BIT,
457+ DECODE_FORMAT_UNCOMPRESSED_14_BIT,
458+ 14,
459+ 1,
460+ },
461+ {
462+ MEDIA_BUS_FMT_SGRBG14_1X14,
463+ DATA_TYPE_RAW_14BIT,
464+ DECODE_FORMAT_UNCOMPRESSED_14_BIT,
465+ 14,
466+ 1,
467+ },
468+ {
469+ MEDIA_BUS_FMT_SRGGB14_1X14,
470+ DATA_TYPE_RAW_14BIT,
471+ DECODE_FORMAT_UNCOMPRESSED_14_BIT,
472+ 14,
473+ 1,
474+ },
475+};
476+
477+const struct csid_formats csid_formats_4_1 = {
478+ .nformats = ARRAY_SIZE(formats_4_1),
479+ .formats = formats_4_1
480+};
481+
482+const struct csid_formats csid_formats_4_7 = {
483+ .nformats = ARRAY_SIZE(formats_4_7),
484+ .formats = formats_4_7
485+};
486+
487+const struct csid_formats csid_formats_gen2 = {
488+ .nformats = ARRAY_SIZE(formats_gen2),
489+ .formats = formats_gen2
490+};
491+
48492 u32 csid_find_code(u32 *codes, unsigned int ncodes,
49493 unsigned int match_format_idx, u32 match_code)
50494 {
@@ -65,9 +509,9 @@ u32 csid_find_code(u32 *codes, unsigned int ncodes, · 14 unmodified lines
65509 return codes[0];
66510 }
67511
68−const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats,
69− unsigned int nformats,
70− u32 code)
512+const struct csid_format_info *csid_get_fmt_entry(const struct csid_format_info *formats,
513+ unsigned int nformats,
514+ u32 code)
71515 {
72516 unsigned int i;
73517
@@ -87,12 +531,12 @@ const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats, · 13 unmodified lines
87531 static int csid_set_clock_rates(struct csid_device *csid)
88532 {
89533 struct device *dev = csid->camss->dev;
90− const struct csid_format *fmt;
534+ const struct csid_format_info *fmt;
91535 s64 link_freq;
92536 int i, j;
93537 int ret;
94538
95− fmt = csid_get_fmt_entry(csid->formats, csid->nformats,
539+ fmt = csid_get_fmt_entry(csid->res->formats->formats, csid->res->formats->nformats,
96540 csid->fmt[MSM_CSIPHY_PAD_SINK].code);
97541 link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp,
98542 csid->phy.lane_cnt);
@@ -158,7 +602,6 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) · 59 unmodified lines
158602 struct csid_device *csid = v4l2_get_subdevdata(sd);
159603 struct camss *camss = csid->camss;
160604 struct device *dev = camss->dev;
161− struct vfe_device *vfe = &camss->vfe[csid->id];
162605 int ret = 0;
163606
164607 if (on) {
@@ -167,7 +610,7 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) · 2 unmodified lines
167610 * switching on the CSID. Do so unconditionally, as there is no
168611 * drawback in following the same powering order on older SoCs.
169612 */
170− ret = vfe_get(vfe);
613+ ret = csid->res->parent_dev_ops->get(camss, csid->id);
171614 if (ret < 0)
172615 return ret;
173616
@@ -202,7 +645,7 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) · 28 unmodified lines
202645
203646 enable_irq(csid->irq);
204647
205− ret = csid->ops->reset(csid);
648+ ret = csid->res->hw_ops->reset(csid);
206649 if (ret < 0) {
207650 disable_irq(csid->irq);
208651 camss_disable_clocks(csid->nclocks, csid->clock);
@@ -212,14 +655,14 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) · 3 unmodified lines
212655 return ret;
213656 }
214657
215− csid->ops->hw_version(csid);
658+ csid->res->hw_ops->hw_version(csid);
216659 } else {
217660 disable_irq(csid->irq);
218661 camss_disable_clocks(csid->nclocks, csid->clock);
219662 regulator_bulk_disable(csid->num_supplies,
220663 csid->supplies);
221664 pm_runtime_put_sync(dev);
222− vfe_put(vfe);
665+ csid->res->parent_dev_ops->put(camss, csid->id);
223666 }
224667
225668 return ret;
@@ -253,7 +696,7 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) · 27 unmodified lines
253696 }
254697
255698 if (csid->phy.need_vc_update) {
256− csid->ops->configure_stream(csid, enable);
699+ csid->res->hw_ops->configure_stream(csid, enable);
257700 csid->phy.need_vc_update = false;
258701 }
259702
@@ -301,12 +744,12 @@ static void csid_try_format(struct csid_device *csid, · 41 unmodified lines
301744 case MSM_CSID_PAD_SINK:
302745 /* Set format on sink pad */
303746
304− for (i = 0; i < csid->nformats; i++)
305− if (fmt->code == csid->formats[i].code)
747+ for (i = 0; i < csid->res->formats->nformats; i++)
748+ if (fmt->code == csid->res->formats->formats[i].code)
306749 break;
307750
308751 /* If not found, use UYVY as default */
309− if (i >= csid->nformats)
752+ if (i >= csid->res->formats->nformats)
310753 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
311754
312755 fmt->width = clamp_t(u32, fmt->width, 1, 8191);
@@ -325,17 +768,17 @@ static void csid_try_format(struct csid_device *csid, · 12 unmodified lines
325768
326769 *fmt = *__csid_get_format(csid, sd_state,
327770 MSM_CSID_PAD_SINK, which);
328− fmt->code = csid->ops->src_pad_code(csid, fmt->code, 0, code);
771+ fmt->code = csid->res->hw_ops->src_pad_code(csid, fmt->code, 0, code);
329772 } else {
330773 /* Test generator is enabled, set format on source */
331774 /* pad to allow test generator usage */
332775
333− for (i = 0; i < csid->nformats; i++)
334− if (csid->formats[i].code == fmt->code)
776+ for (i = 0; i < csid->res->formats->nformats; i++)
777+ if (csid->res->formats->formats[i].code == fmt->code)
335778 break;
336779
337780 /* If not found, use UYVY as default */
338− if (i >= csid->nformats)
781+ if (i >= csid->res->formats->nformats)
339782 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
340783
341784 fmt->width = clamp_t(u32, fmt->width, 1, 8191);
@@ -363,10 +806,10 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, · 21 unmodified lines
363806 struct csid_device *csid = v4l2_get_subdevdata(sd);
364807
365808 if (code->pad == MSM_CSID_PAD_SINK) {
366− if (code->index >= csid->nformats)
809+ if (code->index >= csid->res->formats->nformats)
367810 return -EINVAL;
368811
369− code->code = csid->formats[code->index].code;
812+ code->code = csid->res->formats->formats[code->index].code;
370813 } else {
371814 if (csid->testgen_mode->cur.val == 0) {
372815 struct v4l2_mbus_framefmt *sink_fmt;
@@ -375,15 +818,15 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, · 2 unmodified lines
375818 MSM_CSID_PAD_SINK,
376819 code->which);
377820
378− code->code = csid->ops->src_pad_code(csid, sink_fmt->code,
379− code->index, 0);
821+ code->code = csid->res->hw_ops->src_pad_code(csid, sink_fmt->code,
822+ code->index, 0);
380823 if (!code->code)
381824 return -EINVAL;
382825 } else {
383− if (code->index >= csid->nformats)
826+ if (code->index >= csid->res->formats->nformats)
384827 return -EINVAL;
385828
386− code->code = csid->formats[code->index].code;
829+ code->code = csid->res->formats->formats[code->index].code;
387830 }
388831 }
389832
@@ -529,7 +972,7 @@ static int csid_set_test_pattern(struct csid_device *csid, s32 value) · 139 unmodified lines
529972
530973 tg->enabled = !!value;
531974
532− return csid->ops->configure_testgen_pattern(csid, value);
975+ return csid->res->hw_ops->configure_testgen_pattern(csid, value);
533976 }
534977
535978 /*
@@ -575,9 +1018,14 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, · 39 unmodified lines
5751018
5761019 csid->camss = camss;
5771020 csid->id = id;
578− csid->ops = res->ops;
1021+ csid->res = &res->csid;
1022+
1023+ if (dev_WARN_ONCE(dev, !csid->res->parent_dev_ops,
1024+ "Error: CSID depends on VFE/IFE device ops!\n")) {
1025+ return -EINVAL;
1026+ }
5791027
580− csid->ops->subdev_init(csid);
1028+ csid->res->hw_ops->subdev_init(csid);
5811029
5821030 /* Memory */
5831031
@@ -587,9 +1035,11 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, · 3 unmodified lines
5871035 * VFE to be initialized before CSID
5881036 */
5891037 if (id >= 2) /* VFE/CSID lite */
590− csid->base = camss->vfe[id].base + VFE_480_LITE_CSID_OFFSET;
1038+ csid->base = csid->res->parent_dev_ops->get_base_address(camss, id)
1039+ + VFE_480_LITE_CSID_OFFSET;
5911040 else
592− csid->base = camss->vfe[id].base + VFE_480_CSID_OFFSET;
1041+ csid->base = csid->res->parent_dev_ops->get_base_address(camss, id)
1042+ + VFE_480_CSID_OFFSET;
5931043 } else {
5941044 csid->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]);
5951045 if (IS_ERR(csid->base))
@@ -605,7 +1055,7 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, · 9 unmodified lines
6051055 csid->irq = ret;
6061056 snprintf(csid->irq_name, sizeof(csid->irq_name), "%s_%s%d",
6071057 dev_name(dev), MSM_CSID_NAME, csid->id);
608− ret = devm_request_irq(dev, csid->irq, csid->ops->isr,
1058+ ret = devm_request_irq(dev, csid->irq, csid->res->hw_ops->isr,
6091059 IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN,
6101060 csid->irq_name, csid);
6111061 if (ret < 0) {
@@ -899,5 +1349,5 @@ void msm_csid_unregister_entity(struct csid_device *csid) · 287 unmodified lines
8991349
9001350 inline bool csid_is_lite(struct csid_device *csid)
9011351 {
902− return csid->camss->res->csid_res[csid->id].is_lite;
1352+ return csid->camss->res->csid_res[csid->id].csid.is_lite;
9031353 }
drivers/media/platform/qcom/camss/camss-csid.h+23−9
@@ -67,7 +67,7 @@ enum csid_testgen_mode { · 66 unmodified lines
6767 CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2 = 9, /* excluding disabled */
6868 };
6969
70−struct csid_format {
70+struct csid_format_info {
7171 u32 code;
7272 u8 data_type;
7373 u8 decode_format;
@@ -75,6 +75,11 @@ struct csid_format { · 1 unmodified line
7575 u8 spp; /* bus samples per pixel */
7676 };
7777
78+struct csid_formats {
79+ unsigned int nformats;
80+ const struct csid_format_info *formats;
81+};
82+
7883 struct csid_testgen_config {
7984 enum csid_testgen_mode mode;
8085 const char * const*modes;
@@ -149,6 +154,13 @@ struct csid_hw_ops { · 68 unmodified lines
149154 void (*subdev_init)(struct csid_device *csid);
150155 };
151156
157+struct csid_subdev_resources {
158+ bool is_lite;
159+ const struct csid_hw_ops *hw_ops;
160+ const struct parent_dev_ops *parent_dev_ops;
161+ const struct csid_formats *formats;
162+};
163+
152164 struct csid_device {
153165 struct camss *camss;
154166 u8 id;
@@ -167,9 +179,7 @@ struct csid_device { · 12 unmodified lines
167179 struct v4l2_mbus_framefmt fmt[MSM_CSID_PADS_NUM];
168180 struct v4l2_ctrl_handler ctrls;
169181 struct v4l2_ctrl *testgen_mode;
170− const struct csid_format *formats;
171− unsigned int nformats;
172− const struct csid_hw_ops *ops;
182+ const struct csid_subdev_resources *res;
173183 };
174184
175185 struct camss_subdev_resources;
@@ -188,16 +198,16 @@ u32 csid_find_code(u32 *codes, unsigned int ncode, · 12 unmodified lines
188198 unsigned int match_format_idx, u32 match_code);
189199
190200 /*
191− * csid_get_fmt_entry - Find csid_format entry with matching format code
192− * @formats: Array of format csid_format entries
201+ * csid_get_fmt_entry - Find csid_format_info entry with matching format code
202+ * @formats: Array of format csid_format_info entries
193203 * @nformats: Length of @nformats array
194204 * @code: Desired format code
195205 *
196206 * Return formats[0] on failure to find code
197207 */
198−const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats,
199− unsigned int nformats,
200− u32 code);
208+const struct csid_format_info *csid_get_fmt_entry(const struct csid_format_info *formats,
209+ unsigned int nformats,
210+ u32 code);
201211
202212 int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
203213 const struct camss_subdev_resources *res, u8 id);
@@ -211,6 +221,10 @@ void msm_csid_get_csid_id(struct media_entity *entity, u8 *id); · 7 unmodified lines
211221
212222 extern const char * const csid_testgen_modes[];
213223
224+extern const struct csid_formats csid_formats_4_1;
225+extern const struct csid_formats csid_formats_4_7;
226+extern const struct csid_formats csid_formats_gen2;
227+
214228 extern const struct csid_hw_ops csid_ops_4_1;
215229 extern const struct csid_hw_ops csid_ops_4_7;
216230 extern const struct csid_hw_ops csid_ops_gen2;
drivers/media/platform/qcom/camss/camss-csiphy.c+33−41
@@ -24,12 +24,7 @@ · 23 unmodified lines
2424
2525 #define MSM_CSIPHY_NAME "msm_csiphy"
2626
27−struct csiphy_format {
28− u32 code;
29− u8 bpp;
30−};
31−
32−static const struct csiphy_format csiphy_formats_8x16[] = {
27+static const struct csiphy_format_info formats_8x16[] = {
3328 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },
3429 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },
3530 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },
@@ -49,7 +44,7 @@ static const struct csiphy_format csiphy_formats_8x16[] = { · 13 unmodified lines
4944 { MEDIA_BUS_FMT_Y10_1X10, 10 },
5045 };
5146
52−static const struct csiphy_format csiphy_formats_8x96[] = {
47+static const struct csiphy_format_info formats_8x96[] = {
5348 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },
5449 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },
5550 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },
@@ -73,7 +68,7 @@ static const struct csiphy_format csiphy_formats_8x96[] = { · 17 unmodified lines
7368 { MEDIA_BUS_FMT_Y10_1X10, 10 },
7469 };
7570
76−static const struct csiphy_format csiphy_formats_sdm845[] = {
71+static const struct csiphy_format_info formats_sdm845[] = {
7772 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },
7873 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },
7974 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },
@@ -98,6 +93,21 @@ static const struct csiphy_format csiphy_formats_sdm845[] = { · 18 unmodified lines
9893 { MEDIA_BUS_FMT_Y10_1X10, 10 },
9994 };
10095
96+const struct csiphy_formats csiphy_formats_8x16 = {
97+ .nformats = ARRAY_SIZE(formats_8x16),
98+ .formats = formats_8x16
99+};
100+
101+const struct csiphy_formats csiphy_formats_8x96 = {
102+ .nformats = ARRAY_SIZE(formats_8x96),
103+ .formats = formats_8x96
104+};
105+
106+const struct csiphy_formats csiphy_formats_sdm845 = {
107+ .nformats = ARRAY_SIZE(formats_sdm845),
108+ .formats = formats_sdm845
109+};
110+
101111 /*
102112 * csiphy_get_bpp - map media bus format to bits per pixel
103113 * @formats: supported media bus formats array
@@ -106,7 +116,7 @@ static const struct csiphy_format csiphy_formats_sdm845[] = { · 2 unmodified lines
106116 *
107117 * Return number of bits per pixel
108118 */
109−static u8 csiphy_get_bpp(const struct csiphy_format *formats,
119+static u8 csiphy_get_bpp(const struct csiphy_format_info *formats,
110120 unsigned int nformats, u32 code)
111121 {
112122 unsigned int i;
@@ -131,7 +141,7 @@ static int csiphy_set_clock_rates(struct csiphy_device *csiphy) · 18 unmodified lines
131141 int i, j;
132142 int ret;
133143
134− u8 bpp = csiphy_get_bpp(csiphy->formats, csiphy->nformats,
144+ u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats,
135145 csiphy->fmt[MSM_CSIPHY_PAD_SINK].code);
136146 u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data;
137147
@@ -216,9 +226,9 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) · 78 unmodified lines
216226
217227 enable_irq(csiphy->irq);
218228
219− csiphy->ops->reset(csiphy);
229+ csiphy->res->hw_ops->reset(csiphy);
220230
221− csiphy->ops->hw_version_read(csiphy, dev);
231+ csiphy->res->hw_ops->hw_version_read(csiphy, dev);
222232 } else {
223233 disable_irq(csiphy->irq);
224234
@@ -243,8 +253,8 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) · 18 unmodified lines
243253 {
244254 struct csiphy_config *cfg = &csiphy->cfg;
245255 s64 link_freq;
246− u8 lane_mask = csiphy->ops->get_lane_mask(&cfg->csi2->lane_cfg);
247− u8 bpp = csiphy_get_bpp(csiphy->formats, csiphy->nformats,
256+ u8 lane_mask = csiphy->res->hw_ops->get_lane_mask(&cfg->csi2->lane_cfg);
257+ u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats,
248258 csiphy->fmt[MSM_CSIPHY_PAD_SINK].code);
249259 u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data;
250260 u8 val;
@@ -272,7 +282,7 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) · 21 unmodified lines
272282 wmb();
273283 }
274284
275− csiphy->ops->lanes_enable(csiphy, cfg, link_freq, lane_mask);
285+ csiphy->res->hw_ops->lanes_enable(csiphy, cfg, link_freq, lane_mask);
276286
277287 return 0;
278288 }
@@ -285,7 +295,7 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) · 6 unmodified lines
285295 */
286296 static void csiphy_stream_off(struct csiphy_device *csiphy)
287297 {
288− csiphy->ops->lanes_disable(csiphy, &csiphy->cfg);
298+ csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg);
289299 }
290300
291301
@@ -350,12 +360,12 @@ static void csiphy_try_format(struct csiphy_device *csiphy, · 58 unmodified lines
350360 case MSM_CSIPHY_PAD_SINK:
351361 /* Set format on sink pad */
352362
353− for (i = 0; i < csiphy->nformats; i++)
354− if (fmt->code == csiphy->formats[i].code)
363+ for (i = 0; i < csiphy->res->formats->nformats; i++)
364+ if (fmt->code == csiphy->res->formats->formats[i].code)
355365 break;
356366
357367 /* If not found, use UYVY as default */
358− if (i >= csiphy->nformats)
368+ if (i >= csiphy->res->formats->nformats)
359369 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
360370
361371 fmt->width = clamp_t(u32, fmt->width, 1, 8191);
@@ -392,10 +402,10 @@ static int csiphy_enum_mbus_code(struct v4l2_subdev *sd, · 30 unmodified lines
392402 struct v4l2_mbus_framefmt *format;
393403
394404 if (code->pad == MSM_CSIPHY_PAD_SINK) {
395− if (code->index >= csiphy->nformats)
405+ if (code->index >= csiphy->res->formats->nformats)
396406 return -EINVAL;
397407
398− code->code = csiphy->formats[code->index].code;
408+ code->code = csiphy->res->formats->formats[code->index].code;
399409 } else {
400410 if (code->index > 0)
401411 return -EINVAL;
@@ -564,25 +574,7 @@ int msm_csiphy_subdev_init(struct camss *camss, · 162 unmodified lines
564574 csiphy->camss = camss;
565575 csiphy->id = id;
566576 csiphy->cfg.combo_mode = 0;
567− csiphy->ops = res->ops;
568−
569− switch (camss->res->version) {
570− case CAMSS_8x16:
571− csiphy->formats = csiphy_formats_8x16;
572− csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x16);
573− break;
574− case CAMSS_8x96:
575− case CAMSS_660:
576− csiphy->formats = csiphy_formats_8x96;
577− csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x96);
578− break;
579− case CAMSS_845:
580− case CAMSS_8250:
581− case CAMSS_8280XP:
582− csiphy->formats = csiphy_formats_sdm845;
583− csiphy->nformats = ARRAY_SIZE(csiphy_formats_sdm845);
584− break;
585− }
577+ csiphy->res = &res->csiphy;
586578
587579 /* Memory */
588580
@@ -610,7 +602,7 @@ int msm_csiphy_subdev_init(struct camss *camss, · 21 unmodified lines
610602 snprintf(csiphy->irq_name, sizeof(csiphy->irq_name), "%s_%s%d",
611603 dev_name(dev), MSM_CSIPHY_NAME, csiphy->id);
612604
613− ret = devm_request_irq(dev, csiphy->irq, csiphy->ops->isr,
605+ ret = devm_request_irq(dev, csiphy->irq, csiphy->res->hw_ops->isr,
614606 IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN,
615607 csiphy->irq_name, csiphy);
616608 if (ret < 0) {
drivers/media/platform/qcom/camss/camss-csiphy.h+20−3
@@ -42,6 +42,16 @@ struct csiphy_config { · 41 unmodified lines
4242 struct csiphy_csi2_cfg *csi2;
4343 };
4444
45+struct csiphy_format_info {
46+ u32 code;
47+ u8 bpp;
48+};
49+
50+struct csiphy_formats {
51+ unsigned int nformats;
52+ const struct csiphy_format_info *formats;
53+};
54+
4555 struct csiphy_device;
4656
4757 struct csiphy_hw_ops {
@@ -63,6 +73,11 @@ struct csiphy_hw_ops { · 15 unmodified lines
6373 irqreturn_t (*isr)(int irq, void *dev);
6474 };
6575
76+struct csiphy_subdev_resources {
77+ const struct csiphy_hw_ops *hw_ops;
78+ const struct csiphy_formats *formats;
79+};
80+
6681 struct csiphy_device {
6782 struct camss *camss;
6883 u8 id;
@@ -78,9 +93,7 @@ struct csiphy_device { · 9 unmodified lines
7893 u32 timer_clk_rate;
7994 struct csiphy_config cfg;
8095 struct v4l2_mbus_framefmt fmt[MSM_CSIPHY_PADS_NUM];
81− const struct csiphy_hw_ops *ops;
82− const struct csiphy_format *formats;
83− unsigned int nformats;
96+ const struct csiphy_subdev_resources *res;
8497 };
8598
8699 struct camss_subdev_resources;
@@ -94,6 +107,10 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, · 7 unmodified lines
94107
95108 void msm_csiphy_unregister_entity(struct csiphy_device *csiphy);
96109
110+extern const struct csiphy_formats csiphy_formats_8x16;
111+extern const struct csiphy_formats csiphy_formats_8x96;
112+extern const struct csiphy_formats csiphy_formats_sdm845;
113+
97114 extern const struct csiphy_hw_ops csiphy_ops_2ph_1_0;
98115 extern const struct csiphy_hw_ops csiphy_ops_3ph_1_0;
99116
drivers/media/platform/qcom/camss/camss-format.c+91−0
@@ -0,0 +1,91 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * camss-format.c
4+ *
5+ * Qualcomm MSM Camera Subsystem - Format helpers
6+ *
7+ * Copyright (c) 2023, The Linux Foundation. All rights reserved.
8+ * Copyright (c) 2023 Qualcomm Technologies, Inc.
9+ */
10+#include <linux/bug.h>
11+#include <linux/errno.h>
12+
13+#include "camss-format.h"
14+
15+/*
16+ * camss_format_get_bpp - Map media bus format to bits per pixel
17+ * @formats: supported media bus formats array
18+ * @nformats: size of @formats array
19+ * @code: media bus format code
20+ *
21+ * Return number of bits per pixel
22+ */
23+u8 camss_format_get_bpp(const struct camss_format_info *formats, unsigned int nformats, u32 code)
24+{
25+ unsigned int i;
26+
27+ for (i = 0; i < nformats; i++)
28+ if (code == formats[i].code)
29+ return formats[i].mbus_bpp;
30+
31+ WARN(1, "Unknown format\n");
32+
33+ return formats[0].mbus_bpp;
34+}
35+
36+/*
37+ * camss_format_find_code - Find a format code in an array
38+ * @code: a pointer to media bus format codes array
39+ * @n_code: size of @code array
40+ * @index: index of code in the array
41+ * @req_code: required code
42+ *
43+ * Return media bus format code
44+ */
45+u32 camss_format_find_code(u32 *code, unsigned int n_code, unsigned int index, u32 req_code)
46+{
47+ unsigned int i;
48+
49+ if (!req_code && index >= n_code)
50+ return 0;
51+
52+ for (i = 0; i < n_code; i++) {
53+ if (req_code) {
54+ if (req_code == code[i])
55+ return req_code;
56+ } else {
57+ if (i == index)
58+ return code[i];
59+ }
60+ }
61+
62+ return code[0];
63+}
64+
65+/*
66+ * camss_format_find_format - Find a format in an array
67+ * @code: media bus format code
68+ * @pixelformat: V4L2 pixel format FCC identifier
69+ * @formats: a pointer to formats array
70+ * @nformats: size of @formats array
71+ *
72+ * Return index of a format or a negative error code otherwise
73+ */
74+int camss_format_find_format(u32 code, u32 pixelformat, const struct camss_format_info *formats,
75+ unsigned int nformats)
76+{
77+ unsigned int i;
78+
79+ for (i = 0; i < nformats; i++) {
80+ if (formats[i].code == code &&
81+ formats[i].pixelformat == pixelformat)
82+ return i;
83+ }
84+
85+ for (i = 0; i < nformats; i++) {
86+ if (formats[i].code == code)
87+ return i;
88+ }
89+
90+ return -EINVAL;
91+}
drivers/media/platform/qcom/camss/camss-format.h+62−0
@@ -0,0 +1,62 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * camss-format.h
4+ *
5+ * Qualcomm MSM Camera Subsystem - Format helpers
6+ *
7+ * Copyright (c) 2023, The Linux Foundation. All rights reserved.
8+ * Copyright (c) 2023 Qualcomm Technologies, Inc.
9+ */
10+#ifndef __CAMSS_FORMAT_H__
11+#define __CAMSS_FORMAT_H__
12+
13+#include <linux/types.h>
14+
15+#define PER_PLANE_DATA(plane, h_fract_num, h_fract_den, v_fract_num, v_fract_den, _bpp) \
16+ .hsub[(plane)].numerator = (h_fract_num), \
17+ .hsub[(plane)].denominator = (h_fract_den), \
18+ .vsub[(plane)].numerator = (v_fract_num), \
19+ .vsub[(plane)].denominator = (v_fract_den), \
20+ .bpp[(plane)] = (_bpp)
21+
22+/*
23+ * struct fract - Represents a fraction
24+ * @numerator: Store the numerator part of the fraction
25+ * @denominator: Store the denominator part of the fraction
26+ */
27+struct fract {
28+ u8 numerator;
29+ u8 denominator;
30+};
31+
32+/*
33+ * struct camss_format_info - ISP media bus format information
34+ * @code: V4L2 media bus format code
35+ * @mbus_bpp: Media bus bits per pixel
36+ * @pixelformat: V4L2 pixel format FCC identifier
37+ * @planes: Number of planes
38+ * @hsub: Horizontal subsampling (for each plane)
39+ * @vsub: Vertical subsampling (for each plane)
40+ * @bpp: Bits per pixel when stored in memory (for each plane)
41+ */
42+struct camss_format_info {
43+ u32 code;
44+ u32 mbus_bpp;
45+ u32 pixelformat;
46+ u8 planes;
47+ struct fract hsub[3];
48+ struct fract vsub[3];
49+ unsigned int bpp[3];
50+};
51+
52+struct camss_formats {
53+ unsigned int nformats;
54+ const struct camss_format_info *formats;
55+};
56+
57+u8 camss_format_get_bpp(const struct camss_format_info *formats, unsigned int nformats, u32 code);
58+u32 camss_format_find_code(u32 *code, unsigned int n_code, unsigned int index, u32 req_code);
59+int camss_format_find_format(u32 code, u32 pixelformat, const struct camss_format_info *formats,
60+ unsigned int nformats);
61+
62+#endif /* __CAMSS_FORMAT_H__ */
drivers/media/platform/qcom/camss/camss-vfe-17x.c+5−5
@@ -353,7 +353,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 352 unmodified lines
353353 writel_relaxed(status0, vfe->base + VFE_IRQ_CLEAR_0);
354354 writel_relaxed(status1, vfe->base + VFE_IRQ_CLEAR_1);
355355
356− for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) {
356+ for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) {
357357 vfe_bus_status[i] = readl_relaxed(vfe->base + VFE_BUS_IRQ_STATUS(i));
358358 writel_relaxed(vfe_bus_status[i], vfe->base + VFE_BUS_IRQ_CLEAR(i));
359359 }
@@ -367,11 +367,11 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 7 unmodified lines
367367 if (status0 & STATUS_0_RESET_ACK)
368368 vfe->isr_ops.reset_ack(vfe);
369369
370− for (i = VFE_LINE_RDI0; i < vfe->line_num; i++)
370+ for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)
371371 if (status0 & STATUS_0_RDI_REG_UPDATE(i))
372372 vfe->isr_ops.reg_update(vfe, i);
373373
374− for (i = VFE_LINE_RDI0; i < vfe->line_num; i++)
374+ for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)
375375 if (status0 & STATUS_1_RDI_SOF(i))
376376 vfe->isr_ops.sof(vfe, i);
377377
@@ -442,7 +442,7 @@ static int vfe_enable_output(struct vfe_line *line) · 64 unmodified lines
442442 {
443443 struct vfe_device *vfe = to_vfe(line);
444444 struct vfe_output *output = &line->output;
445− const struct vfe_hw_ops *ops = vfe->ops;
445+ const struct vfe_hw_ops *ops = vfe->res->hw_ops;
446446 struct media_entity *sensor;
447447 unsigned long flags;
448448 unsigned int frame_skip = 0;
@@ -560,7 +560,7 @@ static void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) · 111 unmodified lines
560560 unsigned long flags;
561561
562562 spin_lock_irqsave(&vfe->output_lock, flags);
563− vfe->ops->reg_update_clear(vfe, line_id);
563+ vfe->res->hw_ops->reg_update_clear(vfe, line_id);
564564
565565 output = &vfe->line[line_id].output;
566566
drivers/media/platform/qcom/camss/camss-vfe-4-1.c+2−2
@@ -892,7 +892,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 891 unmodified lines
892892 u32 value0, value1;
893893 int i, j;
894894
895− vfe->ops->isr_read(vfe, &value0, &value1);
895+ vfe->res->hw_ops->isr_read(vfe, &value0, &value1);
896896
897897 dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",
898898 value0, value1);
@@ -901,7 +901,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 2 unmodified lines
901901 vfe->isr_ops.reset_ack(vfe);
902902
903903 if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
904− vfe->ops->violation_read(vfe);
904+ vfe->res->hw_ops->violation_read(vfe);
905905
906906 if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
907907 vfe->isr_ops.halt_ack(vfe);
drivers/media/platform/qcom/camss/camss-vfe-4-7.c+3−3
@@ -1050,7 +1050,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 1049 unmodified lines
10501050 u32 value0, value1;
10511051 int i, j;
10521052
1053− vfe->ops->isr_read(vfe, &value0, &value1);
1053+ vfe->res->hw_ops->isr_read(vfe, &value0, &value1);
10541054
10551055 dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",
10561056 value0, value1);
@@ -1059,12 +1059,12 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 2 unmodified lines
10591059 vfe->isr_ops.reset_ack(vfe);
10601060
10611061 if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
1062− vfe->ops->violation_read(vfe);
1062+ vfe->res->hw_ops->violation_read(vfe);
10631063
10641064 if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
10651065 vfe->isr_ops.halt_ack(vfe);
10661066
1067− for (i = VFE_LINE_RDI0; i < vfe->line_num; i++)
1067+ for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)
10681068 if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))
10691069 vfe->isr_ops.reg_update(vfe, i);

1 more lines aren’t shown here.

drivers/media/platform/qcom/camss/camss-vfe-4-8.c+3−3

This diff is large: its 24 lines aren’t shown here.

drivers/media/platform/qcom/camss/camss-vfe-gen1.c+4−4

This diff is large: its 35 lines aren’t shown here.

drivers/media/platform/qcom/camss/camss-vfe.c+288−195

This diff is large: its 741 lines aren’t shown here.

drivers/media/platform/qcom/camss/camss-vfe.h+19−3

This diff is large: its 52 lines aren’t shown here.

drivers/media/platform/qcom/camss/camss-video.c+3−291

This diff is large: its 326 lines aren’t shown here.

drivers/media/platform/qcom/camss/camss-video.h+1−3

This diff is large: its 18 lines aren’t shown here.

drivers/media/platform/qcom/camss/camss.c+497−186

This diff is large: its 1328 lines aren’t shown here.

drivers/media/platform/qcom/camss/camss.h+15−5

This diff is large: its 55 lines aren’t shown here.

drivers/media/platform/qcom/venus/core.c+44−1

This diff is large: its 73 lines aren’t shown here.

drivers/media/platform/qcom/venus/core.h+2−0

This diff is large: its 16 lines aren’t shown here.

drivers/media/platform/qcom/venus/vdec.c+2−1

This diff is large: its 17 lines aren’t shown here.

drivers/media/platform/raspberrypi/Kconfig+5−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/platform/raspberrypi/Makefile+3−0

This diff is large: its 4 lines aren’t shown here.

drivers/media/platform/raspberrypi/pisp_be/Kconfig+12−0

This diff is large: its 13 lines aren’t shown here.

drivers/media/platform/raspberrypi/pisp_be/Makefile+6−0

This diff is large: its 7 lines aren’t shown here.

drivers/media/platform/raspberrypi/pisp_be/pisp_be.c+1797−0

This diff is large: its 1798 lines aren’t shown here.

drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h+519−0

This diff is large: its 520 lines aren’t shown here.

drivers/media/platform/renesas/rcar-csi2.c+93−62

This diff is large: its 343 lines aren’t shown here.

drivers/media/platform/renesas/rcar-vin/rcar-dma.c+13−3

This diff is large: its 26 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_brx.c+11−20

This diff is large: its 103 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_clu.c+2−2

This diff is large: its 18 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_drm.c+22−5

This diff is large: its 84 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_drm.h+2−0

This diff is large: its 16 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_entity.c+12−54

This diff is large: its 139 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_entity.h+26−22

This diff is large: its 82 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_hgo.c+13−15

This diff is large: its 55 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_hgt.c+9−11

This diff is large: its 48 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_histo.c+24−52

This diff is large: its 217 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_hsit.c+3−3

This diff is large: its 27 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_lif.c+2−2

This diff is large: its 18 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_lut.c+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_pipe.c+97−6

This diff is large: its 129 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_pipe.h+27−21

This diff is large: its 98 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_rpf.c+27−29

This diff is large: its 109 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_rwpf.c+8−18

This diff is large: its 81 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_rwpf.h+0−3

This diff is large: its 8 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_sru.c+16−21

This diff is large: its 107 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_uds.c+20−31

This diff is large: its 137 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_uif.c+6−9

This diff is large: its 57 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_video.c+68−132

This diff is large: its 250 lines aren’t shown here.

drivers/media/platform/renesas/vsp1/vsp1_wpf.c+16−27

This diff is large: its 103 lines aren’t shown here.

drivers/media/platform/rockchip/rga/rga-buf.c+5−0

This diff is large: its 12 lines aren’t shown here.

drivers/media/platform/rockchip/rga/rga.c+4−0

This diff is large: its 18 lines aren’t shown here.

drivers/media/platform/rockchip/rga/rga.h+3−0

This diff is large: its 10 lines aren’t shown here.

drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c+4−4

This diff is large: its 36 lines aren’t shown here.

drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c+4−4

This diff is large: its 24 lines aren’t shown here.

drivers/media/platform/samsung/exynos4-is/common.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/platform/samsung/exynos4-is/fimc-is.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/platform/samsung/exynos4-is/fimc-lite.c+1−0

This diff is large: its 7 lines aren’t shown here.

drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c+7−7

This diff is large: its 49 lines aren’t shown here.

drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-debugfs.h+2−2

This diff is large: its 11 lines aren’t shown here.

drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c+2−2

This diff is large: its 11 lines aren’t shown here.

drivers/media/platform/ti/vpe/vpdma.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/platform/verisilicon/Kconfig+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/media/platform/verisilicon/hantro_jpeg.c+13−116

This diff is large: its 186 lines aren’t shown here.

drivers/media/platform/xilinx/xilinx-dma.c+2−2

This diff is large: its 11 lines aren’t shown here.

drivers/media/platform/xilinx/xilinx-dma.h+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/media/radio/si470x/radio-si470x-common.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/radio/wl128x/fmdrv.h+3−2

This diff is large: its 21 lines aren’t shown here.

drivers/media/radio/wl128x/fmdrv_common.c+20−20

This diff is large: its 133 lines aren’t shown here.

drivers/media/rc/imon.c+1−4

This diff is large: its 12 lines aren’t shown here.

drivers/media/rc/keymaps/Makefile+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/media/rc/keymaps/rc-mygica-utv3.c+69−0

This diff is large: its 70 lines aren’t shown here.

drivers/media/rc/mceusb.c+3−10

This diff is large: its 36 lines aren’t shown here.

drivers/media/rc/rc-main.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/spi/gs1662.c+0−8

This diff is large: its 15 lines aren’t shown here.

drivers/media/test-drivers/vimc/vimc-capture.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/media/test-drivers/vimc/vimc-common.c+24−1

This diff is large: its 63 lines aren’t shown here.

drivers/media/test-drivers/vimc/vimc-common.h+8−6

This diff is large: its 42 lines aren’t shown here.

drivers/media/test-drivers/vimc/vimc-core.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/media/test-drivers/vimc/vimc-debayer.c+91−110

This diff is large: its 371 lines aren’t shown here.

drivers/media/test-drivers/vimc/vimc-lens.c+3−2

This diff is large: its 23 lines aren’t shown here.

drivers/media/test-drivers/vimc/vimc-scaler.c+54−80

This diff is large: its 268 lines aren’t shown here.

drivers/media/test-drivers/vimc/vimc-sensor.c+56−69

This diff is large: its 247 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-cec.c+69−19

This diff is large: its 130 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-core.c+215−35

This diff is large: its 432 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-core.h+114−11

This diff is large: its 196 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-ctrls.c+152−110

This diff is large: its 363 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-kthread-cap.c+55−31

This diff is large: its 188 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-sdr-cap.c+6−1

This diff is large: its 15 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-touch-cap.c+3−3

This diff is large: its 17 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-vbi-cap.c+5−2

This diff is large: its 35 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-vbi-out.c+2−0

This diff is large: its 9 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-vid-cap.c+76−44

This diff is large: its 229 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-vid-cap.h+2−0

This diff is large: its 9 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-vid-common.c+98−36

This diff is large: its 187 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-vid-common.h+4−1

This diff is large: its 13 lines aren’t shown here.

drivers/media/test-drivers/vivid/vivid-vid-out.c+18−23

This diff is large: its 107 lines aren’t shown here.

drivers/media/tuners/tda9887.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/tuners/tuner-types.c+21−0

This diff is large: its 35 lines aren’t shown here.

drivers/media/tuners/xc2028.c+8−1

This diff is large: its 18 lines aren’t shown here.

drivers/media/usb/b2c2/flexcop-usb.c+4−3

This diff is large: its 32 lines aren’t shown here.

drivers/media/usb/cx231xx/cx231xx-417.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/media/usb/cx231xx/cx231xx-video.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/media/usb/dvb-usb/dibusb-common.c+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/media/usb/dvb-usb/dibusb-mc-common.c+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/media/usb/dvb-usb/dvb-usb-init.c+31−4

This diff is large: its 54 lines aren’t shown here.

drivers/media/usb/dvb-usb/opera1.c+0−4

This diff is large: its 11 lines aren’t shown here.

drivers/media/usb/em28xx/em28xx-cards.c+52−0

This diff is large: its 80 lines aren’t shown here.

drivers/media/usb/em28xx/em28xx-core.c+2−1

This diff is large: its 11 lines aren’t shown here.

drivers/media/usb/em28xx/em28xx.h+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/media/usb/go7007/go7007-driver.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/usb/go7007/go7007-i2c.c+19−11

This diff is large: its 51 lines aren’t shown here.

drivers/media/usb/go7007/go7007-usb.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/media/usb/pvrusb2/pvrusb2-debugifc.c+0−5

This diff is large: its 12 lines aren’t shown here.

drivers/media/usb/ttusb-dec/ttusb_dec.c+11−10

This diff is large: its 85 lines aren’t shown here.

drivers/media/usb/uvc/uvc_ctrl.c+108−85

This diff is large: its 238 lines aren’t shown here.

drivers/media/usb/uvc/uvc_driver.c+30−130

This diff is large: its 221 lines aren’t shown here.

drivers/media/usb/uvc/uvc_video.c+116−53

This diff is large: its 312 lines aren’t shown here.

drivers/media/usb/uvc/uvcvideo.h+7−3

This diff is large: its 53 lines aren’t shown here.

drivers/media/v4l2-core/v4l2-async.c+8−0

This diff is large: its 20 lines aren’t shown here.

drivers/media/v4l2-core/v4l2-cci.c+9−0

This diff is large: its 16 lines aren’t shown here.

drivers/media/v4l2-core/v4l2-common.c+2−0

This diff is large: its 9 lines aren’t shown here.

drivers/media/v4l2-core/v4l2-ctrls-defs.c+5−0

This diff is large: its 19 lines aren’t shown here.

drivers/media/v4l2-core/v4l2-fwnode.c+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/media/v4l2-core/v4l2-ioctl.c+13−0

This diff is large: its 34 lines aren’t shown here.

drivers/media/v4l2-core/v4l2-jpeg.c+116−0

This diff is large: its 123 lines aren’t shown here.

drivers/media/v4l2-core/v4l2-subdev.c+232−161

This diff is large: its 549 lines aren’t shown here.

drivers/staging/media/atomisp/TODO+2−29

This diff is large: its 49 lines aren’t shown here.

drivers/staging/media/atomisp/i2c/atomisp-libmsrlisthelper.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c+1−0

This diff is large: its 6 lines aren’t shown here.

drivers/staging/media/atomisp/include/linux/atomisp_platform.h+11−16

This diff is large: its 42 lines aren’t shown here.

drivers/staging/media/atomisp/pci/atomisp_common.h+0−1

This diff is large: its 8 lines aren’t shown here.

drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c+14−0

This diff is large: its 28 lines aren’t shown here.

drivers/staging/media/atomisp/pci/atomisp_ioctl.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/staging/media/atomisp/pci/atomisp_v4l2.c+16−25

This diff is large: its 62 lines aren’t shown here.

drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_comm.h+6−0

This diff is large: its 25 lines aren’t shown here.

drivers/staging/media/atomisp/pci/camera/util/interface/ia_css_util.h+0−11

This diff is large: its 18 lines aren’t shown here.

drivers/staging/media/atomisp/pci/camera/util/src/util.c+11−14

This diff is large: its 40 lines aren’t shown here.

drivers/staging/media/atomisp/pci/gpio_block_defs.h+0−17

This diff is large: its 28 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hive_isp_css_common/gpio_global.h+0−23

This diff is large: its 32 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gpio_local.h+0−21

This diff is large: its 22 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hive_isp_css_common/host/gpio_private.h+3−6

This diff is large: its 25 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hive_isp_css_include/assert_support.h+0−23

This diff is large: its 30 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hive_isp_css_include/gpio.h+0−46

This diff is large: its 47 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hive_isp_css_include/host/gpio_public.h+0−46

This diff is large: its 47 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h+2−108

This diff is large: its 136 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hive_isp_css_include/type_support.h+3−2

This diff is large: its 13 lines aren’t shown here.

drivers/staging/media/atomisp/pci/hmm/hmm_bo.c+2−2

This diff is large: its 18 lines aren’t shown here.

drivers/staging/media/atomisp/pci/ia_css_3a.h+5−0

This diff is large: its 19 lines aren’t shown here.

drivers/staging/media/atomisp/pci/ia_css_dvs.h+4−0

This diff is large: its 18 lines aren’t shown here.

drivers/staging/media/atomisp/pci/ia_css_metadata.h+4−0

This diff is large: its 18 lines aren’t shown here.

drivers/staging/media/atomisp/pci/ia_css_types.h+2−0

This diff is large: its 9 lines aren’t shown here.

drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8.host.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.c+3−3

This diff is large: its 20 lines aren’t shown here.

drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c+0−2

This diff is large: its 9 lines aren’t shown here.

drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c+2−2

This diff is large: its 18 lines aren’t shown here.

drivers/staging/media/atomisp/pci/runtime/spctrl/interface/ia_css_spctrl_comm.h+4−0

This diff is large: its 16 lines aren’t shown here.

drivers/staging/media/atomisp/pci/sh_css.c+4−44

This diff is large: its 72 lines aren’t shown here.

drivers/staging/media/atomisp/pci/sh_css_frac.h+3−1

This diff is large: its 11 lines aren’t shown here.

drivers/staging/media/atomisp/pci/sh_css_internal.h+15−4

This diff is large: its 86 lines aren’t shown here.

drivers/staging/media/atomisp/pci/sh_css_sp.c+13−11

This diff is large: its 94 lines aren’t shown here.

drivers/staging/media/av7110/Kconfig+0−22

This diff is large: its 29 lines aren’t shown here.

drivers/staging/media/av7110/Makefile+0−2

This diff is large: its 9 lines aren’t shown here.

drivers/staging/media/av7110/TODO+0−3

This diff is large: its 4 lines aren’t shown here.

drivers/staging/media/av7110/audio-bilingual-channel-select.rst+0−58

This diff is large: its 59 lines aren’t shown here.

drivers/staging/media/av7110/audio-channel-select.rst+0−57

This diff is large: its 58 lines aren’t shown here.

drivers/staging/media/av7110/audio-clear-buffer.rst+0−48

This diff is large: its 49 lines aren’t shown here.

drivers/staging/media/av7110/audio-continue.rst+0−48

This diff is large: its 49 lines aren’t shown here.

drivers/staging/media/av7110/audio-fclose.rst+0−51

This diff is large: its 52 lines aren’t shown here.

drivers/staging/media/av7110/audio-fopen.rst+0−103

This diff is large: its 104 lines aren’t shown here.

drivers/staging/media/av7110/audio-fwrite.rst+0−79

This diff is large: its 80 lines aren’t shown here.

drivers/staging/media/av7110/audio-get-capabilities.rst+0−54

This diff is large: its 55 lines aren’t shown here.

drivers/staging/media/av7110/audio-get-status.rst+0−54

This diff is large: its 55 lines aren’t shown here.

drivers/staging/media/av7110/audio-pause.rst+0−49

This diff is large: its 50 lines aren’t shown here.

drivers/staging/media/av7110/audio-play.rst+0−48

This diff is large: its 49 lines aren’t shown here.

drivers/staging/media/av7110/audio-select-source.rst+0−56

This diff is large: its 57 lines aren’t shown here.

drivers/staging/media/av7110/audio-set-av-sync.rst+0−58

This diff is large: its 59 lines aren’t shown here.

drivers/staging/media/av7110/audio-set-bypass-mode.rst+0−62

This diff is large: its 63 lines aren’t shown here.

drivers/staging/media/av7110/audio-set-id.rst+0−59

This diff is large: its 60 lines aren’t shown here.

drivers/staging/media/av7110/audio-set-mixer.rst+0−53

This diff is large: its 54 lines aren’t shown here.

drivers/staging/media/av7110/audio-set-mute.rst+0−62

This diff is large: its 63 lines aren’t shown here.

drivers/staging/media/av7110/audio-set-streamtype.rst+0−66

This diff is large: its 67 lines aren’t shown here.

drivers/staging/media/av7110/audio-stop.rst+0−48

This diff is large: its 49 lines aren’t shown here.

drivers/staging/media/av7110/audio.rst+0−27

This diff is large: its 28 lines aren’t shown here.

drivers/staging/media/av7110/audio_data_types.rst+0−116

This diff is large: its 117 lines aren’t shown here.

drivers/staging/media/av7110/audio_function_calls.rst+0−30

This diff is large: its 31 lines aren’t shown here.

drivers/staging/media/av7110/av7110.c+235−261

This diff is large: its 1553 lines aren’t shown here.

drivers/staging/media/av7110/av7110.h+22−28

This diff is large: its 156 lines aren’t shown here.

drivers/staging/media/av7110/av7110_av.c+121−113

This diff is large: its 826 lines aren’t shown here.

drivers/staging/media/av7110/av7110_av.h+18−19

This diff is large: its 48 lines aren’t shown here.

drivers/staging/media/av7110/av7110_ca.c+20−23

This diff is large: its 159 lines aren’t shown here.

drivers/staging/media/av7110/av7110_ca.h+6−6

This diff is large: its 19 lines aren’t shown here.

drivers/staging/media/av7110/av7110_hw.c+108−122

This diff is large: its 738 lines aren’t shown here.

drivers/staging/media/av7110/av7110_hw.h+33−46

This diff is large: its 194 lines aren’t shown here.

drivers/staging/media/av7110/av7110_ipack.c+136−146

This diff is large: its 415 lines aren’t shown here.

drivers/staging/media/av7110/av7110_ipack.h+6−6

This diff is large: its 19 lines aren’t shown here.

drivers/staging/media/av7110/av7110_ir.c+1−2

This diff is large: its 10 lines aren’t shown here.

drivers/staging/media/av7110/av7110_v4l.c+52−50

This diff is large: its 353 lines aren’t shown here.

drivers/staging/media/av7110/budget-patch.c+0−665

This diff is large: its 666 lines aren’t shown here.

drivers/staging/media/av7110/dvb_filter.c+58−58

This diff is large: its 167 lines aren’t shown here.

drivers/staging/media/av7110/dvb_filter.h+9−13

This diff is large: its 75 lines aren’t shown here.

drivers/staging/media/av7110/sp8870.c+108−92

This diff is large: its 495 lines aren’t shown here.

drivers/staging/media/av7110/sp8870.h+10−14

This diff is large: its 46 lines aren’t shown here.

drivers/staging/media/av7110/video-clear-buffer.rst+0−54

This diff is large: its 55 lines aren’t shown here.

drivers/staging/media/av7110/video-command.rst+0−96

This diff is large: its 97 lines aren’t shown here.

drivers/staging/media/av7110/video-continue.rst+0−57

This diff is large: its 58 lines aren’t shown here.

drivers/staging/media/av7110/video-fast-forward.rst+0−72

This diff is large: its 73 lines aren’t shown here.

drivers/staging/media/av7110/video-fclose.rst+0−51

This diff is large: its 52 lines aren’t shown here.

drivers/staging/media/av7110/video-fopen.rst+0−111

This diff is large: its 112 lines aren’t shown here.

drivers/staging/media/av7110/video-freeze.rst+0−61

This diff is large: its 62 lines aren’t shown here.

drivers/staging/media/av7110/video-fwrite.rst+0−79

This diff is large: its 80 lines aren’t shown here.

drivers/staging/media/av7110/video-get-capabilities.rst+0−61

This diff is large: its 62 lines aren’t shown here.

drivers/staging/media/av7110/video-get-event.rst+0−105

This diff is large: its 106 lines aren’t shown here.

drivers/staging/media/av7110/video-get-frame-count.rst+0−65

This diff is large: its 66 lines aren’t shown here.

drivers/staging/media/av7110/video-get-pts.rst+0−69

This diff is large: its 70 lines aren’t shown here.

drivers/staging/media/av7110/video-get-size.rst+0−69

This diff is large: its 70 lines aren’t shown here.

drivers/staging/media/av7110/video-get-status.rst+0−72

This diff is large: its 73 lines aren’t shown here.

drivers/staging/media/av7110/video-play.rst+0−57

This diff is large: its 58 lines aren’t shown here.

drivers/staging/media/av7110/video-select-source.rst+0−76

This diff is large: its 77 lines aren’t shown here.

drivers/staging/media/av7110/video-set-blank.rst+0−64

This diff is large: its 65 lines aren’t shown here.

drivers/staging/media/av7110/video-set-display-format.rst+0−60

This diff is large: its 61 lines aren’t shown here.

drivers/staging/media/av7110/video-set-format.rst+0−82

This diff is large: its 83 lines aren’t shown here.

drivers/staging/media/av7110/video-set-streamtype.rst+0−61

This diff is large: its 62 lines aren’t shown here.

drivers/staging/media/av7110/video-slowmotion.rst+0−72

This diff is large: its 73 lines aren’t shown here.

drivers/staging/media/av7110/video-stillpicture.rst+0−61

This diff is large: its 62 lines aren’t shown here.

drivers/staging/media/av7110/video-stop.rst+0−74

This diff is large: its 75 lines aren’t shown here.

drivers/staging/media/av7110/video-try-command.rst+0−66

This diff is large: its 67 lines aren’t shown here.

drivers/staging/media/av7110/video.rst+0−36

This diff is large: its 37 lines aren’t shown here.

drivers/staging/media/av7110/video_function_calls.rst+0−35

This diff is large: its 36 lines aren’t shown here.

drivers/staging/media/av7110/video_types.rst+0−248

This diff is large: its 249 lines aren’t shown here.

drivers/staging/media/max96712/max96712.c+28−9

This diff is large: its 64 lines aren’t shown here.

include/media/ipu-bridge.h+1−0

This diff is large: its 8 lines aren’t shown here.

include/media/rc-map.h+1−0

This diff is large: its 8 lines aren’t shown here.

include/media/tuner.h+1−0

This diff is large: its 8 lines aren’t shown here.

include/media/v4l2-jpeg.h+32−0

This diff is large: its 44 lines aren’t shown here.

include/media/v4l2-subdev.h+67−25

This diff is large: its 160 lines aren’t shown here.

include/uapi/linux/media/raspberrypi/pisp_be_config.h+968−0

This diff is large: its 969 lines aren’t shown here.

include/uapi/linux/media/raspberrypi/pisp_common.h+202−0

This diff is large: its 203 lines aren’t shown here.

include/uapi/linux/v4l2-controls.h+2−0

This diff is large: its 9 lines aren’t shown here.

include/uapi/linux/videodev2.h+17−0

This diff is large: its 38 lines aren’t shown here.