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
438 - MyGica iGrabber438 - MyGica iGrabber
439 - em2860439 - em2860
440 - 1f4d:1abe440 - 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
135.. code-block:: none135.. code-block:: none
136 136
137 media-ctl -l "\"ov2740 14-0036\":0 -> \"Intel IPU6 CSI2 1\":0[1]"137 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]"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[5]"139 media-ctl -l "\"Intel IPU6 CSI2 1\":2 -> \"Intel IPU6 ISYS Capture 1\":0[1]"
140 140
141 # set routing141 # 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]]"
143 143
144 media-ctl -v "\"Intel IPU6 CSI2 1\":0/0 [fmt:SGRBG10/1932x1092]"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]"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]"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]"147 media-ctl -V "\"Intel IPU6 CSI2 1\":2/1 [fmt:GENERIC_8/97x1]"
148 148
149 CAPTURE_DEV=$(media-ctl -e "Intel IPU6 ISYS Capture 0")149 CAPTURE_DEV=$(media-ctl -e "Intel IPU6 ISYS Capture 0")
150 ./yavta --data-prefix -c100 -n5 -I -s1932x1092 --file=/tmp/frame-#.bin \150 ./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 @@
1digraph 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=========================================================
4Raspberry Pi PiSP Back End Memory-to-Memory ISP (pisp-be)
5=========================================================
6
7The PiSP Back End
8=================
9
10The PiSP Back End is a memory-to-memory Image Signal Processor (ISP) which reads
11image data from DRAM memory and performs image processing as specified by the
12application through the parameters in a configuration buffer, before writing
13pixel data back to memory through two distinct output channels.
14
15The ISP registers and programming model are documented in the `Raspberry Pi
16Image Signal Processor (PiSP) Specification document`_
17
18The PiSP Back End ISP processes images in tiles. The handling of image
19tessellation and the computation of low-level configuration parameters is
20realized by a free software library called `libpisp
21<https://github.com/raspberrypi/libpisp>`_.
22
23The full image processing pipeline, which involves capturing RAW Bayer data from
24an image sensor through a MIPI CSI-2 compatible capture interface, storing them
25in DRAM memory and processing them in the PiSP Back End to obtain images usable
26by an application is implemented in `libcamera <https://libcamera.org>`_ as
27part of the Raspberry Pi platform support.
28
29The pisp-be driver
30==================
31
32The Raspberry Pi PiSP Back End (pisp-be) driver is located under
33drivers/media/platform/raspberrypi/pisp-be. It uses the `V4L2 API` to register
34a number of video capture and output devices, the `V4L2 subdev API` to register
35a subdevice for the ISP that connects the video devices in a single media graph
36realized using the `Media Controller (MC) API`.
37
38The 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
47The 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
59pispbe-input
60------------
61
62Images to be processed by the ISP are queued to the `pispbe-input` output device
63node. 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
66pispbe-tdn_input, pispbe-tdn_output
67-----------------------------------
68
69The `pispbe-tdn_input` output video device receives images to be processed by
70the temporal denoise block which are captured from the `pispbe-tdn_output`
71capture video device. Userspace is responsible for maintaining queues on both
72devices, and ensuring that buffers completed on the output are queued to the
73input.
74
75pispbe-stitch_input, pispbe-stitch_output
76-----------------------------------------
77
78To realize HDR (high dynamic range) image processing the image stitching and
79tonemapping blocks are used. The `pispbe-stitch_output` writes images to memory
80and the `pispbe-stitch_input` receives the previously written frame to process
81it along with the current input image. Userspace is responsible for maintaining
82queues on both devices, and ensuring that buffers completed on the output are
83queued to the input.
84
85pispbe-output0, pispbe-output1
86------------------------------
87
88The two capture devices write to memory the pixel data as processed by the ISP.
89
90pispbe-config
91-------------
92
93The `pispbe-config` output video devices receives a buffer of configuration
94parameters that define the desired image processing to be performed by the ISP.
95
96The 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
98described in the `Raspberry Pi Image Signal Processor (PiSP) Specification
99document`_.
100
101ISP configuration
102=================
103
104The ISP configuration is described solely by the content of the parameters
105buffer. The only parameter that userspace needs to configure using the V4L2 API
106is the image format on the output and capture video devices for validation of
107the 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
9789 Sony BTF-PG472Z PAL/SECAM9789 Sony BTF-PG472Z PAL/SECAM
9890 Sony BTF-PK467Z NTSC-M-JP9890 Sony BTF-PK467Z NTSC-M-JP
9991 Sony BTF-PB463Z NTSC-M9991 Sony BTF-PB463Z NTSC-M
10092 Silicon Labs Si2157 tuner
10193 Tena TNF931D-DFDR1
100============ =====================================================102============ =====================================================
Documentation/admin-guide/media/v4l-drivers.rst+1−0
@@ -23,6 +23,7 @@ Video4Linux (V4L) driver-specific documentation · 22 unmodified lines
23 omap4_camera23 omap4_camera
24 philips24 philips
25 qcom_camss25 qcom_camss
26 raspberrypi-pisp-be
26 rcar-fdp127 rcar-fdp1
27 rkisp128 rkisp1
28 saa713429 saa7134
Documentation/admin-guide/media/vivid.rst+65−120
@@ -302,6 +302,15 @@ all configurable using the following module options: · 301 unmodified lines
302 - 0: forbid hints302 - 0: forbid hints
303 - 1: allow hints303 - 1: allow hints
304 304
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
305Taken together, all these module options allow you to precisely customize314Taken together, all these module options allow you to precisely customize
306the driver behavior and test your application with all sorts of permutations.315the driver behavior and test your application with all sorts of permutations.
307It is also very suitable to emulate hardware that is not yet available, e.g.316It is also very suitable to emulate hardware that is not yet available, e.g.
@@ -313,10 +322,10 @@ Video Capture · 5 unmodified lines
313 322
314This is probably the most frequently used feature. The video capture device323This is probably the most frequently used feature. The video capture device
315can be configured by using the module options num_inputs, input_types and324can be configured by using the module options num_inputs, input_types and
316ccs_cap_mode (see section 1 for more detailed information), but by default325ccs_cap_mode (see "Configuring the driver" for more detailed information),
317four inputs are configured: a webcam, a TV tuner, an S-Video and an HDMI326but by default four inputs are configured: a webcam, a TV tuner, an S-Video
318input, one input for each input type. Those are described in more detail327and an HDMI input, one input for each input type. Those are described in more
319below.328detail below.
320 329
321Special attention has been given to the rate at which new frames become330Special attention has been given to the rate at which new frames become
322available. The jitter will be around 1 jiffie (that depends on the HZ331available. The jitter will be around 1 jiffie (that depends on the HZ
@@ -434,10 +443,10 @@ Video Output · 111 unmodified lines
434------------443------------
435 444
436The video output device can be configured by using the module options445The video output device can be configured by using the module options
437num_outputs, output_types and ccs_out_mode (see section 1 for more detailed446num_outputs, output_types and ccs_out_mode (see "Configuring the driver"
438information), but by default two outputs are configured: an S-Video and an447for more detailed information), but by default two outputs are configured:
439HDMI input, one output for each output type. Those are described in more detail448an S-Video and an HDMI input, one output for each output type. Those are
440below.449described in more detail below.
441 450
442Like with video capture the framerate is also exact in the long term.451Like with video capture the framerate is also exact in the long term.
443 452
@@ -1011,11 +1020,6 @@ Digital Video Controls · 567 unmodified lines
1011 affects the reported colorspace since DVI_D outputs will always use1020 affects the reported colorspace since DVI_D outputs will always use
1012 sRGB.1021 sRGB.
1013 1022
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
1019 1023
1020FM Radio Receiver Controls1024FM Radio Receiver Controls
1021~~~~~~~~~~~~~~~~~~~~~~~~~~1025~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1130,35 +1134,34 @@ Metadata Capture Controls · 108 unmodified lines
1130 1134
1131 if set, then the generated metadata stream contains Source Clock information.1135 if set, then the generated metadata stream contains Source Clock information.
1132 1136
1133Video, VBI and RDS Looping
1134--------------------------
1135 1137
1136The vivid driver supports looping of video output to video input, VBI output1138Video, Sliced VBI and HDMI CEC Looping
1137to VBI input and RDS output to RDS input. For video/VBI looping this emulates1139--------------------------------------
1138as if a cable was hooked up between the output and input connector. So video
1139and VBI looping is only supported between S-Video and HDMI inputs and outputs.
1140VBI is only valid for S-Video as it makes no sense for HDMI.
1141 1140
1142Since radio is wireless this looping always happens if the radio receiver1141Video Looping functionality is supported for devices created by the same
1143frequency is close to the radio transmitter frequency. In that case the radio1142vivid driver instance, as well as across multiple instances of the vivid driver.
1144transmitter will 'override' the emulated radio stations.1143The vivid driver supports looping of video and Sliced VBI data between an S-Video output
1145 1144and an S-Video input. It also supports looping of video and HDMI CEC data between an
1146Looping is currently supported only between devices created by the same1145HDMI output and an HDMI input.
1147vivid driver instance.
1148 1146
1147To enable looping, set the 'HDMI/S-Video XXX-N Is Connected To' control(s) to select
1148whether an input uses the Test Pattern Generator, or is disconnected, or is connected
1149to an output. An input can be connected to an output from any vivid instance.
1150The 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
1152XXX will be 000. And N is the Nth S-Video/HDMI input or output of that instance.
1153If vivid is loaded without module options, then you can connect the S-Video 000-0 input
1154to the S-Video 000-0 output, or the HDMI 000-0 input to the HDMI 000-0 output.
1155This is the equivalent of connecting or disconnecting a cable between an input and an
1156output in a physical device.
1149 1157
1150Video and Sliced VBI looping1158If an 'HDMI/S-Video XXX-N Is Connected To' control selected an output, then the video
1151~~~~~~~~~~~~~~~~~~~~~~~~~~~~1159output will be looped to the video input provided that:
1152 1160
1153The way to enable video/VBI looping is currently fairly crude. A 'Loop Video'1161- the currently selected input matches the input indicated by the control name.
1154control is available in the "Vivid" control class of the video
1155capture and VBI capture devices. When checked the video looping will be enabled.
1156Once enabled any video S-Video or HDMI input will show a static test pattern
1157until the video output has started. At that time the video output will be
1158looped to the video input provided that:
1159 1162
1160- the input type matches the output type. So the HDMI input cannot receive1163- in the vivid instance of the output connector, the currently selected output matches
1161 video from the S-Video output.1164 the output indicated by the control's value.
1162 1165
1163- the video resolution of the video input must match that of the video output.1166- the video resolution of the video input must match that of the video output.
1164 So it is not possible to loop a 50 Hz (720x576) S-Video output to a 60 Hz1167 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
1185 "DV Timings Signal Mode" for the HDMI input should be configured so that a1188 "DV Timings Signal Mode" for the HDMI input should be configured so that a
1186 valid signal is passed to the video input.1189 valid signal is passed to the video input.
1187 1190
1191If any condition is not valid, then the 'Noise' test pattern is shown.
1192
1188The framerates do not have to match, although this might change in the future.1193The framerates do not have to match, although this might change in the future.
1189 1194
1190By default you will see the OSD text superimposed on top of the looped video.1195By 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
1198 1203
1199 1204
1200Radio & RDS Looping1205Radio & RDS Looping
1201~~~~~~~~~~~~~~~~~~~1206-------------------
1202 1207
1203As mentioned in section 6 the radio receiver emulates stations are regular1208The vivid driver supports looping of RDS output to RDS input.
1204frequency intervals. Depending on the frequency of the radio receiver a1209
1205signal strength value is calculated (this is returned by VIDIOC_G_TUNER).1210Since radio is wireless this looping always happens if the radio receiver
1206However, it will also look at the frequency set by the radio transmitter and1211frequency is close to the radio transmitter frequency. In that case the radio
1207if that results in a higher signal strength than the settings of the radio1212transmitter will 'override' the emulated radio stations.
1208transmitter will be used as if it was a valid station. This also includes1213
1209the RDS data (if any) that the transmitter 'transmits'. This is received1214RDS looping is currently supported only between devices created by the same
1210faithfully on the receiver side. Note that when the driver is loaded the1215vivid driver instance.
1211frequencies of the radio receiver and transmitter are not identical, so1216
1217As mentioned in the "Radio Receiver" section, the radio receiver emulates
1218stations at regular frequency intervals. Depending on the frequency of the
1219radio receiver a signal strength value is calculated (this is returned by
1220VIDIOC_G_TUNER). However, it will also look at the frequency set by the radio
1221transmitter and if that results in a higher signal strength than the settings
1222of the radio transmitter will be used as if it was a valid station. This also
1223includes the RDS data (if any) that the transmitter 'transmits'. This is
1224received faithfully on the receiver side. Note that when the driver is loaded
1225the frequencies of the radio receiver and transmitter are not identical, so
1212initially no looping takes place.1226initially no looping takes place.
1213 1227
1214 1228
@@ -1218,8 +1232,8 @@ Cropping, Composing, Scaling · 3 unmodified lines
1218This driver supports cropping, composing and scaling in any combination. Normally1232This driver supports cropping, composing and scaling in any combination. Normally
1219which features are supported can be selected through the Vivid controls,1233which features are supported can be selected through the Vivid controls,
1220but it is also possible to hardcode it when the module is loaded through the1234but it is also possible to hardcode it when the module is loaded through the
1221ccs_cap_mode and ccs_out_mode module options. See section 1 on the details of1235ccs_cap_mode and ccs_out_mode module options. See "Configuring the driver" on
1222these module options.1236the details of these module options.
1223 1237
1224This allows you to test your application for all these variations.1238This allows you to test your application for all these variations.
1225 1239
@@ -1260,7 +1274,8 @@ is set, then the alpha component is only used for the color red and set to · 34 unmodified lines
1260 1274
1261The driver has to be configured to support the multiplanar formats. By default1275The driver has to be configured to support the multiplanar formats. By default
1262the driver instances are single-planar. This can be changed by setting the1276the driver instances are single-planar. This can be changed by setting the
1263multiplanar module option, see section 1 for more details on that option.1277multiplanar module option, see "Configuring the driver" for more details on that
1278option.
1264 1279
1265If the driver instance is using the multiplanar formats/API, then the first1280If the driver instance is using the multiplanar formats/API, then the first
1266single planar format (YUYV) and the multiplanar NV16M and NV61M formats the1281single 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
1270Video output will also honor any data_offset that the application set.1285Video output will also honor any data_offset that the application set.
1271 1286
1272 1287
1273Capture Overlay
1274---------------
1275
1276Note: capture overlay support is implemented primarily to test the existing
1277V4L2 capture overlay API. In practice few if any GPUs support such overlays
1278anymore, and neither are they generally needed anymore since modern hardware
1279is so much more capable. By setting flag 0x10000 in the node_types module
1280option the vivid driver will create a simple framebuffer device that can be
1281used for testing this API. Whether this API should be used for new drivers is
1282questionable.
1283
1284This driver has support for a destructive capture overlay with bitmap clipping
1285and list clipping (up to 16 rectangles) capabilities. Overlays are not
1286supported for multiplanar formats. It also honors the struct v4l2_window field
1287setting: if it is set to FIELD_TOP or FIELD_BOTTOM and the capture setting is
1288FIELD_ALTERNATE, then only the top or bottom fields will be copied to the overlay.
1289
1290The overlay only works if you are also capturing at that same time. This is a
1291vivid limitation since it copies from a buffer to the overlay instead of
1292filling the overlay directly. And if you are not capturing, then no buffers
1293are available to fill.
1294
1295In addition, the pixelformat of the capture format and that of the framebuffer
1296must be the same for the overlay to work. Otherwise VIDIOC_OVERLAY will return
1297an error.
1298
1299In order to really see what it going on you will need to create two vivid
1300instances: the first with a framebuffer enabled. You configure the capture
1301overlay of the second instance to use the framebuffer of the first, then
1302you start capturing in the second instance. For the first instance you setup
1303the output overlay for the video output, turn on video looping and capture
1304to see the blended framebuffer overlay that's being written to by the second
1305instance. 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
1324And from another console:
1325
1326.. code-block:: none
1327
1328 $ v4l2-ctl -d1 --stream-out-mmap
1329
1330And yet another console:
1331
1332.. code-block:: none
1333
1334 $ qv4l2
1335
1336and start streaming.
1337
1338As you can see, this is not for the faint of heart...
1339
1340
1341Output Overlay1288Output Overlay
1342--------------1289--------------
1343 1290
@@ -1405,8 +1352,6 @@ Just as a reminder and in no particular order: · 61 unmodified lines
1405- Add ARGB888 overlay support: better testing of the alpha channel1352- Add ARGB888 overlay support: better testing of the alpha channel
1406- Improve pixel aspect support in the tpg code by passing a real v4l2_fract1353- Improve pixel aspect support in the tpg code by passing a real v4l2_fract
1407- Use per-queue locks and/or per-device locks to improve throughput1354- 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
1410- The SDR radio should use the same 'frequencies' for stations as the normal1355- The SDR radio should use the same 'frequencies' for stations as the normal
1411 radio receiver, and give back noise if the frequency doesn't match up with1356 radio receiver, and give back noise if the frequency doesn't match up with
1412 a station frequency1357 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
8title: GalaxyCore gc05a2 1/5" 5M Pixel MIPI CSI-2 sensor
9
10maintainers:
11 - Zhi Mao <zhi.mao@mediatek.com>
12
13description:
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
18properties:
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
70required:
71 - compatible
72 - reg
73 - clocks
74 - dovdd-supply
75 - avdd-supply
76 - dvdd-supply
77 - reset-gpios
78 - port
79
80additionalProperties: false
81
82examples:
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
8title: GalaxyCore gc08a3 1/4" 8M Pixel MIPI CSI-2 sensor
9
10maintainers:
11 - Zhi Mao <zhi.mao@mediatek.com>
12
13description:
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
18properties:
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
70required:
71 - compatible
72 - reg
73 - clocks
74 - dovdd-supply
75 - avdd-supply
76 - dvdd-supply
77 - reset-gpios
78 - port
79
80additionalProperties: false
81
82examples:
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
8title: Maxim MAX96714 GMSL2 to CSI-2 Deserializer
9
10maintainers:
11 - Julien Massot <julien.massot@collabora.com>
12
13description:
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
27properties:
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
98required:
99 - compatible
100 - reg
101 - ports
102
103additionalProperties: false
104
105examples:
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
8title: MAX96717 CSI-2 to GMSL2 Serializer
9
10maintainers:
11 - Julien Massot <julien.massot@collabora.com>
12
13description:
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
29properties:
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
94required:
95 - compatible
96 - reg
97 - ports
98
99additionalProperties: false
100
101examples:
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 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.22%YAML 1.2
3---3---
4$id: http://devicetree.org/schemas/media/i2c/imx258.yaml#4$id: http://devicetree.org/schemas/media/i2c/sony,imx258.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#5$schema: http://devicetree.org/meta-schemas/core.yaml#
6 6
7title: Sony IMX258 13 Mpixel CMOS Digital Image Sensor7title: Sony IMX258 13 Mpixel CMOS Digital Image Sensor
@@ -13,11 +13,16 @@ description: |- · 5 unmodified lines
13 IMX258 is a diagonal 5.867mm (Type 1/3.06) 13 Mega-pixel CMOS active pixel13 IMX258 is a diagonal 5.867mm (Type 1/3.06) 13 Mega-pixel CMOS active pixel
14 type stacked image sensor with a square pixel array of size 4208 x 3120. It14 type stacked image sensor with a square pixel array of size 4208 x 3120. It
15 is programmable through I2C interface. Image data is sent through MIPI15 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.
17 20
18properties:21properties:
19 compatible:22 compatible:
20 const: sony,imx25823 enum:
24 - sony,imx258
25 - sony,imx258-pdaf
21 26
22 assigned-clocks: true27 assigned-clocks: true
23 assigned-clock-parents: true28 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
8title: Sony IMX283 Sensor
9
10maintainers:
11 - Kieran Bingham <kieran.bingham@ideasonboard.com>
12 - Umang Jain <umang.jain@ideasonboard.com>
13
14description:
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
20properties:
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
71required:
72 - compatible
73 - reg
74 - clocks
75 - port
76
77additionalProperties: false
78
79examples:
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
7title: Imagination E5010 JPEG Encoder
8
9maintainers:
10 - Devarsh Thakkar <devarsht@ti.com>
11
12description: |
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
18properties:
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
48required:
49 - compatible
50 - reg
51 - reg-names
52 - interrupts
53 - clocks
54
55additionalProperties: false
56
57examples:
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
23 oneOf:23 oneOf:
24 - enum:24 - enum:
25 - mediatek,mt8183-mdp3-rdma25 - mediatek,mt8183-mdp3-rdma
26 - mediatek,mt8188-mdp3-rdma
26 - mediatek,mt8195-mdp3-rdma27 - mediatek,mt8195-mdp3-rdma
27 - mediatek,mt8195-vdo1-rdma28 - mediatek,mt8195-vdo1-rdma
28 - items:29 - 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
7title: MediaTek Consumer Infrared Receiver on-SoC Controller
8
9maintainers:
10 - Sean Wang <sean.wang@mediatek.com>
11
12allOf:
13 - $ref: rc.yaml#
14
15properties:
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
35required:
36 - reg
37 - interrupts
38 - clocks
39 - clock-names
40
41unevaluatedProperties: false
42
43examples:
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 @@
1Device-Tree bindings for Mediatek consumer IR controller
2found in Mediatek SoC family
3
4Required 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
16Optional properties:
17- linux,rc-map-name : see rc.txt file in the same directory.
18
19Example:
20
21cir: 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
18 18
19properties:19properties:
20 compatible:20 compatible:
21 const: qcom,msm8996-venus21 enum:
22 - qcom,msm8996-venus
23 - qcom,msm8998-venus
22 24
23 power-domains:25 power-domains:
24 maxItems: 126 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
7title: Raspberry Pi PiSP Image Signal Processor (ISP) Back End
8
9maintainers:
10 - Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
11 - Jacopo Mondi <jacopo.mondi@ideasonboard.com>
12
13description: |
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
21properties:
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
40required:
41 - compatible
42 - reg
43 - interrupts
44 - clocks
45
46additionalProperties: false
47
48examples:
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
103 - rc-msi-digivox-iii103 - rc-msi-digivox-iii
104 - rc-msi-tvanywhere104 - rc-msi-tvanywhere
105 - rc-msi-tvanywhere-plus105 - rc-msi-tvanywhere-plus
106 - rc-mygica-utv3
106 - rc-nebula107 - rc-nebula
107 - rc-nec-terratec-cinergy-xs108 - rc-nec-terratec-cinergy-xs
108 - rc-norwood109 - rc-norwood
Documentation/devicetree/bindings/media/rockchip-rga.yaml+1−0
@@ -24,6 +24,7 @@ properties: · 23 unmodified lines
24 - enum:24 - enum:
25 - rockchip,rk3228-rga25 - rockchip,rk3228-rga
26 - rockchip,rk3568-rga26 - rockchip,rk3568-rga
27 - rockchip,rk3588-rga
27 - const: rockchip,rk3288-rga28 - const: rockchip,rk3288-rga
28 29
29 reg:30 reg:
Documentation/driver-api/media/v4l2-core.rst+1−0
@@ -26,3 +26,4 @@ Video4Linux devices · 25 unmodified lines
26 v4l2-tuner26 v4l2-tuner
27 v4l2-common27 v4l2-common
28 v4l2-tveeprom28 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
3V4L2 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
35 max217535 max2175
36 npcm-video36 npcm-video
37 omap3isp-uapi37 omap3isp-uapi
38 st-vgxy61
39 thp731238 thp7312
40 uvcvideo39 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
971 - ``horizontal_scale``971 - ``horizontal_scale``
972 - Horizontal scaling factor.972 - Horizontal scaling factor.
973 * - __u8973 * - __u8
974 - ``vertical_scaling factor``974 - ``vertical_scale``
975 - Vertical scale.975 - Vertical scaling factor.
976 * - __u8976 * - __u8
977 - ``version``977 - ``version``
978 - Bitstream version.978 - 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
1653 Quantization parameter for a P frame for FWHT. Valid range: from 11653 Quantization parameter for a P frame for FWHT. Valid range: from 1
1654 to 31.1654 to 31.
1655 1655
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
1656.. raw:: latex1670.. raw:: latex
1657 1671
1658 \normalsize1672 \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
15 metafmt-d4xx15 metafmt-d4xx
16 metafmt-generic16 metafmt-generic
17 metafmt-intel-ipu317 metafmt-intel-ipu3
18 metafmt-pisp-be
18 metafmt-rkisp119 metafmt-rkisp1
19 metafmt-uvc20 metafmt-uvc
20 metafmt-vivid21 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************************
6V4L2_META_FMT_RPI_BE_CFG
7************************
8
9Raspberry Pi PiSP Back End configuration format
10===============================================
11
12The Raspberry Pi PiSP Back End memory-to-memory image signal processor is
13configured by userspace by providing a buffer of configuration parameters
14to the `pispbe-config` output video device node using the
15:c:type:`v4l2_meta_format` interface.
16
17The PiSP Back End processes images in tiles, and its configuration requires
18specifying 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
21The `Raspberry Pi PiSP technical specification
22<https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf>`_
23provide detailed description of the ISP back end configuration and programming
24model.
25
26Global configuration data
27-------------------------
28
29The global configuration data describe how the pixels in a particular image are
30to be processed and is therefore shared across all the tiles of the image. So
31for example, LSC (Lens Shading Correction) or Denoise parameters would be common
32across all tiles from the same frame.
33
34Global configuration data are passed to the ISP by populating the member of
35:c:type:`pisp_be_config`.
36
37Tile parameters
38---------------
39
40As the ISP processes images in tiles, each set of tiles parameters describe how
41a single tile in an image is going to be processed. A single set of tile
42parameters consist of 160 bytes of data and to process a batch of tiles several
43sets of tiles parameters are required.
44
45Tiles 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
48Raspberry Pi PiSP Back End uAPI data types
49==========================================
50
51This section describes the data types exposed to userspace by the Raspberry Pi
52PiSP Back End. The section is informative only, for a detailed description of
53each 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
20 :maxdepth: 120 :maxdepth: 1
21 21
22 pixfmt-srggb822 pixfmt-srggb8
23 pixfmt-srggb8-pisp-comp
23 pixfmt-srggb1024 pixfmt-srggb10
24 pixfmt-srggb10p25 pixfmt-srggb10p
25 pixfmt-srggb10alaw826 pixfmt-srggb10alaw8
Documentation/userspace-api/media/v4l/pixfmt-rgb.rst+54−0
@@ -996,6 +996,60 @@ arranged in little endian order. · 995 unmodified lines
996 996
997 \normalsize997 \normalsize
998 998
99916 Bits Per Component
1000=====================
1001
1002These formats store an RGB triplet in six bytes, with 16 bits per component
1003stored in memory in little endian byte order. They are named based on the order
1004of 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
1006the DRM format nomenclature that instead uses the order of components as seen in
1007the 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
999Deprecated RGB Formats1053Deprecated RGB Formats
1000======================1054======================
1001 1055
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**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
15V4L2_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================================================
19Raspberry Pi PiSP compressed 8-bit Bayer formats
20================================================
21
22Description
23===========
24
25The Raspberry Pi ISP (PiSP) uses a family of three fixed-rate compressed Bayer
26formats. A black-level offset may be subtracted to improve compression
27efficiency; the nominal black level and amount of offset must be signalled out
28of band. Each scanline is padded to a multiple of 8 pixels wide, and each block
29of 8 horizontally-contiguous pixels is coded using 8 bytes.
30
31Mode 1 uses a quantization and delta-based coding scheme which preserves up to
3212 significant bits. Mode 2 is a simple sqrt-like companding scheme with 6 PWL
33chords, 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
36The remainder of this description applies to Modes 1 and 3.
37
38Each block of 8 pixels is separated into even and odd phases of 4 pixels,
39coded independently by 32-bit words at successive locations in memory.
40The two LS bits of each 32-bit word give its "quantization mode".
41
42In quantization mode 0, the lowest 321 quantization levels are multiples of
43FSD/4096 and the remaining levels are successive multiples of FSD/2048.
44Quantization modes 1 and 2 use linear quantization with step sizes of
45FSD/1024 and FSD/512 respectively. Each of the four pixels is quantized
46independently, with rounding to the nearest level.
47In 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
49followed by 7 bits for (q2 & 127). Otherwise, for quantization modes
500, 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
53Each of the outer samples (q0,q3) is encoded using a 7-bit field based
54on its inner neighbour q1 or q2. In quantization mode 2 where the inner
55sample 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
57is encoded as (q0-MAX(0,q1-64)). q3 is likewise coded based on q2.
58Each of these values must be in the range [0..127]. All these fields
59of 2, 9, 7, 7, 7 bits respectively are packed in little-endian order
60to give a 32-bit word with LE byte order.
61
62Quantization mode 3 has a "7.5-bit" escape, used when none of the above
63encodings will fit. Each pixel value is quantized to the nearest of 176
64levels, where the lowest 95 levels are multiples of FSD/256 and the
65remaining levels are multiples of FSD/128 (level 175 represents values
66very close to FSD and may require saturating arithmetic to decode).
67
68Each pair of quantized pixels (q0,q1) or (q2,q3) is jointly coded
69by a 15-bit field: 2816*(q0>>4) + 16*q1 + (q0&15).
70Three fields of 2, 15, 15 bits are packed in LE order {15,15,2}.
71
72An implementation of a software decoder of compressed formats is available
73in `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
209 For Y012 and Y12 formats, Y012 places its data in the 12 high bits, with209 For Y012 and Y12 formats, Y012 places its data in the 12 high bits, with
210 padding zeros in the 4 low bits, in contrast to the Y12 format, which has210 padding zeros in the 4 low bits, in contrast to the Y12 format, which has
211 its padding located in the most significant bits of the 16 bit word.211 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
9190F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc0308.yaml9190F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc0308.yaml
9191F: drivers/media/i2c/gc0308.c9191F: drivers/media/i2c/gc0308.c
9192 9192
9193GALAXYCORE GC05a2 CAMERA SENSOR DRIVER
9194M: Zhi Mao <zhi.mao@mediatek.com>
9195L: linux-media@vger.kernel.org
9196S: Maintained
9197F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc05a2.yaml
9198F: drivers/media/i2c/gc05a2.c
9199
9200GALAXYCORE GC08A3 CAMERA SENSOR DRIVER
9201M: Zhi Mao <zhi.mao@mediatek.com>
9202L: linux-media@vger.kernel.org
9203S: Maintained
9204F: Documentation/devicetree/bindings/media/i2c/galaxycore,gc08a3.yaml
9205F: drivers/media/i2c/gc08a3.c
9206
9193GALAXYCORE GC2145 SENSOR DRIVER9207GALAXYCORE GC2145 SENSOR DRIVER
9194M: Alain Volmat <alain.volmat@foss.st.com>9208M: Alain Volmat <alain.volmat@foss.st.com>
9195L: linux-media@vger.kernel.org9209L: linux-media@vger.kernel.org
@@ -10872,6 +10886,13 @@ S: Maintained · 1676 unmodified lines
10872F: Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml10886F: Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml
10873F: drivers/auxdisplay/img-ascii-lcd.c10887F: drivers/auxdisplay/img-ascii-lcd.c
10874 10888
10889IMGTEC JPEG ENCODER DRIVER
10890M: Devarsh Thakkar <devarsht@ti.com>
10891L: linux-media@vger.kernel.org
10892S: Supported
10893F: Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml
10894F: drivers/media/platform/imagination/e5010*
10895
10875IMGTEC IR DECODER DRIVER10896IMGTEC IR DECODER DRIVER
10876S: Orphan10897S: Orphan
10877F: drivers/media/rc/img-ir/10898F: drivers/media/rc/img-ir/
@@ -13632,6 +13653,20 @@ S: Maintained · 2754 unmodified lines
13632F: Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml13653F: Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml
13633F: drivers/staging/media/max96712/max96712.c13654F: drivers/staging/media/max96712/max96712.c
13634 13655
13656MAX96714 GMSL2 DESERIALIZER DRIVER
13657M: Julien Massot <julien.massot@collabora.com>
13658L: linux-media@vger.kernel.org
13659S: Maintained
13660F: Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml
13661F: drivers/media/i2c/max96714.c
13662
13663MAX96717 GMSL2 SERIALIZER DRIVER
13664M: Julien Massot <julien.massot@collabora.com>
13665L: linux-media@vger.kernel.org
13666S: Maintained
13667F: Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
13668F: drivers/media/i2c/max96717.c
13669
13635MAX9860 MONO AUDIO VOICE CODEC DRIVER13670MAX9860 MONO AUDIO VOICE CODEC DRIVER
13636M: Peter Rosin <peda@axentia.se>13671M: Peter Rosin <peda@axentia.se>
13637L: alsa-devel@alsa-project.org (moderated for non-subscribers)13672L: alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -18948,6 +18983,15 @@ L: linux-edac@vger.kernel.org · 5310 unmodified lines
18948S: Maintained18983S: Maintained
18949F: drivers/ras/amd/fmpm.c18984F: drivers/ras/amd/fmpm.c
18950 18985
18986RASPBERRY PI PISP BACK END
18987M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
18988L: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
18989L: linux-media@vger.kernel.org
18990S: Maintained
18991F: Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml
18992F: drivers/media/platform/raspberrypi/pisp_be/
18993F: include/uapi/linux/media/raspberrypi/
18994
18951RC-CORE / LIRC FRAMEWORK18995RC-CORE / LIRC FRAMEWORK
18952M: Sean Young <sean@mess.org>18996M: Sean Young <sean@mess.org>
18953L: linux-media@vger.kernel.org18997L: linux-media@vger.kernel.org
@@ -20898,7 +20942,6 @@ F: include/uapi/rdma/rdma_user_rxe.h · 1944 unmodified lines
20898 20942
20899SOFTLOGIC 6x10 MPEG CODEC20943SOFTLOGIC 6x10 MPEG CODEC
20900M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>20944M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
20901M: Anton Sviridenko <anton@corp.bluecherry.net>
20902M: Andrey Utkin <andrey_utkin@fastmail.com>20945M: Andrey Utkin <andrey_utkin@fastmail.com>
20903M: Ismael Luceno <ismael@iodev.co.uk>20946M: Ismael Luceno <ismael@iodev.co.uk>
20904L: linux-media@vger.kernel.org20947L: linux-media@vger.kernel.org
@@ -20994,7 +21037,7 @@ M: Sakari Ailus <sakari.ailus@linux.intel.com> · 89 unmodified lines
20994L: linux-media@vger.kernel.org21037L: linux-media@vger.kernel.org
20995S: Maintained21038S: Maintained
20996T: git git://linuxtv.org/media_tree.git21039T: git git://linuxtv.org/media_tree.git
20997F: Documentation/devicetree/bindings/media/i2c/imx258.yaml21040F: Documentation/devicetree/bindings/media/i2c/sony,imx258.yaml
20998F: drivers/media/i2c/imx258.c21041F: drivers/media/i2c/imx258.c
20999 21042
21000SONY IMX274 SENSOR DRIVER21043SONY IMX274 SENSOR DRIVER
@@ -21005,6 +21048,15 @@ T: git git://linuxtv.org/media_tree.git · 4 unmodified lines
21005F: Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml21048F: Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml
21006F: drivers/media/i2c/imx274.c21049F: drivers/media/i2c/imx274.c
21007 21050
21051SONY IMX283 SENSOR DRIVER
21052M: Kieran Bingham <kieran.bingham@ideasonboard.com>
21053M: Umang Jain <umang.jain@ideasonboard.com>
21054L: linux-media@vger.kernel.org
21055S: Maintained
21056T: git git://linuxtv.org/media_tree.git
21057F: Documentation/devicetree/bindings/media/i2c/sony,imx283.yaml
21058F: drivers/media/i2c/imx283.c
21059
21008SONY IMX290 SENSOR DRIVER21060SONY IMX290 SENSOR DRIVER
21009M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>21061M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
21010L: linux-media@vger.kernel.org21062L: linux-media@vger.kernel.org
@@ -21381,8 +21433,8 @@ L: linux-media@vger.kernel.org · 370 unmodified lines
21381S: Maintained21433S: Maintained
21382T: git git://linuxtv.org/media_tree.git21434T: git git://linuxtv.org/media_tree.git
21383F: Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml21435F: Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml
21384F: Documentation/userspace-api/media/drivers/st-vgxy61.rst21436F: Documentation/userspace-api/media/drivers/vgxy61.rst
21385F: drivers/media/i2c/st-vgxy61.c21437F: drivers/media/i2c/vgxy61.c
21386 21438
21387ST VL53L0X ToF RANGER(I2C) IIO DRIVER21439ST VL53L0X ToF RANGER(I2C) IIO DRIVER
21388M: Song Qiang <songqiang1304521@gmail.com>21440M: Song Qiang <songqiang1304521@gmail.com>
@@ -23108,7 +23160,6 @@ F: tools/testing/selftests/turbostat/ · 1719 unmodified lines
23108 23160
23109TW5864 VIDEO4LINUX DRIVER23161TW5864 VIDEO4LINUX DRIVER
23110M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>23162M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
23111M: Anton Sviridenko <anton@corp.bluecherry.net>
23112M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>23163M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>
23113M: Andrey Utkin <andrey_utkin@fastmail.com>23164M: Andrey Utkin <andrey_utkin@fastmail.com>
23114L: linux-media@vger.kernel.org23165L: linux-media@vger.kernel.org
@@ -23725,7 +23776,7 @@ F: drivers/media/i2c/mt* · 610 unmodified lines
23725F: drivers/media/i2c/og*23776F: drivers/media/i2c/og*
23726F: drivers/media/i2c/ov*23777F: drivers/media/i2c/ov*
23727F: drivers/media/i2c/s5*23778F: drivers/media/i2c/s5*
23728F: drivers/media/i2c/st-vgxy61.c23779F: drivers/media/i2c/vgxy61.c
23729 23780
23730VF610 NAND DRIVER23781VF610 NAND DRIVER
23731M: Stefan Agner <stefan@agner.ch>23782M: 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
839 mtu_msg.x_msg_header.msg_flags = 0;839 mtu_msg.x_msg_header.msg_flags = 0;
840 mtu_msg.x_msg_header.msg_type = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;840 mtu_msg.x_msg_header.msg_type = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;
841 mtu_msg.x_msg_header.msg_length = sizeof(mtu_msg);841 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;
843 843
844 coredev->sendrequest_handler(coredev->context, &mtu_msg,844 coredev->sendrequest_handler(coredev->context, &mtu_msg,
845 sizeof(mtu_msg));845 sizeof(mtu_msg));
@@ -852,7 +852,7 @@ static int smscore_configure_board(struct smscore_device_t *coredev) · 6 unmodified lines
852 SMS_INIT_MSG(&crys_msg.x_msg_header,852 SMS_INIT_MSG(&crys_msg.x_msg_header,
853 MSG_SMS_NEW_CRYSTAL_REQ,853 MSG_SMS_NEW_CRYSTAL_REQ,
854 sizeof(crys_msg));854 sizeof(crys_msg));
855 crys_msg.msg_data[0] = board->crystal;855 crys_msg.msg_data = board->crystal;
856 856
857 coredev->sendrequest_handler(coredev->context, &crys_msg,857 coredev->sendrequest_handler(coredev->context, &crys_msg,
858 sizeof(crys_msg));858 sizeof(crys_msg));
@@ -1306,7 +1306,7 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode) · 447 unmodified lines
1306 msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);1306 msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);
1307 SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,1307 SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
1308 sizeof(struct sms_msg_data));1308 sizeof(struct sms_msg_data));
1309 msg->msg_data[0] = mode;1309 msg->msg_data = mode;
1310 1310
1311 rc = smscore_sendrequest_and_wait(coredev, msg,1311 rc = smscore_sendrequest_and_wait(coredev, msg,
1312 msg->x_msg_header. msg_length,1312 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
1394 1394
1395 SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,1395 SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
1396 sizeof(struct sms_msg_data));1396 sizeof(struct sms_msg_data));
1397 msg->msg_data[0] = mode;1397 msg->msg_data = mode;
1398 1398
1399 rc = smscore_sendrequest_and_wait(1399 rc = smscore_sendrequest_and_wait(
1400 coredev, msg, msg->x_msg_header.msg_length,1400 coredev, msg, msg->x_msg_header.msg_length,
@@ -1554,7 +1554,7 @@ void smscore_onresponse(struct smscore_device_t *coredev, · 153 unmodified lines
1554 struct sms_msg_data *validity = (struct sms_msg_data *) phdr;1554 struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
1555 1555
1556 pr_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x\n",1556 pr_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x\n",
1557 validity->msg_data[0]);1557 validity->msg_data);
1558 complete(&coredev->data_validity_done);1558 complete(&coredev->data_validity_done);
1559 break;1559 break;
1560 }1560 }
drivers/media/common/siano/smscoreapi.h+2−16
@@ -616,7 +616,7 @@ struct sms_msg_hdr { · 615 unmodified lines
616 616
617struct sms_msg_data {617struct sms_msg_data {
618 struct sms_msg_hdr x_msg_header;618 struct sms_msg_hdr x_msg_header;
619 u32 msg_data[1];619 u32 msg_data;
620};620};
621 621
622struct sms_msg_data2 {622struct sms_msg_data2 {
@@ -666,7 +666,7 @@ struct sms_firmware { · 43 unmodified lines
666 u32 check_sum;666 u32 check_sum;
667 u32 length;667 u32 length;
668 u32 start_address;668 u32 start_address;
669 u8 payload[1];669 u8 payload[];
670};670};
671 671
672/* statistics information returned as response for672/* statistics information returned as response for
@@ -1042,20 +1042,6 @@ struct sms_srvm_signal_status { · 369 unmodified lines
1042 u32 request_id;1042 u32 request_id;
1043};1043};
1044 1044
1045struct 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
1052struct 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
1059struct smscore_config_gpio {1045struct smscore_config_gpio {
1060#define SMS_GPIO_DIRECTION_INPUT 01046#define SMS_GPIO_DIRECTION_INPUT 0
1061#define SMS_GPIO_DIRECTION_OUTPUT 11047#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
689 pid_msg.x_msg_header.msg_flags = 0;689 pid_msg.x_msg_header.msg_flags = 0;
690 pid_msg.x_msg_header.msg_type = MSG_SMS_ADD_PID_FILTER_REQ;690 pid_msg.x_msg_header.msg_type = MSG_SMS_ADD_PID_FILTER_REQ;
691 pid_msg.x_msg_header.msg_length = sizeof(pid_msg);691 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;
693 693
694 return smsclient_sendrequest(client->smsclient,694 return smsclient_sendrequest(client->smsclient,
695 &pid_msg, sizeof(pid_msg));695 &pid_msg, sizeof(pid_msg));
@@ -711,7 +711,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed) · 15 unmodified lines
711 pid_msg.x_msg_header.msg_flags = 0;711 pid_msg.x_msg_header.msg_flags = 0;
712 pid_msg.x_msg_header.msg_type = MSG_SMS_REMOVE_PID_FILTER_REQ;712 pid_msg.x_msg_header.msg_type = MSG_SMS_REMOVE_PID_FILTER_REQ;
713 pid_msg.x_msg_header.msg_length = sizeof(pid_msg);713 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;
715 715
716 return smsclient_sendrequest(client->smsclient,716 return smsclient_sendrequest(client->smsclient,
717 &pid_msg, sizeof(pid_msg));717 &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
20 struct sms_msg_data *msg = buffer;20 struct sms_msg_data *msg = buffer;
21 int i;21 int i;
22 int msg_words;22 int msg_words;
23 u32 *msg_data = &msg->msg_data;
23 24
24 switch (msg->x_msg_header.msg_type) {25 switch (msg->x_msg_header.msg_type) {
25 case MSG_SMS_DATA_DOWNLOAD_REQ:26 case MSG_SMS_DATA_DOWNLOAD_REQ:
26 {27 {
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));
28 break;29 break;
29 }30 }
30 31
@@ -33,7 +34,7 @@ void smsendian_handle_tx_message(void *buffer) · 2 unmodified lines
33 sizeof(struct sms_msg_hdr))/4;34 sizeof(struct sms_msg_hdr))/4;
34 35
35 for (i = 0; i < msg_words; i++)36 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]);
37 38
38 break;39 break;
39 }40 }
@@ -66,11 +67,12 @@ void smsendian_handle_rx_message(void *buffer) · 26 unmodified lines
66 67
67 default:68 default:
68 {69 {
70 u32 *msg_data = &msg->msg_data;
69 msg_words = (msg->x_msg_header.msg_length -71 msg_words = (msg->x_msg_header.msg_length -
70 sizeof(struct sms_msg_hdr))/4;72 sizeof(struct sms_msg_hdr))/4;
71 73
72 for (i = 0; i < msg_words; i++)74 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]);
74 76
75 break;77 break;
76 }78 }
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
180}180}
181EXPORT_SYMBOL_GPL(uvc_format_by_guid);181EXPORT_SYMBOL_GPL(uvc_format_by_guid);
182 182
183MODULE_DESCRIPTION("USB Video Class common code");
183MODULE_LICENSE("GPL");184MODULE_LICENSE("GPL");
drivers/media/common/videobuf2/videobuf2-core.c+0−1
@@ -199,7 +199,6 @@ module_param(debug, int, 0644); · 198 unmodified lines
199})199})
200 200
201static void __vb2_queue_cancel(struct vb2_queue *q);201static void __vb2_queue_cancel(struct vb2_queue *q);
202static void __enqueue_in_driver(struct vb2_buffer *vb);
203 202
204static const char *vb2_state_name(enum vb2_buffer_state s)203static const char *vb2_state_name(enum vb2_buffer_state s)
205{204{
drivers/media/common/videobuf2/videobuf2-dvb.c+1−0
@@ -19,6 +19,7 @@ · 18 unmodified lines
19/* ------------------------------------------------------------------ */19/* ------------------------------------------------------------------ */
20 20
21MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");21MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
22MODULE_DESCRIPTION("Videobuf2 helper library for simple DVB cards");
22MODULE_LICENSE("GPL");23MODULE_LICENSE("GPL");
23 24
24/* ------------------------------------------------------------------ */25/* ------------------------------------------------------------------ */
drivers/media/dvb-frontends/au8522_decoder.c+1−0
@@ -25,6 +25,7 @@ · 24 unmodified lines
25#include "au8522_priv.h"25#include "au8522_priv.h"
26 26
27MODULE_AUTHOR("Devin Heitmueller");27MODULE_AUTHOR("Devin Heitmueller");
28MODULE_DESCRIPTION("Auvitek AU8522 QAM/8VSB demodulator driver and video decoder");
28MODULE_LICENSE("GPL");29MODULE_LICENSE("GPL");
29 30
30static int au8522_analog_debug;31static 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
32 __func__, ##arg); \32 __func__, ##arg); \
33} while (0)33} while (0)
34 34
35struct i2c_device {
36 struct i2c_adapter *i2c_adap;
37 u8 i2c_addr;
38};
39
40struct dib7000p_state {35struct dib7000p_state {
41 struct dvb_frontend demod;36 struct dvb_frontend demod;
42 struct dib7000p_config cfg;37 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
976/*-----------------------------------------------------------------------------976/*-----------------------------------------------------------------------------
977STRUCTURES977STRUCTURES
978----------------------------------------------------------------------------*/978----------------------------------------------------------------------------*/
979struct drxjeq_stat {
980 u16 eq_mse;
981 u8 eq_mode;
982 u8 eq_ctrl;
983 u8 eq_stat;
984};
985
986/* HI command */979/* HI command */
987struct drxj_hi_cmd {980struct drxj_hi_cmd {
988 u16 cmd;981 u16 cmd;
drivers/media/dvb-frontends/mb86a16.c+1−0
@@ -1854,5 +1854,6 @@ error: · 1853 unmodified lines
1854 return NULL;1854 return NULL;
1855}1855}
1856EXPORT_SYMBOL_GPL(mb86a16_attach);1856EXPORT_SYMBOL_GPL(mb86a16_attach);
1857MODULE_DESCRIPTION("Fujitsu MB86A16 DVB-S/DSS DC Receiver driver");
1857MODULE_LICENSE("GPL");1858MODULE_LICENSE("GPL");
1858MODULE_AUTHOR("Manu Abraham");1859MODULE_AUTHOR("Manu Abraham");
drivers/media/dvb-frontends/mxl5xx_defs.h+2−2
@@ -168,7 +168,7 @@ struct MBIN_FILE_HEADER_T { · 167 unmodified lines
168 168
169struct MBIN_FILE_T {169struct MBIN_FILE_T {
170 struct MBIN_FILE_HEADER_T header;170 struct MBIN_FILE_HEADER_T header;
171 u8 data[1];171 u8 data[];
172};172};
173 173
174struct MBIN_SEGMENT_HEADER_T {174struct MBIN_SEGMENT_HEADER_T {
@@ -179,7 +179,7 @@ struct MBIN_SEGMENT_HEADER_T { · 4 unmodified lines
179 179
180struct MBIN_SEGMENT_T {180struct MBIN_SEGMENT_T {
181 struct MBIN_SEGMENT_HEADER_T header;181 struct MBIN_SEGMENT_HEADER_T header;
182 u8 data[1];182 u8 data[];
183};183};
184 184
185enum MXL_CMD_TYPE_E { MXL_CMD_WRITE = 0, MXL_CMD_READ };185enum 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
748 return stv090x_write_regs(state, reg, &tmp, 1);748 return stv090x_write_regs(state, reg, &tmp, 1);
749}749}
750 750
751static 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
759static 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
751static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)767static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
752{768{
753 u32 reg;769 u32 reg;
@@ -761,12 +777,8 @@ static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable) · 7 unmodified lines
761 * In case of any error, the lock is unlocked and exit within the777 * In case of any error, the lock is unlocked and exit within the
762 * relevant operations themselves.778 * relevant operations themselves.
763 */779 */
764 if (enable) {780 if (enable)
765 if (state->config->tuner_i2c_lock)781 stv090x_tuner_i2c_lock(state);
766 state->config->tuner_i2c_lock(&state->frontend, 1);
767 else
768 mutex_lock(&state->internal->tuner_lock);
769 }
770 782
771 reg = STV090x_READ_DEMOD(state, I2CRPT);783 reg = STV090x_READ_DEMOD(state, I2CRPT);
772 if (enable) {784 if (enable) {
@@ -782,20 +794,13 @@ static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable) · 9 unmodified lines
782 goto err;794 goto err;
783 }795 }
784 796
785 if (!enable) {797 if (!enable)
786 if (state->config->tuner_i2c_lock)798 stv090x_tuner_i2c_unlock(state);
787 state->config->tuner_i2c_lock(&state->frontend, 0);
788 else
789 mutex_unlock(&state->internal->tuner_lock);
790 }
791 799
792 return 0;800 return 0;
793err:801err:
794 dprintk(FE_ERROR, 1, "I/O error");802 dprintk(FE_ERROR, 1, "I/O error");
795 if (state->config->tuner_i2c_lock)803 stv090x_tuner_i2c_unlock(state);
796 state->config->tuner_i2c_lock(&state->frontend, 0);
797 else
798 mutex_unlock(&state->internal->tuner_lock);
799 return -1;804 return -1;
800}805}
801 806
drivers/media/dvb-frontends/stv0910.c+0−5
@@ -119,11 +119,6 @@ struct stv { · 118 unmodified lines
119 u8 vth[6];119 u8 vth[6];
120};120};
121 121
122struct sinit_table {
123 u16 address;
124 u8 data;
125};
126
127struct slookup {122struct slookup {
128 s16 value;123 s16 value;
129 u32 reg_value;124 u32 reg_value;
drivers/media/i2c/Kconfig+67−1
@@ -70,6 +70,26 @@ config VIDEO_GC0308 · 69 unmodified lines
70 To compile this driver as a module, choose M here: the70 To compile this driver as a module, choose M here: the
71 module will be called gc0308.71 module will be called gc0308.
72 72
73config 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
83config 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
73config VIDEO_GC214593config VIDEO_GC2145
74 select V4L2_CCI_I2C94 select V4L2_CCI_I2C
75 tristate "GalaxyCore GC2145 sensor support"95 tristate "GalaxyCore GC2145 sensor support"
@@ -139,6 +159,7 @@ config VIDEO_IMX219 · 63 unmodified lines
139 159
140config VIDEO_IMX258160config VIDEO_IMX258
141 tristate "Sony IMX258 sensor support"161 tristate "Sony IMX258 sensor support"
162 select V4L2_CCI_I2C
142 help163 help
143 This is a Video4Linux2 sensor driver for the Sony164 This is a Video4Linux2 sensor driver for the Sony
144 IMX258 camera.165 IMX258 camera.
@@ -153,6 +174,16 @@ config VIDEO_IMX274 · 8 unmodified lines
153 This is a V4L2 sensor driver for the Sony IMX274174 This is a V4L2 sensor driver for the Sony IMX274
154 CMOS image sensor.175 CMOS image sensor.
155 176
177config 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
156config VIDEO_IMX290187config VIDEO_IMX290
157 tristate "Sony IMX290 sensor support"188 tristate "Sony IMX290 sensor support"
158 select REGMAP_I2C189 select REGMAP_I2C
@@ -659,7 +690,7 @@ config VIDEO_S5K6A3 · 500 unmodified lines
659 This is a V4L2 sensor driver for Samsung S5K6A3 raw690 This is a V4L2 sensor driver for Samsung S5K6A3 raw
660 camera sensor.691 camera sensor.
661 692
662config VIDEO_ST_VGXY61693config VIDEO_VGXY61
663 tristate "ST VGXY61 sensor support"694 tristate "ST VGXY61 sensor support"
664 select V4L2_CCI_I2C695 select V4L2_CCI_I2C
665 depends on OF && GPIOLIB696 depends on OF && GPIOLIB
@@ -679,6 +710,7 @@ config VIDEO_THP7312 · 13 unmodified lines
679 tristate "THine THP7312 support"710 tristate "THine THP7312 support"
680 depends on I2C711 depends on I2C
681 select FW_LOADER712 select FW_LOADER
713 select FW_UPLOAD
682 select MEDIA_CONTROLLER714 select MEDIA_CONTROLLER
683 select V4L2_CCI_I2C715 select V4L2_CCI_I2C
684 select V4L2_FWNODE716 select V4L2_FWNODE
@@ -1575,6 +1607,40 @@ config VIDEO_DS90UB960 · 890 unmodified lines
1575 Device driver for the Texas Instruments DS90UB9601607 Device driver for the Texas Instruments DS90UB960
1576 FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer.1608 FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer.
1577 1609
1610config 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
1627config 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
1578endmenu1644endmenu
1579 1645
1580endif # VIDEO_DEV1646endif # VIDEO_DEV
drivers/media/i2c/Makefile+6−1
@@ -38,6 +38,8 @@ obj-$(CONFIG_VIDEO_DW9768) += dw9768.o · 37 unmodified lines
38obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o38obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
39obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/39obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/
40obj-$(CONFIG_VIDEO_GC0308) += gc0308.o40obj-$(CONFIG_VIDEO_GC0308) += gc0308.o
41obj-$(CONFIG_VIDEO_GC05A2) += gc05a2.o
42obj-$(CONFIG_VIDEO_GC08A3) += gc08a3.o
41obj-$(CONFIG_VIDEO_GC2145) += gc2145.o43obj-$(CONFIG_VIDEO_GC2145) += gc2145.o
42obj-$(CONFIG_VIDEO_HI556) += hi556.o44obj-$(CONFIG_VIDEO_HI556) += hi556.o
43obj-$(CONFIG_VIDEO_HI846) += hi846.o45obj-$(CONFIG_VIDEO_HI846) += hi846.o
@@ -48,6 +50,7 @@ obj-$(CONFIG_VIDEO_IMX214) += imx214.o · 4 unmodified lines
48obj-$(CONFIG_VIDEO_IMX219) += imx219.o50obj-$(CONFIG_VIDEO_IMX219) += imx219.o
49obj-$(CONFIG_VIDEO_IMX258) += imx258.o51obj-$(CONFIG_VIDEO_IMX258) += imx258.o
50obj-$(CONFIG_VIDEO_IMX274) += imx274.o52obj-$(CONFIG_VIDEO_IMX274) += imx274.o
53obj-$(CONFIG_VIDEO_IMX283) += imx283.o
51obj-$(CONFIG_VIDEO_IMX290) += imx290.o54obj-$(CONFIG_VIDEO_IMX290) += imx290.o
52obj-$(CONFIG_VIDEO_IMX296) += imx296.o55obj-$(CONFIG_VIDEO_IMX296) += imx296.o
53obj-$(CONFIG_VIDEO_IMX319) += imx319.o56obj-$(CONFIG_VIDEO_IMX319) += imx319.o
@@ -64,6 +67,8 @@ obj-$(CONFIG_VIDEO_LM3646) += lm3646.o · 10 unmodified lines
64obj-$(CONFIG_VIDEO_M52790) += m52790.o67obj-$(CONFIG_VIDEO_M52790) += m52790.o
65obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o68obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
66obj-$(CONFIG_VIDEO_MAX9286) += max9286.o69obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
70obj-$(CONFIG_VIDEO_MAX96714) += max96714.o
71obj-$(CONFIG_VIDEO_MAX96717) += max96717.o
67obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o72obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
68obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o73obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
69obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o74obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
@@ -124,7 +129,6 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o · 54 unmodified lines
124obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o129obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
125obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o130obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
126obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o131obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
127obj-$(CONFIG_VIDEO_ST_VGXY61) += st-vgxy61.o
128obj-$(CONFIG_VIDEO_TC358743) += tc358743.o132obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
129obj-$(CONFIG_VIDEO_TC358746) += tc358746.o133obj-$(CONFIG_VIDEO_TC358746) += tc358746.o
130obj-$(CONFIG_VIDEO_TDA1997X) += tda1997x.o134obj-$(CONFIG_VIDEO_TDA1997X) += tda1997x.o
@@ -148,6 +152,7 @@ obj-$(CONFIG_VIDEO_TW9910) += tw9910.o · 17 unmodified lines
148obj-$(CONFIG_VIDEO_UDA1342) += uda1342.o152obj-$(CONFIG_VIDEO_UDA1342) += uda1342.o
149obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o153obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
150obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o154obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
155obj-$(CONFIG_VIDEO_VGXY61) += vgxy61.o
151obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o156obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
152obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o157obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
153obj-$(CONFIG_VIDEO_WM8739) += wm8739.o158obj-$(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
114{114{
115 memset(fmt, 0, sizeof(*fmt));115 memset(fmt, 0, sizeof(*fmt));
116 116
117 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;117 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
118 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;118 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
119 fmt->field = V4L2_FIELD_ALTERNATE;119 fmt->field = V4L2_FIELD_ALTERNATE;
120 120
@@ -337,7 +337,7 @@ static int adv748x_afe_enum_mbus_code(struct v4l2_subdev *sd, · 216 unmodified lines
337 if (code->index != 0)337 if (code->index != 0)
338 return -EINVAL;338 return -EINVAL;
339 339
340 code->code = MEDIA_BUS_FMT_UYVY8_2X8;340 code->code = MEDIA_BUS_FMT_UYVY8_1X16;
341 341
342 return 0;342 return 0;
343}343}
drivers/media/i2c/adv748x/adv748x-csi2.c+95−50
@@ -6,7 +6,6 @@ · 5 unmodified lines
6 */6 */
7 7
8#include <linux/module.h>8#include <linux/module.h>
9#include <linux/mutex.h>
10 9
11#include <media/v4l2-ctrls.h>10#include <media/v4l2-ctrls.h>
12#include <media/v4l2-device.h>11#include <media/v4l2-device.h>
@@ -14,6 +13,15 @@ · 1 unmodified line
14 13
15#include "adv748x.h"14#include "adv748x.h"
16 15
16static const unsigned int adv748x_csi2_txa_fmts[] = {
17 MEDIA_BUS_FMT_UYVY8_1X16,
18 MEDIA_BUS_FMT_RGB888_1X24,
19};
20
21static const unsigned int adv748x_csi2_txb_fmts[] = {
22 MEDIA_BUS_FMT_UYVY8_1X16,
23};
24
17int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc)25int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc)
18{26{
19 return tx_write(tx, ADV748X_CSI_VC_REF, vc << ADV748X_CSI_VC_REF_SHIFT);27 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
59 67
60/* -----------------------------------------------------------------------------68/* -----------------------------------------------------------------------------
61 * v4l2_subdev_internal_ops69 * v4l2_subdev_internal_ops
62 *70 */
71
72static 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/*
63 * We use the internal registered operation to be able to ensure that our97 * We use the internal registered operation to be able to ensure that our
64 * incremental subdevices (not connected in the forward path) can be registered98 * incremental subdevices (not connected in the forward path) can be registered
65 * against the resulting video path and media device.99 * against the resulting video path and media device.
@@ -109,6 +143,7 @@ static int adv748x_csi2_registered(struct v4l2_subdev *sd) · 43 unmodified lines
109}143}
110 144
111static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = {145static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = {
146 .init_state = adv748x_csi2_init_state,
112 .registered = adv748x_csi2_registered,147 .registered = adv748x_csi2_registered,
113};148};
114 149
@@ -139,39 +174,55 @@ static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = { · 24 unmodified lines
139 * But we must support setting the pad formats for format propagation.174 * But we must support setting the pad formats for format propagation.
140 */175 */
141 176
142static struct v4l2_mbus_framefmt *177static int adv748x_csi2_enum_mbus_code(struct v4l2_subdev *sd,
143adv748x_csi2_get_pad_format(struct v4l2_subdev *sd,178 struct v4l2_subdev_state *sd_state,
144 struct v4l2_subdev_state *sd_state,179 struct v4l2_subdev_mbus_code_enum *code)
145 unsigned int pad, u32 which)
146{180{
147 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);181 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);
148 187
149 if (which == V4L2_SUBDEV_FORMAT_TRY)188 /*
150 return v4l2_subdev_state_get_format(sd_state, pad);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;
151 194
152 return &tx->format;195 if (code->index)
153}196 return -EINVAL;
154 197
155static int adv748x_csi2_get_format(struct v4l2_subdev *sd,198 fmt = v4l2_subdev_state_get_format(sd_state, ADV748X_CSI2_SINK);
156 struct v4l2_subdev_state *sd_state,199 code->code = fmt->code;
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;
162 200
163 mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad,201 return 0;
164 sdformat->which);202 }
165 if (!mbusformat)203
204 if (code->index >= num_fmts)
166 return -EINVAL;205 return -EINVAL;
167 206
168 mutex_lock(&state->mutex);207 code->code = codes[code->index];
169 208
170 sdformat->format = *mbusformat;209 return 0;
210}
171 211
172 mutex_unlock(&state->mutex);212static 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 }
173 224
174 return 0;225 return false;
175}226}
176 227
177static int adv748x_csi2_set_format(struct v4l2_subdev *sd,228static 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
179 struct v4l2_subdev_format *sdformat)230 struct v4l2_subdev_format *sdformat)
180{231{
181 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);232 struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
182 struct adv748x_state *state = tx->state;
183 struct v4l2_mbus_framefmt *mbusformat;233 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);
192 234
193 if (sdformat->pad == ADV748X_CSI2_SOURCE) {235 if (sdformat->pad == ADV748X_CSI2_SOURCE)
194 const struct v4l2_mbus_framefmt *sink_fmt;236 return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
195 237
196 sink_fmt = adv748x_csi2_get_pad_format(sd, sd_state,238 /*
197 ADV748X_CSI2_SINK,239 * Make sure the format is supported, if not default it to
198 sdformat->which);240 * UYVY8 as it's supported by both TXes.
199 241 */
200 if (!sink_fmt) {242 if (!adv748x_csi2_is_fmt_supported(tx, sdformat->format.code))
201 ret = -EINVAL;243 sdformat->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
202 goto unlock;
203 }
204
205 sdformat->format = *sink_fmt;
206 }
207 244
245 mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
208 *mbusformat = sdformat->format;246 *mbusformat = sdformat->format;
209 247
210unlock:248 /* Propagate format to the source pad. */
211 mutex_unlock(&state->mutex);249 mbusformat = v4l2_subdev_state_get_format(sd_state, ADV748X_CSI2_SOURCE);
250 *mbusformat = sdformat->format;
212 251
213 return ret;252 return 0;
214}253}
215 254
216static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,255static 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
228}267}
229 268
230static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {269static 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,
232 .set_fmt = adv748x_csi2_set_format,272 .set_fmt = adv748x_csi2_set_format,
233 .get_mbus_config = adv748x_csi2_get_mbus_config,273 .get_mbus_config = adv748x_csi2_get_mbus_config,
234};274};
@@ -320,6 +360,11 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) · 85 unmodified lines
320 if (ret)360 if (ret)
321 goto err_cleanup_subdev;361 goto err_cleanup_subdev;
322 362
363 tx->sd.state_lock = &state->mutex;
364 ret = v4l2_subdev_init_finalize(&tx->sd);
365 if (ret)
366 goto err_free_ctrl;
367
323 ret = v4l2_async_register_subdev(&tx->sd);368 ret = v4l2_async_register_subdev(&tx->sd);
324 if (ret)369 if (ret)
325 goto err_free_ctrl;370 goto err_free_ctrl;
drivers/media/i2c/adv748x/adv748x.h+0−1
@@ -75,7 +75,6 @@ enum adv748x_csi2_pads { · 74 unmodified lines
75 75
76struct adv748x_csi2 {76struct adv748x_csi2 {
77 struct adv748x_state *state;77 struct adv748x_state *state;
78 struct v4l2_mbus_framefmt format;
79 unsigned int page;78 unsigned int page;
80 unsigned int port;79 unsigned int port;
81 unsigned int num_lanes;80 unsigned int num_lanes;
drivers/media/i2c/adv7511-v4l2.c+0−5
@@ -62,11 +62,6 @@ MODULE_LICENSE("GPL v2"); · 61 unmodified lines
62**********************************************************************62**********************************************************************
63*/63*/
64 64
65struct i2c_reg_value {
66 unsigned char reg;
67 unsigned char value;
68};
69
70struct adv7511_state_edid {65struct adv7511_state_edid {
71 /* total number of blocks */66 /* total number of blocks */
72 u32 blocks;67 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
403static int alvium_get_fw_version(struct alvium_dev *alvium)403static int alvium_get_fw_version(struct alvium_dev *alvium)
404{404{
405 struct device *dev = &alvium->i2c_client->dev;405 struct device *dev = &alvium->i2c_client->dev;
406 u64 spec, maj, min, pat;406 u64 val;
407 int ret = 0;407 int ret;
408 408
409 ret = alvium_read(alvium, REG_BCRM_DEVICE_FW_SPEC_VERSION_R,409 ret = alvium_read(alvium, REG_BCRM_DEVICE_FW, &val, NULL);
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);
417 if (ret)410 if (ret)
418 return ret;411 return ret;
419 412
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));
421 422
422 return 0;423 return 0;
423}424}
@@ -1188,6 +1189,20 @@ static int alvium_set_frame_rate(struct alvium_dev *alvium, u64 fr) · 764 unmodified lines
1188 struct device *dev = &alvium->i2c_client->dev;1189 struct device *dev = &alvium->i2c_client->dev;
1189 int ret;1190 int ret;
1190 1191
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
1191 ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW,1206 ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW,
1192 fr);1207 fr);
1193 if (ret) {1208 if (ret) {
@@ -1707,6 +1722,27 @@ alvium_code_to_pixfmt(struct alvium_dev *alvium, u32 code) · 513 unmodified lines
1707 return &alvium->alvium_csi2_fmt[0];1722 return &alvium->alvium_csi2_fmt[0];
1708}1723}
1709 1724
1725static 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
1710static int alvium_set_mode(struct alvium_dev *alvium,1746static int alvium_set_mode(struct alvium_dev *alvium,
1711 struct v4l2_subdev_state *state)1747 struct v4l2_subdev_state *state)
1712{1748{
@@ -1962,7 +1998,7 @@ static int alvium_g_volatile_ctrl(struct v4l2_ctrl *ctrl) · 249 unmodified lines
1962 int val;1998 int val;
1963 1999
1964 switch (ctrl->id) {2000 switch (ctrl->id) {
1965 case V4L2_CID_GAIN:2001 case V4L2_CID_ANALOGUE_GAIN:
1966 val = alvium_get_gain(alvium);2002 val = alvium_get_gain(alvium);
1967 if (val < 0)2003 if (val < 0)
1968 return val;2004 return val;
@@ -1994,7 +2030,7 @@ static int alvium_s_ctrl(struct v4l2_ctrl *ctrl) · 25 unmodified lines
1994 return 0;2030 return 0;
1995 2031
1996 switch (ctrl->id) {2032 switch (ctrl->id) {
1997 case V4L2_CID_GAIN:2033 case V4L2_CID_ANALOGUE_GAIN:
1998 ret = alvium_set_ctrl_gain(alvium, ctrl->val);2034 ret = alvium_set_ctrl_gain(alvium, ctrl->val);
1999 break;2035 break;
2000 case V4L2_CID_AUTOGAIN:2036 case V4L2_CID_AUTOGAIN:
@@ -2123,7 +2159,7 @@ static int alvium_ctrl_init(struct alvium_dev *alvium) · 122 unmodified lines
2123 2159
2124 if (alvium->avail_ft.gain) {2160 if (alvium->avail_ft.gain) {
2125 ctrls->gain = v4l2_ctrl_new_std(hdl, ops,2161 ctrls->gain = v4l2_ctrl_new_std(hdl, ops,
2126 V4L2_CID_GAIN,2162 V4L2_CID_ANALOGUE_GAIN,
2127 alvium->min_gain,2163 alvium->min_gain,
2128 alvium->max_gain,2164 alvium->max_gain,
2129 alvium->inc_gain,2165 alvium->inc_gain,
@@ -2214,6 +2250,7 @@ static const struct v4l2_subdev_video_ops alvium_video_ops = { · 84 unmodified lines
2214 2250
2215static const struct v4l2_subdev_pad_ops alvium_pad_ops = {2251static const struct v4l2_subdev_pad_ops alvium_pad_ops = {
2216 .enum_mbus_code = alvium_enum_mbus_code,2252 .enum_mbus_code = alvium_enum_mbus_code,
2253 .enum_frame_size = alvium_enum_frame_size,
2217 .get_fmt = v4l2_subdev_get_fmt,2254 .get_fmt = v4l2_subdev_get_fmt,
2218 .set_fmt = alvium_set_fmt,2255 .set_fmt = alvium_set_fmt,
2219 .get_selection = alvium_get_selection,2256 .get_selection = alvium_get_selection,
drivers/media/i2c/alvium-csi2.h+11−5
@@ -31,10 +31,7 @@ · 30 unmodified lines
31#define REG_BCRM_REG_ADDR_R CCI_REG16(0x0014)31#define REG_BCRM_REG_ADDR_R CCI_REG16(0x0014)
32 32
33#define REG_BCRM_FEATURE_INQUIRY_R REG_BCRM_V4L2_64BIT(0x0008)33#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)34#define REG_BCRM_DEVICE_FW REG_BCRM_V4L2_64BIT(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)
38#define REG_BCRM_WRITE_HANDSHAKE_RW REG_BCRM_V4L2_8BIT(0x0018)35#define REG_BCRM_WRITE_HANDSHAKE_RW REG_BCRM_V4L2_8BIT(0x0018)
39 36
40/* Streaming Control Registers */37/* Streaming Control Registers */
@@ -66,7 +63,7 @@ · 25 unmodified lines
66#define REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R REG_BCRM_V4L2_64BIT(0x0098)63#define REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R REG_BCRM_V4L2_64BIT(0x0098)
67#define REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R REG_BCRM_V4L2_64BIT(0x00a0)64#define REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R REG_BCRM_V4L2_64BIT(0x00a0)
68#define REG_BCRM_ACQUISITION_FRAME_RATE_INC_R REG_BCRM_V4L2_64BIT(0x00a8)65#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)
70 67
71#define REG_BCRM_FRAME_START_TRIGGER_MODE_RW REG_BCRM_V4L2_8BIT(0x00b4)68#define REG_BCRM_FRAME_START_TRIGGER_MODE_RW REG_BCRM_V4L2_8BIT(0x00b4)
72#define REG_BCRM_FRAME_START_TRIGGER_SOURCE_RW REG_BCRM_V4L2_8BIT(0x00b8)69#define REG_BCRM_FRAME_START_TRIGGER_SOURCE_RW REG_BCRM_V4L2_8BIT(0x00b8)
@@ -205,6 +202,15 @@ · 132 unmodified lines
205 202
206#define ALVIUM_LP2HS_DELAY_MS 100203#define ALVIUM_LP2HS_DELAY_MS 100
207 204
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
208enum alvium_bcrm_mode {214enum alvium_bcrm_mode {
209 ALVIUM_BCM_MODE,215 ALVIUM_BCM_MODE,
210 ALVIUM_GENCP_MODE,216 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
115 return container_of(subdev, struct dw9768, sd);115 return container_of(subdev, struct dw9768, sd);
116}116}
117 117
118struct regval_list {
119 u8 reg_num;
120 u8 value;
121};
122
123struct dw9768_aac_mode_ot_multi {118struct dw9768_aac_mode_ot_multi {
124 u32 aac_mode_enum;119 u32 aac_mode_enum;
125 u32 ot_multi_base100;120 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
66static 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
73static const s64 gc05a2_link_freq_menu_items[] = {
74 (448 * HZ_PER_MHZ),
75 (224 * HZ_PER_MHZ),
76};
77
78static const char *const gc05a2_supply_name[] = {
79 "avdd",
80 "dvdd",
81 "dovdd",
82};
83
84struct 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
110struct gc05a2_reg_list {
111 u32 num_of_regs;
112 const struct cci_reg_sequence *regs;
113};
114
115static 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
204static 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
293static 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
570struct 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. */
581static 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
608static inline struct gc05a2 *to_gc05a2(struct v4l2_subdev *sd)
609{
610 return container_of(sd, struct gc05a2, sd);
611}
612
613static 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
642static 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
655static 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
667static 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
685static 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
720static 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
734static 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
765static 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
787static 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
805static 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
821static 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
837static 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
881static 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
946static const struct v4l2_ctrl_ops gc05a2_ctrl_ops = {
947 .s_ctrl = gc05a2_set_ctrl,
948};
949
950static 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
973static 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
1015err_rpm_put:
1016 pm_runtime_put(gc05a2->dev);
1017 return ret;
1018}
1019
1020static 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
1032static 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
1050static const struct v4l2_subdev_video_ops gc05a2_video_ops = {
1051 .s_stream = gc05a2_s_stream,
1052};
1053
1054static 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
1062static 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
1067static 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
1073static const struct v4l2_subdev_internal_ops gc05a2_internal_ops = {
1074 .init_state = gc05a2_init_state,
1075};
1076
1077static 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
1088static 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
1117done:
1118 v4l2_fwnode_endpoint_free(&bus_cfg);
1119 fwnode_handle_put(endpoint);
1120 return ret;
1121}
1122
1123static 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
1131static 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
1218error_ctrls:
1219 v4l2_ctrl_handler_free(ctrl_hdlr);
1220
1221 return ret;
1222}
1223
1224static 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
1306err_rpm:
1307 pm_runtime_disable(gc05a2->dev);
1308 v4l2_subdev_cleanup(&gc05a2->sd);
1309
1310err_media_entity_cleanup:
1311 media_entity_cleanup(&gc05a2->sd.entity);
1312
1313err_v4l2_ctrl_handler_free:
1314 v4l2_ctrl_handler_free(&gc05a2->ctrls);
1315
1316 return ret;
1317}
1318
1319static 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
1335static const struct of_device_id gc05a2_of_match[] = {
1336 { .compatible = "galaxycore,gc05a2" },
1337 {}
1338};
1339MODULE_DEVICE_TABLE(of, gc05a2_of_match);
1340
1341static DEFINE_RUNTIME_DEV_PM_OPS(gc05a2_pm_ops,
1342 gc05a2_power_off,
1343 gc05a2_power_on,
1344 NULL);
1345
1346static 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};
1355module_i2c_driver(gc05a2_i2c_driver);
1356
1357MODULE_DESCRIPTION("GalaxyCore gc05a2 Camera driver");
1358MODULE_AUTHOR("Zhi Mao <zhi.mao@mediatek.com>");
1359MODULE_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
68static 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
73static const s64 gc08a3_link_freq_menu_items[] = {
74 (336 * HZ_PER_MHZ),
75 (207 * HZ_PER_MHZ),
76};
77
78static const char *const gc08a3_supply_name[] = {
79 "avdd",
80 "dvdd",
81 "dovdd",
82};
83
84struct 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
107struct gc08a3_reg_list {
108 u32 num_of_regs;
109 const struct cci_reg_sequence *regs;
110};
111
112static 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
192static 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
271static 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
545struct 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. */
556static 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
583static inline struct gc08a3 *to_gc08a3(struct v4l2_subdev *sd)
584{
585 return container_of(sd, struct gc08a3, sd);
586}
587
588static 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
617static 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
630static 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
642static 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
660static 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
695static 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
709static 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
741static 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
763static 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
781static 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
797static 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
813static 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
851static 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
916static const struct v4l2_ctrl_ops gc08a3_ctrl_ops = {
917 .s_ctrl = gc08a3_set_ctrl,
918};
919
920static 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
957err_rpm_put:
958 pm_runtime_put(gc08a3->dev);
959 return ret;
960}
961
962static 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
974static 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
992static const struct v4l2_subdev_video_ops gc08a3_video_ops = {
993 .s_stream = gc08a3_s_stream,
994};
995
996static 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
1004static 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
1009static 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
1015static const struct v4l2_subdev_internal_ops gc08a3_internal_ops = {
1016 .init_state = gc08a3_init_state,
1017};
1018
1019static 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
1030static 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
1061done:
1062 v4l2_fwnode_endpoint_free(&bus_cfg);
1063 fwnode_handle_put(endpoint);
1064 return ret;
1065}
1066
1067static 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
1075static 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
1162error_ctrls:
1163 v4l2_ctrl_handler_free(ctrl_hdlr);
1164
1165 return ret;
1166}
1167
1168static 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
1188static 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
1283err_rpm:
1284 pm_runtime_disable(gc08a3->dev);
1285 v4l2_subdev_cleanup(&gc08a3->sd);
1286
1287err_media_entity_cleanup:
1288 media_entity_cleanup(&gc08a3->sd.entity);
1289
1290err_v4l2_ctrl_handler_free:
1291 v4l2_ctrl_handler_free(gc08a3->sd.ctrl_handler);
1292
1293err_power_off:
1294 gc08a3_power_off(gc08a3->dev);
1295
1296 return ret;
1297}
1298
1299static 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
1315static const struct of_device_id gc08a3_of_match[] = {
1316 { .compatible = "galaxycore,gc08a3" },
1317 {}
1318};
1319MODULE_DEVICE_TABLE(of, gc08a3_of_match);
1320
1321static DEFINE_RUNTIME_DEV_PM_OPS(gc08a3_pm_ops,
1322 gc08a3_power_off,
1323 gc08a3_power_on,
1324 NULL);
1325
1326static 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};
1335module_i2c_driver(gc08a3_i2c_driver);
1336
1337MODULE_DESCRIPTION("GalaxyCore gc08a3 Camera driver");
1338MODULE_AUTHOR("Zhi Mao <zhi.mao@mediatek.com>");
1339MODULE_LICENSE("GPL");
drivers/media/i2c/gc2145.c+72−18
@@ -68,8 +68,7 @@ · 67 unmodified lines
68#define GC2145_DPHY_CLK_DELAY BIT(4)68#define GC2145_DPHY_CLK_DELAY BIT(4)
69#define GC2145_DPHY_LANE0_DELAY BIT(5)69#define GC2145_DPHY_LANE0_DELAY BIT(5)
70#define GC2145_DPHY_LANE1_DELAY BIT(6)70#define GC2145_DPHY_LANE1_DELAY BIT(6)
71#define GC2145_REG_FIFO_FULL_LVL_LOW CCI_REG8(0x04)71#define GC2145_REG_FIFO_FULL_LVL CCI_REG16_LE(0x04)
72#define GC2145_REG_FIFO_FULL_LVL_HIGH CCI_REG8(0x05)
73#define GC2145_REG_FIFO_MODE CCI_REG8(0x06)72#define GC2145_REG_FIFO_MODE CCI_REG8(0x06)
74#define GC2145_FIFO_MODE_READ_GATE BIT(3)73#define GC2145_FIFO_MODE_READ_GATE BIT(3)
75#define GC2145_FIFO_MODE_MIPI_CLK_MODULE BIT(7)74#define GC2145_FIFO_MODE_MIPI_CLK_MODULE BIT(7)
@@ -79,8 +78,7 @@ · 3 unmodified lines
79#define GC2145_CSI2_MODE_MIPI_EN BIT(4)78#define GC2145_CSI2_MODE_MIPI_EN BIT(4)
80#define GC2145_CSI2_MODE_EN BIT(7)79#define GC2145_CSI2_MODE_EN BIT(7)
81#define GC2145_REG_MIPI_DT CCI_REG8(0x11)80#define GC2145_REG_MIPI_DT CCI_REG8(0x11)
82#define GC2145_REG_LWC_LOW CCI_REG8(0x12)81#define GC2145_REG_LWC CCI_REG16_LE(0x12)
83#define GC2145_REG_LWC_HIGH CCI_REG8(0x13)
84#define GC2145_REG_DPHY_MODE CCI_REG8(0x15)82#define GC2145_REG_DPHY_MODE CCI_REG8(0x15)
85#define GC2145_DPHY_MODE_TRIGGER_PROG BIT(4)83#define GC2145_DPHY_MODE_TRIGGER_PROG BIT(4)
86#define GC2145_REG_FIFO_GATE_MODE CCI_REG8(0x17)84#define GC2145_REG_FIFO_GATE_MODE CCI_REG8(0x17)
@@ -542,45 +540,82 @@ static const struct gc2145_mode supported_modes[] = { · 455 unmodified lines
542/**540/**
543 * struct gc2145_format - GC2145 pixel format description541 * struct gc2145_format - GC2145 pixel format description
544 * @code: media bus (MBUS) associated code542 * @code: media bus (MBUS) associated code
543 * @colorspace: V4L2 colorspace
545 * @datatype: MIPI CSI2 data type544 * @datatype: MIPI CSI2 data type
546 * @output_fmt: GC2145 output format545 * @output_fmt: GC2145 output format
547 * @switch_bit: GC2145 first/second switch546 * @switch_bit: GC2145 first/second switch
547 * @row_col_switch: GC2145 switch row and/or column
548 */548 */
549struct gc2145_format {549struct gc2145_format {
550 unsigned int code;550 unsigned int code;
551 unsigned int colorspace;
551 unsigned char datatype;552 unsigned char datatype;
552 unsigned char output_fmt;553 unsigned char output_fmt;
553 bool switch_bit;554 bool switch_bit;
555 unsigned char row_col_switch;
554};556};
555 557
556/* All supported formats */558/* All supported formats */
557static const struct gc2145_format supported_formats[] = {559static const struct gc2145_format supported_formats[] = {
558 {560 {
559 .code = MEDIA_BUS_FMT_UYVY8_1X16,561 .code = MEDIA_BUS_FMT_UYVY8_1X16,
562 .colorspace = V4L2_COLORSPACE_SRGB,
560 .datatype = MIPI_CSI2_DT_YUV422_8B,563 .datatype = MIPI_CSI2_DT_YUV422_8B,
561 .output_fmt = 0x00,564 .output_fmt = 0x00,
562 },565 },
563 {566 {
564 .code = MEDIA_BUS_FMT_VYUY8_1X16,567 .code = MEDIA_BUS_FMT_VYUY8_1X16,
568 .colorspace = V4L2_COLORSPACE_SRGB,
565 .datatype = MIPI_CSI2_DT_YUV422_8B,569 .datatype = MIPI_CSI2_DT_YUV422_8B,
566 .output_fmt = 0x01,570 .output_fmt = 0x01,
567 },571 },
568 {572 {
569 .code = MEDIA_BUS_FMT_YUYV8_1X16,573 .code = MEDIA_BUS_FMT_YUYV8_1X16,
574 .colorspace = V4L2_COLORSPACE_SRGB,
570 .datatype = MIPI_CSI2_DT_YUV422_8B,575 .datatype = MIPI_CSI2_DT_YUV422_8B,
571 .output_fmt = 0x02,576 .output_fmt = 0x02,
572 },577 },
573 {578 {
574 .code = MEDIA_BUS_FMT_YVYU8_1X16,579 .code = MEDIA_BUS_FMT_YVYU8_1X16,
580 .colorspace = V4L2_COLORSPACE_SRGB,
575 .datatype = MIPI_CSI2_DT_YUV422_8B,581 .datatype = MIPI_CSI2_DT_YUV422_8B,
576 .output_fmt = 0x03,582 .output_fmt = 0x03,
577 },583 },
578 {584 {
579 .code = MEDIA_BUS_FMT_RGB565_1X16,585 .code = MEDIA_BUS_FMT_RGB565_1X16,
586 .colorspace = V4L2_COLORSPACE_SRGB,
580 .datatype = MIPI_CSI2_DT_RGB565,587 .datatype = MIPI_CSI2_DT_RGB565,
581 .output_fmt = 0x06,588 .output_fmt = 0x06,
582 .switch_bit = true,589 .switch_bit = true,
583 },590 },
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 },
584};619};
585 620
586struct gc2145_ctrls {621struct gc2145_ctrls {
@@ -641,7 +676,8 @@ gc2145_get_format_code(struct gc2145 *gc2145, u32 code) · 54 unmodified lines
641 676
642static void gc2145_update_pad_format(struct gc2145 *gc2145,677static void gc2145_update_pad_format(struct gc2145 *gc2145,
643 const struct gc2145_mode *mode,678 const struct gc2145_mode *mode,
644 struct v4l2_mbus_framefmt *fmt, u32 code)679 struct v4l2_mbus_framefmt *fmt, u32 code,
680 u32 colorspace)
645{681{
646 fmt->code = code;682 fmt->code = code;
647 fmt->width = mode->width;683 fmt->width = mode->width;
@@ -663,7 +699,8 @@ static int gc2145_init_state(struct v4l2_subdev *sd, · 15 unmodified lines
663 /* Initialize pad format */699 /* Initialize pad format */
664 format = v4l2_subdev_state_get_format(state, 0);700 format = v4l2_subdev_state_get_format(state, 0);
665 gc2145_update_pad_format(gc2145, &supported_modes[0], format,701 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);
667 704
668 /* Initialize crop rectangle. */705 /* Initialize crop rectangle. */
669 crop = v4l2_subdev_state_get_crop(state, 0);706 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
754 width, height,791 width, height,
755 fmt->format.width, fmt->format.height);792 fmt->format.width, fmt->format.height);
756 793
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);
758 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);801 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
759 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {802 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
760 gc2145->mode = mode;803 gc2145->mode = mode;
@@ -811,9 +854,12 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145, · 50 unmodified lines
811 * For RAW8, LWC = image width854 * For RAW8, LWC = image width
812 * For RAW10, LWC = image width * 1.25855 * For RAW10, LWC = image width * 1.25
813 */856 */
814 lwc = gc2145->mode->width * 2;857 if (gc2145_format->colorspace != V4L2_COLORSPACE_RAW)
815 cci_write(gc2145->regmap, GC2145_REG_LWC_HIGH, lwc >> 8, &ret);858 lwc = gc2145->mode->width * 2;
816 cci_write(gc2145->regmap, GC2145_REG_LWC_LOW, lwc & 0xff, &ret);859 else
860 lwc = gc2145->mode->width;
861
862 cci_write(gc2145->regmap, GC2145_REG_LWC, lwc, &ret);
817 863
818 /*864 /*
819 * Adjust the MIPI FIFO Full Level865 * Adjust the MIPI FIFO Full Level
@@ -821,21 +867,25 @@ static int gc2145_config_mipi_mode(struct gc2145 *gc2145, · 1 unmodified line
821 * 1280x720 / 1600x1200 (aka no scaler) non RAW: 0x0001867 * 1280x720 / 1600x1200 (aka no scaler) non RAW: 0x0001
822 * 1600x1200 RAW: 0x0190868 * 1600x1200 RAW: 0x0190
823 */869 */
824 if (gc2145->mode->width == 1280 || gc2145->mode->width == 1600)870 if (gc2145_format->colorspace != V4L2_COLORSPACE_RAW) {
825 fifo_full_lvl = 0x0001;871 if (gc2145->mode->width == 1280 || gc2145->mode->width == 1600)
826 else872 fifo_full_lvl = 0x0001;
873 else
874 fifo_full_lvl = 0x0190;
875 } else {
827 fifo_full_lvl = 0x0190;876 fifo_full_lvl = 0x0190;
877 }
828 878
829 cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL_HIGH,879 cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL,
830 fifo_full_lvl >> 8, &ret);880 fifo_full_lvl, &ret);
831 cci_write(gc2145->regmap, GC2145_REG_FIFO_FULL_LVL_LOW,
832 fifo_full_lvl & 0xff, &ret);
833 881
834 /*882 /*
835 * Set the FIFO gate mode / MIPI wdiv set:883 * Set the FIFO gate mode / MIPI wdiv set:
836 * 0xf1 in case of RAW mode and 0xf0 otherwise884 * 0xf1 in case of RAW mode and 0xf0 otherwise
837 */885 */
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);
839 889
840 /* Set the MIPI data type */890 /* Set the MIPI data type */
841 cci_write(gc2145->regmap, GC2145_REG_MIPI_DT,891 cci_write(gc2145->regmap, GC2145_REG_MIPI_DT,
@@ -883,6 +933,10 @@ static int gc2145_start_streaming(struct gc2145 *gc2145, · 41 unmodified lines
883 GC2145_BYPASS_MODE_SWITCH,933 GC2145_BYPASS_MODE_SWITCH,
884 gc2145_format->switch_bit ? GC2145_BYPASS_MODE_SWITCH934 gc2145_format->switch_bit ? GC2145_BYPASS_MODE_SWITCH
885 : 0, &ret);935 : 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);
886 if (ret) {940 if (ret) {
887 dev_err(&client->dev, "%s failed to write regs\n", __func__);941 dev_err(&client->dev, "%s failed to write regs\n", __func__);
888 goto err_rpm_put;942 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
1851 mutex_lock(&hi846->mutex);1851 mutex_lock(&hi846->mutex);
1852 switch (sel->which) {1852 switch (sel->which) {
1853 case V4L2_SUBDEV_FORMAT_TRY:1853 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);
1855 break;1855 break;
1856 case V4L2_SUBDEV_FORMAT_ACTIVE:1856 case V4L2_SUBDEV_FORMAT_ACTIVE:
1857 sel->r = hi846->cur_mode->crop;1857 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
162 { IMX219_REG_MODE_SELECT, 0x00 }, /* Mode Select */162 { IMX219_REG_MODE_SELECT, 0x00 }, /* Mode Select */
163 163
164 /* To Access Addresses 3000-5fff, send the following commands */164 /* To Access Addresses 3000-5fff, send the following commands */
165 { CCI_REG8(0x30eb), 0x0c },
166 { CCI_REG8(0x30eb), 0x05 },165 { CCI_REG8(0x30eb), 0x05 },
166 { CCI_REG8(0x30eb), 0x0c },
167 { CCI_REG8(0x300a), 0xff },167 { CCI_REG8(0x300a), 0xff },
168 { CCI_REG8(0x300b), 0xff },168 { CCI_REG8(0x300b), 0xff },
169 { CCI_REG8(0x30eb), 0x05 },169 { CCI_REG8(0x30eb), 0x05 },
drivers/media/i2c/imx258.c+810−614
@@ -7,97 +7,150 @@ · 6 unmodified lines
7#include <linux/i2c.h>7#include <linux/i2c.h>
8#include <linux/module.h>8#include <linux/module.h>
9#include <linux/pm_runtime.h>9#include <linux/pm_runtime.h>
10#include <linux/regulator/consumer.h>
11#include <media/v4l2-cci.h>
10#include <media/v4l2-ctrls.h>12#include <media/v4l2-ctrls.h>
11#include <media/v4l2-device.h>13#include <media/v4l2-device.h>
12#include <media/v4l2-fwnode.h>14#include <media/v4l2-fwnode.h>
13#include <asm/unaligned.h>15#include <asm/unaligned.h>
14 16
15#define IMX258_REG_VALUE_08BIT 117#define IMX258_REG_MODE_SELECT CCI_REG8(0x0100)
16#define IMX258_REG_VALUE_16BIT 2
17
18#define IMX258_REG_MODE_SELECT 0x0100
19#define IMX258_MODE_STANDBY 0x0018#define IMX258_MODE_STANDBY 0x00
20#define IMX258_MODE_STREAMING 0x0119#define IMX258_MODE_STREAMING 0x01
21 20
21#define IMX258_REG_RESET CCI_REG8(0x0103)
22
22/* Chip ID */23/* Chip ID */
23#define IMX258_REG_CHIP_ID 0x001624#define IMX258_REG_CHIP_ID CCI_REG16(0x0016)
24#define IMX258_CHIP_ID 0x025825#define IMX258_CHIP_ID 0x0258
25 26
26/* V_TIMING internal */27/* V_TIMING internal */
27#define IMX258_VTS_30FPS 0x0c5028#define IMX258_VTS_30FPS 0x0c50
28#define IMX258_VTS_30FPS_2K 0x063829#define IMX258_VTS_30FPS_2K 0x0638
29#define IMX258_VTS_30FPS_VGA 0x034c30#define IMX258_VTS_30FPS_VGA 0x034c
30#define IMX258_VTS_MAX 0xffff31#define IMX258_VTS_MAX 65525
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
37 32
38/* HBLANK control - read only */33/* HBLANK control - read only */
39#define IMX258_PPL_DEFAULT 535234#define IMX258_PPL_DEFAULT 5352
40 35
41/* Exposure control */36/* Exposure control */
42#define IMX258_REG_EXPOSURE 0x020237#define IMX258_REG_EXPOSURE CCI_REG16(0x0202)
38#define IMX258_EXPOSURE_OFFSET 10
43#define IMX258_EXPOSURE_MIN 439#define IMX258_EXPOSURE_MIN 4
44#define IMX258_EXPOSURE_STEP 140#define IMX258_EXPOSURE_STEP 1
45#define IMX258_EXPOSURE_DEFAULT 0x64041#define IMX258_EXPOSURE_DEFAULT 0x640
46#define IMX258_EXPOSURE_MAX 6553542#define IMX258_EXPOSURE_MAX (IMX258_VTS_MAX - IMX258_EXPOSURE_OFFSET)
47 43
48/* Analog gain control */44/* Analog gain control */
49#define IMX258_REG_ANALOG_GAIN 0x020445#define IMX258_REG_ANALOG_GAIN CCI_REG16(0x0204)
50#define IMX258_ANA_GAIN_MIN 046#define IMX258_ANA_GAIN_MIN 0
51#define IMX258_ANA_GAIN_MAX 48047#define IMX258_ANA_GAIN_MAX 480
52#define IMX258_ANA_GAIN_STEP 148#define IMX258_ANA_GAIN_STEP 1
53#define IMX258_ANA_GAIN_DEFAULT 0x049#define IMX258_ANA_GAIN_DEFAULT 0x0
54 50
55/* Digital gain control */51/* Digital gain control */
56#define IMX258_REG_GR_DIGITAL_GAIN 0x020e52#define IMX258_REG_GR_DIGITAL_GAIN CCI_REG16(0x020e)
57#define IMX258_REG_R_DIGITAL_GAIN 0x021053#define IMX258_REG_R_DIGITAL_GAIN CCI_REG16(0x0210)
58#define IMX258_REG_B_DIGITAL_GAIN 0x021254#define IMX258_REG_B_DIGITAL_GAIN CCI_REG16(0x0212)
59#define IMX258_REG_GB_DIGITAL_GAIN 0x021455#define IMX258_REG_GB_DIGITAL_GAIN CCI_REG16(0x0214)
60#define IMX258_DGTL_GAIN_MIN 056#define IMX258_DGTL_GAIN_MIN 0
61#define IMX258_DGTL_GAIN_MAX 4096 /* Max = 0xFFF */57#define IMX258_DGTL_GAIN_MAX 4096 /* Max = 0xFFF */
62#define IMX258_DGTL_GAIN_DEFAULT 102458#define IMX258_DGTL_GAIN_DEFAULT 1024
63#define IMX258_DGTL_GAIN_STEP 159#define IMX258_DGTL_GAIN_STEP 1
64 60
65/* HDR control */61/* HDR control */
66#define IMX258_REG_HDR 0x022062#define IMX258_REG_HDR CCI_REG8(0x0220)
67#define IMX258_HDR_ON BIT(0)63#define IMX258_HDR_ON BIT(0)
68#define IMX258_REG_HDR_RATIO 0x022264#define IMX258_REG_HDR_RATIO CCI_REG8(0x0222)
69#define IMX258_HDR_RATIO_MIN 065#define IMX258_HDR_RATIO_MIN 0
70#define IMX258_HDR_RATIO_MAX 566#define IMX258_HDR_RATIO_MAX 5
71#define IMX258_HDR_RATIO_STEP 167#define IMX258_HDR_RATIO_STEP 1
72#define IMX258_HDR_RATIO_DEFAULT 0x068#define IMX258_HDR_RATIO_DEFAULT 0x0
73 69
74/* Test Pattern Control */70/* Test Pattern Control */
75#define IMX258_REG_TEST_PATTERN 0x060071#define IMX258_REG_TEST_PATTERN CCI_REG16(0x0600)
72
73#define IMX258_CLK_BLANK_STOP CCI_REG8(0x4040)
76 74
77/* Orientation */75/* Orientation */
78#define REG_MIRROR_FLIP_CONTROL 0x010176#define REG_MIRROR_FLIP_CONTROL CCI_REG8(0x0101)
79#define REG_CONFIG_MIRROR_FLIP 0x0377#define REG_CONFIG_MIRROR_HFLIP 0x01
80#define REG_CONFIG_FLIP_TEST_PATTERN 0x0278#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)
81 131
82/* Input clock frequency in Hz */132struct imx258_reg_list {
83#define IMX258_INPUT_CLOCK_FREQ 19200000133 u32 num_of_regs;
134 const struct cci_reg_sequence *regs;
135};
84 136
85struct imx258_reg {137struct imx258_link_cfg {
86 u16 address;138 unsigned int lf_to_pix_rate_factor;
87 u8 val;139 struct imx258_reg_list reg_list;
88};140};
89 141
90struct imx258_reg_list {142enum {
91 u32 num_of_regs;143 IMX258_2_LANE_MODE,
92 const struct imx258_reg *regs;144 IMX258_4_LANE_MODE,
145 IMX258_LANE_CONFIGS,
93};146};
94 147
95/* Link frequency config */148/* Link frequency config */
96struct imx258_link_freq_config {149struct imx258_link_freq_config {
97 u32 pixels_per_line;150 u32 pixels_per_line;
98 151
99 /* PLL registers for this link frequency */152 /* Configuration for this link frequency / num lanes selection */
100 struct imx258_reg_list reg_list;153 struct imx258_link_cfg link_cfg[IMX258_LANE_CONFIGS];
101};154};
102 155
103/* Mode : resolution and related config&values */156/* Mode : resolution and related config&values */
@@ -115,400 +168,307 @@ struct imx258_mode { · 11 unmodified lines
115 u32 link_freq_index;168 u32 link_freq_index;
116 /* Default register values */169 /* Default register values */
117 struct imx258_reg_list reg_list;170 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 */
181static 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
198static 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
215static 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
232static 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
249static 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
266static 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 },
118};281};
119 282
120/* 4208x3118 needs 1267Mbps/lane, 4 lanes */283static const struct cci_reg_sequence mipi_642mbps_24mhz_2l[] = {
121static const struct imx258_reg mipi_data_rate_1267mbps[] = {284 { IMX258_REG_EXCK_FREQ, 0x1800 },
122 { 0x0301, 0x05 },285 { IMX258_REG_IVTPXCK_DIV, 5 },
123 { 0x0303, 0x02 },286 { IMX258_REG_IVTSYCK_DIV, 2 },
124 { 0x0305, 0x03 },287 { IMX258_REG_PREPLLCK_VT_DIV, 4 },
125 { 0x0306, 0x00 },288 { IMX258_REG_PLL_IVT_MPY, 107 },
126 { 0x0307, 0xC6 },289 { IMX258_REG_IOPPXCK_DIV, 10 },
127 { 0x0309, 0x0A },290 { IMX258_REG_IOPSYCK_DIV, 1 },
128 { 0x030B, 0x01 },291 { IMX258_REG_PREPLLCK_OP_DIV, 2 },
129 { 0x030D, 0x02 },292 { IMX258_REG_PLL_IOP_MPY, 216 },
130 { 0x030E, 0x00 },293 { IMX258_REG_PLL_MULT_DRIV, 0 },
131 { 0x030F, 0xD8 },294
132 { 0x0310, 0x00 },295 { IMX258_REG_CSI_LANE_MODE, 1 },
133 { 0x0820, 0x13 },296 { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 642 * 2 },
134 { 0x0821, 0x4C },297 { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
135 { 0x0822, 0xCC },
136 { 0x0823, 0xCC },
137};298};
138 299
139static const struct imx258_reg mipi_data_rate_640mbps[] = {300static const struct cci_reg_sequence mipi_642mbps_24mhz_4l[] = {
140 { 0x0301, 0x05 },301 { IMX258_REG_EXCK_FREQ, 0x1800 },
141 { 0x0303, 0x02 },302 { IMX258_REG_IVTPXCK_DIV, 5 },
142 { 0x0305, 0x03 },303 { IMX258_REG_IVTSYCK_DIV, 2 },
143 { 0x0306, 0x00 },304 { IMX258_REG_PREPLLCK_VT_DIV, 4 },
144 { 0x0307, 0x64 },305 { IMX258_REG_PLL_IVT_MPY, 107 },
145 { 0x0309, 0x0A },306 { IMX258_REG_IOPPXCK_DIV, 10 },
146 { 0x030B, 0x01 },307 { IMX258_REG_IOPSYCK_DIV, 1 },
147 { 0x030D, 0x02 },308 { IMX258_REG_PREPLLCK_OP_DIV, 2 },
148 { 0x030E, 0x00 },309 { IMX258_REG_PLL_IOP_MPY, 216 },
149 { 0x030F, 0xD8 },310 { IMX258_REG_PLL_MULT_DRIV, 0 },
150 { 0x0310, 0x00 },311
151 { 0x0820, 0x0A },312 { IMX258_REG_CSI_LANE_MODE, 3 },
152 { 0x0821, 0x00 },313 { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_H, 642 * 4 },
153 { 0x0822, 0x00 },314 { IMX258_REG_REQ_LINK_BIT_RATE_MBPS_L, 0 },
154 { 0x0823, 0x00 },
155};315};
156 316
157static const struct imx258_reg mode_4208x3118_regs[] = {317static const struct cci_reg_sequence mode_common_regs[] = {
158 { 0x0136, 0x13 },318 { CCI_REG8(0x3051), 0x00 },
159 { 0x0137, 0x33 },319 { CCI_REG8(0x6B11), 0xCF },
160 { 0x3051, 0x00 },320 { CCI_REG8(0x7FF0), 0x08 },
161 { 0x3052, 0x00 },321 { CCI_REG8(0x7FF1), 0x0F },
162 { 0x4E21, 0x14 },322 { CCI_REG8(0x7FF2), 0x08 },
163 { 0x6B11, 0xCF },323 { CCI_REG8(0x7FF3), 0x1B },
164 { 0x7FF0, 0x08 },324 { CCI_REG8(0x7FF4), 0x23 },
165 { 0x7FF1, 0x0F },325 { CCI_REG8(0x7FF5), 0x60 },
166 { 0x7FF2, 0x08 },326 { CCI_REG8(0x7FF6), 0x00 },
167 { 0x7FF3, 0x1B },327 { CCI_REG8(0x7FF7), 0x01 },
168 { 0x7FF4, 0x23 },328 { CCI_REG8(0x7FF8), 0x00 },
169 { 0x7FF5, 0x60 },329 { CCI_REG8(0x7FF9), 0x78 },
170 { 0x7FF6, 0x00 },330 { CCI_REG8(0x7FFA), 0x00 },
171 { 0x7FF7, 0x01 },331 { CCI_REG8(0x7FFB), 0x00 },
172 { 0x7FF8, 0x00 },332 { CCI_REG8(0x7FFC), 0x00 },
173 { 0x7FF9, 0x78 },333 { CCI_REG8(0x7FFD), 0x00 },
174 { 0x7FFA, 0x00 },334 { CCI_REG8(0x7FFE), 0x00 },
175 { 0x7FFB, 0x00 },335 { CCI_REG8(0x7FFF), 0x03 },
176 { 0x7FFC, 0x00 },336 { CCI_REG8(0x7F76), 0x03 },
177 { 0x7FFD, 0x00 },337 { CCI_REG8(0x7F77), 0xFE },
178 { 0x7FFE, 0x00 },338 { CCI_REG8(0x7FA8), 0x03 },
179 { 0x7FFF, 0x03 },339 { CCI_REG8(0x7FA9), 0xFE },
180 { 0x7F76, 0x03 },340 { CCI_REG8(0x7B24), 0x81 },
181 { 0x7F77, 0xFE },341 { CCI_REG8(0x6564), 0x07 },
182 { 0x7FA8, 0x03 },342 { CCI_REG8(0x6B0D), 0x41 },
183 { 0x7FA9, 0xFE },343 { CCI_REG8(0x653D), 0x04 },
184 { 0x7B24, 0x81 },344 { CCI_REG8(0x6B05), 0x8C },
185 { 0x7B25, 0x00 },345 { CCI_REG8(0x6B06), 0xF9 },
186 { 0x6564, 0x07 },346 { CCI_REG8(0x6B08), 0x65 },
187 { 0x6B0D, 0x41 },347 { CCI_REG8(0x6B09), 0xFC },
188 { 0x653D, 0x04 },348 { CCI_REG8(0x6B0A), 0xCF },
189 { 0x6B05, 0x8C },349 { CCI_REG8(0x6B0B), 0xD2 },
190 { 0x6B06, 0xF9 },350 { CCI_REG8(0x6700), 0x0E },
191 { 0x6B08, 0x65 },351 { CCI_REG8(0x6707), 0x0E },
192 { 0x6B09, 0xFC },352 { CCI_REG8(0x9104), 0x00 },
193 { 0x6B0A, 0xCF },353 { CCI_REG8(0x4648), 0x7F },
194 { 0x6B0B, 0xD2 },354 { CCI_REG8(0x7420), 0x00 },
195 { 0x6700, 0x0E },355 { CCI_REG8(0x7421), 0x1C },
196 { 0x6707, 0x0E },356 { CCI_REG8(0x7422), 0x00 },
197 { 0x9104, 0x00 },357 { CCI_REG8(0x7423), 0xD7 },
198 { 0x4648, 0x7F },358 { CCI_REG8(0x5F04), 0x00 },
199 { 0x7420, 0x00 },359 { CCI_REG8(0x5F05), 0xED },
200 { 0x7421, 0x1C },360 {IMX258_REG_CSI_DT_FMT, 0x0a0a},
201 { 0x7422, 0x00 },361 {IMX258_REG_LINE_LENGTH_PCK, 5352},
202 { 0x7423, 0xD7 },362 {IMX258_REG_X_ADD_STA, 0},
203 { 0x5F04, 0x00 },363 {IMX258_REG_Y_ADD_STA, 0},
204 { 0x5F05, 0xED },364 {IMX258_REG_X_ADD_END, 4207},
205 { 0x0112, 0x0A },365 {IMX258_REG_Y_ADD_END, 3119},
206 { 0x0113, 0x0A },366 {IMX258_REG_X_EVN_INC, 1},
207 { 0x0114, 0x03 },367 {IMX258_REG_X_ODD_INC, 1},
208 { 0x0342, 0x14 },368 {IMX258_REG_Y_EVN_INC, 1},
209 { 0x0343, 0xE8 },369 {IMX258_REG_Y_ODD_INC, 1},
210 { 0x0340, 0x0C },370 {IMX258_REG_DIG_CROP_X_OFFSET, 0},
211 { 0x0341, 0x50 },371 {IMX258_REG_DIG_CROP_Y_OFFSET, 0},
212 { 0x0344, 0x00 },372 {IMX258_REG_DIG_CROP_IMAGE_WIDTH, 4208},
213 { 0x0345, 0x00 },373 {IMX258_REG_SCALE_MODE_EXT, 0},
214 { 0x0346, 0x00 },374 {IMX258_REG_SCALE_M_EXT, 16},
215 { 0x0347, 0x00 },375 {IMX258_REG_FORCE_FD_SUM, 0},
216 { 0x0348, 0x10 },376 {IMX258_REG_FRM_LENGTH_CTL, 0},
217 { 0x0349, 0x6F },377 {IMX258_REG_ANALOG_GAIN, 0},
218 { 0x034A, 0x0C },378 {IMX258_REG_GR_DIGITAL_GAIN, 256},
219 { 0x034B, 0x2E },379 {IMX258_REG_R_DIGITAL_GAIN, 256},
220 { 0x0381, 0x01 },380 {IMX258_REG_B_DIGITAL_GAIN, 256},
221 { 0x0383, 0x01 },381 {IMX258_REG_GB_DIGITAL_GAIN, 256},
222 { 0x0385, 0x01 },382 {IMX258_REG_AF_WINDOW_MODE, 0},
223 { 0x0387, 0x01 },383 { CCI_REG8(0x94DC), 0x20 },
224 { 0x0900, 0x00 },384 { CCI_REG8(0x94DD), 0x20 },
225 { 0x0901, 0x11 },385 { CCI_REG8(0x94DE), 0x20 },
226 { 0x0401, 0x00 },386 { CCI_REG8(0x95DC), 0x20 },
227 { 0x0404, 0x00 },387 { CCI_REG8(0x95DD), 0x20 },
228 { 0x0405, 0x10 },388 { CCI_REG8(0x95DE), 0x20 },
229 { 0x0408, 0x00 },389 { CCI_REG8(0x7FB0), 0x00 },
230 { 0x0409, 0x00 },390 { CCI_REG8(0x9010), 0x3E },
231 { 0x040A, 0x00 },391 { CCI_REG8(0x9419), 0x50 },
232 { 0x040B, 0x00 },392 { CCI_REG8(0x941B), 0x50 },
233 { 0x040C, 0x10 },393 { CCI_REG8(0x9519), 0x50 },
234 { 0x040D, 0x70 },394 { CCI_REG8(0x951B), 0x50 },
235 { 0x040E, 0x0C },395 {IMX258_REG_PHASE_PIX_OUTEN, 0},
236 { 0x040F, 0x30 },396 {IMX258_REG_PDPIX_DATA_RATE, 0},
237 { 0x3038, 0x00 },397 {IMX258_REG_HDR, 0},
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 },
274};398};
275 399
276static const struct imx258_reg mode_2104_1560_regs[] = {400static const struct cci_reg_sequence mode_4208x3120_regs[] = {
277 { 0x0136, 0x13 },401 {IMX258_REG_BINNING_MODE, 0},
278 { 0x0137, 0x33 },402 {IMX258_REG_BINNING_TYPE_V, 0x11},
279 { 0x3051, 0x00 },403 {IMX258_REG_SCALE_MODE, 0},
280 { 0x3052, 0x00 },404 {IMX258_REG_SCALE_M, 16},
281 { 0x4E21, 0x14 },405 {IMX258_REG_DIG_CROP_IMAGE_HEIGHT, 3120},
282 { 0x6B11, 0xCF },406 {IMX258_REG_X_OUT_SIZE, 4208},
283 { 0x7FF0, 0x08 },407 {IMX258_REG_Y_OUT_SIZE, 3120},
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 },
393};408};
394 409
395static const struct imx258_reg mode_1048_780_regs[] = {410static const struct cci_reg_sequence mode_2104_1560_regs[] = {
396 { 0x0136, 0x13 },411 {IMX258_REG_BINNING_MODE, 1},
397 { 0x0137, 0x33 },412 {IMX258_REG_BINNING_TYPE_V, 0x12},
398 { 0x3051, 0x00 },413 {IMX258_REG_SCALE_MODE, 1},
399 { 0x3052, 0x00 },414 {IMX258_REG_SCALE_M, 32},
400 { 0x4E21, 0x14 },415 {IMX258_REG_DIG_CROP_IMAGE_HEIGHT, 1560},
401 { 0x6B11, 0xCF },416 {IMX258_REG_X_OUT_SIZE, 2104},
402 { 0x7FF0, 0x08 },417 {IMX258_REG_Y_OUT_SIZE, 1560},
403 { 0x7FF1, 0x0F },418};
404 { 0x7FF2, 0x08 },419
405 { 0x7FF3, 0x1B },420static const struct cci_reg_sequence mode_1048_780_regs[] = {
406 { 0x7FF4, 0x23 },421 {IMX258_REG_BINNING_MODE, 1},
407 { 0x7FF5, 0x60 },422 {IMX258_REG_BINNING_TYPE_V, 0x14},
408 { 0x7FF6, 0x00 },423 {IMX258_REG_SCALE_MODE, 1},
409 { 0x7FF7, 0x01 },424 {IMX258_REG_SCALE_M, 64},
410 { 0x7FF8, 0x00 },425 {IMX258_REG_DIG_CROP_IMAGE_HEIGHT, 780},
411 { 0x7FF9, 0x78 },426 {IMX258_REG_X_OUT_SIZE, 1048},
412 { 0x7FFA, 0x00 },427 {IMX258_REG_Y_OUT_SIZE, 780},
413 { 0x7FFB, 0x00 },428};
414 { 0x7FFC, 0x00 },429
415 { 0x7FFD, 0x00 },430struct imx258_variant_cfg {
416 { 0x7FFE, 0x00 },431 const struct cci_reg_sequence *regs;
417 { 0x7FFF, 0x03 },432 unsigned int num_regs;
418 { 0x7F76, 0x03 },433};
419 { 0x7F77, 0xFE },434
420 { 0x7FA8, 0x03 },435static const struct cci_reg_sequence imx258_cfg_regs[] = {
421 { 0x7FA9, 0xFE },436 { CCI_REG8(0x3052), 0x00 },
422 { 0x7B24, 0x81 },437 { CCI_REG8(0x4E21), 0x14 },
423 { 0x7B25, 0x00 },438 { CCI_REG8(0x7B25), 0x00 },
424 { 0x6564, 0x07 },439};
425 { 0x6B0D, 0x41 },440
426 { 0x653D, 0x04 },441static const struct imx258_variant_cfg imx258_cfg = {
427 { 0x6B05, 0x8C },442 .regs = imx258_cfg_regs,
428 { 0x6B06, 0xF9 },443 .num_regs = ARRAY_SIZE(imx258_cfg_regs),
429 { 0x6B08, 0x65 },444};
430 { 0x6B09, 0xFC },445
431 { 0x6B0A, 0xCF },446static const struct cci_reg_sequence imx258_pdaf_cfg_regs[] = {
432 { 0x6B0B, 0xD2 },447 { CCI_REG8(0x3052), 0x01 },
433 { 0x6700, 0x0E },448 { CCI_REG8(0x4E21), 0x10 },
434 { 0x6707, 0x0E },449 { CCI_REG8(0x7B25), 0x01 },
435 { 0x9104, 0x00 },450};
436 { 0x4648, 0x7F },451
437 { 0x7420, 0x00 },452static const struct imx258_variant_cfg imx258_pdaf_cfg = {
438 { 0x7421, 0x1C },453 .regs = imx258_pdaf_cfg_regs,
439 { 0x7422, 0x00 },454 .num_regs = ARRAY_SIZE(imx258_pdaf_cfg_regs),
440 { 0x7423, 0xD7 },455};
441 { 0x5F04, 0x00 },456
442 { 0x5F05, 0xED },457/*
443 { 0x0112, 0x0A },458 * The supported formats.
444 { 0x0113, 0x0A },459 * This table MUST contain 4 entries per format, to cover the various flip
445 { 0x0114, 0x03 },460 * combinations in the order
446 { 0x0342, 0x14 },461 * - no flip
447 { 0x0343, 0xE8 },462 * - h flip
448 { 0x0340, 0x03 },463 * - v flip
449 { 0x0341, 0x4C },464 * - h&v flips
450 { 0x0344, 0x00 },465 */
451 { 0x0345, 0x00 },466static const u32 codes[] = {
452 { 0x0346, 0x00 },467 /* 10-bit modes. */
453 { 0x0347, 0x00 },468 MEDIA_BUS_FMT_SRGGB10_1X10,
454 { 0x0348, 0x10 },469 MEDIA_BUS_FMT_SGRBG10_1X10,
455 { 0x0349, 0x6F },470 MEDIA_BUS_FMT_SGBRG10_1X10,
456 { 0x034A, 0x0C },471 MEDIA_BUS_FMT_SBGGR10_1X10
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 },
512};472};
513 473
514static const char * const imx258_test_pattern_menu[] = {474static const char * const imx258_test_pattern_menu[] = {
@@ -519,9 +479,15 @@ static const char * const imx258_test_pattern_menu[] = { · 4 unmodified lines
519 "Pseudorandom Sequence (PN9)",479 "Pseudorandom Sequence (PN9)",
520};480};
521 481
522/* Configurations for supported link frequencies */482/* regulator supplies */
523#define IMX258_LINK_FREQ_634MHZ 633600000ULL483static const char * const imx258_supply_name[] = {
524#define IMX258_LINK_FREQ_320MHZ 320000000ULL484 /* 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)
525 491
526enum {492enum {
527 IMX258_LINK_FREQ_1267MBPS,493 IMX258_LINK_FREQ_1267MBPS,
@@ -529,37 +495,96 @@ enum { · 1 unmodified line
529};495};
530 496
531/*497/*
532 * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample498 * Pixel rate does not necessarily relate to link frequency on this sensor as
533 * data rate => double data rate; number of lanes => 4; bits per pixel => 10499 * 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.
534 */510 */
535static u64 link_freq_to_pixel_rate(u64 f)511static u64 link_freq_to_pixel_rate(u64 f, const struct imx258_link_cfg *link_cfg)
536{512{
537 f *= 2 * 4;513 f *= 2 * link_cfg->lf_to_pix_rate_factor;
538 do_div(f, 10);514 do_div(f, 10);
539 515
540 return f;516 return f;
541}517}
542 518
543/* Menu items for LINK_FREQ V4L2 control */519/* Menu items for LINK_FREQ V4L2 control */
544static const s64 link_freq_menu_items[] = {520/* Configurations for supported link frequencies */
545 IMX258_LINK_FREQ_634MHZ,521static const s64 link_freq_menu_items_19_2[] = {
546 IMX258_LINK_FREQ_320MHZ,522 633600000ULL,
523 320000000ULL,
547};524};
548 525
526static 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
549/* Link frequency configs */533/* Link frequency configs */
550static const struct imx258_link_freq_config link_freq_configs[] = {534static const struct imx258_link_freq_config link_freq_configs_19_2[] = {
551 [IMX258_LINK_FREQ_1267MBPS] = {535 [IMX258_LINK_FREQ_1267MBPS] = {
552 .pixels_per_line = IMX258_PPL_DEFAULT,536 .pixels_per_line = IMX258_PPL_DEFAULT,
553 .reg_list = {537 .link_cfg = {
554 .num_of_regs = ARRAY_SIZE(mipi_data_rate_1267mbps),538 [IMX258_2_LANE_MODE] = {
555 .regs = mipi_data_rate_1267mbps,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 },
556 }546 }
557 },547 },
558 [IMX258_LINK_FREQ_640MBPS] = {548 [IMX258_LINK_FREQ_640MBPS] = {
559 .pixels_per_line = IMX258_PPL_DEFAULT,549 .pixels_per_line = IMX258_PPL_DEFAULT,
560 .reg_list = {550 .link_cfg = {
561 .num_of_regs = ARRAY_SIZE(mipi_data_rate_640mbps),551 [IMX258_2_LANE_MODE] = {
562 .regs = mipi_data_rate_640mbps,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
563static 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 },
563 }588 }
564 },589 },
565};590};
@@ -568,14 +593,20 @@ static const struct imx258_link_freq_config link_freq_configs[] = { · 2 unmodified lines
568static const struct imx258_mode supported_modes[] = {593static const struct imx258_mode supported_modes[] = {
569 {594 {
570 .width = 4208,595 .width = 4208,
571 .height = 3118,596 .height = 3120,
572 .vts_def = IMX258_VTS_30FPS,597 .vts_def = IMX258_VTS_30FPS,
573 .vts_min = IMX258_VTS_30FPS,598 .vts_min = IMX258_VTS_30FPS,
574 .reg_list = {599 .reg_list = {
575 .num_of_regs = ARRAY_SIZE(mode_4208x3118_regs),600 .num_of_regs = ARRAY_SIZE(mode_4208x3120_regs),
576 .regs = mode_4208x3118_regs,601 .regs = mode_4208x3120_regs,
577 },602 },
578 .link_freq_index = IMX258_LINK_FREQ_1267MBPS,603 .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 },
579 },610 },
580 {611 {
581 .width = 2104,612 .width = 2104,
@@ -587,6 +618,12 @@ static const struct imx258_mode supported_modes[] = { · 5 unmodified lines
587 .regs = mode_2104_1560_regs,618 .regs = mode_2104_1560_regs,
588 },619 },
589 .link_freq_index = IMX258_LINK_FREQ_640MBPS,620 .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 },
590 },627 },
591 {628 {
592 .width = 1048,629 .width = 1048,
@@ -598,12 +635,21 @@ static const struct imx258_mode supported_modes[] = { · 5 unmodified lines
598 .regs = mode_1048_780_regs,635 .regs = mode_1048_780_regs,
599 },636 },
600 .link_freq_index = IMX258_LINK_FREQ_640MBPS,637 .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 },
601 },644 },
602};645};
603 646
604struct imx258 {647struct imx258 {
605 struct v4l2_subdev sd;648 struct v4l2_subdev sd;
606 struct media_pad pad;649 struct media_pad pad;
650 struct regmap *regmap;
651
652 const struct imx258_variant_cfg *variant_cfg;
607 653
608 struct v4l2_ctrl_handler ctrl_handler;654 struct v4l2_ctrl_handler ctrl_handler;
609 /* V4L2 Controls */655 /* V4L2 Controls */
@@ -612,10 +658,18 @@ struct imx258 { · 2 unmodified lines
612 struct v4l2_ctrl *vblank;658 struct v4l2_ctrl *vblank;
613 struct v4l2_ctrl *hblank;659 struct v4l2_ctrl *hblank;
614 struct v4l2_ctrl *exposure;660 struct v4l2_ctrl *exposure;
661 struct v4l2_ctrl *hflip;
662 struct v4l2_ctrl *vflip;
615 663
616 /* Current mode */664 /* Current mode */
617 const struct imx258_mode *cur_mode;665 const struct imx258_mode *cur_mode;
618 666
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
619 /*673 /*
620 * Mutex for serialized access:674 * Mutex for serialized access:
621 * Protect sensor module set pad format and start/stop streaming safely.675 * Protect sensor module set pad format and start/stop streaming safely.
@@ -623,6 +677,7 @@ struct imx258 { · 1 unmodified line
623 struct mutex mutex;677 struct mutex mutex;
624 678
625 struct clk *clk;679 struct clk *clk;
680 struct regulator_bulk_data supplies[IMX258_NUM_SUPPLIES];
626};681};
627 682
628static inline struct imx258 *to_imx258(struct v4l2_subdev *_sd)683static 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
630 return container_of(_sd, struct imx258, sd);685 return container_of(_sd, struct imx258, sd);
631}686}
632 687
633/* Read registers up to 2 at a time */688/* Get bayer order based on flip setting. */
634static int imx258_read_reg(struct imx258 *imx258, u16 reg, u32 len, u32 *val)689static u32 imx258_get_format_code(const struct imx258 *imx258)
635{690{
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 */
667static 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 */
684static 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);
688 unsigned int i;691 unsigned int i;
689 int ret;
690 692
691 for (i = 0; i < len; i++) {693 lockdep_assert_held(&imx258->mutex);
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);
699 694
700 return ret;695 i = (imx258->vflip->val ? 2 : 0) |
701 }696 (imx258->hflip->val ? 1 : 0);
702 }
703 697
704 return 0;698 return codes[i];
705}699}
706 700
707/* Open sub-device */701/* Open sub-device */
708static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)702static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
709{703{
704 struct imx258 *imx258 = to_imx258(sd);
710 struct v4l2_mbus_framefmt *try_fmt =705 struct v4l2_mbus_framefmt *try_fmt =
711 v4l2_subdev_state_get_format(fh->state, 0);706 v4l2_subdev_state_get_format(fh->state, 0);
707 struct v4l2_rect *try_crop;
712 708
713 /* Initialize try_fmt */709 /* Initialize try_fmt */
714 try_fmt->width = supported_modes[0].width;710 try_fmt->width = supported_modes[0].width;
715 try_fmt->height = supported_modes[0].height;711 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);
717 try_fmt->field = V4L2_FIELD_NONE;713 try_fmt->field = V4L2_FIELD_NONE;
718 714
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
719 return 0;722 return 0;
720}723}
721 724
722static int imx258_update_digital_gain(struct imx258 *imx258, u32 len, u32 val)725static int imx258_update_digital_gain(struct imx258 *imx258, u32 val)
723{726{
724 int ret;727 int ret = 0;
725 728
726 ret = imx258_write_reg(imx258, IMX258_REG_GR_DIGITAL_GAIN,729 cci_write(imx258->regmap, IMX258_REG_GR_DIGITAL_GAIN, val, &ret);
727 IMX258_REG_VALUE_16BIT,730 cci_write(imx258->regmap, IMX258_REG_GB_DIGITAL_GAIN, val, &ret);
728 val);731 cci_write(imx258->regmap, IMX258_REG_R_DIGITAL_GAIN, val, &ret);
729 if (ret)732 cci_write(imx258->regmap, IMX258_REG_B_DIGITAL_GAIN, val, &ret);
730 return ret;733
731 ret = imx258_write_reg(imx258, IMX258_REG_GB_DIGITAL_GAIN,734 return ret;
732 IMX258_REG_VALUE_16BIT,735}
733 val);736
734 if (ret)737static void imx258_adjust_exposure_range(struct imx258 *imx258)
735 return ret;738{
736 ret = imx258_write_reg(imx258, IMX258_REG_R_DIGITAL_GAIN,739 int exposure_max, exposure_def;
737 IMX258_REG_VALUE_16BIT,740
738 val);741 /* Honour the VBLANK limits when setting exposure. */
739 if (ret)742 exposure_max = imx258->cur_mode->height + imx258->vblank->val -
740 return ret;743 IMX258_EXPOSURE_OFFSET;
741 ret = imx258_write_reg(imx258, IMX258_REG_B_DIGITAL_GAIN,744 exposure_def = min(exposure_max, imx258->exposure->val);
742 IMX258_REG_VALUE_16BIT,745 __v4l2_ctrl_modify_range(imx258->exposure, imx258->exposure->minimum,
743 val);746 exposure_max, imx258->exposure->step,
744 if (ret)747 exposure_def);
745 return ret;
746 return 0;
747}748}
748 749
749static int imx258_set_ctrl(struct v4l2_ctrl *ctrl)750static int imx258_set_ctrl(struct v4l2_ctrl *ctrl)
@@ -753,6 +754,13 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl) · 3 unmodified lines
753 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);754 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
754 int ret = 0;755 int ret = 0;
755 756
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
756 /*764 /*
757 * Applying V4L2 control value only happens765 * Applying V4L2 control value only happens
758 * when power is up for streaming766 * when power is up for streaming
@@ -762,44 +770,46 @@ static int imx258_set_ctrl(struct v4l2_ctrl *ctrl) · 3 unmodified lines
762 770
763 switch (ctrl->id) {771 switch (ctrl->id) {
764 case V4L2_CID_ANALOGUE_GAIN:772 case V4L2_CID_ANALOGUE_GAIN:
765 ret = imx258_write_reg(imx258, IMX258_REG_ANALOG_GAIN,773 ret = cci_write(imx258->regmap, IMX258_REG_ANALOG_GAIN,
766 IMX258_REG_VALUE_16BIT,774 ctrl->val, NULL);
767 ctrl->val);
768 break;775 break;
769 case V4L2_CID_EXPOSURE:776 case V4L2_CID_EXPOSURE:
770 ret = imx258_write_reg(imx258, IMX258_REG_EXPOSURE,777 ret = cci_write(imx258->regmap, IMX258_REG_EXPOSURE,
771 IMX258_REG_VALUE_16BIT,778 ctrl->val, NULL);
772 ctrl->val);
773 break;779 break;
774 case V4L2_CID_DIGITAL_GAIN:780 case V4L2_CID_DIGITAL_GAIN:
775 ret = imx258_update_digital_gain(imx258, IMX258_REG_VALUE_16BIT,781 ret = imx258_update_digital_gain(imx258, ctrl->val);
776 ctrl->val);
777 break;782 break;
778 case V4L2_CID_TEST_PATTERN:783 case V4L2_CID_TEST_PATTERN:
779 ret = imx258_write_reg(imx258, IMX258_REG_TEST_PATTERN,784 ret = cci_write(imx258->regmap, IMX258_REG_TEST_PATTERN,
780 IMX258_REG_VALUE_16BIT,785 ctrl->val, NULL);
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);
786 break;786 break;
787 case V4L2_CID_WIDE_DYNAMIC_RANGE:787 case V4L2_CID_WIDE_DYNAMIC_RANGE:
788 if (!ctrl->val) {788 if (!ctrl->val) {
789 ret = imx258_write_reg(imx258, IMX258_REG_HDR,789 ret = cci_write(imx258->regmap, IMX258_REG_HDR,
790 IMX258_REG_VALUE_08BIT,790 IMX258_HDR_RATIO_MIN, NULL);
791 IMX258_HDR_RATIO_MIN);
792 } else {791 } else {
793 ret = imx258_write_reg(imx258, IMX258_REG_HDR,792 ret = cci_write(imx258->regmap, IMX258_REG_HDR,
794 IMX258_REG_VALUE_08BIT,793 IMX258_HDR_ON, NULL);
795 IMX258_HDR_ON);
796 if (ret)794 if (ret)
797 break;795 break;
798 ret = imx258_write_reg(imx258, IMX258_REG_HDR_RATIO,796 ret = cci_write(imx258->regmap, IMX258_REG_HDR_RATIO,
799 IMX258_REG_VALUE_08BIT,797 BIT(IMX258_HDR_RATIO_MAX), NULL);
800 BIT(IMX258_HDR_RATIO_MAX));
801 }798 }
802 break;799 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;
803 default:813 default:
804 dev_info(&client->dev,814 dev_info(&client->dev,
805 "ctrl(id:0x%x,val:0x%x) is not handled\n",815 "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
821 struct v4l2_subdev_state *sd_state,831 struct v4l2_subdev_state *sd_state,
822 struct v4l2_subdev_mbus_code_enum *code)832 struct v4l2_subdev_mbus_code_enum *code)
823{833{
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 */
825 if (code->index > 0)837 if (code->index > 0)
826 return -EINVAL;838 return -EINVAL;
827 839
828 code->code = MEDIA_BUS_FMT_SGRBG10_1X10;840 code->code = imx258_get_format_code(imx258);
829 841
830 return 0;842 return 0;
831}843}
@@ -834,10 +846,11 @@ static int imx258_enum_frame_size(struct v4l2_subdev *sd, · 2 unmodified lines
834 struct v4l2_subdev_state *sd_state,846 struct v4l2_subdev_state *sd_state,
835 struct v4l2_subdev_frame_size_enum *fse)847 struct v4l2_subdev_frame_size_enum *fse)
836{848{
849 struct imx258 *imx258 = to_imx258(sd);
837 if (fse->index >= ARRAY_SIZE(supported_modes))850 if (fse->index >= ARRAY_SIZE(supported_modes))
838 return -EINVAL;851 return -EINVAL;
839 852
840 if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)853 if (fse->code != imx258_get_format_code(imx258))
841 return -EINVAL;854 return -EINVAL;
842 855
843 fse->min_width = supported_modes[fse->index].width;856 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
848 return 0;861 return 0;
849}862}
850 863
851static void imx258_update_pad_format(const struct imx258_mode *mode,864static void imx258_update_pad_format(struct imx258 *imx258,
865 const struct imx258_mode *mode,
852 struct v4l2_subdev_format *fmt)866 struct v4l2_subdev_format *fmt)
853{867{
854 fmt->format.width = mode->width;868 fmt->format.width = mode->width;
855 fmt->format.height = mode->height;869 fmt->format.height = mode->height;
856 fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;870 fmt->format.code = imx258_get_format_code(imx258);
857 fmt->format.field = V4L2_FIELD_NONE;871 fmt->format.field = V4L2_FIELD_NONE;
858}872}
859 873
@@ -865,7 +879,7 @@ static int __imx258_get_pad_format(struct imx258 *imx258, · 5 unmodified lines
865 fmt->format = *v4l2_subdev_state_get_format(sd_state,879 fmt->format = *v4l2_subdev_state_get_format(sd_state,
866 fmt->pad);880 fmt->pad);
867 else881 else
868 imx258_update_pad_format(imx258->cur_mode, fmt);882 imx258_update_pad_format(imx258, imx258->cur_mode, fmt);
869 883
870 return 0;884 return 0;
871}885}
@@ -889,8 +903,10 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 17 unmodified lines
889 struct v4l2_subdev_format *fmt)903 struct v4l2_subdev_format *fmt)
890{904{
891 struct imx258 *imx258 = to_imx258(sd);905 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;
893 struct v4l2_mbus_framefmt *framefmt;908 struct v4l2_mbus_framefmt *framefmt;
909 const struct imx258_mode *mode;
894 s32 vblank_def;910 s32 vblank_def;
895 s32 vblank_min;911 s32 vblank_min;
896 s64 h_blank;912 s64 h_blank;
@@ -899,13 +915,12 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 2 unmodified lines
899 915
900 mutex_lock(&imx258->mutex);916 mutex_lock(&imx258->mutex);
901 917
902 /* Only one raw bayer(GBRG) order is supported */918 fmt->format.code = imx258_get_format_code(imx258);
903 fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
904 919
905 mode = v4l2_find_nearest_size(supported_modes,920 mode = v4l2_find_nearest_size(supported_modes,
906 ARRAY_SIZE(supported_modes), width, height,921 ARRAY_SIZE(supported_modes), width, height,
907 fmt->format.width, fmt->format.height);922 fmt->format.width, fmt->format.height);
908 imx258_update_pad_format(mode, fmt);923 imx258_update_pad_format(imx258, mode, fmt);
909 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {924 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
910 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);925 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
911 *framefmt = fmt->format;926 *framefmt = fmt->format;
@@ -913,9 +928,14 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 1 unmodified line
913 imx258->cur_mode = mode;928 imx258->cur_mode = mode;
914 __v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index);929 __v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index);
915 930
916 link_freq = link_freq_menu_items[mode->link_freq_index];931 link_freq = imx258->link_freq_menu_items[mode->link_freq_index];
917 pixel_rate = link_freq_to_pixel_rate(link_freq);932 link_freq_cfgs =
918 __v4l2_ctrl_s_ctrl_int64(imx258->pixel_rate, pixel_rate);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);
919 /* Update limits and set FPS to default */939 /* Update limits and set FPS to default */
920 vblank_def = imx258->cur_mode->vts_def -940 vblank_def = imx258->cur_mode->vts_def -
921 imx258->cur_mode->height;941 imx258->cur_mode->height;
@@ -927,7 +947,7 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 5 unmodified lines
927 vblank_def);947 vblank_def);
928 __v4l2_ctrl_s_ctrl(imx258->vblank, vblank_def);948 __v4l2_ctrl_s_ctrl(imx258->vblank, vblank_def);
929 h_blank =949 h_blank =
930 link_freq_configs[mode->link_freq_index].pixels_per_line950 imx258->link_freq_configs[mode->link_freq_index].pixels_per_line
931 - imx258->cur_mode->width;951 - imx258->cur_mode->width;
932 __v4l2_ctrl_modify_range(imx258->hblank, h_blank,952 __v4l2_ctrl_modify_range(imx258->hblank, h_blank,
933 h_blank, 1, h_blank);953 h_blank, 1, h_blank);
@@ -938,48 +958,125 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd, · 4 unmodified lines
938 return 0;958 return 0;
939}959}
940 960
961static 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
976static 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
941/* Start streaming */1013/* Start streaming */
942static int imx258_start_streaming(struct imx258 *imx258)1014static int imx258_start_streaming(struct imx258 *imx258)
943{1015{
944 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);1016 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
945 const struct imx258_reg_list *reg_list;1017 const struct imx258_reg_list *reg_list;
1018 const struct imx258_link_freq_config *link_freq_cfg;
946 int ret, link_freq_index;1019 int ret, link_freq_index;
947 1020
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
948 /* Setup PLL */1030 /* Setup PLL */
949 link_freq_index = imx258->cur_mode->link_freq_index;1031 link_freq_index = imx258->cur_mode->link_freq_index;
950 reg_list = &link_freq_configs[link_freq_index].reg_list;1032 link_freq_cfg = &imx258->link_freq_configs[link_freq_index];
951 ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);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);
952 if (ret) {1036 if (ret) {
953 dev_err(&client->dev, "%s failed to set plls\n", __func__);1037 dev_err(&client->dev, "%s failed to set plls\n", __func__);
954 return ret;1038 return ret;
955 }1039 }
956 1040
957 /* Apply default values of current mode */1041 ret = cci_multi_reg_write(imx258->regmap, mode_common_regs,
958 reg_list = &imx258->cur_mode->reg_list;1042 ARRAY_SIZE(mode_common_regs), NULL);
959 ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
960 if (ret) {1043 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__);
962 return ret;1045 return ret;
963 }1046 }
964 1047
965 /* Set Orientation be 180 degree */1048 ret = cci_multi_reg_write(imx258->regmap, imx258->variant_cfg->regs,
966 ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL,1049 imx258->variant_cfg->num_regs, NULL);
967 IMX258_REG_VALUE_08BIT, REG_CONFIG_MIRROR_FLIP);
968 if (ret) {1050 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",
970 __func__);1052 __func__);
971 return ret;1053 return ret;
972 }1054 }
973 1055
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
974 /* Apply customized values from user */1072 /* Apply customized values from user */
975 ret = __v4l2_ctrl_handler_setup(imx258->sd.ctrl_handler);1073 ret = __v4l2_ctrl_handler_setup(imx258->sd.ctrl_handler);
976 if (ret)1074 if (ret)
977 return ret;1075 return ret;
978 1076
979 /* set stream on register */1077 /* set stream on register */
980 return imx258_write_reg(imx258, IMX258_REG_MODE_SELECT,1078 return cci_write(imx258->regmap, IMX258_REG_MODE_SELECT,
981 IMX258_REG_VALUE_08BIT,1079 IMX258_MODE_STREAMING, NULL);
982 IMX258_MODE_STREAMING);
983}1080}
984 1081
985/* Stop streaming */1082/* Stop streaming */
@@ -989,8 +1086,8 @@ static int imx258_stop_streaming(struct imx258 *imx258) · 3 unmodified lines
989 int ret;1086 int ret;
990 1087
991 /* set stream off register */1088 /* set stream off register */
992 ret = imx258_write_reg(imx258, IMX258_REG_MODE_SELECT,1089 ret = cci_write(imx258->regmap, IMX258_REG_MODE_SELECT,
993 IMX258_REG_VALUE_08BIT, IMX258_MODE_STANDBY);1090 IMX258_MODE_STANDBY, NULL);
994 if (ret)1091 if (ret)
995 dev_err(&client->dev, "%s failed to set stream\n", __func__);1092 dev_err(&client->dev, "%s failed to set stream\n", __func__);
996 1093
@@ -1007,9 +1104,19 @@ static int imx258_power_on(struct device *dev) · 10 unmodified lines
1007 struct imx258 *imx258 = to_imx258(sd);1104 struct imx258 *imx258 = to_imx258(sd);
1008 int ret;1105 int ret;
1009 1106
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
1010 ret = clk_prepare_enable(imx258->clk);1115 ret = clk_prepare_enable(imx258->clk);
1011 if (ret)1116 if (ret) {
1012 dev_err(dev, "failed to enable clock\n");1117 dev_err(dev, "failed to enable clock\n");
1118 regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies);
1119 }
1013 1120
1014 return ret;1121 return ret;
1015}1122}
@@ -1020,6 +1127,7 @@ static int imx258_power_off(struct device *dev) · 4 unmodified lines
1020 struct imx258 *imx258 = to_imx258(sd);1127 struct imx258 *imx258 = to_imx258(sd);
1021 1128
1022 clk_disable_unprepare(imx258->clk);1129 clk_disable_unprepare(imx258->clk);
1130 regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies);
1023 1131
1024 return 0;1132 return 0;
1025}1133}
@@ -1066,10 +1174,10 @@ static int imx258_identify_module(struct imx258 *imx258) · 40 unmodified lines
1066{1174{
1067 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);1175 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
1068 int ret;1176 int ret;
1069 u32 val;1177 u64 val;
1070 1178
1071 ret = imx258_read_reg(imx258, IMX258_REG_CHIP_ID,1179 ret = cci_read(imx258->regmap, IMX258_REG_CHIP_ID,
1072 IMX258_REG_VALUE_16BIT, &val);1180 &val, NULL);
1073 if (ret) {1181 if (ret) {
1074 dev_err(&client->dev, "failed to read chip id %x\n",1182 dev_err(&client->dev, "failed to read chip id %x\n",
1075 IMX258_CHIP_ID);1183 IMX258_CHIP_ID);
@@ -1077,7 +1185,7 @@ static int imx258_identify_module(struct imx258 *imx258) · 1 unmodified line
1077 }1185 }
1078 1186
1079 if (val != IMX258_CHIP_ID) {1187 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",
1081 IMX258_CHIP_ID, val);1189 IMX258_CHIP_ID, val);
1082 return -EIO;1190 return -EIO;
1083 }1191 }
@@ -1094,6 +1202,7 @@ static const struct v4l2_subdev_pad_ops imx258_pad_ops = { · 10 unmodified lines
1094 .get_fmt = imx258_get_pad_format,1202 .get_fmt = imx258_get_pad_format,
1095 .set_fmt = imx258_set_pad_format,1203 .set_fmt = imx258_set_pad_format,
1096 .enum_frame_size = imx258_enum_frame_size,1204 .enum_frame_size = imx258_enum_frame_size,
1205 .get_selection = imx258_get_selection,
1097};1206};
1098 1207
1099static const struct v4l2_subdev_ops imx258_subdev_ops = {1208static 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
1109static int imx258_init_controls(struct imx258 *imx258)1218static int imx258_init_controls(struct imx258 *imx258)
1110{1219{
1111 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);1220 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
1221 const struct imx258_link_freq_config *link_freq_cfgs;
1112 struct v4l2_fwnode_device_properties props;1222 struct v4l2_fwnode_device_properties props;
1113 struct v4l2_ctrl_handler *ctrl_hdlr;1223 struct v4l2_ctrl_handler *ctrl_hdlr;
1114 struct v4l2_ctrl *vflip, *hflip;1224 const struct imx258_link_cfg *link_cfg;
1115 s64 vblank_def;1225 s64 vblank_def;
1116 s64 vblank_min;1226 s64 vblank_min;
1117 s64 pixel_rate_min;1227 s64 pixel_rate;
1118 s64 pixel_rate_max;
1119 int ret;1228 int ret;
1120 1229
1121 ctrl_hdlr = &imx258->ctrl_handler;1230 ctrl_hdlr = &imx258->ctrl_handler;
@@ -1128,32 +1237,33 @@ static int imx258_init_controls(struct imx258 *imx258) · 6 unmodified lines
1128 imx258->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,1237 imx258->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
1129 &imx258_ctrl_ops,1238 &imx258_ctrl_ops,
1130 V4L2_CID_LINK_FREQ,1239 V4L2_CID_LINK_FREQ,
1131 ARRAY_SIZE(link_freq_menu_items) - 1,1240 ARRAY_SIZE(link_freq_menu_items_19_2) - 1,
1132 0,1241 0,
1133 link_freq_menu_items);1242 imx258->link_freq_menu_items);
1134 1243
1135 if (imx258->link_freq)1244 if (imx258->link_freq)
1136 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;1245 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1137 1246
1138 /* The driver only supports one bayer order and flips by default. */1247 imx258->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
1139 hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,1248 V4L2_CID_HFLIP, 0, 1, 1, 1);
1140 V4L2_CID_HFLIP, 1, 1, 1, 1);1249 if (imx258->hflip)
1141 if (hflip)1250 imx258->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
1142 hflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;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;
1143 1256
1144 vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,1257 link_freq_cfgs = &imx258->link_freq_configs[0];
1145 V4L2_CID_VFLIP, 1, 1, 1, 1);1258 link_cfg = link_freq_cfgs[imx258->lane_mode_idx].link_cfg;
1146 if (vflip)1259 pixel_rate = link_freq_to_pixel_rate(imx258->link_freq_menu_items[0],
1147 vflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;1260 link_cfg);
1148 1261
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]);
1151 /* By default, PIXEL_RATE is read only */1262 /* By default, PIXEL_RATE is read only */
1152 imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,1263 imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
1153 V4L2_CID_PIXEL_RATE,1264 V4L2_CID_PIXEL_RATE,
1154 pixel_rate_min, pixel_rate_max,1265 pixel_rate, pixel_rate,
1155 1, pixel_rate_max);1266 1, pixel_rate);
1156
1157 1267
1158 vblank_def = imx258->cur_mode->vts_def - imx258->cur_mode->height;1268 vblank_def = imx258->cur_mode->vts_def - imx258->cur_mode->height;
1159 vblank_min = imx258->cur_mode->vts_min - imx258->cur_mode->height;1269 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
1163 IMX258_VTS_MAX - imx258->cur_mode->height, 1,1273 IMX258_VTS_MAX - imx258->cur_mode->height, 1,
1164 vblank_def);1274 vblank_def);
1165 1275
1166 if (imx258->vblank)
1167 imx258->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1168
1169 imx258->hblank = v4l2_ctrl_new_std(1276 imx258->hblank = v4l2_ctrl_new_std(
1170 ctrl_hdlr, &imx258_ctrl_ops, V4L2_CID_HBLANK,1277 ctrl_hdlr, &imx258_ctrl_ops, V4L2_CID_HBLANK,
1171 IMX258_PPL_DEFAULT - imx258->cur_mode->width,1278 IMX258_PPL_DEFAULT - imx258->cur_mode->width,
@@ -1232,9 +1339,25 @@ static void imx258_free_controls(struct imx258 *imx258) · 60 unmodified lines
1232 mutex_destroy(&imx258->mutex);1339 mutex_destroy(&imx258->mutex);
1233}1340}
1234 1341
1342static 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
1235static int imx258_probe(struct i2c_client *client)1354static int imx258_probe(struct i2c_client *client)
1236{1355{
1237 struct imx258 *imx258;1356 struct imx258 *imx258;
1357 struct fwnode_handle *endpoint;
1358 struct v4l2_fwnode_endpoint ep = {
1359 .bus_type = V4L2_MBUS_CSI2_DPHY
1360 };
1238 int ret;1361 int ret;
1239 u32 val = 0;1362 u32 val = 0;
1240 1363
@@ -1242,6 +1365,18 @@ static int imx258_probe(struct i2c_client *client) · 1 unmodified line
1242 if (!imx258)1365 if (!imx258)
1243 return -ENOMEM;1366 return -ENOMEM;
1244 1367
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
1245 imx258->clk = devm_clk_get_optional(&client->dev, NULL);1380 imx258->clk = devm_clk_get_optional(&client->dev, NULL);
1246 if (IS_ERR(imx258->clk))1381 if (IS_ERR(imx258->clk))
1247 return dev_err_probe(&client->dev, PTR_ERR(imx258->clk),1382 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
1254 } else {1389 } else {
1255 val = clk_get_rate(imx258->clk);1390 val = clk_get_rate(imx258->clk);
1256 }1391 }
1257 if (val != IMX258_INPUT_CLOCK_FREQ) {1392
1258 dev_err(&client->dev, "input clock frequency not supported\n");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);
1259 return -EINVAL;1405 return -EINVAL;
1260 }1406 }
1261 1407
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
1262 /* Initialize subdev */1453 /* Initialize subdev */
1263 v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);1454 v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);
1264 1455
1265 /* Will be powered off via pm_runtime_idle */1456 /* Will be powered off via pm_runtime_idle */
1266 ret = imx258_power_on(&client->dev);1457 ret = imx258_power_on(&client->dev);
1267 if (ret)1458 if (ret)
1268 return ret;1459 goto error_endpoint_free;
1269 1460
1270 /* Check module identity */1461 /* Check module identity */
1271 ret = imx258_identify_module(imx258);1462 ret = imx258_identify_module(imx258);
@@ -1298,6 +1489,7 @@ static int imx258_probe(struct i2c_client *client) · 26 unmodified lines
1298 pm_runtime_set_active(&client->dev);1489 pm_runtime_set_active(&client->dev);
1299 pm_runtime_enable(&client->dev);1490 pm_runtime_enable(&client->dev);
1300 pm_runtime_idle(&client->dev);1491 pm_runtime_idle(&client->dev);
1492 v4l2_fwnode_endpoint_free(&ep);
1301 1493
1302 return 0;1494 return 0;
1303 1495
@@ -1310,6 +1502,9 @@ error_handler_free: · 6 unmodified lines
1310error_identify:1502error_identify:
1311 imx258_power_off(&client->dev);1503 imx258_power_off(&client->dev);
1312 1504
1505error_endpoint_free:
1506 v4l2_fwnode_endpoint_free(&ep);
1507
1313 return ret;1508 return ret;
1314}1509}
1315 1510
@@ -1342,7 +1537,8 @@ MODULE_DEVICE_TABLE(acpi, imx258_acpi_ids); · 26 unmodified lines
1342#endif1537#endif
1343 1538
1344static const struct of_device_id imx258_dt_ids[] = {1539static 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 },
1346 { /* sentinel */ }1542 { /* sentinel */ }
1347};1543};
1348MODULE_DEVICE_TABLE(of, imx258_dt_ids);1544MODULE_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. */
180static const struct v4l2_rect imx283_native_area = {
181 .top = 0,
182 .left = 0,
183 .width = 5592,
184 .height = 3710,
185};
186
187static const struct v4l2_rect imx283_active_area = {
188 .top = 40,
189 .left = 108,
190 .width = 5472,
191 .height = 3648,
192};
193
194struct 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 */
200struct 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
258struct imx283_input_frequency {
259 unsigned int mhz;
260 unsigned int reg_count;
261 struct cci_reg_sequence regs[4];
262};
263
264static 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
307enum 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
320struct imx283_readout_mode {
321 u8 mdsel1;
322 u8 mdsel2;
323 u8 mdsel3;
324 u8 mdsel4;
325};
326
327static 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
356static 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
375static 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
394static 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
399static 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 */
411static 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
477static 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
503static const u32 imx283_mbus_codes[] = {
504 MEDIA_BUS_FMT_SRGGB12_1X12,
505 MEDIA_BUS_FMT_SRGGB10_1X10,
506};
507
508/* regulator supplies */
509static 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
515struct 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
542static inline struct imx283 *to_imx283(struct v4l2_subdev *sd)
543{
544 return container_of_const(sd, struct imx283, sd);
545}
546
547static 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 */
575static 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 */
590static 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) */
609static 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 */
628static 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
644static 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 */
663static 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
678static 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
688static 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
698static 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
717static 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
824static const struct v4l2_ctrl_ops imx283_ctrl_ops = {
825 .s_ctrl = imx283_set_ctrl,
826};
827
828static 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
840static 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
860static 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
873static 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
895static 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
923static 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
956static 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 */
1001static 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
1091static 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
1113err_rpm_put:
1114 pm_runtime_mark_last_busy(imx283->dev);
1115 pm_runtime_put_autosuspend(imx283->dev);
1116
1117 return ret;
1118}
1119
1120static 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 */
1141static 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
1165reg_off:
1166 regulator_bulk_disable(ARRAY_SIZE(imx283_supply_name), imx283->supplies);
1167 return ret;
1168}
1169
1170static 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
1179static 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
1187static 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
1197static 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 */
1210static 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
1231static 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
1254static 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
1259static const struct v4l2_subdev_video_ops imx283_video_ops = {
1260 .s_stream = v4l2_subdev_s_stream_helper,
1261};
1262
1263static 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
1273static const struct v4l2_subdev_internal_ops imx283_internal_ops = {
1274 .init_state = imx283_init_state,
1275};
1276
1277static 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 */
1284static 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
1383error:
1384 v4l2_ctrl_handler_free(ctrl_hdlr);
1385
1386 return ret;
1387}
1388
1389static 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
1423done_endpoint_free:
1424 v4l2_fwnode_endpoint_free(&bus_cfg);
1425
1426 return ret;
1427};
1428
1429static 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
1554error_subdev_cleanup:
1555 v4l2_subdev_cleanup(&imx283->sd);
1556
1557error_media_entity:
1558 media_entity_cleanup(&imx283->sd.entity);
1559
1560error_handler_free:
1561 v4l2_ctrl_handler_free(imx283->sd.ctrl_handler);
1562
1563error_pm:
1564 pm_runtime_disable(imx283->dev);
1565 pm_runtime_set_suspended(imx283->dev);
1566error_power_off:
1567 imx283_power_off(imx283);
1568
1569 return ret;
1570}
1571
1572static 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
1588static DEFINE_RUNTIME_DEV_PM_OPS(imx283_pm_ops, imx283_runtime_suspend,
1589 imx283_runtime_resume, NULL);
1590
1591static const struct of_device_id imx283_dt_ids[] = {
1592 { .compatible = "sony,imx283" },
1593 { /* sentinel */ }
1594};
1595MODULE_DEVICE_TABLE(of, imx283_dt_ids);
1596
1597static 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};
1606module_i2c_driver(imx283_i2c_driver);
1607
1608MODULE_AUTHOR("Will Whang <will@willwhang.com>");
1609MODULE_AUTHOR("Kieran Bingham <kieran.bingham@ideasonboard.com>");
1610MODULE_AUTHOR("Umang Jain <umang.jain@ideasonboard.com>");
1611MODULE_DESCRIPTION("Sony IMX283 Sensor Driver");
1612MODULE_LICENSE("GPL");
drivers/media/i2c/imx412.c+4−5
@@ -542,14 +542,13 @@ static int imx412_update_controls(struct imx412 *imx412, · 541 unmodified lines
542 */542 */
543static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain)543static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain)
544{544{
545 u32 lpfr, shutter;545 u32 lpfr;
546 int ret;546 int ret;
547 547
548 lpfr = imx412->vblank + imx412->cur_mode->height;548 lpfr = imx412->vblank + imx412->cur_mode->height;
549 shutter = lpfr - exposure;
550 549
551 dev_dbg(imx412->dev, "Set exp %u, analog gain %u, shutter %u, lpfr %u",550 dev_dbg(imx412->dev, "Set exp %u, analog gain %u, lpfr %u",
552 exposure, gain, shutter, lpfr);551 exposure, gain, lpfr);
553 552
554 ret = imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 1);553 ret = imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 1);
555 if (ret)554 if (ret)
@@ -559,7 +558,7 @@ static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain) · 3 unmodified lines
559 if (ret)558 if (ret)
560 goto error_release_group_hold;559 goto error_release_group_hold;
561 560
562 ret = imx412_write_reg(imx412, IMX412_REG_EXPOSURE_CIT, 2, shutter);561 ret = imx412_write_reg(imx412, IMX412_REG_EXPOSURE_CIT, 2, exposure);
563 if (ret)562 if (ret)
564 goto error_release_group_hold;563 goto error_release_group_hold;
565 564
drivers/media/i2c/ks0127.c+0−8
@@ -175,14 +175,6 @@ MODULE_LICENSE("GPL"); · 174 unmodified lines
175* mga_dev : represents one ks0127 chip.175* mga_dev : represents one ks0127 chip.
176****************************************************************************/176****************************************************************************/
177 177
178struct adjust {
179 int contrast;
180 int bright;
181 int hue;
182 int ugain;
183 int vgain;
184};
185
186struct ks0127 {178struct ks0127 {
187 struct v4l2_subdev sd;179 struct v4l2_subdev sd;
188 v4l2_std_id norm;180 v4l2_std_id norm;
drivers/media/i2c/max9286.c+68−113
@@ -19,7 +19,6 @@ · 18 unmodified lines
19#include <linux/i2c.h>19#include <linux/i2c.h>
20#include <linux/i2c-mux.h>20#include <linux/i2c-mux.h>
21#include <linux/module.h>21#include <linux/module.h>
22#include <linux/mutex.h>
23#include <linux/of_graph.h>22#include <linux/of_graph.h>
24#include <linux/regulator/consumer.h>23#include <linux/regulator/consumer.h>
25#include <linux/slab.h>24#include <linux/slab.h>
@@ -198,12 +197,6 @@ struct max9286_priv { · 172 unmodified lines
198 struct v4l2_ctrl *pixelrate_ctrl;197 struct v4l2_ctrl *pixelrate_ctrl;
199 unsigned int pixelrate;198 unsigned int pixelrate;
200 199
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
207 unsigned int nsources;200 unsigned int nsources;
208 unsigned int source_mask;201 unsigned int source_mask;
209 unsigned int route_mask;202 unsigned int route_mask;
@@ -576,11 +569,14 @@ static void max9286_set_video_format(struct max9286_priv *priv, · 366 unmodified lines
576 MAX9286_INVVS | MAX9286_HVSRC_D14);569 MAX9286_INVVS | MAX9286_HVSRC_D14);
577}570}
578 571
579static void max9286_set_fsync_period(struct max9286_priv *priv)572static void max9286_set_fsync_period(struct max9286_priv *priv,
573 struct v4l2_subdev_state *state)
580{574{
575 const struct v4l2_fract *interval;
581 u32 fsync;576 u32 fsync;
582 577
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) {
584 /*580 /*
585 * Special case, a null interval enables automatic FRAMESYNC581 * Special case, a null interval enables automatic FRAMESYNC
586 * mode. FRAMESYNC is taken from the slowest link.582 * 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
596 * The FRAMESYNC generator is configured with a period expressed as a592 * The FRAMESYNC generator is configured with a period expressed as a
597 * number of PCLK periods.593 * number of PCLK periods.
598 */594 */
599 fsync = div_u64((u64)priv->pixelrate * priv->interval.numerator,595 fsync = div_u64((u64)priv->pixelrate * interval->numerator,
600 priv->interval.denominator);596 interval->denominator);
601 597
602 dev_dbg(&priv->client->dev, "fsync period %u (pclk %u)\n", fsync,598 dev_dbg(&priv->client->dev, "fsync period %u (pclk %u)\n", fsync,
603 priv->pixelrate);599 priv->pixelrate);
@@ -788,22 +784,25 @@ static void max9286_v4l2_notifier_unregister(struct max9286_priv *priv) · 184 unmodified lines
788static int max9286_s_stream(struct v4l2_subdev *sd, int enable)784static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
789{785{
790 struct max9286_priv *priv = sd_to_max9286(sd);786 struct max9286_priv *priv = sd_to_max9286(sd);
787 struct v4l2_subdev_state *state;
791 struct max9286_source *source;788 struct max9286_source *source;
792 unsigned int i;789 unsigned int i;
793 bool sync = false;790 bool sync = false;
794 int ret;791 int ret = 0;
792
793 state = v4l2_subdev_lock_and_get_active_state(sd);
795 794
796 if (enable) {795 if (enable) {
797 const struct v4l2_mbus_framefmt *format;796 const struct v4l2_mbus_framefmt *format;
798 797
799 /*798 /*
800 * Get the format from the first used sink pad, as all sink799 * Get the format from the source pad, as all formats must be
801 * formats must be identical.800 * identical.
802 */801 */
803 format = &priv->fmt[__ffs(priv->bound_sources)];802 format = v4l2_subdev_state_get_format(state, MAX9286_SRC_PAD);
804 803
805 max9286_set_video_format(priv, format);804 max9286_set_video_format(priv, format);
806 max9286_set_fsync_period(priv);805 max9286_set_fsync_period(priv, state);
807 806
808 /*807 /*
809 * The frame sync between cameras is transmitted across the808 * 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
816 for_each_source(priv, source) {815 for_each_source(priv, source) {
817 ret = v4l2_subdev_call(source->sd, video, s_stream, 1);816 ret = v4l2_subdev_call(source->sd, video, s_stream, 1);
818 if (ret)817 if (ret)
819 return ret;818 goto unlock;
820 }819 }
821 820
822 ret = max9286_check_video_links(priv);821 ret = max9286_check_video_links(priv);
823 if (ret)822 if (ret)
824 return ret;823 goto unlock;
825 824
826 /*825 /*
827 * Wait until frame synchronization is locked.826 * Wait until frame synchronization is locked.
@@ -842,7 +841,8 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) · 14 unmodified lines
842 if (!sync) {841 if (!sync) {
843 dev_err(&priv->client->dev,842 dev_err(&priv->client->dev,
844 "Failed to get frame synchronization\n");843 "Failed to get frame synchronization\n");
845 return -EXDEV; /* Invalid cross-device link */844 ret = -EXDEV; /* Invalid cross-device link */
845 goto unlock;
846 }846 }
847 847
848 /*848 /*
@@ -865,26 +865,21 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) · 16 unmodified lines
865 max9286_i2c_mux_close(priv);865 max9286_i2c_mux_close(priv);
866 }866 }
867 867
868 return 0;868unlock:
869 v4l2_subdev_unlock_state(state);
870
871 return ret;
869}872}
870 873
871static int max9286_get_frame_interval(struct v4l2_subdev *sd,874static int max9286_get_frame_interval(struct v4l2_subdev *sd,
872 struct v4l2_subdev_state *sd_state,875 struct v4l2_subdev_state *sd_state,
873 struct v4l2_subdev_frame_interval *interval)876 struct v4l2_subdev_frame_interval *interval)
874{877{
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
884 if (interval->pad != MAX9286_SRC_PAD)878 if (interval->pad != MAX9286_SRC_PAD)
885 return -EINVAL;879 return -EINVAL;
886 880
887 interval->interval = priv->interval;881 interval->interval = *v4l2_subdev_state_get_interval(sd_state,
882 interval->pad);
888 883
889 return 0;884 return 0;
890}885}
@@ -893,19 +888,11 @@ static int max9286_set_frame_interval(struct v4l2_subdev *sd, · 2 unmodified lines
893 struct v4l2_subdev_state *sd_state,888 struct v4l2_subdev_state *sd_state,
894 struct v4l2_subdev_frame_interval *interval)889 struct v4l2_subdev_frame_interval *interval)
895{890{
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
905 if (interval->pad != MAX9286_SRC_PAD)891 if (interval->pad != MAX9286_SRC_PAD)
906 return -EINVAL;892 return -EINVAL;
907 893
908 priv->interval = interval->interval;894 *v4l2_subdev_state_get_interval(sd_state,
895 interval->pad) = interval->interval;
909 896
910 return 0;897 return 0;
911}898}
@@ -914,39 +901,28 @@ static int max9286_enum_mbus_code(struct v4l2_subdev *sd, · 2 unmodified lines
914 struct v4l2_subdev_state *sd_state,901 struct v4l2_subdev_state *sd_state,
915 struct v4l2_subdev_mbus_code_enum *code)902 struct v4l2_subdev_mbus_code_enum *code)
916{903{
917 if (code->pad || code->index > 0)904 if (code->pad || code->index >= ARRAY_SIZE(max9286_formats))
918 return -EINVAL;905 return -EINVAL;
919 906
920 code->code = MEDIA_BUS_FMT_UYVY8_1X16;907 code->code = max9286_formats[code->index].code;
921 908
922 return 0;909 return 0;
923}910}
924 911
925static struct v4l2_mbus_framefmt *
926max9286_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
940static int max9286_set_fmt(struct v4l2_subdev *sd,912static int max9286_set_fmt(struct v4l2_subdev *sd,
941 struct v4l2_subdev_state *sd_state,913 struct v4l2_subdev_state *state,
942 struct v4l2_subdev_format *format)914 struct v4l2_subdev_format *format)
943{915{
944 struct max9286_priv *priv = sd_to_max9286(sd);916 struct max9286_priv *priv = sd_to_max9286(sd);
945 struct v4l2_mbus_framefmt *cfg_fmt;917 struct max9286_source *source;
946 unsigned int i;918 unsigned int i;
947 919
920 /*
921 * Disable setting format on the source pad: format is propagated
922 * from the sinks.
923 */
948 if (format->pad == MAX9286_SRC_PAD)924 if (format->pad == MAX9286_SRC_PAD)
949 return -EINVAL;925 return v4l2_subdev_get_fmt(sd, state, format);
950 926
951 /* Validate the format. */927 /* Validate the format. */
952 for (i = 0; i < ARRAY_SIZE(max9286_formats); ++i) {928 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
957 if (i == ARRAY_SIZE(max9286_formats))933 if (i == ARRAY_SIZE(max9286_formats))
958 format->format.code = max9286_formats[0].code;934 format->format.code = max9286_formats[0].code;
959 935
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
972static 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
980 /*936 /*
981 * Multiplexed Stream Support: Support link validation by returning the937 * Apply the same format on all the other pad as all links must have the
982 * format of the first bound link. All links must have the same format,938 * same format.
983 * as we do not support mixing and matching of cameras connected to the
984 * max9286.
985 */939 */
986 if (pad == MAX9286_SRC_PAD)940 for_each_source(priv, source) {
987 pad = __ffs(priv->bound_sources);941 unsigned int index = to_index(priv, source);
988 942
989 cfg_fmt = max9286_get_pad_format(priv, sd_state, pad, format->which);943 *v4l2_subdev_state_get_format(state, index) = format->format;
990 if (!cfg_fmt)944 }
991 return -EINVAL;
992 945
993 mutex_lock(&priv->mutex);946 *v4l2_subdev_state_get_format(state, MAX9286_SRC_PAD) = format->format;
994 format->format = *cfg_fmt;
995 mutex_unlock(&priv->mutex);
996 947
997 return 0;948 return 0;
998}949}
@@ -1003,7 +954,7 @@ static const struct v4l2_subdev_video_ops max9286_video_ops = { · 4 unmodified lines
1003 954
1004static const struct v4l2_subdev_pad_ops max9286_pad_ops = {955static const struct v4l2_subdev_pad_ops max9286_pad_ops = {
1005 .enum_mbus_code = max9286_enum_mbus_code,956 .enum_mbus_code = max9286_enum_mbus_code,
1006 .get_fmt = max9286_get_fmt,957 .get_fmt = v4l2_subdev_get_fmt,
1007 .set_fmt = max9286_set_fmt,958 .set_fmt = max9286_set_fmt,
1008 .get_frame_interval = max9286_get_frame_interval,959 .get_frame_interval = max9286_get_frame_interval,
1009 .set_frame_interval = max9286_set_frame_interval,960 .set_frame_interval = max9286_set_frame_interval,
@@ -1025,26 +976,29 @@ static const struct v4l2_mbus_framefmt max9286_default_format = { · 15 unmodified lines
1025 .xfer_func = V4L2_XFER_FUNC_DEFAULT,976 .xfer_func = V4L2_XFER_FUNC_DEFAULT,
1026};977};
1027 978
1028static void max9286_init_format(struct v4l2_mbus_framefmt *fmt)979static int max9286_init_state(struct v4l2_subdev *sd,
980 struct v4l2_subdev_state *state)
1029{981{
1030 *fmt = max9286_default_format;982 struct v4l2_fract *interval;
1031}
1032 983
1033static int max9286_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)984 for (unsigned int i = 0; i < MAX9286_N_PADS; i++)
1034{985 *v4l2_subdev_state_get_format(state, i) = max9286_default_format;
1035 struct v4l2_mbus_framefmt *format;
1036 unsigned int i;
1037 986
1038 for (i = 0; i < MAX9286_N_SINKS; i++) {987 /*
1039 format = v4l2_subdev_state_get_format(fh->state, i);988 * Special case: a null interval enables automatic FRAMESYNC mode.
1040 max9286_init_format(format);989 *
1041 }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;
1042 996
1043 return 0;997 return 0;
1044}998}
1045 999
1046static const struct v4l2_subdev_internal_ops max9286_subdev_internal_ops = {1000static const struct v4l2_subdev_internal_ops max9286_subdev_internal_ops = {
1047 .open = max9286_open,1001 .init_state = max9286_init_state,
1048};1002};
1049 1003
1050static const struct media_entity_operations max9286_media_ops = {1004static const struct media_entity_operations max9286_media_ops = {
@@ -1079,10 +1033,6 @@ static int max9286_v4l2_register(struct max9286_priv *priv) · 28 unmodified lines
1079 }1033 }
1080 1034
1081 /* Configure V4L2 for the MAX9286 itself */1035 /* Configure V4L2 for the MAX9286 itself */
1082
1083 for (i = 0; i < MAX9286_N_SINKS; i++)
1084 max9286_init_format(&priv->fmt[i]);
1085
1086 v4l2_i2c_subdev_init(&priv->sd, priv->client, &max9286_subdev_ops);1036 v4l2_i2c_subdev_init(&priv->sd, priv->client, &max9286_subdev_ops);
1087 priv->sd.internal_ops = &max9286_subdev_internal_ops;1037 priv->sd.internal_ops = &max9286_subdev_internal_ops;
1088 priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1038 priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -1109,14 +1059,21 @@ static int max9286_v4l2_register(struct max9286_priv *priv) · 20 unmodified lines
1109 if (ret)1059 if (ret)
1110 goto err_async;1060 goto err_async;
1111 1061
1062 priv->sd.state_lock = priv->ctrls.lock;
1063 ret = v4l2_subdev_init_finalize(&priv->sd);
1064 if (ret)
1065 goto err_async;
1066
1112 ret = v4l2_async_register_subdev(&priv->sd);1067 ret = v4l2_async_register_subdev(&priv->sd);
1113 if (ret < 0) {1068 if (ret < 0) {
1114 dev_err(dev, "Unable to register subdevice\n");1069 dev_err(dev, "Unable to register subdevice\n");
1115 goto err_async;1070 goto err_subdev;
1116 }1071 }
1117 1072
1118 return 0;1073 return 0;
1119 1074
1075err_subdev:
1076 v4l2_subdev_cleanup(&priv->sd);
1120err_async:1077err_async:
1121 v4l2_ctrl_handler_free(&priv->ctrls);1078 v4l2_ctrl_handler_free(&priv->ctrls);
1122 max9286_v4l2_notifier_unregister(priv);1079 max9286_v4l2_notifier_unregister(priv);
@@ -1126,6 +1083,7 @@ err_async: · 3 unmodified lines
1126 1083
1127static void max9286_v4l2_unregister(struct max9286_priv *priv)1084static void max9286_v4l2_unregister(struct max9286_priv *priv)
1128{1085{
1086 v4l2_subdev_cleanup(&priv->sd);
1129 v4l2_ctrl_handler_free(&priv->ctrls);1087 v4l2_ctrl_handler_free(&priv->ctrls);
1130 v4l2_async_unregister_subdev(&priv->sd);1088 v4l2_async_unregister_subdev(&priv->sd);
1131 max9286_v4l2_notifier_unregister(priv);1089 max9286_v4l2_notifier_unregister(priv);
@@ -1182,7 +1140,6 @@ static int max9286_setup(struct max9286_priv *priv) · 50 unmodified lines
1182 max9286_write(priv, 0x69, (0xf & ~priv->route_mask));1140 max9286_write(priv, 0x69, (0xf & ~priv->route_mask));
1183 1141
1184 max9286_set_video_format(priv, &max9286_default_format);1142 max9286_set_video_format(priv, &max9286_default_format);
1185 max9286_set_fsync_period(priv);
1186 1143
1187 cfg = max9286_read(priv, 0x1c);1144 cfg = max9286_read(priv, 0x1c);
1188 if (cfg < 0)1145 if (cfg < 0)
@@ -1629,8 +1586,6 @@ static int max9286_probe(struct i2c_client *client) · 440 unmodified lines
1629 if (!priv)1586 if (!priv)
1630 return -ENOMEM;1587 return -ENOMEM;
1631 1588
1632 mutex_init(&priv->mutex);
1633
1634 priv->client = client;1589 priv->client = client;
1635 1590
1636 /* GPIO values default to high */1591 /* 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
83enum max96714_vpg_mode {
84 MAX96714_VPG_DISABLED = 0,
85 MAX96714_VPG_CHECKERBOARD = 1,
86 MAX96714_VPG_GRADIENT = 2,
87};
88
89struct 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
98struct max96714_txport {
99 struct v4l2_fwnode_endpoint vep;
100};
101
102struct 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
118static inline struct max96714_priv *sd_to_max96714(struct v4l2_subdev *sd)
119{
120 return container_of(sd, struct max96714_priv, sd);
121}
122
123static 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
130static 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
136static 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
145static 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
198static 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
216static 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
242static const char * const max96714_test_pattern[] = {
243 "Disabled",
244 "Checkerboard",
245 "Gradient"
246};
247
248static const struct v4l2_ctrl_ops max96714_ctrl_ops = {
249 .s_ctrl = max96714_s_ctrl,
250};
251
252static 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
290err:
291 if (!priv->enabled_source_streams)
292 max96714_disable_tx_port(priv);
293
294 return ret;
295}
296
297static 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
328static 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
359static 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
387static 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
400static 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
421static 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
430static 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
439static 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
446static 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
455static 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
462static 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
474static 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
488static const struct v4l2_subdev_core_ops max96714_subdev_core_ops = {
489 .log_status = max96714_log_status,
490};
491
492static const struct v4l2_subdev_video_ops max96714_video_ops = {
493 .s_stream = v4l2_subdev_s_stream_helper,
494};
495
496static const struct v4l2_subdev_internal_ops max96714_internal_ops = {
497 .init_state = max96714_init_state,
498};
499
500static 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
506static const struct media_entity_operations max96714_entity_ops = {
507 .link_validate = v4l2_subdev_link_validate,
508};
509
510static 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
544static const struct v4l2_async_notifier_operations max96714_notify_ops = {
545 .bound = max96714_notify_bound,
546};
547
548static 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
581static 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
637err_unreg_notif:
638 v4l2_async_nf_unregister(&priv->notifier);
639 v4l2_async_nf_cleanup(&priv->notifier);
640err_subdev_cleanup:
641 v4l2_subdev_cleanup(&priv->sd);
642err_entity_cleanup:
643 media_entity_cleanup(&priv->sd.entity);
644err_free_ctrl:
645 v4l2_ctrl_handler_free(&priv->ctrl_handler);
646
647 return ret;
648};
649
650static 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
662static int max96714_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
663{
664 return 0;
665}
666
667static 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
678static 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
737static 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
747static 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
757static 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
803err_free_vep:
804 v4l2_fwnode_endpoint_free(&vep);
805
806 return ret;
807}
808
809static 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
843err_put_source_ep_fwnode:
844 fwnode_handle_put(rxport->source.ep_fwnode);
845 return ret;
846}
847
848static 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
867static 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
914err_pd_gpio:
915 gpiod_set_value_cansleep(priv->pd_gpio, 1);
916 return ret;
917}
918
919static void max96714_disable_core_hw(struct max96714_priv *priv)
920{
921 gpiod_set_value_cansleep(priv->pd_gpio, 1);
922}
923
924static 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
940static 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
980err_del_mux:
981 i2c_mux_del_adapters(priv->mux);
982err_disable_poc:
983 max96714_rxport_disable_poc(priv);
984err_free_ports:
985 fwnode_handle_put(priv->rxport.source.ep_fwnode);
986err_disable_core_hw:
987 max96714_disable_core_hw(priv);
988
989 return ret;
990}
991
992static 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
1005static const struct of_device_id max96714_of_ids[] = {
1006 { .compatible = "maxim,max96714f" },
1007 { }
1008};
1009MODULE_DEVICE_TABLE(of, max96714_of_ids);
1010
1011static 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
1020module_i2c_driver(max96714_i2c_driver);
1021
1022MODULE_LICENSE("GPL");
1023MODULE_DESCRIPTION("Maxim Integrated GMSL2 Deserializers Driver");
1024MODULE_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
85struct 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
101static inline struct max96717_priv *sd_to_max96717(struct v4l2_subdev *sd)
102{
103 return container_of(sd, struct max96717_priv, sd);
104}
105
106static 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
111static int max96717_i2c_mux_select(struct i2c_mux_core *mux, u32 chan)
112{
113 return 0;
114}
115
116static 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
127static 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
134static 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
152static 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
161static 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
175static 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
185static 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
195static 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
232static 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
256static 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
269static 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
306static 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
326static 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
335static 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
346static 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
375stop_csi:
376 if (!priv->enabled_source_streams)
377 max96717_start_csi(priv, false);
378 return ret;
379}
380
381static 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
406static 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
414static const struct v4l2_subdev_core_ops max96717_subdev_core_ops = {
415 .log_status = max96717_log_status,
416};
417
418static const struct v4l2_subdev_internal_ops max96717_internal_ops = {
419 .init_state = max96717_init_state,
420};
421
422static const struct v4l2_subdev_ops max96717_subdev_ops = {
423 .core = &max96717_subdev_core_ops,
424 .pad = &max96717_pad_ops,
425};
426
427static const struct media_entity_operations max96717_entity_ops = {
428 .link_validate = v4l2_subdev_link_validate,
429};
430
431static 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
465static const struct v4l2_async_notifier_operations max96717_notify_ops = {
466 .bound = max96717_notify_bound,
467};
468
469static 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
508static 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
548err_unreg_notif:
549 v4l2_async_nf_unregister(&priv->notifier);
550 v4l2_async_nf_cleanup(&priv->notifier);
551err_free_state:
552 v4l2_subdev_cleanup(&priv->sd);
553err_entity_cleanup:
554 media_entity_cleanup(&priv->sd.entity);
555
556 return ret;
557}
558
559static 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
568struct max96717_pll_predef_freq {
569 unsigned long freq;
570 bool is_alt;
571 u8 val;
572};
573
574static 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
580static unsigned long
581max96717_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
588static 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
608static 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
625static 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
653static 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
661static 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
668static 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
676static 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
716free_init_name:
717 kfree(init.name);
718 return ret;
719}
720
721static 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
783static 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
818static 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
850static 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
899static 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
908static const struct of_device_id max96717_of_ids[] = {
909 { .compatible = "maxim,max96717f" },
910 { }
911};
912MODULE_DEVICE_TABLE(of, max96717_of_ids);
913
914static 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
923module_i2c_driver(max96717_i2c_driver);
924
925MODULE_DESCRIPTION("Maxim GMSL2 MAX96717 Serializer Driver");
926MODULE_AUTHOR("Julien Massot <julien.massot@collabora.com>");
927MODULE_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
971 if (ret < 0)971 if (ret < 0)
972 return ret;972 return ret;
973 973
974 v4l2_ctrl_handler_init(hdl, 5);974 v4l2_ctrl_handler_init(hdl, 11);
975 975
976 hdl->lock = &sensor->lock;976 hdl->lock = &sensor->lock;
977 977
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
1360 struct v4l2_fwnode_endpoint bus_cfg = {1360 struct v4l2_fwnode_endpoint bus_cfg = {
1361 .bus_type = V4L2_MBUS_CSI2_DPHY,1361 .bus_type = V4L2_MBUS_CSI2_DPHY,
1362 };1362 };
1363 struct device_node *ep;1363 struct device_node *ep __free(device_node) =
1364 of_graph_get_endpoint_by_regs(np, 0, -1);
1364 int ret;1365 int ret;
1365 1366
1366 ep = of_graph_get_endpoint_by_regs(np, 0, -1);
1367 if (!ep)1367 if (!ep)
1368 return -EINVAL;1368 return -EINVAL;
1369 1369
1370 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);1370 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
1371 if (ret)1371 if (ret)
1372 goto out;1372 return ret;
1373 1373
1374 sensor->clock_ncont = bus_cfg.bus.mipi_csi2.flags &1374 sensor->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
1375 V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;1375 V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
1376 1376
1377out:1377 return 0;
1378 of_node_put(ep);
1379
1380 return ret;
1381}1378}
1382 1379
1383static int ov5647_probe(struct i2c_client *client)1380static int ov5647_probe(struct i2c_client *client)
drivers/media/i2c/ov5693.c+0−10
@@ -141,7 +141,6 @@ struct ov5693_device { · 140 unmodified lines
141 141
142 struct gpio_desc *reset;142 struct gpio_desc *reset;
143 struct gpio_desc *powerdown;143 struct gpio_desc *powerdown;
144 struct gpio_desc *privacy_led;
145 struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];144 struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
146 struct clk *xvclk;145 struct clk *xvclk;
147 146
@@ -657,7 +656,6 @@ static int ov5693_sensor_init(struct ov5693_device *ov5693) · 509 unmodified lines
657 656
658static void ov5693_sensor_powerdown(struct ov5693_device *ov5693)657static void ov5693_sensor_powerdown(struct ov5693_device *ov5693)
659{658{
660 gpiod_set_value_cansleep(ov5693->privacy_led, 0);
661 gpiod_set_value_cansleep(ov5693->reset, 1);659 gpiod_set_value_cansleep(ov5693->reset, 1);
662 gpiod_set_value_cansleep(ov5693->powerdown, 1);660 gpiod_set_value_cansleep(ov5693->powerdown, 1);
663 661
@@ -687,7 +685,6 @@ static int ov5693_sensor_powerup(struct ov5693_device *ov5693) · 23 unmodified lines
687 685
688 gpiod_set_value_cansleep(ov5693->powerdown, 0);686 gpiod_set_value_cansleep(ov5693->powerdown, 0);
689 gpiod_set_value_cansleep(ov5693->reset, 0);687 gpiod_set_value_cansleep(ov5693->reset, 0);
690 gpiod_set_value_cansleep(ov5693->privacy_led, 1);
691 688
692 usleep_range(5000, 7500);689 usleep_range(5000, 7500);
693 690
@@ -1201,13 +1198,6 @@ static int ov5693_configure_gpios(struct ov5693_device *ov5693) · 507 unmodified lines
1201 return PTR_ERR(ov5693->powerdown);1198 return PTR_ERR(ov5693->powerdown);
1202 }1199 }
1203 1200
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
1211 return 0;1201 return 0;
1212}1202}
1213 1203
drivers/media/i2c/tw9910.c+0−5
@@ -212,11 +212,6 @@ · 211 unmodified lines
212 * structure212 * structure
213 */213 */
214 214
215struct regval_list {
216 unsigned char reg_num;
217 unsigned char value;
218};
219
220struct tw9910_scale_ctrl {215struct tw9910_scale_ctrl {
221 char *name;216 char *name;
222 unsigned short width;217 unsigned short width;
drivers/media/i2c/uda1342.c+1−0
@@ -95,4 +95,5 @@ static struct i2c_driver uda1342_driver = { · 94 unmodified lines
95 95
96module_i2c_driver(uda1342_driver);96module_i2c_driver(uda1342_driver);
97 97
98MODULE_DESCRIPTION("Philips UDA1342 audio codec driver");
98MODULE_LICENSE("GPL v2");99MODULE_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
1878 1878
1879static struct i2c_driver vgxy61_i2c_driver = {1879static struct i2c_driver vgxy61_i2c_driver = {
1880 .driver = {1880 .driver = {
1881 .name = "st-vgxy61",1881 .name = "vgxy61",
1882 .of_match_table = vgxy61_dt_ids,1882 .of_match_table = vgxy61_dt_ids,
1883 .pm = &vgxy61_pm_ops,1883 .pm = &vgxy61_pm_ops,
1884 },1884 },
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
300 }300 }
301 if (astat & BT878_ARISCI) {301 if (astat & BT878_ARISCI) {
302 bt->finished_block = (stat & BT878_ARISCS) >> 28;302 bt->finished_block = (stat & BT878_ARISCS) >> 28;
303 if (bt->tasklet.callback)303 if (bt->bh_work.func)
304 tasklet_schedule(&bt->tasklet);304 queue_work(system_bh_wq, &bt->bh_work);
305 break;305 break;
306 }306 }
307 count++;307 count++;
@@ -478,8 +478,8 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) · 170 unmodified lines
478 btwrite(0, BT878_AINT_MASK);478 btwrite(0, BT878_AINT_MASK);
479 bt878_num++;479 bt878_num++;
480 480
481 if (!bt->tasklet.func)481 if (!bt->bh_work.func)
482 tasklet_disable(&bt->tasklet);482 disable_work_sync(&bt->bh_work);
483 483
484 return 0;484 return 0;
485 485
@@ -563,4 +563,5 @@ static void __exit bt878_cleanup_module(void) · 77 unmodified lines
563module_init(bt878_init_module);563module_init(bt878_init_module);
564module_exit(bt878_cleanup_module);564module_exit(bt878_cleanup_module);
565 565
566MODULE_DESCRIPTION("DVB/ATSC Support for bt878 based TV cards");
566MODULE_LICENSE("GPL");567MODULE_LICENSE("GPL");
drivers/media/pci/bt8xx/bt878.h+2−1
@@ -14,6 +14,7 @@ · 13 unmodified lines
14#include <linux/sched.h>14#include <linux/sched.h>
15#include <linux/spinlock.h>15#include <linux/spinlock.h>
16#include <linux/mutex.h>16#include <linux/mutex.h>
17#include <linux/workqueue.h>
17 18
18#include "bt848.h"19#include "bt848.h"
19#include "bttv.h"20#include "bttv.h"
@@ -120,7 +121,7 @@ struct bt878 { · 100 unmodified lines
120 dma_addr_t risc_dma;121 dma_addr_t risc_dma;
121 u32 risc_pos;122 u32 risc_pos;
122 123
123 struct tasklet_struct tasklet;124 struct work_struct bh_work;
124 int shutdown;125 int shutdown;
125};126};
126 127
drivers/media/pci/bt8xx/dvb-bt8xx.c+4−4
@@ -39,9 +39,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); · 38 unmodified lines
39 39
40#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */40#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
41 41
42static void dvb_bt8xx_task(struct tasklet_struct *t)42static void dvb_bt8xx_work(struct work_struct *t)
43{43{
44 struct bt878 *bt = from_tasklet(bt, t, tasklet);44 struct bt878 *bt = from_work(bt, t, bh_work);
45 struct dvb_bt8xx_card *card = dev_get_drvdata(&bt->adapter->dev);45 struct dvb_bt8xx_card *card = dev_get_drvdata(&bt->adapter->dev);
46 46
47 dprintk("%d\n", card->bt->finished_block);47 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
782 goto err_disconnect_frontend;782 goto err_disconnect_frontend;
783 }783 }
784 784
785 tasklet_setup(&card->bt->tasklet, dvb_bt8xx_task);785 INIT_WORK(&card->bt->bh_work, dvb_bt8xx_work);
786 786
787 frontend_init(card, type);787 frontend_init(card, type);
788 788
@@ -922,7 +922,7 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub) · 133 unmodified lines
922 dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);922 dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
923 923
924 bt878_stop(card->bt);924 bt878_stop(card->bt);
925 tasklet_kill(&card->bt->tasklet);925 cancel_work_sync(&card->bt->bh_work);
926 dvb_net_release(&card->dvbnet);926 dvb_net_release(&card->dvbnet);
927 card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);927 card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
928 card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);928 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
258 struct cx18_mailbox ppu2epu_mb;258 struct cx18_mailbox ppu2epu_mb;
259 259
260 struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS];260 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[];
262};262};
263 263
264void cx18_init_scb(struct cx18 *cx);264void cx18_init_scb(struct cx18 *cx);
drivers/media/pci/ddbridge/ddbridge.h+1−1
@@ -298,7 +298,7 @@ struct ddb_link { · 297 unmodified lines
298 spinlock_t lock; /* lock link access */298 spinlock_t lock; /* lock link access */
299 struct mutex flash_mutex; /* lock flash access */299 struct mutex flash_mutex; /* lock flash access */
300 struct ddb_lnb lnb;300 struct ddb_lnb lnb;
301 struct tasklet_struct tasklet;301 struct work_struct bh_work;
302 struct ddb_ids ids;302 struct ddb_ids ids;
303 303
304 spinlock_t temp_lock; /* lock temp chip access */304 spinlock_t temp_lock; /* lock temp chip access */
drivers/media/pci/intel/ipu-bridge.c+29−11
@@ -43,28 +43,46 @@ · 42 unmodified lines
43 * becoming apparent in the future.43 * becoming apparent in the future.
44 *44 *
45 * Do not add an entry for a sensor that is not actually supported.45 * Do not add an entry for a sensor that is not actually supported.
46 *
47 * Please keep the list sorted by ACPI HID.
46 */48 */
47static const struct ipu_sensor_config ipu_supported_sensors[] = {49static 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),
48 /* Omnivision OV5693 */58 /* Omnivision OV5693 */
49 IPU_SENSOR_CONFIG("INT33BE", 1, 419200000),59 IPU_SENSOR_CONFIG("INT33BE", 1, 419200000),
60 /* Omnivision OV2740 */
61 IPU_SENSOR_CONFIG("INT3474", 1, 180000000),
50 /* Omnivision OV8865 */62 /* Omnivision OV8865 */
51 IPU_SENSOR_CONFIG("INT347A", 1, 360000000),63 IPU_SENSOR_CONFIG("INT347A", 1, 360000000),
52 /* Omnivision OV7251 */64 /* Omnivision OV7251 */
53 IPU_SENSOR_CONFIG("INT347E", 1, 319200000),65 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),
54 /* Omnivision OV2680 */82 /* Omnivision OV2680 */
55 IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000),83 IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000),
56 /* Omnivision ov8856 */84 /* Omnivision OV8856 */
57 IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),85 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),
68};86};
69 87
70static const struct ipu_property_names prop_names = {88static 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
163 writel(ENTRY, isp->base + ipc->csr_out);163 writel(ENTRY, isp->base + ipc->csr_out);
164 break;164 break;
165 default:165 default:
166 dev_warn_ratelimited(&isp->pdev->dev,166 dev_dbg_ratelimited(&isp->pdev->dev,
167 "Unexpected CSR 0x%x\n", val);167 "Unexpected CSR 0x%x\n", val);
168 break;168 break;
169 }169 }
170 } while (retries--);170 } 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
345 return ret;345 return ret;
346}346}
347 347
348static int set_stream(struct v4l2_subdev *sd, int enable)348static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
349 struct v4l2_subdev_state *state,
350 u32 pad, u64 streams_mask)
349{351{
350 struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);352 struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd);
351 struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd);353 struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd);
352 struct device *dev = &csi2->isys->adev->auxdev.dev;
353 struct ipu6_isys_csi2_timing timing = { };354 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;
355 int ret;358 int ret;
356 359
357 dev_dbg(dev, "csi2 stream %s callback\n", enable ? "on" : "off");360 remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]);
358 361 remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
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 }
372 362
373 nlanes = csi2->nlanes;363 sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC,
364 CSI2_PAD_SINK,
365 &streams_mask);
374 366
375 ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV);367 ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV);
376 if (ret)368 if (ret)
377 return ret;369 return ret;
378 370
379 ret = ipu6_isys_csi2_set_stream(sd, &timing, nlanes, enable);371 ret = ipu6_isys_csi2_set_stream(sd, &timing, csi2->nlanes, true);
380 if (ret)372 if (ret)
381 return ret;373 return ret;
382 374
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
385static 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);
384 403
385 return 0;404 return 0;
386}405}
@@ -475,10 +494,6 @@ static int ipu6_isys_csi2_get_sel(struct v4l2_subdev *sd, · 88 unmodified lines
475 return ret;494 return ret;
476}495}
477 496
478static const struct v4l2_subdev_video_ops csi2_sd_video_ops = {
479 .s_stream = set_stream,
480};
481
482static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = {497static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = {
483 .get_fmt = v4l2_subdev_get_fmt,498 .get_fmt = v4l2_subdev_get_fmt,
484 .set_fmt = ipu6_isys_subdev_set_fmt,499 .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
486 .set_selection = ipu6_isys_csi2_set_sel,501 .set_selection = ipu6_isys_csi2_set_sel,
487 .enum_mbus_code = ipu6_isys_subdev_enum_mbus_code,502 .enum_mbus_code = ipu6_isys_subdev_enum_mbus_code,
488 .set_routing = ipu6_isys_subdev_set_routing,503 .set_routing = ipu6_isys_subdev_set_routing,
504 .enable_streams = ipu6_isys_csi2_enable_streams,
505 .disable_streams = ipu6_isys_csi2_disable_streams,
489};506};
490 507
491static const struct v4l2_subdev_ops csi2_sd_ops = {508static const struct v4l2_subdev_ops csi2_sd_ops = {
492 .core = &csi2_sd_core_ops,509 .core = &csi2_sd_core_ops,
493 .video = &csi2_sd_video_ops,
494 .pad = &csi2_sd_pad_ops,510 .pad = &csi2_sd_pad_ops,
495};511};
496 512
@@ -631,33 +647,3 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream, · 134 unmodified lines
631 647
632 return 0;648 return 0;
633}649}
634
635void 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
45 u32 receiver_errors;45 u32 receiver_errors;
46 unsigned int nlanes;46 unsigned int nlanes;
47 unsigned int port;47 unsigned int port;
48 unsigned int stream_count;
49};48};
50 49
51struct ipu6_isys_csi2_timing {50struct ipu6_isys_csi2_timing {
@@ -77,6 +76,5 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream, · 25 unmodified lines
77 struct ipu6_isys_csi2 *csi2,76 struct ipu6_isys_csi2 *csi2,
78 struct media_entity *source_entity,77 struct media_entity *source_entity,
79 struct v4l2_mbus_frame_desc_entry *entry);78 struct v4l2_mbus_frame_desc_entry *entry);
80void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status);
81 79
82#endif /* IPU6_ISYS_CSI2_H */80#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
551 stream->nr_queues);551 stream->nr_queues);
552 552
553 list_add(&aq->node, &stream->queues);553 list_add(&aq->node, &stream->queues);
554 ipu6_isys_set_csi2_streams_status(av, true);
555 ipu6_isys_configure_stream_watermark(av, true);554 ipu6_isys_configure_stream_watermark(av, true);
556 ipu6_isys_update_stream_watermark(av, true);555 ipu6_isys_update_stream_watermark(av, true);
557 556
@@ -598,8 +597,6 @@ static void stop_streaming(struct vb2_queue *q) · 40 unmodified lines
598 struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq);597 struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq);
599 struct ipu6_isys_stream *stream = av->stream;598 struct ipu6_isys_stream *stream = av->stream;
600 599
601 ipu6_isys_set_csi2_streams_status(av, false);
602
603 mutex_lock(&stream->mutex);600 mutex_lock(&stream->mutex);
604 601
605 ipu6_isys_update_stream_watermark(av, false);602 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
990 struct v4l2_subdev_state *subdev_state;990 struct v4l2_subdev_state *subdev_state;
991 struct device *dev = &av->isys->adev->auxdev.dev;991 struct device *dev = &av->isys->adev->auxdev.dev;
992 struct v4l2_subdev *sd;992 struct v4l2_subdev *sd;
993 struct v4l2_subdev *ssd;
994 struct media_pad *r_pad;993 struct media_pad *r_pad;
995 struct media_pad *s_pad;
996 u32 sink_pad, sink_stream;994 u32 sink_pad, sink_stream;
997 u64 r_stream;995 u64 r_stream;
998 u64 stream_mask = 0;996 u64 stream_mask = 0;
@@ -1003,7 +1001,6 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, · 4 unmodified lines
1003 if (WARN(!stream->source_entity, "No source entity for stream\n"))1001 if (WARN(!stream->source_entity, "No source entity for stream\n"))
1004 return -ENODEV;1002 return -ENODEV;
1005 1003
1006 ssd = media_entity_to_v4l2_subdev(stream->source_entity);
1007 sd = &stream->asd->sd;1004 sd = &stream->asd->sd;
1008 r_pad = media_pad_remote_pad_first(&av->pad);1005 r_pad = media_pad_remote_pad_first(&av->pad);
1009 r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index);1006 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
1017 if (ret)1014 if (ret)
1018 return ret;1015 return ret;
1019 1016
1020 s_pad = media_pad_remote_pad_first(&stream->asd->pad[sink_pad]);
1021
1022 stream_mask = get_stream_mask_by_pipeline(av);1017 stream_mask = get_stream_mask_by_pipeline(av);
1023 if (!state) {1018 if (!state) {
1024 stop_streaming_firmware(av);1019 stop_streaming_firmware(av);
1025 1020
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
1037 /* stop sub-device which connects with video */1021 /* stop sub-device which connects with video */
1038 dev_dbg(dev, "stream off entity %s pad:%d\n", sd->name,1022 dev_dbg(dev, "stream off entity %s pad:%d mask:0x%llx\n",
1039 r_pad->index);1023 sd->name, r_pad->index, stream_mask);
1040 ret = v4l2_subdev_call(sd, video, s_stream, state);1024 ret = v4l2_subdev_disable_streams(sd, r_pad->index,
1025 stream_mask);
1041 if (ret) {1026 if (ret) {
1042 dev_err(dev, "stream off %s failed with %d\n", sd->name,1027 dev_err(dev, "stream off %s failed with %d\n", sd->name,
1043 ret);1028 ret);
@@ -1052,34 +1037,20 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, · 8 unmodified lines
1052 }1037 }
1053 1038
1054 /* start sub-device which connects with video */1039 /* start sub-device which connects with video */
1055 dev_dbg(dev, "stream on %s pad %d\n", sd->name, r_pad->index);1040 dev_dbg(dev, "stream on %s pad %d mask 0x%llx\n", sd->name,
1056 ret = v4l2_subdev_call(sd, video, s_stream, state);1041 r_pad->index, stream_mask);
1042 ret = v4l2_subdev_enable_streams(sd, r_pad->index, stream_mask);
1057 if (ret) {1043 if (ret) {
1058 dev_err(dev, "stream on %s failed with %d\n", sd->name,1044 dev_err(dev, "stream on %s failed with %d\n", sd->name,
1059 ret);1045 ret);
1060 goto out_media_entity_stop_streaming_firmware;1046 goto out_media_entity_stop_streaming_firmware;
1061 }1047 }
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 }
1074 }1048 }
1075 1049
1076 av->streaming = state;1050 av->streaming = state;
1077 1051
1078 return 0;1052 return 0;
1079 1053
1080out_media_entity_stop_streaming:
1081 v4l2_subdev_disable_streams(sd, r_pad->index, BIT(r_stream));
1082
1083out_media_entity_stop_streaming_firmware:1054out_media_entity_stop_streaming_firmware:
1084 stop_streaming_firmware(av);1055 stop_streaming_firmware(av);
1085 1056
drivers/media/pci/intel/ivsc/mei_csi.c+15−9
@@ -126,6 +126,8 @@ struct mei_csi { · 125 unmodified lines
126 struct v4l2_ctrl_handler ctrl_handler;126 struct v4l2_ctrl_handler ctrl_handler;
127 struct v4l2_ctrl *freq_ctrl;127 struct v4l2_ctrl *freq_ctrl;
128 struct v4l2_ctrl *privacy_ctrl;128 struct v4l2_ctrl *privacy_ctrl;
129 /* lock for v4l2 controls */
130 struct mutex ctrl_lock;
129 unsigned int remote_pad;131 unsigned int remote_pad;
130 /* start streaming or not */132 /* start streaming or not */
131 int streaming;133 int streaming;
@@ -136,9 +138,6 @@ struct mei_csi { · 4 unmodified lines
136 u32 nr_of_lanes;138 u32 nr_of_lanes;
137 /* frequency of the CSI-2 link */139 /* frequency of the CSI-2 link */
138 u64 link_freq;140 u64 link_freq;
139
140 /* privacy status */
141 enum ivsc_privacy_status status;
142};141};
143 142
144static const struct v4l2_mbus_framefmt mei_csi_format_mbus_default = {143static 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
190 189
191 /* command response status */190 /* command response status */
192 ret = csi->cmd_response.status;191 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) {
194 ret = -EINVAL;197 ret = -EINVAL;
195 goto out;198 goto out;
196 }199 }
@@ -265,10 +268,9 @@ static void mei_csi_rx(struct mei_cl_device *cldev) · 68 unmodified lines
265 268
266 switch (notif.cmd_id) {269 switch (notif.cmd_id) {
267 case CSI_PRIVACY_NOTIF:270 case CSI_PRIVACY_NOTIF:
268 if (notif.cont.cont < CSI_PRIVACY_MAX) {271 if (notif.cont.cont < CSI_PRIVACY_MAX)
269 csi->status = notif.cont.cont;272 v4l2_ctrl_s_ctrl(csi->privacy_ctrl,
270 v4l2_ctrl_s_ctrl(csi->privacy_ctrl, csi->status);273 notif.cont.cont == CSI_PRIVACY_ON);
271 }
272 break;274 break;
273 case CSI_SET_OWNER:275 case CSI_SET_OWNER:
274 case CSI_SET_CONF:276 case CSI_SET_CONF:
@@ -559,11 +561,13 @@ static int mei_csi_init_controls(struct mei_csi *csi) · 284 unmodified lines
559 u32 max;561 u32 max;
560 int ret;562 int ret;
561 563
564 mutex_init(&csi->ctrl_lock);
565
562 ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 2);566 ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 2);
563 if (ret)567 if (ret)
564 return ret;568 return ret;
565 569
566 csi->ctrl_handler.lock = &csi->lock;570 csi->ctrl_handler.lock = &csi->ctrl_lock;
567 571
568 max = ARRAY_SIZE(link_freq_menu_items) - 1;572 max = ARRAY_SIZE(link_freq_menu_items) - 1;
569 csi->freq_ctrl = v4l2_ctrl_new_int_menu(&csi->ctrl_handler,573 csi->freq_ctrl = v4l2_ctrl_new_int_menu(&csi->ctrl_handler,
@@ -755,6 +759,7 @@ err_entity: · 185 unmodified lines
755 759
756err_ctrl_handler:760err_ctrl_handler:
757 v4l2_ctrl_handler_free(&csi->ctrl_handler);761 v4l2_ctrl_handler_free(&csi->ctrl_handler);
762 mutex_destroy(&csi->ctrl_lock);
758 v4l2_async_nf_unregister(&csi->notifier);763 v4l2_async_nf_unregister(&csi->notifier);
759 v4l2_async_nf_cleanup(&csi->notifier);764 v4l2_async_nf_cleanup(&csi->notifier);
760 765
@@ -774,6 +779,7 @@ static void mei_csi_remove(struct mei_cl_device *cldev) · 13 unmodified lines
774 v4l2_async_nf_unregister(&csi->notifier);779 v4l2_async_nf_unregister(&csi->notifier);
775 v4l2_async_nf_cleanup(&csi->notifier);780 v4l2_async_nf_cleanup(&csi->notifier);
776 v4l2_ctrl_handler_free(&csi->ctrl_handler);781 v4l2_ctrl_handler_free(&csi->ctrl_handler);
782 mutex_destroy(&csi->ctrl_lock);
777 v4l2_async_unregister_subdev(&csi->subdev);783 v4l2_async_unregister_subdev(&csi->subdev);
778 v4l2_subdev_cleanup(&csi->subdev);784 v4l2_subdev_cleanup(&csi->subdev);
779 media_entity_cleanup(&csi->subdev.entity);785 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
371 return 0;371 return 0;
372}372}
373 373
374/* Release ioremapped memory */
375static 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
401/* Hauppauge card? get values from tveeprom */374/* Hauppauge card? get values from tveeprom */
402void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv)375void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv)
403{376{
@@ -833,7 +806,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, · 429 unmodified lines
833 806
834 IVTV_DEBUG_INFO("Enabling pci device\n");807 IVTV_DEBUG_INFO("Enabling pci device\n");
835 808
836 if (pci_enable_device(pdev)) {809 if (pcim_enable_device(pdev)) {
837 IVTV_ERR("Can't enable device!\n");810 IVTV_ERR("Can't enable device!\n");
838 return -EIO;811 return -EIO;
839 }812 }
@@ -841,24 +814,24 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, · 1 unmodified line
841 IVTV_ERR("No suitable DMA available.\n");814 IVTV_ERR("No suitable DMA available.\n");
842 return -EIO;815 return -EIO;
843 }816 }
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")) {
845 IVTV_ERR("Cannot request encoder memory region.\n");819 IVTV_ERR("Cannot request encoder memory region.\n");
846 return -EIO;820 return -EIO;
847 }821 }
848 822
849 if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET,823 if (!devm_request_mem_region(&pdev->dev,
850 IVTV_REG_SIZE, "ivtv registers")) {824 itv->base_addr + IVTV_REG_OFFSET,
825 IVTV_REG_SIZE, "ivtv registers")) {
851 IVTV_ERR("Cannot request register memory region.\n");826 IVTV_ERR("Cannot request register memory region.\n");
852 release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
853 return -EIO;827 return -EIO;
854 }828 }
855 829
856 if (itv->has_cx23415 &&830 if (itv->has_cx23415 &&
857 !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,831 !devm_request_mem_region(&pdev->dev,
858 IVTV_DECODER_SIZE, "ivtv decoder")) {832 itv->base_addr + IVTV_DECODER_OFFSET,
833 IVTV_DECODER_SIZE, "ivtv decoder")) {
859 IVTV_ERR("Cannot request decoder memory region.\n");834 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);
862 return -EIO;835 return -EIO;
863 }836 }
864 837
@@ -870,11 +843,6 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, · 5 unmodified lines
870 pci_read_config_word(pdev, PCI_COMMAND, &cmd);843 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
871 if (!(cmd & PCI_COMMAND_MASTER)) {844 if (!(cmd & PCI_COMMAND_MASTER)) {
872 IVTV_ERR("Bus Mastering is not enabled\n");845 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);
878 return -ENXIO;846 return -ENXIO;
879 }847 }
880 }848 }
@@ -1033,37 +1001,37 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) · 152 unmodified lines
1033 1001
1034 /* PCI Device Setup */1002 /* PCI Device Setup */
1035 retval = ivtv_setup_pci(itv, pdev, pci_id);1003 retval = ivtv_setup_pci(itv, pdev, pci_id);
1036 if (retval == -EIO)1004 if (retval == -EIO || retval == -ENXIO)
1037 goto free_worker;1005 goto free_worker;
1038 if (retval == -ENXIO)
1039 goto free_mem;
1040 1006
1041 /* map io memory */1007 /* map io memory */
1042 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",1008 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
1043 (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE);1009 (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE);
1044 itv->enc_mem = ioremap(itv->base_addr + IVTV_ENCODER_OFFSET,1010 itv->enc_mem = devm_ioremap(&pdev->dev,
1045 IVTV_ENCODER_SIZE);1011 itv->base_addr + IVTV_ENCODER_OFFSET,
1012 IVTV_ENCODER_SIZE);
1046 if (!itv->enc_mem) {1013 if (!itv->enc_mem) {
1047 IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n");1014 IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n");
1048 IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of vmalloc address space for this window\n");1015 IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of vmalloc address space for this window\n");
1049 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");1016 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
1050 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");1017 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
1051 retval = -ENOMEM;1018 retval = -ENOMEM;
1052 goto free_mem;1019 goto free_worker;
1053 }1020 }
1054 1021
1055 if (itv->has_cx23415) {1022 if (itv->has_cx23415) {
1056 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",1023 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
1057 (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);1024 (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
1058 itv->dec_mem = ioremap(itv->base_addr + IVTV_DECODER_OFFSET,1025 itv->dec_mem = devm_ioremap(&pdev->dev,
1059 IVTV_DECODER_SIZE);1026 itv->base_addr + IVTV_DECODER_OFFSET,
1027 IVTV_DECODER_SIZE);
1060 if (!itv->dec_mem) {1028 if (!itv->dec_mem) {
1061 IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n");1029 IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n");
1062 IVTV_ERR("Each capture card with a CX23415 needs 8 MB of vmalloc address space for this window\n");1030 IVTV_ERR("Each capture card with a CX23415 needs 8 MB of vmalloc address space for this window\n");
1063 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");1031 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
1064 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");1032 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
1065 retval = -ENOMEM;1033 retval = -ENOMEM;
1066 goto free_mem;1034 goto free_worker;
1067 }1035 }
1068 }1036 }
1069 else {1037 else {
@@ -1073,26 +1041,27 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) · 3 unmodified lines
1073 /* map registers memory */1041 /* map registers memory */
1074 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",1042 IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
1075 (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);1043 (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
1076 itv->reg_mem =1044 itv->reg_mem = devm_ioremap(&pdev->dev,
1077 ioremap(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);1045 itv->base_addr + IVTV_REG_OFFSET,
1046 IVTV_REG_SIZE);
1078 if (!itv->reg_mem) {1047 if (!itv->reg_mem) {
1079 IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n");1048 IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n");
1080 IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n");1049 IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n");
1081 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");1050 IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
1082 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");1051 IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
1083 retval = -ENOMEM;1052 retval = -ENOMEM;
1084 goto free_io;1053 goto free_worker;
1085 }1054 }
1086 1055
1087 retval = ivtv_gpio_init(itv);1056 retval = ivtv_gpio_init(itv);
1088 if (retval)1057 if (retval)
1089 goto free_io;1058 goto free_worker;
1090 1059
1091 /* active i2c */1060 /* active i2c */
1092 IVTV_DEBUG_INFO("activating i2c...\n");1061 IVTV_DEBUG_INFO("activating i2c...\n");
1093 if (init_ivtv_i2c(itv)) {1062 if (init_ivtv_i2c(itv)) {
1094 IVTV_ERR("Could not initialize i2c\n");1063 IVTV_ERR("Could not initialize i2c\n");
1095 goto free_io;1064 goto free_worker;
1096 }1065 }
1097 1066
1098 if (itv->card->hw_all & IVTV_HW_TVEEPROM) {1067 if (itv->card->hw_all & IVTV_HW_TVEEPROM) {
@@ -1277,13 +1246,6 @@ free_irq: · 178 unmodified lines
1277free_i2c:1246free_i2c:
1278 v4l2_ctrl_handler_free(&itv->cxhdl.hdl);1247 v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
1279 exit_ivtv_i2c(itv);1248 exit_ivtv_i2c(itv);
1280free_io:
1281 ivtv_iounmap(itv);
1282free_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);
1287free_worker:1249free_worker:
1288 kthread_stop(itv->irq_worker_task);1250 kthread_stop(itv->irq_worker_task);
1289err:1251err:
@@ -1439,14 +1401,7 @@ static void ivtv_remove(struct pci_dev *pdev) · 149 unmodified lines
1439 exit_ivtv_i2c(itv);1401 exit_ivtv_i2c(itv);
1440 1402
1441 free_irq(itv->pdev->irq, (void *)itv);1403 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);
1448 1404
1449 pci_disable_device(itv->pdev);
1450 for (i = 0; i < IVTV_VBI_FRAMES; i++)1405 for (i = 0; i < IVTV_VBI_FRAMES; i++)
1451 kfree(itv->vbi.sliced_mpeg_data[i]);1406 kfree(itv->vbi.sliced_mpeg_data[i]);
1452 1407
drivers/media/pci/ivtv/ivtv-fileops.c+39−27
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#include "ivtv-ioctl.h"21#include "ivtv-ioctl.h"
22#include "ivtv-cards.h"22#include "ivtv-cards.h"
23#include "ivtv-firmware.h"23#include "ivtv-firmware.h"
24#include <linux/lockdep.h>
24#include <media/v4l2-event.h>25#include <media/v4l2-event.h>
25#include <media/i2c/saa7115.h>26#include <media/i2c/saa7115.h>
26 27
@@ -190,12 +191,27 @@ static void ivtv_update_pgm_info(struct ivtv *itv) · 163 unmodified lines
190 itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;191 itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
191}192}
192 193
194static 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
193static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err)210static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err)
194{211{
195 struct ivtv *itv = s->itv;212 struct ivtv *itv = s->itv;
196 struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];213 struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
197 struct ivtv_buffer *buf;214 struct ivtv_buffer *buf;
198 DEFINE_WAIT(wait);
199 215
200 *err = 0;216 *err = 0;
201 while (1) {217 while (1) {
@@ -258,13 +274,7 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, · 56 unmodified lines
258 }274 }
259 275
260 /* wait for more data to arrive */276 /* wait for more data to arrive */
261 mutex_unlock(&itv->serialize_lock);277 ivtv_schedule(s);
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);
268 if (signal_pending(current)) {278 if (signal_pending(current)) {
269 /* return if a signal was received */279 /* return if a signal was received */
270 IVTV_DEBUG_INFO("User stopped %s\n", s->name);280 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
533 return 0;543 return 0;
534}544}
535 545
546static 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
536static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)565static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
537{566{
538 struct ivtv_open_id *id = fh2id(filp->private_data);567 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
544 int bytes_written = 0;573 int bytes_written = 0;
545 int mode;574 int mode;
546 int rc;575 int rc;
547 DEFINE_WAIT(wait);
548 576
549 IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name);577 IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name);
550 578
@@ -618,13 +646,7 @@ retry: · 67 unmodified lines
618 break;646 break;
619 if (filp->f_flags & O_NONBLOCK)647 if (filp->f_flags & O_NONBLOCK)
620 return -EAGAIN;648 return -EAGAIN;
621 mutex_unlock(&itv->serialize_lock);649 ivtv_schedule(s);
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);
628 if (signal_pending(current)) {650 if (signal_pending(current)) {
629 IVTV_DEBUG_INFO("User stopped %s\n", s->name);651 IVTV_DEBUG_INFO("User stopped %s\n", s->name);
630 return -EINTR;652 return -EINTR;
@@ -674,20 +696,10 @@ retry: · 43 unmodified lines
674 696
675 if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) {697 if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) {
676 if (s->q_full.length >= itv->dma_data_req_size) {698 if (s->q_full.length >= itv->dma_data_req_size) {
677 int got_sig;
678
679 if (mode == OUT_YUV)699 if (mode == OUT_YUV)
680 ivtv_yuv_setup_stream_frame(itv);700 ivtv_yuv_setup_stream_frame(itv);
681 701
682 mutex_unlock(&itv->serialize_lock);702 if (ivtv_schedule_dma(s)) {
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) {
691 IVTV_DEBUG_INFO("User interrupted %s\n", s->name);703 IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
692 return -EINTR;704 return -EINTR;
693 }705 }
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
131 131
132 /* Fill SG List with new values */132 /* Fill SG List with new values */
133 if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) {133 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__);
134 unpin_user_pages(dma->map, dma->page_count);136 unpin_user_pages(dma->map, dma->page_count);
135 dma->page_count = 0;137 dma->page_count = 0;
136 return -ENOMEM;138 return -ENOMEM;
@@ -139,6 +141,12 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, · 2 unmodified lines
139 /* Map SG List */141 /* Map SG List */
140 dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,142 dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
141 dma->page_count, DMA_TO_DEVICE);143 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 }
142 150
143 /* Fill SG Array with new values */151 /* Fill SG Array with new values */
144 ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1);152 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
114 }114 }
115 dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,115 dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
116 dma->page_count, DMA_TO_DEVICE);116 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 }
117 123
118 /* Fill SG Array with new values */124 /* Fill SG Array with new values */
119 ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);125 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
104 "\t\t\tdefault 640");104 "\t\t\tdefault 640");
105 105
106MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");106MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
107MODULE_DESCRIPTION("Conexant cx23415 framebuffer support");
107MODULE_LICENSE("GPL");108MODULE_LICENSE("GPL");
108 109
109/* --------------------------------------------------------------------- */110/* --------------------------------------------------------------------- */
@@ -281,10 +282,10 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, · 171 unmodified lines
281 /* Map User DMA */282 /* Map User DMA */
282 if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {283 if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
283 mutex_unlock(&itv->udma.lock);284 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 IVTVFB_WARN("%s, Error in ivtv_udma_setup: %d bytes, %d pages returned\n",
285 size_in_bytes, itv->udma.page_count);286 __func__, size_in_bytes, itv->udma.page_count);
286 287
287 /* pin_user_pages must have failed completely */288 /* pin_user_pages or DMA must have failed completely */
288 return -EIO;289 return -EIO;
289 }290 }
290 291
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
116 if (stat & MANTIS_INT_RISCI) {116 if (stat & MANTIS_INT_RISCI) {
117 dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);117 dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
118 mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;118 mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
119 tasklet_schedule(&mantis->tasklet);119 queue_work(system_bh_wq, &mantis->bh_work);
120 }120 }
121 if (stat & MANTIS_INT_I2CDONE) {121 if (stat & MANTIS_INT_I2CDONE) {
122 dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);122 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
125 if (stat & MANTIS_INT_RISCI) {125 if (stat & MANTIS_INT_RISCI) {
126 dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);126 dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
127 mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;127 mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
128 tasklet_schedule(&mantis->tasklet);128 queue_work(system_bh_wq, &mantis->bh_work);
129 }129 }
130 if (stat & MANTIS_INT_I2CDONE) {130 if (stat & MANTIS_INT_I2CDONE) {
131 dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);131 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
125 __le32 *risc_cpu;125 __le32 *risc_cpu;
126 dma_addr_t risc_dma;126 dma_addr_t risc_dma;
127 127
128 struct tasklet_struct tasklet;128 struct work_struct bh_work;
129 spinlock_t intmask_lock;129 spinlock_t intmask_lock;
130 130
131 struct i2c_adapter adapter;131 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
200}200}
201 201
202 202
203void mantis_dma_xfer(struct tasklet_struct *t)203void mantis_dma_xfer(struct work_struct *t)
204{204{
205 struct mantis_pci *mantis = from_tasklet(mantis, t, tasklet);205 struct mantis_pci *mantis = from_work(mantis, t, bh_work);
206 struct mantis_hwconfig *config = mantis->hwconfig;206 struct mantis_hwconfig *config = mantis->hwconfig;
207 207
208 while (mantis->last_block != mantis->busy_block) {208 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
13extern int mantis_dma_exit(struct mantis_pci *mantis);13extern int mantis_dma_exit(struct mantis_pci *mantis);
14extern void mantis_dma_start(struct mantis_pci *mantis);14extern void mantis_dma_start(struct mantis_pci *mantis);
15extern void mantis_dma_stop(struct mantis_pci *mantis);15extern void mantis_dma_stop(struct mantis_pci *mantis);
16extern void mantis_dma_xfer(struct tasklet_struct *t);16extern void mantis_dma_xfer(struct work_struct *t);
17 17
18#endif /* __MANTIS_DMA_H */18#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
105 if (mantis->feeds == 1) {105 if (mantis->feeds == 1) {
106 dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");106 dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
107 mantis_dma_start(mantis);107 mantis_dma_start(mantis);
108 tasklet_enable(&mantis->tasklet);108 enable_and_queue_work(system_bh_wq, &mantis->bh_work);
109 }109 }
110 110
111 return mantis->feeds;111 return mantis->feeds;
@@ -125,7 +125,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) · 13 unmodified lines
125 mantis->feeds--;125 mantis->feeds--;
126 if (mantis->feeds == 0) {126 if (mantis->feeds == 0) {
127 dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");127 dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
128 tasklet_disable(&mantis->tasklet);128 disable_work_sync(&mantis->bh_work);
129 mantis_dma_stop(mantis);129 mantis_dma_stop(mantis);
130 }130 }
131 131
@@ -205,8 +205,8 @@ int mantis_dvb_init(struct mantis_pci *mantis) · 73 unmodified lines
205 }205 }
206 206
207 dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);207 dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
208 tasklet_setup(&mantis->tasklet, mantis_dma_xfer);208 INIT_WORK(&mantis->bh_work, mantis_dma_xfer);
209 tasklet_disable(&mantis->tasklet);209 disable_work_sync(&mantis->bh_work);
210 if (mantis->hwconfig) {210 if (mantis->hwconfig) {
211 result = config->frontend_init(mantis, mantis->fe);211 result = config->frontend_init(mantis, mantis->fe);
212 if (result < 0) {212 if (result < 0) {
@@ -235,7 +235,7 @@ int mantis_dvb_init(struct mantis_pci *mantis) · 22 unmodified lines
235 235
236 /* Error conditions .. */236 /* Error conditions .. */
237err5:237err5:
238 tasklet_kill(&mantis->tasklet);238 cancel_work_sync(&mantis->bh_work);
239 dvb_net_release(&mantis->dvbnet);239 dvb_net_release(&mantis->dvbnet);
240 if (mantis->fe) {240 if (mantis->fe) {
241 dvb_unregister_frontend(mantis->fe);241 dvb_unregister_frontend(mantis->fe);
@@ -273,7 +273,7 @@ int mantis_dvb_exit(struct mantis_pci *mantis) · 31 unmodified lines
273 dvb_frontend_detach(mantis->fe);273 dvb_frontend_detach(mantis->fe);
274 }274 }
275 275
276 tasklet_kill(&mantis->tasklet);276 cancel_work_sync(&mantis->bh_work);
277 dvb_net_release(&mantis->dvbnet);277 dvb_net_release(&mantis->dvbnet);
278 278
279 mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);279 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
50/* nGene interrupt handler **************************************************/50/* nGene interrupt handler **************************************************/
51/****************************************************************************/51/****************************************************************************/
52 52
53static void event_tasklet(struct tasklet_struct *t)53static void event_bh_work(struct work_struct *t)
54{54{
55 struct ngene *dev = from_tasklet(dev, t, event_tasklet);55 struct ngene *dev = from_work(dev, t, event_bh_work);
56 56
57 while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) {57 while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) {
58 struct EVENT_BUFFER Event =58 struct EVENT_BUFFER Event =
@@ -68,9 +68,9 @@ static void event_tasklet(struct tasklet_struct *t) · 9 unmodified lines
68 }68 }
69}69}
70 70
71static void demux_tasklet(struct tasklet_struct *t)71static void demux_bh_work(struct work_struct *t)
72{72{
73 struct ngene_channel *chan = from_tasklet(chan, t, demux_tasklet);73 struct ngene_channel *chan = from_work(chan, t, demux_bh_work);
74 struct device *pdev = &chan->dev->pci_dev->dev;74 struct device *pdev = &chan->dev->pci_dev->dev;
75 struct SBufferHeader *Cur = chan->nextBuffer;75 struct SBufferHeader *Cur = chan->nextBuffer;
76 76
@@ -204,7 +204,7 @@ static irqreturn_t irq_handler(int irq, void *dev_id) · 127 unmodified lines
204 dev->EventQueueOverflowFlag = 1;204 dev->EventQueueOverflowFlag = 1;
205 }205 }
206 dev->EventBuffer->EventStatus &= ~0x80;206 dev->EventBuffer->EventStatus &= ~0x80;
207 tasklet_schedule(&dev->event_tasklet);207 queue_work(system_bh_wq, &dev->event_bh_work);
208 rc = IRQ_HANDLED;208 rc = IRQ_HANDLED;
209 }209 }
210 210
@@ -217,8 +217,8 @@ static irqreturn_t irq_handler(int irq, void *dev_id) · 6 unmodified lines
217 ngeneBuffer.SR.Flags & 0xC0) == 0x80) {217 ngeneBuffer.SR.Flags & 0xC0) == 0x80) {
218 dev->channel[i].nextBuffer->218 dev->channel[i].nextBuffer->
219 ngeneBuffer.SR.Flags |= 0x40;219 ngeneBuffer.SR.Flags |= 0x40;
220 tasklet_schedule(220 queue_work(system_bh_wq,
221 &dev->channel[i].demux_tasklet);221 &dev->channel[i].demux_bh_work);
222 rc = IRQ_HANDLED;222 rc = IRQ_HANDLED;
223 }223 }
224 }224 }
@@ -1181,7 +1181,7 @@ static void ngene_init(struct ngene *dev) · 956 unmodified lines
1181 struct device *pdev = &dev->pci_dev->dev;1181 struct device *pdev = &dev->pci_dev->dev;
1182 int i;1182 int i;
1183 1183
1184 tasklet_setup(&dev->event_tasklet, event_tasklet);1184 INIT_WORK(&dev->event_bh_work, event_bh_work);
1185 1185
1186 memset_io(dev->iomem + 0xc000, 0x00, 0x220);1186 memset_io(dev->iomem + 0xc000, 0x00, 0x220);
1187 memset_io(dev->iomem + 0xc400, 0x00, 0x100);1187 memset_io(dev->iomem + 0xc400, 0x00, 0x100);
@@ -1395,7 +1395,7 @@ static void release_channel(struct ngene_channel *chan) · 207 unmodified lines
1395 if (chan->running)1395 if (chan->running)
1396 set_transfer(chan, 0);1396 set_transfer(chan, 0);
1397 1397
1398 tasklet_kill(&chan->demux_tasklet);1398 cancel_work_sync(&chan->demux_bh_work);
1399 1399
1400 if (chan->ci_dev) {1400 if (chan->ci_dev) {
1401 dvb_unregister_device(chan->ci_dev);1401 dvb_unregister_device(chan->ci_dev);
@@ -1445,7 +1445,7 @@ static int init_channel(struct ngene_channel *chan) · 43 unmodified lines
1445 struct ngene_info *ni = dev->card_info;1445 struct ngene_info *ni = dev->card_info;
1446 int io = ni->io_type[nr];1446 int io = ni->io_type[nr];
1447 1447
1448 tasklet_setup(&chan->demux_tasklet, demux_tasklet);1448 INIT_WORK(&chan->demux_bh_work, demux_bh_work);
1449 chan->users = 0;1449 chan->users = 0;
1450 chan->type = io;1450 chan->type = io;
1451 chan->mode = chan->type; /* for now only one mode */1451 chan->mode = chan->type; /* for now only one mode */
@@ -1649,7 +1649,7 @@ void ngene_remove(struct pci_dev *pdev) · 197 unmodified lines
1649 struct ngene *dev = pci_get_drvdata(pdev);1649 struct ngene *dev = pci_get_drvdata(pdev);
1650 int i;1650 int i;
1651 1651
1652 tasklet_kill(&dev->event_tasklet);1652 cancel_work_sync(&dev->event_bh_work);
1653 for (i = MAX_STREAM - 1; i >= 0; i--)1653 for (i = MAX_STREAM - 1; i >= 0; i--)
1654 release_channel(&dev->channel[i]);1654 release_channel(&dev->channel[i]);
1655 if (dev->ci.en)1655 if (dev->ci.en)
drivers/media/pci/ngene/ngene.h+3−2
@@ -16,6 +16,7 @@ · 15 unmodified lines
16#include <linux/scatterlist.h>16#include <linux/scatterlist.h>
17 17
18#include <linux/dvb/frontend.h>18#include <linux/dvb/frontend.h>
19#include <linux/workqueue.h>
19 20
20#include <media/dmxdev.h>21#include <media/dmxdev.h>
21#include <media/dvbdev.h>22#include <media/dvbdev.h>
@@ -621,7 +622,7 @@ struct ngene_channel { · 599 unmodified lines
621 int users;622 int users;
622 struct video_device *v4l_dev;623 struct video_device *v4l_dev;
623 struct dvb_device *ci_dev;624 struct dvb_device *ci_dev;
624 struct tasklet_struct demux_tasklet;625 struct work_struct demux_bh_work;
625 626
626 struct SBufferHeader *nextBuffer;627 struct SBufferHeader *nextBuffer;
627 enum KSSTATE State;628 enum KSSTATE State;
@@ -717,7 +718,7 @@ struct ngene { · 89 unmodified lines
717 struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE];718 struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE];
718 int EventQueueOverflowCount;719 int EventQueueOverflowCount;
719 int EventQueueOverflowFlag;720 int EventQueueOverflowFlag;
720 struct tasklet_struct event_tasklet;721 struct work_struct event_bh_work;
721 struct EVENT_BUFFER *EventBuffer;722 struct EVENT_BUFFER *EventBuffer;
722 int EventQueueWriteIndex;723 int EventQueueWriteIndex;
723 int EventQueueReadIndex;724 int EventQueueReadIndex;
drivers/media/pci/saa7134/saa7134-alsa.c+1−0
@@ -1254,5 +1254,6 @@ static void saa7134_alsa_exit(void) · 1253 unmodified lines
1254/* We initialize this late, to make sure the sound system is up and running */1254/* We initialize this late, to make sure the sound system is up and running */
1255late_initcall(saa7134_alsa_init);1255late_initcall(saa7134_alsa_init);
1256module_exit(saa7134_alsa_exit);1256module_exit(saa7134_alsa_exit);
1257MODULE_DESCRIPTION("Philips SAA7134 DMA audio support");
1257MODULE_LICENSE("GPL");1258MODULE_LICENSE("GPL");
1258MODULE_AUTHOR("Ricardo Cerqueira");1259MODULE_AUTHOR("Ricardo Cerqueira");
drivers/media/pci/saa7134/saa7134-dvb.c+7−2
@@ -52,6 +52,7 @@ · 51 unmodified lines
52#include "s5h1411.h"52#include "s5h1411.h"
53 53
54MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");54MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
55MODULE_DESCRIPTION("DVB/ATSC Support for saa7134 based TV cards");
55MODULE_LICENSE("GPL");56MODULE_LICENSE("GPL");
56 57
57static unsigned int antenna_pwr;58static unsigned int antenna_pwr;
@@ -466,7 +467,9 @@ static int philips_europa_tuner_sleep(struct dvb_frontend *fe) · 408 unmodified lines
466 /* switch the board to analog mode */467 /* switch the board to analog mode */
467 if (fe->ops.i2c_gate_ctrl)468 if (fe->ops.i2c_gate_ctrl)
468 fe->ops.i2c_gate_ctrl(fe, 1);469 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
470 return 0;473 return 0;
471}474}
472 475
@@ -1018,7 +1021,9 @@ static int md8800_set_voltage2(struct dvb_frontend *fe, · 545 unmodified lines
1018 else1021 else
1019 wbuf[1] = rbuf & 0xef;1022 wbuf[1] = rbuf & 0xef;
1020 msg[0].len = 2;1023 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
1022 return 0;1027 return 0;
1023}1028}
1024 1029
drivers/media/pci/saa7134/saa7134-empress.c+1−0
@@ -19,6 +19,7 @@ · 18 unmodified lines
19/* ------------------------------------------------------------------ */19/* ------------------------------------------------------------------ */
20 20
21MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");21MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
22MODULE_DESCRIPTION("Philips SAA7134 empress support");
22MODULE_LICENSE("GPL");23MODULE_LICENSE("GPL");
23 24
24static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };25static 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
516module_init(saa7134_go7007_mod_init);516module_init(saa7134_go7007_mod_init);
517module_exit(saa7134_go7007_mod_cleanup);517module_exit(saa7134_go7007_mod_cleanup);
518 518
519MODULE_DESCRIPTION("go7007 support for saa7134 based TV cards");
519MODULE_LICENSE("GPL v2");520MODULE_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
279 (port->_dmaInterruptCH0 | port->_dmaInterruptCH1));279 (port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
280}280}
281 281
282/* tasklet handler: DMA data to dmx.*/282/* BH work handler: DMA data to dmx.*/
283static void smi_dma_xfer(struct tasklet_struct *t)283static void smi_dma_xfer(struct work_struct *t)
284{284{
285 struct smi_port *port = from_tasklet(port, t, tasklet);285 struct smi_port *port = from_work(port, t, bh_work);
286 struct smi_dev *dev = port->dev;286 struct smi_dev *dev = port->dev;
287 u32 intr_status, finishedData, dmaManagement;287 u32 intr_status, finishedData, dmaManagement;
288 u8 dmaChan0State, dmaChan1State;288 u8 dmaChan0State, dmaChan1State;
@@ -426,8 +426,8 @@ static int smi_port_init(struct smi_port *port, int dmaChanUsed) · 137 unmodified lines
426 }426 }
427 427
428 smi_port_disableInterrupt(port);428 smi_port_disableInterrupt(port);
429 tasklet_setup(&port->tasklet, smi_dma_xfer);429 INIT_WORK(&port->bh_work, smi_dma_xfer);
430 tasklet_disable(&port->tasklet);430 disable_work_sync(&port->bh_work);
431 port->enable = 1;431 port->enable = 1;
432 return 0;432 return 0;
433err:433err:
@@ -438,7 +438,7 @@ err: · 4 unmodified lines
438static void smi_port_exit(struct smi_port *port)438static void smi_port_exit(struct smi_port *port)
439{439{
440 smi_port_disableInterrupt(port);440 smi_port_disableInterrupt(port);
441 tasklet_kill(&port->tasklet);441 cancel_work_sync(&port->bh_work);
442 smi_port_dma_free(port);442 smi_port_dma_free(port);
443 port->enable = 0;443 port->enable = 0;
444}444}
@@ -452,7 +452,7 @@ static int smi_port_irq(struct smi_port *port, u32 int_status) · 7 unmodified lines
452 smi_port_disableInterrupt(port);452 smi_port_disableInterrupt(port);
453 port->_int_status = int_status;453 port->_int_status = int_status;
454 smi_port_clearInterrupt(port);454 smi_port_clearInterrupt(port);
455 tasklet_schedule(&port->tasklet);455 queue_work(system_bh_wq, &port->bh_work);
456 handled = 1;456 handled = 1;
457 }457 }
458 return handled;458 return handled;
@@ -823,7 +823,7 @@ static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed) · 364 unmodified lines
823 smi_port_clearInterrupt(port);823 smi_port_clearInterrupt(port);
824 smi_port_enableInterrupt(port);824 smi_port_enableInterrupt(port);
825 smi_write(port->DMA_MANAGEMENT, dmaManagement);825 smi_write(port->DMA_MANAGEMENT, dmaManagement);
826 tasklet_enable(&port->tasklet);826 enable_and_queue_work(system_bh_wq, &port->bh_work);
827 }827 }
828 return port->users;828 return port->users;
829}829}
@@ -837,7 +837,7 @@ static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed) · 7 unmodified lines
837 if (--port->users)837 if (--port->users)
838 return port->users;838 return port->users;
839 839
840 tasklet_disable(&port->tasklet);840 disable_work_sync(&port->bh_work);
841 smi_port_disableInterrupt(port);841 smi_port_disableInterrupt(port);
842 smi_clear(port->DMA_MANAGEMENT, 0x30003);842 smi_clear(port->DMA_MANAGEMENT, 0x30003);
843 return 0;843 return 0;
drivers/media/pci/smipcie/smipcie.h+2−1
@@ -17,6 +17,7 @@ · 16 unmodified lines
17#include <linux/pci.h>17#include <linux/pci.h>
18#include <linux/dma-mapping.h>18#include <linux/dma-mapping.h>
19#include <linux/slab.h>19#include <linux/slab.h>
20#include <linux/workqueue.h>
20#include <media/rc-core.h>21#include <media/rc-core.h>
21 22
22#include <media/demux.h>23#include <media/demux.h>
@@ -257,7 +258,7 @@ struct smi_port { · 234 unmodified lines
257 u32 _dmaInterruptCH0;258 u32 _dmaInterruptCH0;
258 u32 _dmaInterruptCH1;259 u32 _dmaInterruptCH1;
259 u32 _int_status;260 u32 _int_status;
260 struct tasklet_struct tasklet;261 struct work_struct bh_work;
261 /* dvb */262 /* dvb */
262 struct dmx_frontend hw_frontend;263 struct dmx_frontend hw_frontend;
263 struct dmx_frontend mem_frontend;264 struct dmx_frontend mem_frontend;
drivers/media/pci/ttpci/budget-av.c+2−1
@@ -36,6 +36,7 @@ · 35 unmodified lines
36#include <linux/interrupt.h>36#include <linux/interrupt.h>
37#include <linux/input.h>37#include <linux/input.h>
38#include <linux/spinlock.h>38#include <linux/spinlock.h>
39#include <linux/workqueue.h>
39 40
40#include <media/dvb_ca_en50221.h>41#include <media/dvb_ca_en50221.h>
41 42
@@ -54,7 +55,7 @@ struct budget_av { · 12 unmodified lines
54 struct video_device vd;55 struct video_device vd;
55 int cur_input;56 int cur_input;
56 int has_saa7113;57 int has_saa7113;
57 struct tasklet_struct ciintf_irq_tasklet;58 struct work_struct ciintf_irq_bh_work;
58 int slot_status;59 int slot_status;
59 struct dvb_ca_en50221 ca;60 struct dvb_ca_en50221 ca;
60 u8 reinitialise_demod:1;61 u8 reinitialise_demod:1;
drivers/media/pci/ttpci/budget-ci.c+14−13
@@ -18,6 +18,7 @@ · 17 unmodified lines
18#include <linux/slab.h>18#include <linux/slab.h>
19#include <linux/interrupt.h>19#include <linux/interrupt.h>
20#include <linux/spinlock.h>20#include <linux/spinlock.h>
21#include <linux/workqueue.h>
21#include <media/rc-core.h>22#include <media/rc-core.h>
22 23
23#include "budget.h"24#include "budget.h"
@@ -81,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); · 57 unmodified lines
81 82
82struct budget_ci_ir {83struct budget_ci_ir {
83 struct rc_dev *dev;84 struct rc_dev *dev;
84 struct tasklet_struct msp430_irq_tasklet;85 struct work_struct msp430_irq_bh_work;
85 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */86 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
86 char phys[32];87 char phys[32];
87 int rc5_device;88 int rc5_device;
@@ -92,7 +93,7 @@ struct budget_ci_ir { · 4 unmodified lines
92 93
93struct budget_ci {94struct budget_ci {
94 struct budget budget;95 struct budget budget;
95 struct tasklet_struct ciintf_irq_tasklet;96 struct work_struct ciintf_irq_bh_work;
96 int slot_status;97 int slot_status;
97 int ci_irq;98 int ci_irq;
98 struct dvb_ca_en50221 ca;99 struct dvb_ca_en50221 ca;
@@ -100,9 +101,9 @@ struct budget_ci { · 1 unmodified line
100 u8 tuner_pll_address; /* used for philips_tdm1316l configs */101 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
101};102};
102 103
103static void msp430_ir_interrupt(struct tasklet_struct *t)104static void msp430_ir_interrupt(struct work_struct *t)
104{105{
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);
106 struct budget_ci *budget_ci = container_of(ir, typeof(*budget_ci), ir);107 struct budget_ci *budget_ci = container_of(ir, typeof(*budget_ci), ir);
107 struct rc_dev *dev = budget_ci->ir.dev;108 struct rc_dev *dev = budget_ci->ir.dev;
108 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;109 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
231 232
232 budget_ci->ir.dev = dev;233 budget_ci->ir.dev = dev;
233 234
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);
235 236
236 SAA7146_IER_ENABLE(saa, MASK_06);237 SAA7146_IER_ENABLE(saa, MASK_06);
237 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);238 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
@@ -245,7 +246,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) · 7 unmodified lines
245 246
246 SAA7146_IER_DISABLE(saa, MASK_06);247 SAA7146_IER_DISABLE(saa, MASK_06);
247 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);248 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);
249 250
250 rc_unregister_device(budget_ci->ir.dev);251 rc_unregister_device(budget_ci->ir.dev);
251}252}
@@ -349,10 +350,10 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) · 97 unmodified lines
349 return 0;350 return 0;
350}351}
351 352
352static void ciintf_interrupt(struct tasklet_struct *t)353static void ciintf_interrupt(struct work_struct *t)
353{354{
354 struct budget_ci *budget_ci = from_tasklet(budget_ci, t,355 struct budget_ci *budget_ci = from_work(budget_ci, t,
355 ciintf_irq_tasklet);356 ciintf_irq_bh_work);
356 struct saa7146_dev *saa = budget_ci->budget.dev;357 struct saa7146_dev *saa = budget_ci->budget.dev;
357 unsigned int flags;358 unsigned int flags;
358 359
@@ -491,7 +492,7 @@ static int ciintf_init(struct budget_ci *budget_ci) · 132 unmodified lines
491 492
492 // Setup CI slot IRQ493 // Setup CI slot IRQ
493 if (budget_ci->ci_irq) {494 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);
495 if (budget_ci->slot_status != SLOTSTATUS_NONE)496 if (budget_ci->slot_status != SLOTSTATUS_NONE)
496 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);497 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
497 else498 else
@@ -530,7 +531,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci) · 32 unmodified lines
530 if (budget_ci->ci_irq) {531 if (budget_ci->ci_irq) {
531 SAA7146_IER_DISABLE(saa, MASK_03);532 SAA7146_IER_DISABLE(saa, MASK_03);
532 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);533 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);
534 }535 }
535 536
536 // reset interface537 // reset interface
@@ -556,13 +557,13 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 *isr) · 19 unmodified lines
556 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);557 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
557 558
558 if (*isr & MASK_06)559 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);
560 561
561 if (*isr & MASK_10)562 if (*isr & MASK_10)
562 ttpci_budget_irq10_handler(dev, isr);563 ttpci_budget_irq10_handler(dev, isr);
563 564
564 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))565 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);
566}567}
567 568
568static u8 philips_su1278_tt_inittab[] = {569static 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
172 return ret;172 return ret;
173}173}
174 174
175static void vpeirq(struct tasklet_struct *t)175static void vpeirq(struct work_struct *t)
176{176{
177 struct budget *budget = from_tasklet(budget, t, vpe_tasklet);177 struct budget *budget = from_work(budget, t, vpe_bh_work);
178 u8 *mem = (u8 *) (budget->grabbing);178 u8 *mem = (u8 *) (budget->grabbing);
179 u32 olddma = budget->ttbp;179 u32 olddma = budget->ttbp;
180 u32 newdma = saa7146_read(budget->dev, PCI_VDP3);180 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
525 /* upload all */525 /* upload all */
526 saa7146_write(dev, GPIO_CTRL, 0x000000);526 saa7146_write(dev, GPIO_CTRL, 0x000000);
527 527
528 tasklet_setup(&budget->vpe_tasklet, vpeirq);528 INIT_WORK(&budget->vpe_bh_work, vpeirq);
529 529
530 /* frontend power on */530 /* frontend power on */
531 if (bi->type != BUDGET_FS_ACTIVY)531 if (bi->type != BUDGET_FS_ACTIVY)
@@ -565,7 +565,7 @@ int ttpci_budget_deinit(struct budget *budget) · 33 unmodified lines
565 565
566 budget_unregister(budget);566 budget_unregister(budget);
567 567
568 tasklet_kill(&budget->vpe_tasklet);568 cancel_work_sync(&budget->vpe_bh_work);
569 569
570 saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);570 saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
571 571
@@ -584,7 +584,7 @@ void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 *isr) · 12 unmodified lines
584 dprintk(8, "dev: %p, budget: %p\n", dev, budget);584 dprintk(8, "dev: %p, budget: %p\n", dev, budget);
585 585
586 if (*isr & MASK_10)586 if (*isr & MASK_10)
587 tasklet_schedule(&budget->vpe_tasklet);587 queue_work(system_bh_wq, &budget->vpe_bh_work);
588}588}
589EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);589EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
590 590
@@ -602,4 +602,5 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) · 11 unmodified lines
602}602}
603EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);603EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
604 604
605MODULE_DESCRIPTION("base driver for the SAA7146 based Budget DVB cards");
605MODULE_LICENSE("GPL");606MODULE_LICENSE("GPL");
drivers/media/pci/ttpci/budget.h+3−2
@@ -18,6 +18,7 @@ · 17 unmodified lines
18 18
19#include <linux/module.h>19#include <linux/module.h>
20#include <linux/mutex.h>20#include <linux/mutex.h>
21#include <linux/workqueue.h>
21 22
22#include <media/drv-intf/saa7146.h>23#include <media/drv-intf/saa7146.h>
23 24
@@ -54,8 +55,8 @@ struct budget { · 30 unmodified lines
54 unsigned char *grabbing;55 unsigned char *grabbing;
55 struct saa7146_pgtable pt;56 struct saa7146_pgtable pt;
56 57
57 struct tasklet_struct fidb_tasklet;58 struct work_struct fidb_bh_work;
58 struct tasklet_struct vpe_tasklet;59 struct work_struct vpe_bh_work;
59 60
60 struct dmxdev dmxdev;61 struct dmxdev dmxdev;
61 struct dvb_demux demux;62 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
144 cur_frame->gop_seqno = input->frame_gop_seqno;144 cur_frame->gop_seqno = input->frame_gop_seqno;
145 145
146 dev->h264_buf_w_index = next_frame_index;146 dev->h264_buf_w_index = next_frame_index;
147 tasklet_schedule(&dev->tasklet);147 queue_work(system_bh_wq, &dev->bh_work);
148 148
149 cur_frame = next_frame;149 cur_frame = next_frame;
150 150
drivers/media/pci/tw5864/tw5864-video.c+7−6
@@ -6,6 +6,7 @@ · 5 unmodified lines
6 */6 */
7 7
8#include <linux/module.h>8#include <linux/module.h>
9#include <linux/workqueue.h>
9#include <media/v4l2-common.h>10#include <media/v4l2-common.h>
10#include <media/v4l2-event.h>11#include <media/v4l2-event.h>
11#include <media/videobuf2-dma-contig.h>12#include <media/videobuf2-dma-contig.h>
@@ -175,7 +176,7 @@ static const unsigned int intra4x4_lambda3[] = { · 163 unmodified lines
175static v4l2_std_id tw5864_get_v4l2_std(enum tw5864_vid_std std);176static v4l2_std_id tw5864_get_v4l2_std(enum tw5864_vid_std std);
176static enum tw5864_vid_std tw5864_from_v4l2_std(v4l2_std_id v4l2_std);177static enum tw5864_vid_std tw5864_from_v4l2_std(v4l2_std_id v4l2_std);
177 178
178static void tw5864_handle_frame_task(struct tasklet_struct *t);179static void tw5864_handle_frame_work(struct work_struct *t);
179static void tw5864_handle_frame(struct tw5864_h264_frame *frame);180static void tw5864_handle_frame(struct tw5864_h264_frame *frame);
180static void tw5864_frame_interval_set(struct tw5864_input *input);181static void tw5864_frame_interval_set(struct tw5864_input *input);
181 182
@@ -1062,7 +1063,7 @@ int tw5864_video_init(struct tw5864_dev *dev, int *video_nr) · 880 unmodified lines
1062 dev->irqmask |= TW5864_INTR_VLC_DONE | TW5864_INTR_TIMER;1063 dev->irqmask |= TW5864_INTR_VLC_DONE | TW5864_INTR_TIMER;
1063 tw5864_irqmask_apply(dev);1064 tw5864_irqmask_apply(dev);
1064 1065
1065 tasklet_setup(&dev->tasklet, tw5864_handle_frame_task);1066 INIT_WORK(&dev->bh_work, tw5864_handle_frame_work);
1066 1067
1067 for (i = 0; i < TW5864_INPUTS; i++) {1068 for (i = 0; i < TW5864_INPUTS; i++) {
1068 dev->inputs[i].root = dev;1069 dev->inputs[i].root = dev;
@@ -1079,7 +1080,7 @@ fini_video_inputs: · 10 unmodified lines
1079 for (i = last_input_nr_registered; i >= 0; i--)1080 for (i = last_input_nr_registered; i >= 0; i--)
1080 tw5864_video_input_fini(&dev->inputs[i]);1081 tw5864_video_input_fini(&dev->inputs[i]);
1081 1082
1082 tasklet_kill(&dev->tasklet);1083 cancel_work_sync(&dev->bh_work);
1083 1084
1084free_dma:1085free_dma:
1085 for (i = last_dma_allocated; i >= 0; i--) {1086 for (i = last_dma_allocated; i >= 0; i--) {
@@ -1198,7 +1199,7 @@ void tw5864_video_fini(struct tw5864_dev *dev) · 112 unmodified lines
1198{1199{
1199 int i;1200 int i;
1200 1201
1201 tasklet_kill(&dev->tasklet);1202 cancel_work_sync(&dev->bh_work);
1202 1203
1203 for (i = 0; i < TW5864_INPUTS; i++)1204 for (i = 0; i < TW5864_INPUTS; i++)
1204 tw5864_video_input_fini(&dev->inputs[i]);1205 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
1315 return detected;1316 return detected;
1316}1317}
1317 1318
1318static void tw5864_handle_frame_task(struct tasklet_struct *t)1319static void tw5864_handle_frame_work(struct work_struct *t)
1319{1320{
1320 struct tw5864_dev *dev = from_tasklet(dev, t, tasklet);1321 struct tw5864_dev *dev = from_work(dev, t, bh_work);
1321 unsigned long flags;1322 unsigned long flags;
1322 int batch_size = H264_BUF_CNT;1323 int batch_size = H264_BUF_CNT;
1323 1324
drivers/media/pci/tw5864/tw5864.h+4−3
@@ -12,6 +12,7 @@ · 11 unmodified lines
12#include <linux/mutex.h>12#include <linux/mutex.h>
13#include <linux/io.h>13#include <linux/io.h>
14#include <linux/interrupt.h>14#include <linux/interrupt.h>
15#include <linux/workqueue.h>
15 16
16#include <media/v4l2-common.h>17#include <media/v4l2-common.h>
17#include <media/v4l2-ioctl.h>18#include <media/v4l2-ioctl.h>
@@ -85,7 +86,7 @@ struct tw5864_input { · 67 unmodified lines
85 int nr; /* input number */86 int nr; /* input number */
86 struct tw5864_dev *root;87 struct tw5864_dev *root;
87 struct mutex lock; /* used for vidq and vdev */88 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 */
89 struct video_device vdev;90 struct video_device vdev;
90 struct v4l2_ctrl_handler hdl;91 struct v4l2_ctrl_handler hdl;
91 struct vb2_queue vidq;92 struct vb2_queue vidq;
@@ -142,7 +143,7 @@ struct tw5864_h264_frame { · 50 unmodified lines
142 143
143/* global device status */144/* global device status */
144struct tw5864_dev {145struct 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 */
146 struct v4l2_device v4l2_dev;147 struct v4l2_device v4l2_dev;
147 struct tw5864_input inputs[TW5864_INPUTS];148 struct tw5864_input inputs[TW5864_INPUTS];
148#define H264_BUF_CNT 4149#define H264_BUF_CNT 4
@@ -150,7 +151,7 @@ struct tw5864_dev { · 1 unmodified line
150 int h264_buf_r_index;151 int h264_buf_r_index;
151 int h264_buf_w_index;152 int h264_buf_w_index;
152 153
153 struct tasklet_struct tasklet;154 struct work_struct bh_work;
154 155
155 int encoder_busy;156 int encoder_busy;
156 /* Input number to check next for ready raw picture (in RR fashion) */157 /* 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
70source "drivers/media/platform/broadcom/Kconfig"70source "drivers/media/platform/broadcom/Kconfig"
71source "drivers/media/platform/cadence/Kconfig"71source "drivers/media/platform/cadence/Kconfig"
72source "drivers/media/platform/chips-media/Kconfig"72source "drivers/media/platform/chips-media/Kconfig"
73source "drivers/media/platform/imagination/Kconfig"
73source "drivers/media/platform/intel/Kconfig"74source "drivers/media/platform/intel/Kconfig"
74source "drivers/media/platform/marvell/Kconfig"75source "drivers/media/platform/marvell/Kconfig"
75source "drivers/media/platform/mediatek/Kconfig"76source "drivers/media/platform/mediatek/Kconfig"
@@ -78,6 +79,7 @@ source "drivers/media/platform/nuvoton/Kconfig" · 2 unmodified lines
78source "drivers/media/platform/nvidia/Kconfig"79source "drivers/media/platform/nvidia/Kconfig"
79source "drivers/media/platform/nxp/Kconfig"80source "drivers/media/platform/nxp/Kconfig"
80source "drivers/media/platform/qcom/Kconfig"81source "drivers/media/platform/qcom/Kconfig"
82source "drivers/media/platform/raspberrypi/Kconfig"
81source "drivers/media/platform/renesas/Kconfig"83source "drivers/media/platform/renesas/Kconfig"
82source "drivers/media/platform/rockchip/Kconfig"84source "drivers/media/platform/rockchip/Kconfig"
83source "drivers/media/platform/samsung/Kconfig"85source "drivers/media/platform/samsung/Kconfig"
drivers/media/platform/Makefile+2−0
@@ -13,6 +13,7 @@ obj-y += atmel/ · 12 unmodified lines
13obj-y += broadcom/13obj-y += broadcom/
14obj-y += cadence/14obj-y += cadence/
15obj-y += chips-media/15obj-y += chips-media/
16obj-y += imagination/
16obj-y += intel/17obj-y += intel/
17obj-y += marvell/18obj-y += marvell/
18obj-y += mediatek/19obj-y += mediatek/
@@ -21,6 +22,7 @@ obj-y += nuvoton/ · 2 unmodified lines
21obj-y += nvidia/22obj-y += nvidia/
22obj-y += nxp/23obj-y += nxp/
23obj-y += qcom/24obj-y += qcom/
25obj-y += raspberrypi/
24obj-y += renesas/26obj-y += renesas/
25obj-y += rockchip/27obj-y += rockchip/
26obj-y += samsung/28obj-y += samsung/
drivers/media/platform/allegro-dvt/nal-hevc.h+4−3
@@ -96,10 +96,11 @@ struct nal_hevc_vps { · 95 unmodified lines
96 unsigned int extension_data_flag;96 unsigned int extension_data_flag;
97};97};
98 98
99#define N_HRD_PARAMS 1
99struct nal_hevc_sub_layer_hrd_parameters {100struct nal_hevc_sub_layer_hrd_parameters {
100 unsigned int bit_rate_value_minus1[1];101 unsigned int bit_rate_value_minus1[N_HRD_PARAMS];
101 unsigned int cpb_size_value_minus1[1];102 unsigned int cpb_size_value_minus1[N_HRD_PARAMS];
102 unsigned int cbr_flag[1];103 unsigned int cbr_flag[N_HRD_PARAMS];
103};104};
104 105
105struct nal_hevc_hrd_parameters {106struct 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
195 struct vdec_t *vdec = inst->priv;195 struct vdec_t *vdec = inst->priv;
196 int ret = 0;196 int ret = 0;
197 197
198 vpu_inst_lock(inst);
199 switch (ctrl->id) {198 switch (ctrl->id) {
200 case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:199 case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
201 vdec->params.display_delay_enable = ctrl->val;200 vdec->params.display_delay_enable = ctrl->val;
@@ -207,7 +206,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) · 5 unmodified lines
207 ret = -EINVAL;206 ret = -EINVAL;
208 break;207 break;
209 }208 }
210 vpu_inst_unlock(inst);
211 209
212 return ret;210 return ret;
213}211}
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
518 struct venc_t *venc = inst->priv;518 struct venc_t *venc = inst->priv;
519 int ret = 0;519 int ret = 0;
520 520
521 vpu_inst_lock(inst);
522 switch (ctrl->id) {521 switch (ctrl->id) {
523 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:522 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
524 venc->params.profile = ctrl->val;523 venc->params.profile = ctrl->val;
@@ -579,7 +578,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) · 54 unmodified lines
579 ret = -EINVAL;578 ret = -EINVAL;
580 break;579 break;
581 }580 }
582 vpu_inst_unlock(inst);
583 581
584 return ret;582 return ret;
585}583}
@@ -680,6 +678,9 @@ static int venc_ctrl_init(struct vpu_inst *inst) · 94 unmodified lines
680 ~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),678 ~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
681 V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);679 V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
682 680
681 v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
682 V4L2_CID_MPEG_VIDEO_AVERAGE_QP, 0, 51, 1, 0);
683
683 if (inst->ctrl_handler.error) {684 if (inst->ctrl_handler.error) {
684 ret = inst->ctrl_handler.error;685 ret = inst->ctrl_handler.error;
685 v4l2_ctrl_handler_free(&inst->ctrl_handler);686 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
819 vbuf->field = inst->cap_format.field;820 vbuf->field = inst->cap_format.field;
820 vbuf->flags |= frame->info.pic_type;821 vbuf->flags |= frame->info.pic_type;
821 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);822 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
823 vpu_set_buffer_average_qp(vbuf, frame->info.average_qp);
822 dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);824 dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);
823 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);825 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
824 venc->ready_count++;826 venc->ready_count++;
drivers/media/platform/amphion/vpu.h+1−0
@@ -306,6 +306,7 @@ struct vpu_vb2_buffer { · 305 unmodified lines
306 dma_addr_t chroma_v;306 dma_addr_t chroma_v;
307 unsigned int state;307 unsigned int state;
308 u32 tag;308 u32 tag;
309 u32 average_qp;
309};310};
310 311
311void vpu_writel(struct vpu_dev *vpu, u32 reg, u32 val);312void 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
114 u32 wptr;114 u32 wptr;
115 u32 crc;115 u32 crc;
116 s64 timestamp;116 s64 timestamp;
117 u32 average_qp;
117};118};
118 119
119struct vpu_dec_codec_info {120struct 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
207 u32 reserved;207 u32 reserved;
208};208};
209 209
210struct vpu_malone_frame_buffer {
211 u32 addr;
212 u32 size;
213};
214
215struct vpu_malone_udata {210struct vpu_malone_udata {
216 u32 base;211 u32 base;
217 u32 total_size;212 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
63 return vpu_buf->state;63 return vpu_buf->state;
64}64}
65 65
66void 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
66void vpu_v4l2_set_error(struct vpu_inst *inst)73void vpu_v4l2_set_error(struct vpu_inst *inst)
67{74{
68 vpu_inst_lock(inst);75 vpu_inst_lock(inst);
@@ -539,6 +546,15 @@ static void vpu_vb2_buf_finish(struct vb2_buffer *vb) · 470 unmodified lines
539 struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue);546 struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
540 struct vb2_queue *q = vb->vb2_queue;547 struct vb2_queue *q = vb->vb2_queue;
541 548
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
542 if (vbuf->flags & V4L2_BUF_FLAG_LAST)558 if (vbuf->flags & V4L2_BUF_FLAG_LAST)
543 vpu_notify_eos(inst);559 vpu_notify_eos(inst);
544 560
drivers/media/platform/amphion/vpu_v4l2.h+1−0
@@ -12,6 +12,7 @@ void vpu_inst_lock(struct vpu_inst *inst); · 11 unmodified lines
12void vpu_inst_unlock(struct vpu_inst *inst);12void vpu_inst_unlock(struct vpu_inst *inst);
13void vpu_set_buffer_state(struct vb2_v4l2_buffer *vbuf, unsigned int state);13void vpu_set_buffer_state(struct vb2_v4l2_buffer *vbuf, unsigned int state);
14unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf);14unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf);
15void vpu_set_buffer_average_qp(struct vb2_v4l2_buffer *vbuf, u32 qp);
15 16
16int vpu_v4l2_open(struct file *file, struct vpu_inst *inst);17int vpu_v4l2_open(struct file *file, struct vpu_inst *inst);
17int vpu_v4l2_close(struct file *file);18int 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
499 u32 proc_dacc_rng_wr_cnt;499 u32 proc_dacc_rng_wr_cnt;
500 s32 tv_s;500 s32 tv_s;
501 u32 tv_ns;501 u32 tv_ns;
502 u32 average_qp;
502};503};
503 504
504u32 vpu_windsor_get_data_size(void)505u32 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
734 info->wptr = get_ptr(windsor->str_buff_wptr);735 info->wptr = get_ptr(windsor->str_buff_wptr);
735 info->crc = windsor->frame_crc;736 info->crc = windsor->frame_crc;
736 info->timestamp = timespec64_to_ns(&ts);737 info->timestamp = timespec64_to_ns(&ts);
738 info->average_qp = windsor->average_qp;
737}739}
738 740
739static void vpu_windsor_unpack_mem_req(struct vpu_rpc_event *pkt, void *data)741static 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
29{29{
30 int i;30 int i;
31 31
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)
33 wave5_vdi_free_sram(inst->dev);39 wave5_vdi_free_sram(inst->dev);
34 40
35 for (i = 0; i < inst->fbc_buf_count; i++)41 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
18#define QUEUE_REPORT_MASK 0xffff18#define QUEUE_REPORT_MASK 0xffff
19 19
20/* Encoder support fields */20/* Encoder support fields */
21#define FEATURE_HEVC10BIT_ENC BIT(3)21#define W521_FEATURE_HEVC10BIT_ENC BIT(3)
22#define FEATURE_AVC10BIT_ENC BIT(11)22#define W521_FEATURE_AVC10BIT_ENC BIT(11)
23#define FEATURE_AVC_ENCODER BIT(1)23#define W521_FEATURE_AVC_ENCODER BIT(1)
24#define FEATURE_HEVC_ENCODER BIT(0)24#define W521_FEATURE_HEVC_ENCODER BIT(0)
25 25
26/* Decoder support fields */26/* Decoder support fields */
27#define FEATURE_AVC_DECODER BIT(3)27#define W521_FEATURE_AVC_DECODER BIT(3)
28#define FEATURE_HEVC_DECODER BIT(2)28#define W521_FEATURE_HEVC_DECODER BIT(2)
29#define W515_FEATURE_HEVC10BIT_DEC BIT(1)
30#define W515_FEATURE_HEVC_DECODER BIT(0)
29 31
30#define FEATURE_BACKBONE BIT(16)32#define W521_FEATURE_BACKBONE BIT(16)
31#define FEATURE_VCORE_BACKBONE BIT(22)33#define W521_FEATURE_VCORE_BACKBONE BIT(22)
32#define FEATURE_VCPU_BACKBONE BIT(28)34#define W521_FEATURE_VCPU_BACKBONE BIT(28)
33 35
34#define REMAP_CTRL_MAX_SIZE_BITS ((W5_REMAP_MAX_SIZE >> 12) & 0x1ff)36#define REMAP_CTRL_MAX_SIZE_BITS ((W5_REMAP_MAX_SIZE >> 12) & 0x1ff)
35#define REMAP_CTRL_REGISTER_VALUE(index) ( \37#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
155{157{
156 u32 gdi_status_check_value = 0x3f;158 u32 gdi_status_check_value = 0x3f;
157 159
160 if (vpu_dev->product_code == WAVE515_CODE)
161 gdi_status_check_value = 0x0738;
158 if (vpu_dev->product_code == WAVE521C_CODE ||162 if (vpu_dev->product_code == WAVE521C_CODE ||
159 vpu_dev->product_code == WAVE521_CODE ||163 vpu_dev->product_code == WAVE521_CODE ||
160 vpu_dev->product_code == WAVE521E1_CODE)164 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
186 u32 val = vpu_read_reg(vpu_dev, W5_PRODUCT_NUMBER);190 u32 val = vpu_read_reg(vpu_dev, W5_PRODUCT_NUMBER);
187 191
188 switch (val) {192 switch (val) {
193 case WAVE515_CODE:
194 return PRODUCT_ID_515;
189 case WAVE521C_CODE:195 case WAVE521C_CODE:
190 return PRODUCT_ID_521;196 return PRODUCT_ID_521;
191 case WAVE521_CODE:197 case WAVE521_CODE:
@@ -299,6 +305,27 @@ static int wave5_send_query(struct vpu_device *vpu_dev, struct vpu_instance *ins · 107 unmodified lines
299 return wave5_vpu_firmware_command_queue_error_check(vpu_dev, NULL);305 return wave5_vpu_firmware_command_queue_error_check(vpu_dev, NULL);
300}306}
301 307
308static 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
302static int setup_wave5_properties(struct device *dev)329static int setup_wave5_properties(struct device *dev)
303{330{
304 struct vpu_device *vpu_dev = dev_get_drvdata(dev);331 struct vpu_device *vpu_dev = dev_get_drvdata(dev);
@@ -328,17 +355,35 @@ static int setup_wave5_properties(struct device *dev) · 23 unmodified lines
328 hw_config_def1 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF1);355 hw_config_def1 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF1);
329 hw_config_feature = vpu_read_reg(vpu_dev, W5_RET_CONF_FEATURE);356 hw_config_feature = vpu_read_reg(vpu_dev, W5_RET_CONF_FEATURE);
330 357
331 p_attr->support_hevc10bit_enc = FIELD_GET(FEATURE_HEVC10BIT_ENC, hw_config_feature);358 if (vpu_dev->product_code == WAVE515_CODE) {
332 p_attr->support_avc10bit_enc = FIELD_GET(FEATURE_AVC10BIT_ENC, hw_config_feature);359 p_attr->support_hevc10bit_dec = FIELD_GET(W515_FEATURE_HEVC10BIT_DEC,
333 360 hw_config_feature);
334 p_attr->support_decoders = FIELD_GET(FEATURE_AVC_DECODER, hw_config_def1) << STD_AVC;361 p_attr->support_decoders = FIELD_GET(W515_FEATURE_HEVC_DECODER,
335 p_attr->support_decoders |= FIELD_GET(FEATURE_HEVC_DECODER, hw_config_def1) << STD_HEVC;362 hw_config_def1) << STD_HEVC;
336 p_attr->support_encoders = FIELD_GET(FEATURE_AVC_ENCODER, hw_config_def1) << STD_AVC;363 } else {
337 p_attr->support_encoders |= FIELD_GET(FEATURE_HEVC_ENCODER, hw_config_def1) << STD_HEVC;364 p_attr->support_hevc10bit_enc = FIELD_GET(W521_FEATURE_HEVC10BIT_ENC,
338 365 hw_config_feature);
339 p_attr->support_backbone = FIELD_GET(FEATURE_BACKBONE, hw_config_def0);366 p_attr->support_avc10bit_enc = FIELD_GET(W521_FEATURE_AVC10BIT_ENC,
340 p_attr->support_vcpu_backbone = FIELD_GET(FEATURE_VCPU_BACKBONE, hw_config_def0);367 hw_config_feature);
341 p_attr->support_vcore_backbone = FIELD_GET(FEATURE_VCORE_BACKBONE, hw_config_def0);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);
342 387
343 return 0;388 return 0;
344}389}
@@ -380,12 +425,18 @@ int wave5_vpu_init(struct device *dev, u8 *fw, size_t size) · 35 unmodified lines
380 common_vb = &vpu_dev->common_mem;425 common_vb = &vpu_dev->common_mem;
381 426
382 code_base = common_vb->daddr;427 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
383 /* ALIGN TO 4KB */434 /* ALIGN TO 4KB */
384 code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);435 code_size &= ~0xfff;
385 if (code_size < size * 2)436 if (code_size < size * 2)
386 return -EINVAL;437 return -EINVAL;
387 438
388 temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET;439 temp_base = code_base + code_size;
389 temp_size = WAVE5_TEMPBUF_SIZE;440 temp_size = WAVE5_TEMPBUF_SIZE;
390 441
391 ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size);442 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
413 464
414 /* These register must be reset explicitly */465 /* These register must be reset explicitly */
415 vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);466 vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
416 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);467
417 wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);468 if (vpu_dev->product_code != WAVE515_CODE) {
418 vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);469 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
419 470 wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
420 /* Encoder interrupt */471 vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
421 reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);472 }
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);
429 473
430 reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);474 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)) {
432 reg_val = ((WAVE5_PROC_AXI_ID << 28) |476 reg_val = ((WAVE5_PROC_AXI_ID << 28) |
433 (WAVE5_PRP_AXI_ID << 24) |477 (WAVE5_PRP_AXI_ID << 24) |
434 (WAVE5_FBD_Y_AXI_ID << 20) |478 (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
440 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);484 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
441 }485 }
442 486
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
443 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);505 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
444 vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);506 vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);
445 vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);507 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
480 return -EINVAL;542 return -EINVAL;
481 }543 }
482 544
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
484 ret = wave5_vdi_allocate_dma_memory(inst->dev, &p_dec_info->vb_work);550 ret = wave5_vdi_allocate_dma_memory(inst->dev, &p_dec_info->vb_work);
485 if (ret)551 if (ret)
486 return ret;552 return ret;
487 553
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);
489 556
490 wave5_vdi_clear_memory(inst->dev, &p_dec_info->vb_work);557 wave5_vdi_clear_memory(inst->dev, &p_dec_info->vb_work);
491 558
492 vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_dec_info->vb_work.daddr);559 vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_dec_info->vb_work.daddr);
493 vpu_write_reg(inst->dev, W5_WORK_SIZE, p_dec_info->vb_work.size);560 vpu_write_reg(inst->dev, W5_WORK_SIZE, p_dec_info->vb_work.size);
494 561
495 vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);562 if (inst->dev->product_code != WAVE515_CODE) {
496 vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);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 }
497 566
498 vpu_write_reg(inst->dev, W5_CMD_DEC_BS_START_ADDR, p_dec_info->stream_buf_start_addr);567 vpu_write_reg(inst->dev, W5_CMD_DEC_BS_START_ADDR, p_dec_info->stream_buf_start_addr);
499 vpu_write_reg(inst->dev, W5_CMD_DEC_BS_SIZE, p_dec_info->stream_buf_size);568 vpu_write_reg(inst->dev, W5_CMD_DEC_BS_SIZE, p_dec_info->stream_buf_size);
500 569
501 /* NOTE: SDMA reads MSB first */570 /* NOTE: SDMA reads MSB first */
502 vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, BITSTREAM_ENDIANNESS_BIG_ENDIAN);571 vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, BITSTREAM_ENDIANNESS_BIG_ENDIAN);
503 /* This register must be reset explicitly */572
504 vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);573 if (inst->dev->product_code != WAVE515_CODE) {
505 vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, (COMMAND_QUEUE_DEPTH - 1));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 }
506 579
507 ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL);580 ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL);
508 if (ret) {581 if (ret) {
@@ -553,7 +626,7 @@ static u32 get_bitstream_options(struct dec_info *info) · 44 unmodified lines
553int wave5_vpu_dec_init_seq(struct vpu_instance *inst)626int wave5_vpu_dec_init_seq(struct vpu_instance *inst)
554{627{
555 struct dec_info *p_dec_info = &inst->codec_info->dec_info;628 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;
557 u32 reg_val, fail_res;630 u32 reg_val, fail_res;
558 int ret;631 int ret;
559 632
@@ -563,7 +636,13 @@ int wave5_vpu_dec_init_seq(struct vpu_instance *inst) · 3 unmodified lines
563 vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr);636 vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr);
564 vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);637 vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);
565 638
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);
567 646
568 vpu_write_reg(inst->dev, W5_COMMAND_OPTION, cmd_option);647 vpu_write_reg(inst->dev, W5_COMMAND_OPTION, cmd_option);
569 vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info->user_data_enable);648 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
629 info->profile = FIELD_GET(SEQ_PARAM_PROFILE_MASK, reg_val);708 info->profile = FIELD_GET(SEQ_PARAM_PROFILE_MASK, reg_val);
630 }709 }
631 710
632 info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);711 if (inst->dev->product_code != WAVE515_CODE) {
633 info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE);712 info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);
634 p_dec_info->vlc_buf_size = info->vlc_buf_size;713 info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE);
635 p_dec_info->param_buf_size = info->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 }
636}717}
637 718
638int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct dec_initial_info *info)719int 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
734 815
735 pic_size = (init_info->pic_width << 16) | (init_info->pic_height);816 pic_size = (init_info->pic_width << 16) | (init_info->pic_height);
736 817
737 vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) +818 if (inst->dev->product_code != WAVE515_CODE) {
738 (p_dec_info->param_buf_size * COMMAND_QUEUE_DEPTH);819 vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) +
739 vb_buf.daddr = 0;820 (p_dec_info->param_buf_size * WAVE521_COMMAND_QUEUE_DEPTH);
821 vb_buf.daddr = 0;
740 822
741 if (vb_buf.size != p_dec_info->vb_task.size) {823 if (vb_buf.size != p_dec_info->vb_task.size) {
742 wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task);824 wave5_vdi_free_dma_memory(inst->dev,
743 ret = wave5_vdi_allocate_dma_memory(inst->dev, &vb_buf);825 &p_dec_info->vb_task);
744 if (ret)826 ret = wave5_vdi_allocate_dma_memory(inst->dev,
745 goto free_fbc_c_tbl_buffers;827 &vb_buf);
828 if (ret)
829 goto free_fbc_c_tbl_buffers;
746 830
747 p_dec_info->vb_task = vb_buf;831 p_dec_info->vb_task = vb_buf;
748 }832 }
749 833
750 vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,834 vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,
751 p_dec_info->vb_task.daddr);835 p_dec_info->vb_task.daddr);
752 vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_buf.size);836 vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE,
837 vb_buf.size);
838 }
753 } else {839 } else {
754 pic_size = (init_info->pic_width << 16) | (init_info->pic_height);840 pic_size = (init_info->pic_width << 16) | (init_info->pic_height);
755 841
@@ -830,6 +916,43 @@ free_mv_buffers: · 74 unmodified lines
830 return ret;916 return ret;
831}917}
832 918
919static 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
833int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res)956int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res)
834{957{
835 u32 reg_val;958 u32 reg_val;
@@ -842,9 +965,7 @@ int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res) · 6 unmodified lines
842 vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info));965 vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info));
843 966
844 /* secondary AXI */967 /* secondary AXI */
845 reg_val = p_dec_info->sec_axi_info.use_bit_enable |968 reg_val = wave5_vpu_dec_validate_sec_axi(inst);
846 (p_dec_info->sec_axi_info.use_ip_enable << 9) |
847 (p_dec_info->sec_axi_info.use_lf_row_enable << 15);
848 vpu_write_reg(inst->dev, W5_USE_SEC_AXI, reg_val);969 vpu_write_reg(inst->dev, W5_USE_SEC_AXI, reg_val);
849 970
850 /* set attributes of user buffer */971 /* 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
992 common_vb = &vpu_dev->common_mem;1113 common_vb = &vpu_dev->common_mem;
993 1114
994 code_base = common_vb->daddr;1115 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
995 /* ALIGN TO 4KB */1122 /* ALIGN TO 4KB */
996 code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);1123 code_size &= ~0xfff;
997 if (code_size < size * 2)1124 if (code_size < size * 2)
998 return -EINVAL;1125 return -EINVAL;
999 temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET;1126
1127 temp_base = code_base + code_size;
1000 temp_size = WAVE5_TEMPBUF_SIZE;1128 temp_size = WAVE5_TEMPBUF_SIZE;
1001 1129
1002 old_code_base = vpu_read_reg(vpu_dev, W5_VPU_REMAP_PADDR);1130 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
1030 1158
1031 /* These register must be reset explicitly */1159 /* These register must be reset explicitly */
1032 vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);1160 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);
1036 1161
1037 /* Encoder interrupt */1162 if (vpu_dev->product_code != WAVE515_CODE) {
1038 reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);1163 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
1039 reg_val |= BIT(INT_WAVE5_ENC_PIC);1164 wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
1040 reg_val |= BIT(INT_WAVE5_BSBUF_FULL);1165 vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
1041 /* Decoder interrupt */1166 }
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);
1046 1167
1047 reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);1168 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)) {
1049 reg_val = ((WAVE5_PROC_AXI_ID << 28) |1170 reg_val = ((WAVE5_PROC_AXI_ID << 28) |
1050 (WAVE5_PRP_AXI_ID << 24) |1171 (WAVE5_PRP_AXI_ID << 24) |
1051 (WAVE5_FBD_Y_AXI_ID << 20) |1172 (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
1057 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);1178 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
1058 }1179 }
1059 1180
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
1060 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);1204 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
1061 vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);1205 vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);
1062 vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);1206 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
1080{1224{
1081 u32 reg_val;1225 u32 reg_val;
1082 struct vpu_buf *common_vb;1226 struct vpu_buf *common_vb;
1083 dma_addr_t code_base;1227 dma_addr_t code_base, temp_base;
1084 u32 code_size, reason_code;1228 u32 code_size, temp_size, reason_code;
1085 struct vpu_device *vpu_dev = dev_get_drvdata(dev);1229 struct vpu_device *vpu_dev = dev_get_drvdata(dev);
1086 int ret;1230 int ret;
1087 1231
@@ -1111,13 +1255,22 @@ static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uin · 23 unmodified lines
1111 common_vb = &vpu_dev->common_mem;1255 common_vb = &vpu_dev->common_mem;
1112 1256
1113 code_base = common_vb->daddr;1257 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
1114 /* ALIGN TO 4KB */1264 /* ALIGN TO 4KB */
1115 code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);1265 code_size &= ~0xfff;
1116 if (code_size < size * 2) {1266 if (code_size < size * 2) {
1117 dev_err(dev, "size too small\n");1267 dev_err(dev, "size too small\n");
1118 return -EINVAL;1268 return -EINVAL;
1119 }1269 }
1120 1270
1271 temp_base = code_base + code_size;
1272 temp_size = WAVE5_TEMPBUF_SIZE;
1273
1121 /* Power on without DEBUG mode */1274 /* Power on without DEBUG mode */
1122 vpu_write_reg(vpu_dev, W5_PO_CONF, 0);1275 vpu_write_reg(vpu_dev, W5_PO_CONF, 0);
1123 1276
@@ -1130,22 +1283,17 @@ static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uin · 6 unmodified lines
1130 1283
1131 /* These register must be reset explicitly */1284 /* These register must be reset explicitly */
1132 vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);1285 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);
1136 1286
1137 /* Encoder interrupt */1287 if (vpu_dev->product_code != WAVE515_CODE) {
1138 reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);1288 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0);
1139 reg_val |= BIT(INT_WAVE5_ENC_PIC);1289 wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0);
1140 reg_val |= BIT(INT_WAVE5_BSBUF_FULL);1290 vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0);
1141 /* Decoder interrupt */1291 }
1142 reg_val |= BIT(INT_WAVE5_INIT_SEQ);1292
1143 reg_val |= BIT(INT_WAVE5_DEC_PIC);1293 setup_wave5_interrupts(vpu_dev);
1144 reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);
1145 vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);
1146 1294
1147 reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);1295 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)) {
1149 reg_val = ((WAVE5_PROC_AXI_ID << 28) |1297 reg_val = ((WAVE5_PROC_AXI_ID << 28) |
1150 (WAVE5_PRP_AXI_ID << 24) |1298 (WAVE5_PRP_AXI_ID << 24) |
1151 (WAVE5_FBD_Y_AXI_ID << 20) |1299 (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
1157 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);1305 wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
1158 }1306 }
1159 1307
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
1160 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);1331 vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
1161 vpu_write_reg(vpu_dev, W5_COMMAND, W5_WAKEUP_VPU);1332 vpu_write_reg(vpu_dev, W5_COMMAND, W5_WAKEUP_VPU);
1162 /* Start VPU after settings */1333 /* 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
1401 reg_val = (open_param->line_buf_int_en << 6) | BITSTREAM_ENDIANNESS_BIG_ENDIAN;1572 reg_val = (open_param->line_buf_int_en << 6) | BITSTREAM_ENDIANNESS_BIG_ENDIAN;
1402 vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, reg_val);1573 vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, reg_val);
1403 vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0);1574 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);
1405 1576
1406 /* This register must be reset explicitly */1577 /* This register must be reset explicitly */
1407 vpu_write_reg(inst->dev, W5_CMD_ENC_SRC_OPTIONS, 0);1578 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
1855 p_enc_info->vb_sub_sam_buf = vb_sub_sam_buf;2026 p_enc_info->vb_sub_sam_buf = vb_sub_sam_buf;
1856 2027
1857 vb_task.size = (p_enc_info->vlc_buf_size * VLC_BUF_NUM) +2028 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);
1859 vb_task.daddr = 0;2030 vb_task.daddr = 0;
1860 if (p_enc_info->vb_task.size == 0) {2031 if (p_enc_info->vb_task.size == 0) {
1861 ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_task);2032 ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_task);
@@ -1943,6 +2114,31 @@ free_vb_fbc_y_tbl: · 81 unmodified lines
1943 return ret;2114 return ret;
1944}2115}
1945 2116
2117static 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
1946int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res)2142int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res)
1947{2143{
1948 u32 src_frame_format;2144 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
1964 2160
1965 vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_AXI_SEL, DEFAULT_SRC_AXI);2161 vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_AXI_SEL, DEFAULT_SRC_AXI);
1966 /* secondary AXI */2162 /* secondary AXI */
1967 reg_val = (p_enc_info->sec_axi_info.use_enc_rdo_enable << 11) |2163 reg_val = wave5_vpu_enc_validate_sec_axi(inst);
1968 (p_enc_info->sec_axi_info.use_enc_lf_enable << 15);
1969 vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_USE_SEC_AXI, reg_val);2164 vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_USE_SEC_AXI, reg_val);
1970 2165
1971 vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_REPORT_PARAM, 0);2166 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
205#define W5_ADDR_TEMP_BASE (W5_REG_BASE + 0x011C)205#define W5_ADDR_TEMP_BASE (W5_REG_BASE + 0x011C)
206#define W5_TEMP_SIZE (W5_REG_BASE + 0x0120)206#define W5_TEMP_SIZE (W5_REG_BASE + 0x0120)
207#define W5_HW_OPTION (W5_REG_BASE + 0x012C)207#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)
208#define W5_SEC_AXI_PARAM (W5_REG_BASE + 0x0180)211#define W5_SEC_AXI_PARAM (W5_REG_BASE + 0x0180)
209 212
210/************************************************************************/213/************************************************************************/
@@ -216,7 +219,9 @@ enum query_opt { · 5 unmodified lines
216#define W5_CMD_DEC_BS_SIZE (W5_REG_BASE + 0x0120)219#define W5_CMD_DEC_BS_SIZE (W5_REG_BASE + 0x0120)
217#define W5_CMD_BS_PARAM (W5_REG_BASE + 0x0124)220#define W5_CMD_BS_PARAM (W5_REG_BASE + 0x0124)
218#define W5_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0130)221#define W5_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0130)
222#define W515_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0124)
219#define W5_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0134)223#define W5_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0134)
224#define W515_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0128)
220#define W5_CMD_EXT_ADDR (W5_REG_BASE + 0x0138)225#define W5_CMD_EXT_ADDR (W5_REG_BASE + 0x0138)
221#define W5_CMD_NUM_CQ_DEPTH_M1 (W5_REG_BASE + 0x013C)226#define W5_CMD_NUM_CQ_DEPTH_M1 (W5_REG_BASE + 0x013C)
222#define W5_CMD_ERR_CONCEAL (W5_REG_BASE + 0x0140)227#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
18 if (!vpu_dev->common_mem.vaddr) {18 if (!vpu_dev->common_mem.vaddr) {
19 int ret;19 int ret;
20 20
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
22 ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev->common_mem);26 ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev->common_mem);
23 if (ret) {27 if (ret) {
24 dev_err(dev, "unable to allocate common buffer\n");28 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
174void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev)178void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev)
175{179{
176 struct vpu_buf *vb = &vpu_dev->sram_buf;180 struct vpu_buf *vb = &vpu_dev->sram_buf;
181 dma_addr_t daddr;
182 void *vaddr;
183 size_t size;
177 184
178 if (!vpu_dev->sram_pool || !vpu_dev->sram_size)185 if (!vpu_dev->sram_pool || vb->vaddr)
179 return;186 return;
180 187
181 if (!vb->vaddr) {188 size = min_t(size_t, vpu_dev->sram_size, gen_pool_avail(vpu_dev->sram_pool));
182 vb->size = vpu_dev->sram_size;189 vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, size, &daddr);
183 vb->vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, vb->size,190 if (vaddr) {
184 &vb->daddr);191 vb->vaddr = vaddr;
185 if (!vb->vaddr)192 vb->daddr = daddr;
186 vb->size = 0;193 vb->size = size;
187 }194 }
188 195
189 dev_dbg(vpu_dev->dev, "%s: sram daddr: %pad, size: %zu, vaddr: 0x%p\n",196 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
197 if (!vb->size || !vb->vaddr)204 if (!vb->size || !vb->vaddr)
198 return;205 return;
199 206
200 if (vb->vaddr)207 gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr, vb->size);
201 gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr,
202 vb->size);
203 208
204 memset(vb, 0, sizeof(*vb));209 memset(vb, 0, sizeof(*vb));
205}210}
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
1055 int ret, i;1055 int ret, i;
1056 struct v4l2_m2m_buffer *buf, *n;1056 struct v4l2_m2m_buffer *buf, *n;
1057 struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx;1057 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 }
1058 1074
1059 linear_num = v4l2_m2m_num_dst_bufs_ready(m2m_ctx);1075 linear_num = v4l2_m2m_num_dst_bufs_ready(m2m_ctx);
1060 non_linear_num = inst->fbc_buf_count;1076 non_linear_num = inst->fbc_buf_count;
@@ -1063,7 +1079,7 @@ static int wave5_prepare_fb(struct vpu_instance *inst) · 2 unmodified lines
1063 struct frame_buffer *frame = &inst->frame_buf[i];1079 struct frame_buffer *frame = &inst->frame_buf[i];
1064 struct vpu_buf *vframe = &inst->frame_vbuf[i];1080 struct vpu_buf *vframe = &inst->frame_vbuf[i];
1065 1081
1066 fb_stride = inst->dst_fmt.width;1082 fb_stride = ALIGN(inst->dst_fmt.width * bitdepth / 8, 32);
1067 fb_height = ALIGN(inst->dst_fmt.height, 32);1083 fb_height = ALIGN(inst->dst_fmt.height, 32);
1068 luma_size = fb_stride * fb_height;1084 luma_size = fb_stride * fb_height;
1069 1085
@@ -1408,22 +1424,10 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count · 338 unmodified lines
1408 if (ret)1424 if (ret)
1409 goto free_bitstream_vbuf;1425 goto free_bitstream_vbuf;
1410 } else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {1426 } 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
1414 if (inst->state == VPU_INST_STATE_STOP)1427 if (inst->state == VPU_INST_STATE_STOP)
1415 ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ);1428 ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ);
1416 if (ret)1429 if (ret)
1417 goto return_buffers;1430 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 }
1427 }1431 }
1428 1432
1429 return ret;1433 return ret;
@@ -1864,7 +1868,12 @@ static int wave5_vpu_open_dec(struct file *filp) · 434 unmodified lines
1864 goto cleanup_inst;1868 goto cleanup_inst;
1865 }1869 }
1866 1870
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);
1868 1877
1869 ret = mutex_lock_interruptible(&dev->dev_lock);1878 ret = mutex_lock_interruptible(&dev->dev_lock);
1870 if (ret)1879 if (ret)
@@ -1904,6 +1913,13 @@ int wave5_vpu_dec_register_device(struct vpu_device *dev) · 33 unmodified lines
1904 struct video_device *vdev_dec;1913 struct video_device *vdev_dec;
1905 int ret;1914 int ret;
1906 1915
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
1907 vdev_dec = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_dec), GFP_KERNEL);1923 vdev_dec = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_dec), GFP_KERNEL);
1908 if (!vdev_dec)1924 if (!vdev_dec)
1909 return -ENOMEM;1925 return -ENOMEM;
@@ -1937,6 +1953,13 @@ int wave5_vpu_dec_register_device(struct vpu_device *dev) · 27 unmodified lines
1937 1953
1938void wave5_vpu_dec_unregister_device(struct vpu_device *dev)1954void wave5_vpu_dec_unregister_device(struct vpu_device *dev)
1939{1955{
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
1940 video_unregister_device(dev->video_dev_dec);1963 video_unregister_device(dev->video_dev_dec);
1941 if (dev->v4l2_m2m_dec_dev)1964 if (dev->v4l2_m2m_dec_dev)
1942 v4l2_m2m_release(dev->v4l2_m2m_dec_dev);1965 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
1247 __func__, initial_info.min_frame_buffer_count,1247 __func__, initial_info.min_frame_buffer_count,
1248 initial_info.min_src_frame_count);1248 initial_info.min_src_frame_count);
1249 inst->min_src_buf_count = initial_info.min_src_frame_count +1249 inst->min_src_buf_count = initial_info.min_src_frame_count +
1250 COMMAND_QUEUE_DEPTH;1250 WAVE521_COMMAND_QUEUE_DEPTH;
1251 1251
1252 ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl,1252 ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl,
1253 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT);1253 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT);
drivers/media/platform/chips-media/wave5/wave5-vpu.c+26−9
@@ -10,6 +10,7 @@ · 9 unmodified lines
10#include <linux/clk.h>10#include <linux/clk.h>
11#include <linux/firmware.h>11#include <linux/firmware.h>
12#include <linux/interrupt.h>12#include <linux/interrupt.h>
13#include <linux/reset.h>
13#include "wave5-vpu.h"14#include "wave5-vpu.h"
14#include "wave5-regdefine.h"15#include "wave5-regdefine.h"
15#include "wave5-vpuconfig.h"16#include "wave5-vpuconfig.h"
@@ -24,6 +25,7 @@ · 8 unmodified lines
24struct wave5_match_data {25struct wave5_match_data {
25 int flags;26 int flags;
26 const char *fw_name;27 const char *fw_name;
28 u32 sram_size;
27};29};
28 30
29static int vpu_poll_interval = 5;31static int vpu_poll_interval = 5;
@@ -61,7 +63,13 @@ static void wave5_vpu_handle_irq(void *dev_id) · 31 unmodified lines
61 63
62 if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) ||64 if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) ||
63 irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) {65 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)) {
65 seq_done &= ~BIT(inst->id);73 seq_done &= ~BIT(inst->id);
66 wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO,74 wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO,
67 seq_done);75 seq_done);
@@ -179,6 +187,16 @@ static int wave5_vpu_probe(struct platform_device *pdev) · 111 unmodified lines
179 dev_set_drvdata(&pdev->dev, dev);187 dev_set_drvdata(&pdev->dev, dev);
180 dev->dev = &pdev->dev;188 dev->dev = &pdev->dev;
181 189
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
182 ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks);200 ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks);
183 201
184 /* continue without clock, assume externally managed */202 /* continue without clock, assume externally managed */
@@ -191,20 +209,15 @@ static int wave5_vpu_probe(struct platform_device *pdev) · 6 unmodified lines
191 ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks);209 ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks);
192 if (ret) {210 if (ret) {
193 dev_err(&pdev->dev, "Enabling clocks, fail: %d\n", ret);211 dev_err(&pdev->dev, "Enabling clocks, fail: %d\n", ret);
194 return ret;212 goto err_reset_assert;
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;
202 }213 }
203 214
204 dev->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);215 dev->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
205 if (!dev->sram_pool)216 if (!dev->sram_pool)
206 dev_warn(&pdev->dev, "sram node not found\n");217 dev_warn(&pdev->dev, "sram node not found\n");
207 218
219 dev->sram_size = match_data->sram_size;
220
208 dev->product_code = wave5_vdi_read_register(dev, VPU_PRODUCT_CODE_REGISTER);221 dev->product_code = wave5_vdi_read_register(dev, VPU_PRODUCT_CODE_REGISTER);
209 ret = wave5_vdi_init(&pdev->dev);222 ret = wave5_vdi_init(&pdev->dev);
210 if (ret < 0) {223 if (ret < 0) {
@@ -282,6 +295,8 @@ err_vdi_release: · 71 unmodified lines
282 wave5_vdi_release(&pdev->dev);295 wave5_vdi_release(&pdev->dev);
283err_clk_dis:296err_clk_dis:
284 clk_bulk_disable_unprepare(dev->num_clks, dev->clks);297 clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
298err_reset_assert:
299 reset_control_assert(dev->resets);
285 300
286 return ret;301 return ret;
287}302}
@@ -297,6 +312,7 @@ static void wave5_vpu_remove(struct platform_device *pdev) · 9 unmodified lines
297 312
298 mutex_destroy(&dev->dev_lock);313 mutex_destroy(&dev->dev_lock);
299 mutex_destroy(&dev->hw_lock);314 mutex_destroy(&dev->hw_lock);
315 reset_control_assert(dev->resets);
300 clk_bulk_disable_unprepare(dev->num_clks, dev->clks);316 clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
301 wave5_vpu_enc_unregister_device(dev);317 wave5_vpu_enc_unregister_device(dev);
302 wave5_vpu_dec_unregister_device(dev);318 wave5_vpu_dec_unregister_device(dev);
@@ -308,6 +324,7 @@ static void wave5_vpu_remove(struct platform_device *pdev) · 5 unmodified lines
308static const struct wave5_match_data ti_wave521c_data = {324static const struct wave5_match_data ti_wave521c_data = {
309 .flags = WAVE5_IS_ENC | WAVE5_IS_DEC,325 .flags = WAVE5_IS_ENC | WAVE5_IS_DEC,
310 .fw_name = "cnm/wave521c_k3_codec_fw.bin",326 .fw_name = "cnm/wave521c_k3_codec_fw.bin",
327 .sram_size = (64 * 1024),
311};328};
312 329
313static const struct of_device_id wave5_dt_ids[] = {330static 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
18#include "wave5-vdi.h"18#include "wave5-vdi.h"
19 19
20enum product_id {20enum product_id {
21 PRODUCT_ID_515,
21 PRODUCT_ID_521,22 PRODUCT_ID_521,
22 PRODUCT_ID_511,23 PRODUCT_ID_511,
23 PRODUCT_ID_517,24 PRODUCT_ID_517,
@@ -327,6 +328,7 @@ struct vpu_attr { · 303 unmodified lines
327 u32 support_backbone: 1;328 u32 support_backbone: 1;
328 u32 support_avc10bit_enc: 1;329 u32 support_avc10bit_enc: 1;
329 u32 support_hevc10bit_enc: 1;330 u32 support_hevc10bit_enc: 1;
331 u32 support_hevc10bit_dec: 1;
330 u32 support_vcore_backbone: 1;332 u32 support_vcore_backbone: 1;
331 u32 support_vcpu_backbone: 1;333 u32 support_vcpu_backbone: 1;
332};334};
@@ -761,6 +763,7 @@ struct vpu_device { · 428 unmodified lines
761 struct kthread_worker *worker;763 struct kthread_worker *worker;
762 int vpu_poll_interval;764 int vpu_poll_interval;
763 int num_clks;765 int num_clks;
766 struct reset_control *resets;
764};767};
765 768
766struct vpu_instance;769struct vpu_instance;
drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h+11−5
@@ -8,6 +8,7 @@ · 7 unmodified lines
8#ifndef _VPU_CONFIG_H_8#ifndef _VPU_CONFIG_H_
9#define _VPU_CONFIG_H_9#define _VPU_CONFIG_H_
10 10
11#define WAVE515_CODE 0x5150
11#define WAVE517_CODE 0x517012#define WAVE517_CODE 0x5170
12#define WAVE537_CODE 0x537013#define WAVE537_CODE 0x5370
13#define WAVE511_CODE 0x511014#define WAVE511_CODE 0x5110
@@ -21,12 +22,13 @@ · 7 unmodified lines
21 ((c) == WAVE517_CODE || (c) == WAVE537_CODE || \22 ((c) == WAVE517_CODE || (c) == WAVE537_CODE || \
22 (c) == WAVE511_CODE || (c) == WAVE521_CODE || \23 (c) == WAVE511_CODE || (c) == WAVE521_CODE || \
23 (c) == WAVE521E1_CODE || (c) == WAVE521C_CODE || \24 (c) == WAVE521E1_CODE || (c) == WAVE521C_CODE || \
24 (c) == WAVE521C_DUAL_CODE); \25 (c) == WAVE521C_DUAL_CODE) || (c) == WAVE515_CODE; \
25})26})
26 27
27#define WAVE517_WORKBUF_SIZE (2 * 1024 * 1024)28#define WAVE517_WORKBUF_SIZE (2 * 1024 * 1024)
28#define WAVE521ENC_WORKBUF_SIZE (128 * 1024) //HEVC 128K, AVC 40K29#define WAVE521ENC_WORKBUF_SIZE (128 * 1024) //HEVC 128K, AVC 40K
29#define WAVE521DEC_WORKBUF_SIZE (1784 * 1024)30#define WAVE521DEC_WORKBUF_SIZE (1784 * 1024)
31#define WAVE515DEC_WORKBUF_SIZE (2 * 1024 * 1024)
30 32
31#define MAX_NUM_INSTANCE 3233#define MAX_NUM_INSTANCE 32
32 34
@@ -49,17 +51,21 @@ · 16 unmodified lines
49/************************************************************************/51/************************************************************************/
50#define VLC_BUF_NUM (2)52#define VLC_BUF_NUM (2)
51 53
52#define COMMAND_QUEUE_DEPTH (2)54#define WAVE521_COMMAND_QUEUE_DEPTH (2)
55#define WAVE515_COMMAND_QUEUE_DEPTH (4)
53 56
54#define W5_REMAP_INDEX0 057#define W5_REMAP_INDEX0 0
55#define W5_REMAP_INDEX1 158#define W5_REMAP_INDEX1 1
56#define W5_REMAP_MAX_SIZE (1024 * 1024)59#define W5_REMAP_MAX_SIZE (1024 * 1024)
57 60
58#define WAVE5_MAX_CODE_BUF_SIZE (2 * 1024 * 1024)61#define WAVE521_MAX_CODE_BUF_SIZE (2 * 1024 * 1024)
59#define WAVE5_TEMPBUF_OFFSET WAVE5_MAX_CODE_BUF_SIZE62#define WAVE515_MAX_CODE_BUF_SIZE (1024 * 1024)
60#define WAVE5_TEMPBUF_SIZE (1024 * 1024)63#define WAVE5_TEMPBUF_SIZE (1024 * 1024)
61 64
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)
63 69
64//=====4. VPU REPORT MEMORY ======================//70//=====4. VPU REPORT MEMORY ======================//
65 71
drivers/media/platform/chips-media/wave5/wave5.h+6−0
@@ -22,6 +22,12 @@ · 21 unmodified lines
22 */22 */
23#define BSOPTION_ENABLE_EXPLICIT_END BIT(0)23#define BSOPTION_ENABLE_EXPLICIT_END BIT(0)
24#define BSOPTION_HIGHLIGHT_STREAM_END BIT(1)24#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)
25 31
26/*32/*
27 * Currently the driver only supports hardware with little endian but for source33 * 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
2config 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
2e5010_jpeg_enc-objs := e5010-jpeg-enc-hw.o e5010-jpeg-enc.o
3obj-$(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
16static 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
29static 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
47void 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
71void 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
81int 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
90bool 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
98bool 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
106int 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
115int 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
124int 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
132int 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
140int 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
148int 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
155int 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
162int 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
170int 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
179int 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
188int 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
199int 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
210int 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
219int 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
228void 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
236int 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
241void 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
249void 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
257int e5010_hw_get_output_size(void __iomem *core_base)
258{
259 return readl(core_base + JASPER_OUTPUT_SIZE_OFFSET);
260}
261
262void 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
17int e5010_hw_enable_output_address_error_irq(void __iomem *core_offset, u32 enable);
18int e5010_hw_enable_picture_done_irq(void __iomem *core_offset, u32 enable);
19int e5010_hw_enable_auto_clock_gating(void __iomem *core_offset, u32 enable);
20int e5010_hw_enable_manual_clock_gating(void __iomem *core_offset, u32 enable);
21int e5010_hw_enable_crc_check(void __iomem *core_offset, u32 enable);
22int e5010_hw_set_input_source_to_memory(void __iomem *core_offset, u32 set);
23int e5010_hw_set_input_luma_addr(void __iomem *core_offset, u32 val);
24int e5010_hw_set_input_chroma_addr(void __iomem *core_offset, u32 val);
25int e5010_hw_set_output_base_addr(void __iomem *core_offset, u32 val);
26int e5010_hw_get_output_size(void __iomem *core_offset);
27int e5010_hw_set_horizontal_size(void __iomem *core_offset, u32 val);
28int e5010_hw_set_vertical_size(void __iomem *core_offset, u32 val);
29int e5010_hw_set_luma_stride(void __iomem *core_offset, u32 bytesperline);
30int e5010_hw_set_chroma_stride(void __iomem *core_offset, u32 bytesperline);
31int e5010_hw_set_input_subsampling(void __iomem *core_offset, u32 val);
32int e5010_hw_set_chroma_order(void __iomem *core_offset, u32 val);
33int e5010_hw_set_qpvalue(void __iomem *core_offset, u32 offset, u32 value);
34void e5010_reset(struct device *dev, void __iomem *core_offset, void __iomem *mmu_offset);
35void e5010_hw_set_output_max_size(void __iomem *core_offset, u32 val);
36void e5010_hw_clear_picture_done(void __iomem *core_offset, u32 clear);
37void e5010_hw_encode_start(void __iomem *core_offset, u32 start);
38void e5010_hw_clear_output_error(void __iomem *core_offset, u32 clear);
39void e5010_hw_bypass_mmu(void __iomem *mmu_base, u32 enable);
40bool e5010_hw_pic_done_irq(void __iomem *core_base);
41bool 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 */
36static const struct of_device_id e5010_of_match[];
37
38static const struct v4l2_file_operations e5010_fops;
39
40static const struct v4l2_ioctl_ops e5010_ioctl_ops;
41
42static const struct vb2_ops e5010_video_ops;
43
44static const struct v4l2_m2m_ops e5010_m2m_ops;
45
46static 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
131static unsigned int debug;
132module_param(debug, uint, 0644);
133MODULE_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
138static const struct v4l2_event e5010_eos_event = {
139 .type = V4L2_EVENT_EOS
140};
141
142static 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
154static 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
159static 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
190static 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
219static 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
231static 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
239static 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
252static 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
280static 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
318static 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
381static 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
388static 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
437static 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
463static 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
491static 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
565static 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
579static 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
622static 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
641static const struct v4l2_ctrl_ops e5010_ctrl_ops = {
642 .s_ctrl = e5010_s_ctrl,
643};
644
645static 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
651static 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
673static 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
728static 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
770err_ctrls_setup:
771 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
772exit:
773 v4l2_fh_del(&ctx->fh);
774 v4l2_fh_exit(&ctx->fh);
775 mutex_unlock(&e5010->mutex);
776free:
777 kfree(ctx);
778 return ret;
779}
780
781static 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
798static 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
816static 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
859static 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
888static 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
910static 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
919static 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
985job_unlock:
986 spin_unlock(&e5010->hw_lock);
987 return IRQ_HANDLED;
988}
989
990static 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
1022static 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
1117fail_after_video_register_device:
1118 v4l2_m2m_release(e5010->m2m_dev);
1119fail_after_v4l2_register:
1120 v4l2_device_unregister(&e5010->v4l2_dev);
1121 return ret;
1122}
1123
1124static 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
1134static 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
1155static 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
1185static 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
1197static 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
1210static 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
1238static 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
1257static 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
1289static 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
1313fail:
1314 e5010_vb2_buffers_return(q, VB2_BUF_STATE_QUEUED);
1315
1316 return ret;
1317}
1318
1319static 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
1336static 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
1473device_busy_err:
1474 e5010_reset(e5010->dev, e5010->core_base, e5010->mmu_base);
1475
1476no_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
1493static 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
1507static 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
1518static 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
1527static 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
1548static 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
1554static 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
1590static 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
1602static 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
1611static const struct v4l2_m2m_ops e5010_m2m_ops = {
1612 .device_run = e5010_device_run,
1613};
1614
1615static const struct of_device_id e5010_of_match[] = {
1616 {.compatible = "img,e5010-jpeg-enc"}, { /* end */},
1617};
1618MODULE_DEVICE_TABLE(of, e5010_of_match);
1619
1620static 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};
1629module_platform_driver(e5010_driver);
1630
1631MODULE_LICENSE("GPL");
1632MODULE_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 */
73struct 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 */
91struct 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 */
111struct 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 */
127struct e5010_buffer {
128 struct v4l2_m2m_buffer buffer;
129};
130
131enum {
132 CHROMA_ORDER_CB_CR = 0, //UV ordering
133 CHROMA_ORDER_CR_CB = 1, //VU ordering
134};
135
136enum {
137 SUBSAMPLING_420 = 1,
138 SUBSAMPLING_422 = 2,
139};
140
141/*
142 * e5010 format structure
143 * contains format information
144 */
145struct 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 */
157struct 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
43#include <linux/videodev2.h>43#include <linux/videodev2.h>
44 44
45#include <linux/platform_data/media/camera-pxa.h>45#include <linux/platform_data/media/camera-pxa.h>
46#include <linux/workqueue.h>
46 47
47#define PXA_CAM_VERSION "0.0.6"48#define PXA_CAM_VERSION "0.0.6"
48#define PXA_CAM_DRV_NAME "pxa27x-camera"49#define PXA_CAM_DRV_NAME "pxa27x-camera"
@@ -683,7 +684,7 @@ struct pxa_camera_dev { · 634 unmodified lines
683 unsigned int buf_sequence;684 unsigned int buf_sequence;
684 685
685 struct pxa_buffer *active;686 struct pxa_buffer *active;
686 struct tasklet_struct task_eof;687 struct work_struct eof_bh_work;
687 688
688 u32 save_cicr[5];689 u32 save_cicr[5];
689};690};
@@ -1146,9 +1147,9 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) · 456 unmodified lines
1146 clk_disable_unprepare(pcdev->clk);1147 clk_disable_unprepare(pcdev->clk);
1147}1148}
1148 1149
1149static void pxa_camera_eof(struct tasklet_struct *t)1150static void pxa_camera_eof_bh_work(struct work_struct *t)
1150{1151{
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);
1152 unsigned long cifr;1153 unsigned long cifr;
1153 struct pxa_buffer *buf;1154 struct pxa_buffer *buf;
1154 1155
@@ -1185,7 +1186,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) · 30 unmodified lines
1185 if (status & CISR_EOF) {1186 if (status & CISR_EOF) {
1186 cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM;1187 cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM;
1187 __raw_writel(cicr0, pcdev->base + CICR0);1188 __raw_writel(cicr0, pcdev->base + CICR0);
1188 tasklet_schedule(&pcdev->task_eof);1189 queue_work(system_bh_wq, &pcdev->eof_bh_work);
1189 }1190 }
1190 1191
1191 return IRQ_HANDLED;1192 return IRQ_HANDLED;
@@ -2383,7 +2384,7 @@ static int pxa_camera_probe(struct platform_device *pdev) · 1191 unmodified lines
2383 }2384 }
2384 }2385 }
2385 2386
2386 tasklet_setup(&pcdev->task_eof, pxa_camera_eof);2387 INIT_WORK(&pcdev->eof_bh_work, pxa_camera_eof_bh_work);
2387 2388
2388 pxa_camera_activate(pcdev);2389 pxa_camera_activate(pcdev);
2389 2390
@@ -2409,7 +2410,7 @@ static int pxa_camera_probe(struct platform_device *pdev) · 19 unmodified lines
2409 return 0;2410 return 0;
2410exit_deactivate:2411exit_deactivate:
2411 pxa_camera_deactivate(pcdev);2412 pxa_camera_deactivate(pcdev);
2412 tasklet_kill(&pcdev->task_eof);2413 cancel_work_sync(&pcdev->eof_bh_work);
2413exit_free_dma:2414exit_free_dma:
2414 dma_release_channel(pcdev->dma_chans[2]);2415 dma_release_channel(pcdev->dma_chans[2]);
2415exit_free_dma_u:2416exit_free_dma_u:
@@ -2428,7 +2429,7 @@ static void pxa_camera_remove(struct platform_device *pdev) · 12 unmodified lines
2428 struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);2429 struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
2429 2430
2430 pxa_camera_deactivate(pcdev);2431 pxa_camera_deactivate(pcdev);
2431 tasklet_kill(&pcdev->task_eof);2432 cancel_work_sync(&pcdev->eof_bh_work);
2432 dma_release_channel(pcdev->dma_chans[0]);2433 dma_release_channel(pcdev->dma_chans[0]);
2433 dma_release_channel(pcdev->dma_chans[1]);2434 dma_release_channel(pcdev->dma_chans[1]);
2434 dma_release_channel(pcdev->dma_chans[2]);2435 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
724/*724/*
725 * Queue operations725 * Queue operations
726 */726 */
727struct vb2_dc_conf {
728 struct device *dev;
729};
730
731static int deinterlace_queue_setup(struct vb2_queue *vq,727static int deinterlace_queue_setup(struct vb2_queue *vq,
732 unsigned int *nbuffers, unsigned int *nplanes,728 unsigned int *nbuffers, unsigned int *nplanes,
733 unsigned int sizes[], struct device *alloc_devs[])729 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
439/*439/*
440 * Copy data out to user space in the vmalloc case440 * Copy data out to user space in the vmalloc case
441 */441 */
442static void mcam_frame_tasklet(struct tasklet_struct *t)442static void mcam_frame_work(struct work_struct *t)
443{443{
444 struct mcam_camera *cam = from_tasklet(cam, t, s_tasklet);444 struct mcam_camera *cam = from_work(cam, t, s_bh_work);
445 int i;445 int i;
446 unsigned long flags;446 unsigned long flags;
447 struct mcam_vb_buffer *buf;447 struct mcam_vb_buffer *buf;
@@ -493,7 +493,7 @@ static int mcam_check_dma_buffers(struct mcam_camera *cam) · 45 unmodified lines
493 493
494static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)494static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
495{495{
496 tasklet_schedule(&cam->s_tasklet);496 queue_work(system_bh_wq, &cam->s_bh_work);
497}497}
498 498
499#else /* MCAM_MODE_VMALLOC */499#else /* MCAM_MODE_VMALLOC */
@@ -1305,7 +1305,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam) · 805 unmodified lines
1305 break;1305 break;
1306 case B_vmalloc:1306 case B_vmalloc:
1307#ifdef MCAM_MODE_VMALLOC1307#ifdef MCAM_MODE_VMALLOC
1308 tasklet_setup(&cam->s_tasklet, mcam_frame_tasklet);1308 INIT_WORK(&cam->s_bh_work, mcam_frame_work);
1309 vq->ops = &mcam_vb2_ops;1309 vq->ops = &mcam_vb2_ops;
1310 vq->mem_ops = &vb2_vmalloc_memops;1310 vq->mem_ops = &vb2_vmalloc_memops;
1311 cam->dma_setup = mcam_ctlr_dma_vmalloc;1311 cam->dma_setup = mcam_ctlr_dma_vmalloc;
@@ -1981,5 +1981,6 @@ int mccic_resume(struct mcam_camera *cam) · 669 unmodified lines
1981}1981}
1982EXPORT_SYMBOL_GPL(mccic_resume);1982EXPORT_SYMBOL_GPL(mccic_resume);
1983 1983
1984MODULE_DESCRIPTION("Marvell camera core driver");
1984MODULE_LICENSE("GPL v2");1985MODULE_LICENSE("GPL v2");
1985MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");1986MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
drivers/media/platform/marvell/mcam-core.h+2−1
@@ -9,6 +9,7 @@ · 8 unmodified lines
9 9
10#include <linux/list.h>10#include <linux/list.h>
11#include <linux/clk-provider.h>11#include <linux/clk-provider.h>
12#include <linux/workqueue.h>
12#include <media/v4l2-common.h>13#include <media/v4l2-common.h>
13#include <media/v4l2-ctrls.h>14#include <media/v4l2-ctrls.h>
14#include <media/v4l2-dev.h>15#include <media/v4l2-dev.h>
@@ -167,7 +168,7 @@ struct mcam_camera { · 152 unmodified lines
167 unsigned int dma_buf_size; /* allocated size */168 unsigned int dma_buf_size; /* allocated size */
168 void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */169 void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */
169 dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */170 dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
170 struct tasklet_struct s_tasklet;171 struct work_struct s_bh_work;
171#endif172#endif
172 unsigned int sequence; /* Frame sequence number */173 unsigned int sequence; /* Frame sequence number */
173 unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */174 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
30 30
31MODULE_ALIAS("platform:mmp-camera");31MODULE_ALIAS("platform:mmp-camera");
32MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");32MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
33MODULE_DESCRIPTION("Support for the camera device found on Marvell MMP processors");
33MODULE_LICENSE("GPL");34MODULE_LICENSE("GPL");
34 35
35static char *mcam_clks[] = {"axi", "func", "phy"};36static 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
46 MT8183_MDP_COMP_WROT1, /* 25 */46 MT8183_MDP_COMP_WROT1, /* 25 */
47};47};
48 48
49enum 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
49enum mt8195_mdp_comp_id {96enum mt8195_mdp_comp_id {
50 /* MT8195 Comp id */97 /* MT8195 Comp id */
51 /* ISP */98 /* ISP */
@@ -123,6 +170,13 @@ static const struct of_device_id mt8183_mdp_probe_infra[MDP_INFRA_MAX] = { · 71 unmodified lines
123 [MDP_INFRA_SCP] = { .compatible = "mediatek,mt8183-scp" }170 [MDP_INFRA_SCP] = { .compatible = "mediatek,mt8183-scp" }
124};171};
125 172
173static 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
126static const struct of_device_id mt8195_mdp_probe_infra[MDP_INFRA_MAX] = {180static const struct of_device_id mt8195_mdp_probe_infra[MDP_INFRA_MAX] = {
127 [MDP_INFRA_MMSYS] = { .compatible = "mediatek,mt8195-vppsys0" },181 [MDP_INFRA_MMSYS] = { .compatible = "mediatek,mt8195-vppsys0" },
128 [MDP_INFRA_MMSYS2] = { .compatible = "mediatek,mt8195-vppsys1" },182 [MDP_INFRA_MMSYS2] = { .compatible = "mediatek,mt8195-vppsys1" },
@@ -167,6 +221,40 @@ static const u32 mt8183_mutex_idx[MDP_MAX_COMP_COUNT] = { · 38 unmodified lines
167 [MDP_COMP_CCORR0] = MUTEX_MOD_IDX_MDP_CCORR0,221 [MDP_COMP_CCORR0] = MUTEX_MOD_IDX_MDP_CCORR0,
168};222};
169 223
224static 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
170static const u32 mt8195_mutex_idx[MDP_MAX_COMP_COUNT] = {258static const u32 mt8195_mutex_idx[MDP_MAX_COMP_COUNT] = {
171 [MDP_COMP_RDMA0] = MUTEX_MOD_IDX_MDP_RDMA0,259 [MDP_COMP_RDMA0] = MUTEX_MOD_IDX_MDP_RDMA0,
172 [MDP_COMP_RDMA1] = MUTEX_MOD_IDX_MDP_RDMA1,260 [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
288 },376 },
289};377};
290 378
379static 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
291static const struct mdp_comp_data mt8195_mdp_comp_data[MDP_MAX_COMP_COUNT] = {544static const struct mdp_comp_data mt8195_mdp_comp_data[MDP_MAX_COMP_COUNT] = {
292 [MDP_COMP_WPEI] = {545 [MDP_COMP_WPEI] = {
293 {MDP_COMP_TYPE_WPEI, 0, MT8195_MDP_COMP_WPEI, MDP_MM_SUBSYS_0},546 {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
1046 [MDP_PIPE_RDMA0] = {MDP_PIPE_RDMA0, MDP_MM_SUBSYS_0, 3}1299 [MDP_PIPE_RDMA0] = {MDP_PIPE_RDMA0, MDP_MM_SUBSYS_0, 3}
1047};1300};
1048 1301
1302static 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
1049static const struct mdp_pipe_info mt8195_pipe_info[] = {1311static const struct mdp_pipe_info mt8195_pipe_info[] = {
1050 [MDP_PIPE_WPEI] = {MDP_PIPE_WPEI, MDP_MM_SUBSYS_0, 0},1312 [MDP_PIPE_WPEI] = {MDP_PIPE_WPEI, MDP_MM_SUBSYS_0, 0},
1051 [MDP_PIPE_WPEI2] = {MDP_PIPE_WPEI2, MDP_MM_SUBSYS_0, 1},1313 [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
1082 .pp_used = MDP_PP_USED_1,1344 .pp_used = MDP_PP_USED_1,
1083};1345};
1084 1346
1347const 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
1085const struct mtk_mdp_driver_data mt8195_mdp_driver_data = {1365const struct mtk_mdp_driver_data mt8195_mdp_driver_data = {
1086 .mdp_plat_id = MT8195,1366 .mdp_plat_id = MT8195,
1087 .mdp_con_res = 0x14001000,1367 .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
116 116
117/* Platform config indicator */117/* Platform config indicator */
118#define MT8183 8183118#define MT8183 8183
119#define MT8188 8195
119#define MT8195 8195120#define MT8195 8195
120 121
121#define CFG_CHECK(plat, p_id) ((plat) == (p_id))122#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
10#include <linux/types.h>10#include <linux/types.h>
11 11
12extern const struct mtk_mdp_driver_data mt8183_mdp_driver_data;12extern const struct mtk_mdp_driver_data mt8183_mdp_driver_data;
13extern const struct mtk_mdp_driver_data mt8188_mdp_driver_data;
13extern const struct mtk_mdp_driver_data mt8195_mdp_driver_data;14extern const struct mtk_mdp_driver_data mt8195_mdp_driver_data;
14 15
15struct mdp_dev;16struct 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
21 { .compatible = "mediatek,mt8183-mdp3-rdma",21 { .compatible = "mediatek,mt8183-mdp3-rdma",
22 .data = &mt8183_mdp_driver_data,22 .data = &mt8183_mdp_driver_data,
23 },23 },
24 { .compatible = "mediatek,mt8188-mdp3-rdma",
25 .data = &mt8188_mdp_driver_data,
26 },
24 { .compatible = "mediatek,mt8195-mdp3-rdma",27 { .compatible = "mediatek,mt8195-mdp3-rdma",
25 .data = &mt8195_mdp_driver_data,28 .data = &mt8195_mdp_driver_data,
26 },29 },
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
63 id = dec_ctx->id;63 id = dec_ctx->id;
64 }64 }
65 65
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);
67 if (!mem->va) {68 if (!mem->va) {
68 mtk_v4l2_err(plat_dev, "%s dma_alloc size=0x%zx failed!",69 mtk_v4l2_err(plat_dev, "%s dma_alloc size=0x%zx failed!",
69 __func__, mem->size);70 __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
80 return &ctx->q_data[MTK_Q_DATA_DST];80 return &ctx->q_data[MTK_Q_DATA_DST];
81}81}
82 82
83static int vidioc_try_decoder_cmd(struct file *file, void *priv,83static int stateful_try_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd)
84 struct v4l2_decoder_cmd *cmd)
85{84{
86 return v4l2_m2m_ioctl_try_decoder_cmd(file, priv, cmd);85 return v4l2_m2m_ioctl_try_decoder_cmd(file, priv, cmd);
87}86}
88 87
89 88static int stateful_decoder_cmd(struct file *file, void *priv, struct v4l2_decoder_cmd *cmd)
90static int vidioc_decoder_cmd(struct file *file, void *priv,
91 struct v4l2_decoder_cmd *cmd)
92{89{
93 struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv);90 struct mtk_vcodec_dec_ctx *ctx = fh_to_dec_ctx(priv);
94 struct vb2_queue *src_vq, *dst_vq;91 struct vb2_queue *src_vq, *dst_vq;
95 int ret;92 int ret;
96 93
97 ret = vidioc_try_decoder_cmd(file, priv, cmd);94 ret = stateful_try_decoder_cmd(file, priv, cmd);
98 if (ret)95 if (ret)
99 return ret;96 return ret;
100 97
@@ -128,6 +125,57 @@ static int vidioc_decoder_cmd(struct file *file, void *priv, · 27 unmodified lines
128 return 0;125 return 0;
129}126}
130 127
128static 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
133static 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
159static 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
169static 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
131void mtk_vdec_unlock(struct mtk_vcodec_dec_ctx *ctx)179void mtk_vdec_unlock(struct mtk_vcodec_dec_ctx *ctx)
132{180{
133 mutex_unlock(&ctx->dev->dec_mutex[ctx->hw_id]);181 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
449 inst->frm_cnt, y_fb_dma, c_fb_dma, fb);449 inst->frm_cnt, y_fb_dma, c_fb_dma, fb);
450 450
451 inst->cur_fb = fb;451 inst->cur_fb = fb;
452 dec->bs_dma = (uint64_t)bs->dma_addr;452 dec->bs_dma = bs->dma_addr;
453 dec->bs_sz = bs->size;453 dec->bs_sz = bs->size;
454 dec->cur_y_fb_dma = y_fb_dma;454 dec->cur_y_fb_dma = y_fb_dma;
455 dec->cur_c_fb_dma = c_fb_dma;455 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
233 mtk_vdec_debug(vpu->ctx, "vdec_inst=%p", vpu);233 mtk_vdec_debug(vpu->ctx, "vdec_inst=%p", vpu);
234 234
235 err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg));235 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
236 mtk_vdec_debug(vpu->ctx, "- ret=%d", err);242 mtk_vdec_debug(vpu->ctx, "- ret=%d", err);
237 return err;243 return err;
238}244}
drivers/media/platform/nvidia/tegra-vde/h264.c+0−5
@@ -19,11 +19,6 @@ · 18 unmodified lines
19#define FLAG_B_FRAME 0x119#define FLAG_B_FRAME 0x1
20#define FLAG_REFERENCE 0x220#define FLAG_REFERENCE 0x2
21 21
22struct tegra_vde_h264_frame {
23 unsigned int frame_num;
24 unsigned int flags;
25};
26
27struct tegra_vde_h264_decoder_ctx {22struct tegra_vde_h264_decoder_ctx {
28 unsigned int dpb_frames_nb;23 unsigned int dpb_frames_nb;
29 unsigned int dpb_ref_frames_with_earlier_poc_nb;24 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
47struct iommu_domain;47struct iommu_domain;
48struct reset_control;48struct reset_control;
49struct dma_buf_attachment;49struct dma_buf_attachment;
50struct tegra_vde_h264_frame;
51struct tegra_vde_h264_decoder_ctx;50struct tegra_vde_h264_decoder_ctx;
52 51
53struct tegra_video_frame {52struct 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
1634 dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);1634 dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
1635 q_data->sequence = 0;1635 q_data->sequence = 0;
1636 1636
1637 if (V4L2_TYPE_IS_CAPTURE(q->type))
1638 ctx->need_initial_source_change_evt = false;
1639
1637 ret = pm_runtime_resume_and_get(ctx->mxc_jpeg->dev);1640 ret = pm_runtime_resume_and_get(ctx->mxc_jpeg->dev);
1638 if (ret < 0) {1641 if (ret < 0) {
1639 dev_err(ctx->mxc_jpeg->dev, "Failed to power up jpeg\n");1642 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
1840 1843
1841 q_data_out = mxc_jpeg_get_q_data(ctx,1844 q_data_out = mxc_jpeg_get_q_data(ctx,
1842 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);1845 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 }
1854 q_data_out->w = header.frame.width;1846 q_data_out->w = header.frame.width;
1855 q_data_out->h = header.frame.height;1847 q_data_out->h = header.frame.height;
1856 if (header.frame.width > MXC_JPEG_MAX_WIDTH ||1848 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
320 struct v4l2_subdev sd;320 struct v4l2_subdev sd;
321 struct media_pad pads[CSIS_PADS_NUM];321 struct media_pad pads[CSIS_PADS_NUM];
322 struct v4l2_async_notifier notifier;322 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;
324 328
325 struct v4l2_mbus_config_mipi_csi2 bus;329 struct v4l2_mbus_config_mipi_csi2 bus;
326 u32 clk_frequency;330 u32 clk_frequency;
@@ -597,7 +601,7 @@ static int mipi_csis_calculate_params(struct mipi_csis_device *csis, · 270 unmodified lines
597 u32 lane_rate;601 u32 lane_rate;
598 602
599 /* Calculate the line rate from the pixel rate. */603 /* 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,
601 csis_fmt->width,605 csis_fmt->width,
602 csis->bus.num_data_lanes * 2);606 csis->bus.num_data_lanes * 2);
603 if (link_freq < 0) {607 if (link_freq < 0) {
@@ -958,7 +962,8 @@ static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable) · 354 unmodified lines
958 int ret;962 int ret;
959 963
960 if (!enable) {964 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));
962 967
963 mipi_csis_stop_stream(csis);968 mipi_csis_stop_stream(csis);
964 if (csis->debug.enable)969 if (csis->debug.enable)
@@ -986,7 +991,8 @@ static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable) · 21 unmodified lines
986 991
987 mipi_csis_start_stream(csis, format, csis_fmt);992 mipi_csis_start_stream(csis, format, csis_fmt);
988 993
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));
990 if (ret < 0)996 if (ret < 0)
991 goto err_stop;997 goto err_stop;
992 998
@@ -1233,12 +1239,14 @@ static int mipi_csis_link_setup(struct media_entity *entity, · 240 unmodified lines
1233 remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);1239 remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
1234 1240
1235 if (flags & MEDIA_LNK_FL_ENABLED) {1241 if (flags & MEDIA_LNK_FL_ENABLED) {
1236 if (csis->src_sd)1242 if (csis->source.sd)
1237 return -EBUSY;1243 return -EBUSY;
1238 1244
1239 csis->src_sd = remote_sd;1245 csis->source.sd = remote_sd;
1246 csis->source.pad = remote_pad;
1240 } else {1247 } else {
1241 csis->src_sd = NULL;1248 csis->source.sd = NULL;
1249 csis->source.pad = NULL;
1242 }1250 }
1243 1251
1244 return 0;1252 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
1805 return PTR_ERR(mmio);1805 return PTR_ERR(mmio);
1806 dev->regmap = devm_regmap_init_mmio(&pdev->dev, mmio,1806 dev->regmap = devm_regmap_init_mmio(&pdev->dev, mmio,
1807 &pxp_regmap_config);1807 &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");
1808 1811
1809 irq = platform_get_irq(pdev, 0);1812 irq = platform_get_irq(pdev, 0);
1810 if (irq < 0)1813 if (irq < 0)
drivers/media/platform/qcom/camss/Makefile+1−0
@@ -19,5 +19,6 @@ qcom-camss-objs += \ · 18 unmodified lines
19 camss-vfe-gen1.o \19 camss-vfe-gen1.o \
20 camss-vfe.o \20 camss-vfe.o \
21 camss-video.o \21 camss-video.o \
22 camss-format.o \
22 23
23obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom-camss.o24obj-$(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
45#define CAMSS_CSID_TG_DT_n_CGG_1(n) (0x0b0 + 0xc * (n))45#define CAMSS_CSID_TG_DT_n_CGG_1(n) (0x0b0 + 0xc * (n))
46#define CAMSS_CSID_TG_DT_n_CGG_2(n) (0x0b4 + 0xc * (n))46#define CAMSS_CSID_TG_DT_n_CGG_2(n) (0x0b4 + 0xc * (n))
47 47
48static 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
170static void csid_configure_stream(struct csid_device *csid, u8 enable)48static void csid_configure_stream(struct csid_device *csid, u8 enable)
171{49{
172 struct csid_testgen_config *tg = &csid->testgen;50 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
174 52
175 if (enable) {53 if (enable) {
176 struct v4l2_mbus_framefmt *input_format;54 struct v4l2_mbus_framefmt *input_format;
177 const struct csid_format *format;55 const struct csid_format_info *format;
178 u8 vc = 0; /* Virtual Channel 0 */56 u8 vc = 0; /* Virtual Channel 0 */
179 u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */57 u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */
180 u8 dt_shift;58 u8 dt_shift;
@@ -184,7 +62,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 3 unmodified lines
184 u32 num_lines, num_bytes_per_line;62 u32 num_lines, num_bytes_per_line;
185 63
186 input_format = &csid->fmt[MSM_CSID_PAD_SRC];64 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,
188 input_format->code);67 input_format->code);
189 num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;68 num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;
190 num_lines = input_format->height;69 num_lines = input_format->height;
@@ -211,7 +90,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 20 unmodified lines
211 struct csid_phy_config *phy = &csid->phy;90 struct csid_phy_config *phy = &csid->phy;
212 91
213 input_format = &csid->fmt[MSM_CSID_PAD_SINK];92 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,
215 input_format->code);95 input_format->code);
216 96
217 val = phy->lane_cnt - 1;97 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
311 191
312static void csid_subdev_init(struct csid_device *csid)192static void csid_subdev_init(struct csid_device *csid)
313{193{
314 csid->formats = csid_formats;
315 csid->nformats = ARRAY_SIZE(csid_formats);
316 csid->testgen.modes = csid_testgen_modes;194 csid->testgen.modes = csid_testgen_modes;
317 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1;195 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1;
318}196}
drivers/media/platform/qcom/camss/camss-csid-4-7.c+5−155
@@ -44,156 +44,6 @@ · 43 unmodified lines
44#define CAMSS_CSID_TG_DT_n_CGG_1(n) (0x0b8 + 0xc * (n))44#define CAMSS_CSID_TG_DT_n_CGG_1(n) (0x0b8 + 0xc * (n))
45#define CAMSS_CSID_TG_DT_n_CGG_2(n) (0x0bc + 0xc * (n))45#define CAMSS_CSID_TG_DT_n_CGG_2(n) (0x0bc + 0xc * (n))
46 46
47static 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
197static void csid_configure_stream(struct csid_device *csid, u8 enable)47static void csid_configure_stream(struct csid_device *csid, u8 enable)
198{48{
199 struct csid_testgen_config *tg = &csid->testgen;49 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
203 53
204 if (enable) {54 if (enable) {
205 struct v4l2_mbus_framefmt *input_format;55 struct v4l2_mbus_framefmt *input_format;
206 const struct csid_format *format;56 const struct csid_format_info *format;
207 u8 vc = 0; /* Virtual Channel 0 */57 u8 vc = 0; /* Virtual Channel 0 */
208 u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */58 u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */
209 u8 dt_shift;59 u8 dt_shift;
@@ -213,7 +63,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 3 unmodified lines
213 u32 num_bytes_per_line, num_lines;63 u32 num_bytes_per_line, num_lines;
214 64
215 input_format = &csid->fmt[MSM_CSID_PAD_SRC];65 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,
217 input_format->code);68 input_format->code);
218 num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;69 num_bytes_per_line = input_format->width * format->bpp * format->spp / 8;
219 num_lines = input_format->height;70 num_lines = input_format->height;
@@ -240,7 +91,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) · 20 unmodified lines
240 struct csid_phy_config *phy = &csid->phy;91 struct csid_phy_config *phy = &csid->phy;
241 92
242 input_format = &csid->fmt[MSM_CSID_PAD_SINK];93 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,
244 input_format->code);96 input_format->code);
245 97
246 val = phy->lane_cnt - 1;98 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
387 239
388static void csid_subdev_init(struct csid_device *csid)240static void csid_subdev_init(struct csid_device *csid)
389{241{
390 csid->formats = csid_formats;
391 csid->nformats = ARRAY_SIZE(csid_formats);
392 csid->testgen.modes = csid_testgen_modes;242 csid->testgen.modes = csid_testgen_modes;
393 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1;243 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1;
394}244}
drivers/media/platform/qcom/camss/camss-csid-gen2.c+135−272
@@ -176,306 +176,171 @@ · 175 unmodified lines
176#define TPG_COLOR_BOX_CFG_MODE 0176#define TPG_COLOR_BOX_CFG_MODE 0
177#define TPG_COLOR_BOX_PATTERN_SEL 2177#define TPG_COLOR_BOX_PATTERN_SEL 2
178 178
179static const struct csid_format csid_formats[] = {179static void __csid_configure_rx(struct csid_device *csid,
180 {180 struct csid_phy_config *phy, int vc)
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
336static void __csid_configure_stream(struct csid_device *csid, u8 enable, u8 vc)
337{181{
338 struct csid_testgen_config *tg = &csid->testgen;
339 u32 val;
340 u32 phy_sel = 0;
341 u8 lane_cnt = csid->phy.lane_cnt;182 u8 lane_cnt = csid->phy.lane_cnt;
342 /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */183 int val;
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);
346 184
347 if (!lane_cnt)185 if (!lane_cnt)
348 lane_cnt = 4;186 lane_cnt = 4;
349 187
350 if (!tg->enabled)188 val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
351 phy_sel = csid->phy.csiphy_id;189 val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
352 190 val |= phy->csiphy_id << CSI2_RX_CFG0_PHY_NUM_SEL;
353 if (enable) {191 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);
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 }
397 192
398 val = 1 << RDI_CFG0_BYTE_CNTR_EN;193 val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;
399 val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;194 if (vc > 3)
400 val |= 1 << RDI_CFG0_TIMESTAMP_EN;195 val |= 1 << CSI2_RX_CFG1_VC_MODE;
401 /* note: for non-RDI path, this should be format->decode_format */196 val |= 1 << CSI2_RX_CFG1_MISR_EN;
402 val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;197 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);
403 val |= format->data_type << RDI_CFG0_DATA_TYPE;198}
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));
407 199
408 /* CSID_TIMESTAMP_STB_POST_IRQ */200static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi)
409 val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;201{
410 writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));202 int val;
411 203
412 val = 1;204 if (enable)
413 writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));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}
414 210
415 val = 0;211static void __csid_configure_testgen(struct csid_device *csid, u8 enable, u8 vc)
416 writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(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;
417 220
418 val = 1;221 if (!lane_cnt)
419 writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));222 lane_cnt = 4;
420 223
421 val = 0;224 /* configure one DT, infinite frames */
422 writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));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);
423 229
424 val = 1;230 val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT;
425 writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));231 val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT;
232 writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1);
426 233
427 val = 0;234 writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
428 writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
429 235
430 val = 1;236 val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT;
431 writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));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));
432 239
433 val = 0;240 val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
434 writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));241 writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
435 242
436 val = 0;243 val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE;
437 writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));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));
438 247
439 val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));248 writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG);
440 val |= 1 << RDI_CFG0_ENABLE;
441 writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
442 }
443 249
444 if (tg->enabled) {250 writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG);
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 }
453 251
454 val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;252 val = enable << TPG_CTRL_TEST_EN;
455 val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;253 val |= 1 << TPG_CTRL_FS_PKT_EN;
456 val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL;254 val |= 1 << TPG_CTRL_FE_PKT_EN;
457 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0);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}
458 260
459 val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN;261static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc)
460 if (vc > 3)262{
461 val |= 1 << CSI2_RX_CFG1_VC_MODE;263 /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
462 val |= 1 << CSI2_RX_CFG1_MISR_EN;264 struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
463 writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1);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;
464 269
465 if (enable)270 /*
466 val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;271 * DT_ID is a two bit bitfield that is concatenated with
467 else272 * the four least significant bits of the five bit VC
468 val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD;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;
469 writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));323 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));
470}328}
471 329
472static void csid_configure_stream(struct csid_device *csid, u8 enable)330static void csid_configure_stream(struct csid_device *csid, u8 enable)
473{331{
332 struct csid_testgen_config *tg = &csid->testgen;
474 u8 i;333 u8 i;
475 /* Loop through all enabled VCs and configure stream for each */334 /* Loop through all enabled VCs and configure stream for each */
476 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)335 for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
477 if (csid->phy.en_vc & BIT(i))336 if (csid->phy.en_vc & BIT(i)) {
478 __csid_configure_stream(csid, enable, 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 }
479}344}
480 345
481static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val)346static 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
612 477
613static void csid_subdev_init(struct csid_device *csid)478static void csid_subdev_init(struct csid_device *csid)
614{479{
615 csid->formats = csid_formats;
616 csid->nformats = ARRAY_SIZE(csid_formats);
617 csid->testgen.modes = csid_testgen_modes;480 csid->testgen.modes = csid_testgen_modes;
618 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2;481 csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2;
619}482}
drivers/media/platform/qcom/camss/camss-csid.c+481−31
@@ -45,6 +45,450 @@ const char * const csid_testgen_modes[] = { · 44 unmodified lines
45 NULL45 NULL
46};46};
47 47
48static 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
170static 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
320static 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
477const struct csid_formats csid_formats_4_1 = {
478 .nformats = ARRAY_SIZE(formats_4_1),
479 .formats = formats_4_1
480};
481
482const struct csid_formats csid_formats_4_7 = {
483 .nformats = ARRAY_SIZE(formats_4_7),
484 .formats = formats_4_7
485};
486
487const struct csid_formats csid_formats_gen2 = {
488 .nformats = ARRAY_SIZE(formats_gen2),
489 .formats = formats_gen2
490};
491
48u32 csid_find_code(u32 *codes, unsigned int ncodes,492u32 csid_find_code(u32 *codes, unsigned int ncodes,
49 unsigned int match_format_idx, u32 match_code)493 unsigned int match_format_idx, u32 match_code)
50{494{
@@ -65,9 +509,9 @@ u32 csid_find_code(u32 *codes, unsigned int ncodes, · 14 unmodified lines
65 return codes[0];509 return codes[0];
66}510}
67 511
68const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats,512const struct csid_format_info *csid_get_fmt_entry(const struct csid_format_info *formats,
69 unsigned int nformats,513 unsigned int nformats,
70 u32 code)514 u32 code)
71{515{
72 unsigned int i;516 unsigned int i;
73 517
@@ -87,12 +531,12 @@ const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats, · 13 unmodified lines
87static int csid_set_clock_rates(struct csid_device *csid)531static int csid_set_clock_rates(struct csid_device *csid)
88{532{
89 struct device *dev = csid->camss->dev;533 struct device *dev = csid->camss->dev;
90 const struct csid_format *fmt;534 const struct csid_format_info *fmt;
91 s64 link_freq;535 s64 link_freq;
92 int i, j;536 int i, j;
93 int ret;537 int ret;
94 538
95 fmt = csid_get_fmt_entry(csid->formats, csid->nformats,539 fmt = csid_get_fmt_entry(csid->res->formats->formats, csid->res->formats->nformats,
96 csid->fmt[MSM_CSIPHY_PAD_SINK].code);540 csid->fmt[MSM_CSIPHY_PAD_SINK].code);
97 link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp,541 link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp,
98 csid->phy.lane_cnt);542 csid->phy.lane_cnt);
@@ -158,7 +602,6 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) · 59 unmodified lines
158 struct csid_device *csid = v4l2_get_subdevdata(sd);602 struct csid_device *csid = v4l2_get_subdevdata(sd);
159 struct camss *camss = csid->camss;603 struct camss *camss = csid->camss;
160 struct device *dev = camss->dev;604 struct device *dev = camss->dev;
161 struct vfe_device *vfe = &camss->vfe[csid->id];
162 int ret = 0;605 int ret = 0;
163 606
164 if (on) {607 if (on) {
@@ -167,7 +610,7 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) · 2 unmodified lines
167 * switching on the CSID. Do so unconditionally, as there is no610 * switching on the CSID. Do so unconditionally, as there is no
168 * drawback in following the same powering order on older SoCs.611 * drawback in following the same powering order on older SoCs.
169 */612 */
170 ret = vfe_get(vfe);613 ret = csid->res->parent_dev_ops->get(camss, csid->id);
171 if (ret < 0)614 if (ret < 0)
172 return ret;615 return ret;
173 616
@@ -202,7 +645,7 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) · 28 unmodified lines
202 645
203 enable_irq(csid->irq);646 enable_irq(csid->irq);
204 647
205 ret = csid->ops->reset(csid);648 ret = csid->res->hw_ops->reset(csid);
206 if (ret < 0) {649 if (ret < 0) {
207 disable_irq(csid->irq);650 disable_irq(csid->irq);
208 camss_disable_clocks(csid->nclocks, csid->clock);651 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
212 return ret;655 return ret;
213 }656 }
214 657
215 csid->ops->hw_version(csid);658 csid->res->hw_ops->hw_version(csid);
216 } else {659 } else {
217 disable_irq(csid->irq);660 disable_irq(csid->irq);
218 camss_disable_clocks(csid->nclocks, csid->clock);661 camss_disable_clocks(csid->nclocks, csid->clock);
219 regulator_bulk_disable(csid->num_supplies,662 regulator_bulk_disable(csid->num_supplies,
220 csid->supplies);663 csid->supplies);
221 pm_runtime_put_sync(dev);664 pm_runtime_put_sync(dev);
222 vfe_put(vfe);665 csid->res->parent_dev_ops->put(camss, csid->id);
223 }666 }
224 667
225 return ret;668 return ret;
@@ -253,7 +696,7 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) · 27 unmodified lines
253 }696 }
254 697
255 if (csid->phy.need_vc_update) {698 if (csid->phy.need_vc_update) {
256 csid->ops->configure_stream(csid, enable);699 csid->res->hw_ops->configure_stream(csid, enable);
257 csid->phy.need_vc_update = false;700 csid->phy.need_vc_update = false;
258 }701 }
259 702
@@ -301,12 +744,12 @@ static void csid_try_format(struct csid_device *csid, · 41 unmodified lines
301 case MSM_CSID_PAD_SINK:744 case MSM_CSID_PAD_SINK:
302 /* Set format on sink pad */745 /* Set format on sink pad */
303 746
304 for (i = 0; i < csid->nformats; i++)747 for (i = 0; i < csid->res->formats->nformats; i++)
305 if (fmt->code == csid->formats[i].code)748 if (fmt->code == csid->res->formats->formats[i].code)
306 break;749 break;
307 750
308 /* If not found, use UYVY as default */751 /* If not found, use UYVY as default */
309 if (i >= csid->nformats)752 if (i >= csid->res->formats->nformats)
310 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;753 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
311 754
312 fmt->width = clamp_t(u32, fmt->width, 1, 8191);755 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
325 768
326 *fmt = *__csid_get_format(csid, sd_state,769 *fmt = *__csid_get_format(csid, sd_state,
327 MSM_CSID_PAD_SINK, which);770 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);
329 } else {772 } else {
330 /* Test generator is enabled, set format on source */773 /* Test generator is enabled, set format on source */
331 /* pad to allow test generator usage */774 /* pad to allow test generator usage */
332 775
333 for (i = 0; i < csid->nformats; i++)776 for (i = 0; i < csid->res->formats->nformats; i++)
334 if (csid->formats[i].code == fmt->code)777 if (csid->res->formats->formats[i].code == fmt->code)
335 break;778 break;
336 779
337 /* If not found, use UYVY as default */780 /* If not found, use UYVY as default */
338 if (i >= csid->nformats)781 if (i >= csid->res->formats->nformats)
339 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;782 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
340 783
341 fmt->width = clamp_t(u32, fmt->width, 1, 8191);784 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
363 struct csid_device *csid = v4l2_get_subdevdata(sd);806 struct csid_device *csid = v4l2_get_subdevdata(sd);
364 807
365 if (code->pad == MSM_CSID_PAD_SINK) {808 if (code->pad == MSM_CSID_PAD_SINK) {
366 if (code->index >= csid->nformats)809 if (code->index >= csid->res->formats->nformats)
367 return -EINVAL;810 return -EINVAL;
368 811
369 code->code = csid->formats[code->index].code;812 code->code = csid->res->formats->formats[code->index].code;
370 } else {813 } else {
371 if (csid->testgen_mode->cur.val == 0) {814 if (csid->testgen_mode->cur.val == 0) {
372 struct v4l2_mbus_framefmt *sink_fmt;815 struct v4l2_mbus_framefmt *sink_fmt;
@@ -375,15 +818,15 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, · 2 unmodified lines
375 MSM_CSID_PAD_SINK,818 MSM_CSID_PAD_SINK,
376 code->which);819 code->which);
377 820
378 code->code = csid->ops->src_pad_code(csid, sink_fmt->code,821 code->code = csid->res->hw_ops->src_pad_code(csid, sink_fmt->code,
379 code->index, 0);822 code->index, 0);
380 if (!code->code)823 if (!code->code)
381 return -EINVAL;824 return -EINVAL;
382 } else {825 } else {
383 if (code->index >= csid->nformats)826 if (code->index >= csid->res->formats->nformats)
384 return -EINVAL;827 return -EINVAL;
385 828
386 code->code = csid->formats[code->index].code;829 code->code = csid->res->formats->formats[code->index].code;
387 }830 }
388 }831 }
389 832
@@ -529,7 +972,7 @@ static int csid_set_test_pattern(struct csid_device *csid, s32 value) · 139 unmodified lines
529 972
530 tg->enabled = !!value;973 tg->enabled = !!value;
531 974
532 return csid->ops->configure_testgen_pattern(csid, value);975 return csid->res->hw_ops->configure_testgen_pattern(csid, value);
533}976}
534 977
535/*978/*
@@ -575,9 +1018,14 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, · 39 unmodified lines
575 1018
576 csid->camss = camss;1019 csid->camss = camss;
577 csid->id = id;1020 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 }
579 1027
580 csid->ops->subdev_init(csid);1028 csid->res->hw_ops->subdev_init(csid);
581 1029
582 /* Memory */1030 /* Memory */
583 1031
@@ -587,9 +1035,11 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, · 3 unmodified lines
587 * VFE to be initialized before CSID1035 * VFE to be initialized before CSID
588 */1036 */
589 if (id >= 2) /* VFE/CSID lite */1037 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;
591 else1040 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;
593 } else {1043 } else {
594 csid->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]);1044 csid->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]);
595 if (IS_ERR(csid->base))1045 if (IS_ERR(csid->base))
@@ -605,7 +1055,7 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, · 9 unmodified lines
605 csid->irq = ret;1055 csid->irq = ret;
606 snprintf(csid->irq_name, sizeof(csid->irq_name), "%s_%s%d",1056 snprintf(csid->irq_name, sizeof(csid->irq_name), "%s_%s%d",
607 dev_name(dev), MSM_CSID_NAME, csid->id);1057 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,
609 IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN,1059 IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN,
610 csid->irq_name, csid);1060 csid->irq_name, csid);
611 if (ret < 0) {1061 if (ret < 0) {
@@ -899,5 +1349,5 @@ void msm_csid_unregister_entity(struct csid_device *csid) · 287 unmodified lines
899 1349
900inline bool csid_is_lite(struct csid_device *csid)1350inline bool csid_is_lite(struct csid_device *csid)
901{1351{
902 return csid->camss->res->csid_res[csid->id].is_lite;1352 return csid->camss->res->csid_res[csid->id].csid.is_lite;
903}1353}
drivers/media/platform/qcom/camss/camss-csid.h+23−9
@@ -67,7 +67,7 @@ enum csid_testgen_mode { · 66 unmodified lines
67 CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2 = 9, /* excluding disabled */67 CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2 = 9, /* excluding disabled */
68};68};
69 69
70struct csid_format {70struct csid_format_info {
71 u32 code;71 u32 code;
72 u8 data_type;72 u8 data_type;
73 u8 decode_format;73 u8 decode_format;
@@ -75,6 +75,11 @@ struct csid_format { · 1 unmodified line
75 u8 spp; /* bus samples per pixel */75 u8 spp; /* bus samples per pixel */
76};76};
77 77
78struct csid_formats {
79 unsigned int nformats;
80 const struct csid_format_info *formats;
81};
82
78struct csid_testgen_config {83struct csid_testgen_config {
79 enum csid_testgen_mode mode;84 enum csid_testgen_mode mode;
80 const char * const*modes;85 const char * const*modes;
@@ -149,6 +154,13 @@ struct csid_hw_ops { · 68 unmodified lines
149 void (*subdev_init)(struct csid_device *csid);154 void (*subdev_init)(struct csid_device *csid);
150};155};
151 156
157struct 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
152struct csid_device {164struct csid_device {
153 struct camss *camss;165 struct camss *camss;
154 u8 id;166 u8 id;
@@ -167,9 +179,7 @@ struct csid_device { · 12 unmodified lines
167 struct v4l2_mbus_framefmt fmt[MSM_CSID_PADS_NUM];179 struct v4l2_mbus_framefmt fmt[MSM_CSID_PADS_NUM];
168 struct v4l2_ctrl_handler ctrls;180 struct v4l2_ctrl_handler ctrls;
169 struct v4l2_ctrl *testgen_mode;181 struct v4l2_ctrl *testgen_mode;
170 const struct csid_format *formats;182 const struct csid_subdev_resources *res;
171 unsigned int nformats;
172 const struct csid_hw_ops *ops;
173};183};
174 184
175struct camss_subdev_resources;185struct camss_subdev_resources;
@@ -188,16 +198,16 @@ u32 csid_find_code(u32 *codes, unsigned int ncode, · 12 unmodified lines
188 unsigned int match_format_idx, u32 match_code);198 unsigned int match_format_idx, u32 match_code);
189 199
190/*200/*
191 * csid_get_fmt_entry - Find csid_format entry with matching format code201 * csid_get_fmt_entry - Find csid_format_info entry with matching format code
192 * @formats: Array of format csid_format entries202 * @formats: Array of format csid_format_info entries
193 * @nformats: Length of @nformats array203 * @nformats: Length of @nformats array
194 * @code: Desired format code204 * @code: Desired format code
195 *205 *
196 * Return formats[0] on failure to find code206 * Return formats[0] on failure to find code
197 */207 */
198const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats,208const struct csid_format_info *csid_get_fmt_entry(const struct csid_format_info *formats,
199 unsigned int nformats,209 unsigned int nformats,
200 u32 code);210 u32 code);
201 211
202int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,212int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
203 const struct camss_subdev_resources *res, u8 id);213 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
211 221
212extern const char * const csid_testgen_modes[];222extern const char * const csid_testgen_modes[];
213 223
224extern const struct csid_formats csid_formats_4_1;
225extern const struct csid_formats csid_formats_4_7;
226extern const struct csid_formats csid_formats_gen2;
227
214extern const struct csid_hw_ops csid_ops_4_1;228extern const struct csid_hw_ops csid_ops_4_1;
215extern const struct csid_hw_ops csid_ops_4_7;229extern const struct csid_hw_ops csid_ops_4_7;
216extern const struct csid_hw_ops csid_ops_gen2;230extern 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
24 24
25#define MSM_CSIPHY_NAME "msm_csiphy"25#define MSM_CSIPHY_NAME "msm_csiphy"
26 26
27struct csiphy_format {27static const struct csiphy_format_info formats_8x16[] = {
28 u32 code;
29 u8 bpp;
30};
31
32static const struct csiphy_format csiphy_formats_8x16[] = {
33 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },28 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },
34 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },29 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },
35 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },30 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },
@@ -49,7 +44,7 @@ static const struct csiphy_format csiphy_formats_8x16[] = { · 13 unmodified lines
49 { MEDIA_BUS_FMT_Y10_1X10, 10 },44 { MEDIA_BUS_FMT_Y10_1X10, 10 },
50};45};
51 46
52static const struct csiphy_format csiphy_formats_8x96[] = {47static const struct csiphy_format_info formats_8x96[] = {
53 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },48 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },
54 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },49 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },
55 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },50 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },
@@ -73,7 +68,7 @@ static const struct csiphy_format csiphy_formats_8x96[] = { · 17 unmodified lines
73 { MEDIA_BUS_FMT_Y10_1X10, 10 },68 { MEDIA_BUS_FMT_Y10_1X10, 10 },
74};69};
75 70
76static const struct csiphy_format csiphy_formats_sdm845[] = {71static const struct csiphy_format_info formats_sdm845[] = {
77 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },72 { MEDIA_BUS_FMT_UYVY8_1X16, 8 },
78 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },73 { MEDIA_BUS_FMT_VYUY8_1X16, 8 },
79 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },74 { MEDIA_BUS_FMT_YUYV8_1X16, 8 },
@@ -98,6 +93,21 @@ static const struct csiphy_format csiphy_formats_sdm845[] = { · 18 unmodified lines
98 { MEDIA_BUS_FMT_Y10_1X10, 10 },93 { MEDIA_BUS_FMT_Y10_1X10, 10 },
99};94};
100 95
96const struct csiphy_formats csiphy_formats_8x16 = {
97 .nformats = ARRAY_SIZE(formats_8x16),
98 .formats = formats_8x16
99};
100
101const struct csiphy_formats csiphy_formats_8x96 = {
102 .nformats = ARRAY_SIZE(formats_8x96),
103 .formats = formats_8x96
104};
105
106const struct csiphy_formats csiphy_formats_sdm845 = {
107 .nformats = ARRAY_SIZE(formats_sdm845),
108 .formats = formats_sdm845
109};
110
101/*111/*
102 * csiphy_get_bpp - map media bus format to bits per pixel112 * csiphy_get_bpp - map media bus format to bits per pixel
103 * @formats: supported media bus formats array113 * @formats: supported media bus formats array
@@ -106,7 +116,7 @@ static const struct csiphy_format csiphy_formats_sdm845[] = { · 2 unmodified lines
106 *116 *
107 * Return number of bits per pixel117 * Return number of bits per pixel
108 */118 */
109static u8 csiphy_get_bpp(const struct csiphy_format *formats,119static u8 csiphy_get_bpp(const struct csiphy_format_info *formats,
110 unsigned int nformats, u32 code)120 unsigned int nformats, u32 code)
111{121{
112 unsigned int i;122 unsigned int i;
@@ -131,7 +141,7 @@ static int csiphy_set_clock_rates(struct csiphy_device *csiphy) · 18 unmodified lines
131 int i, j;141 int i, j;
132 int ret;142 int ret;
133 143
134 u8 bpp = csiphy_get_bpp(csiphy->formats, csiphy->nformats,144 u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats,
135 csiphy->fmt[MSM_CSIPHY_PAD_SINK].code);145 csiphy->fmt[MSM_CSIPHY_PAD_SINK].code);
136 u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data;146 u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data;
137 147
@@ -216,9 +226,9 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) · 78 unmodified lines
216 226
217 enable_irq(csiphy->irq);227 enable_irq(csiphy->irq);
218 228
219 csiphy->ops->reset(csiphy);229 csiphy->res->hw_ops->reset(csiphy);
220 230
221 csiphy->ops->hw_version_read(csiphy, dev);231 csiphy->res->hw_ops->hw_version_read(csiphy, dev);
222 } else {232 } else {
223 disable_irq(csiphy->irq);233 disable_irq(csiphy->irq);
224 234
@@ -243,8 +253,8 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) · 18 unmodified lines
243{253{
244 struct csiphy_config *cfg = &csiphy->cfg;254 struct csiphy_config *cfg = &csiphy->cfg;
245 s64 link_freq;255 s64 link_freq;
246 u8 lane_mask = csiphy->ops->get_lane_mask(&cfg->csi2->lane_cfg);256 u8 lane_mask = csiphy->res->hw_ops->get_lane_mask(&cfg->csi2->lane_cfg);
247 u8 bpp = csiphy_get_bpp(csiphy->formats, csiphy->nformats,257 u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats,
248 csiphy->fmt[MSM_CSIPHY_PAD_SINK].code);258 csiphy->fmt[MSM_CSIPHY_PAD_SINK].code);
249 u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data;259 u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data;
250 u8 val;260 u8 val;
@@ -272,7 +282,7 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) · 21 unmodified lines
272 wmb();282 wmb();
273 }283 }
274 284
275 csiphy->ops->lanes_enable(csiphy, cfg, link_freq, lane_mask);285 csiphy->res->hw_ops->lanes_enable(csiphy, cfg, link_freq, lane_mask);
276 286
277 return 0;287 return 0;
278}288}
@@ -285,7 +295,7 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) · 6 unmodified lines
285 */295 */
286static void csiphy_stream_off(struct csiphy_device *csiphy)296static void csiphy_stream_off(struct csiphy_device *csiphy)
287{297{
288 csiphy->ops->lanes_disable(csiphy, &csiphy->cfg);298 csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg);
289}299}
290 300
291 301
@@ -350,12 +360,12 @@ static void csiphy_try_format(struct csiphy_device *csiphy, · 58 unmodified lines
350 case MSM_CSIPHY_PAD_SINK:360 case MSM_CSIPHY_PAD_SINK:
351 /* Set format on sink pad */361 /* Set format on sink pad */
352 362
353 for (i = 0; i < csiphy->nformats; i++)363 for (i = 0; i < csiphy->res->formats->nformats; i++)
354 if (fmt->code == csiphy->formats[i].code)364 if (fmt->code == csiphy->res->formats->formats[i].code)
355 break;365 break;
356 366
357 /* If not found, use UYVY as default */367 /* If not found, use UYVY as default */
358 if (i >= csiphy->nformats)368 if (i >= csiphy->res->formats->nformats)
359 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;369 fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
360 370
361 fmt->width = clamp_t(u32, fmt->width, 1, 8191);371 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
392 struct v4l2_mbus_framefmt *format;402 struct v4l2_mbus_framefmt *format;
393 403
394 if (code->pad == MSM_CSIPHY_PAD_SINK) {404 if (code->pad == MSM_CSIPHY_PAD_SINK) {
395 if (code->index >= csiphy->nformats)405 if (code->index >= csiphy->res->formats->nformats)
396 return -EINVAL;406 return -EINVAL;
397 407
398 code->code = csiphy->formats[code->index].code;408 code->code = csiphy->res->formats->formats[code->index].code;
399 } else {409 } else {
400 if (code->index > 0)410 if (code->index > 0)
401 return -EINVAL;411 return -EINVAL;
@@ -564,25 +574,7 @@ int msm_csiphy_subdev_init(struct camss *camss, · 162 unmodified lines
564 csiphy->camss = camss;574 csiphy->camss = camss;
565 csiphy->id = id;575 csiphy->id = id;
566 csiphy->cfg.combo_mode = 0;576 csiphy->cfg.combo_mode = 0;
567 csiphy->ops = res->ops;577 csiphy->res = &res->csiphy;
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 }
586 578
587 /* Memory */579 /* Memory */
588 580
@@ -610,7 +602,7 @@ int msm_csiphy_subdev_init(struct camss *camss, · 21 unmodified lines
610 snprintf(csiphy->irq_name, sizeof(csiphy->irq_name), "%s_%s%d",602 snprintf(csiphy->irq_name, sizeof(csiphy->irq_name), "%s_%s%d",
611 dev_name(dev), MSM_CSIPHY_NAME, csiphy->id);603 dev_name(dev), MSM_CSIPHY_NAME, csiphy->id);
612 604
613 ret = devm_request_irq(dev, csiphy->irq, csiphy->ops->isr,605 ret = devm_request_irq(dev, csiphy->irq, csiphy->res->hw_ops->isr,
614 IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN,606 IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN,
615 csiphy->irq_name, csiphy);607 csiphy->irq_name, csiphy);
616 if (ret < 0) {608 if (ret < 0) {
drivers/media/platform/qcom/camss/camss-csiphy.h+20−3
@@ -42,6 +42,16 @@ struct csiphy_config { · 41 unmodified lines
42 struct csiphy_csi2_cfg *csi2;42 struct csiphy_csi2_cfg *csi2;
43};43};
44 44
45struct csiphy_format_info {
46 u32 code;
47 u8 bpp;
48};
49
50struct csiphy_formats {
51 unsigned int nformats;
52 const struct csiphy_format_info *formats;
53};
54
45struct csiphy_device;55struct csiphy_device;
46 56
47struct csiphy_hw_ops {57struct csiphy_hw_ops {
@@ -63,6 +73,11 @@ struct csiphy_hw_ops { · 15 unmodified lines
63 irqreturn_t (*isr)(int irq, void *dev);73 irqreturn_t (*isr)(int irq, void *dev);
64};74};
65 75
76struct csiphy_subdev_resources {
77 const struct csiphy_hw_ops *hw_ops;
78 const struct csiphy_formats *formats;
79};
80
66struct csiphy_device {81struct csiphy_device {
67 struct camss *camss;82 struct camss *camss;
68 u8 id;83 u8 id;
@@ -78,9 +93,7 @@ struct csiphy_device { · 9 unmodified lines
78 u32 timer_clk_rate;93 u32 timer_clk_rate;
79 struct csiphy_config cfg;94 struct csiphy_config cfg;
80 struct v4l2_mbus_framefmt fmt[MSM_CSIPHY_PADS_NUM];95 struct v4l2_mbus_framefmt fmt[MSM_CSIPHY_PADS_NUM];
81 const struct csiphy_hw_ops *ops;96 const struct csiphy_subdev_resources *res;
82 const struct csiphy_format *formats;
83 unsigned int nformats;
84};97};
85 98
86struct camss_subdev_resources;99struct camss_subdev_resources;
@@ -94,6 +107,10 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, · 7 unmodified lines
94 107
95void msm_csiphy_unregister_entity(struct csiphy_device *csiphy);108void msm_csiphy_unregister_entity(struct csiphy_device *csiphy);
96 109
110extern const struct csiphy_formats csiphy_formats_8x16;
111extern const struct csiphy_formats csiphy_formats_8x96;
112extern const struct csiphy_formats csiphy_formats_sdm845;
113
97extern const struct csiphy_hw_ops csiphy_ops_2ph_1_0;114extern const struct csiphy_hw_ops csiphy_ops_2ph_1_0;
98extern const struct csiphy_hw_ops csiphy_ops_3ph_1_0;115extern const struct csiphy_hw_ops csiphy_ops_3ph_1_0;
99 116
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 */
23u8 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 */
45u32 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 */
74int 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 */
27struct 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 */
42struct 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
52struct camss_formats {
53 unsigned int nformats;
54 const struct camss_format_info *formats;
55};
56
57u8 camss_format_get_bpp(const struct camss_format_info *formats, unsigned int nformats, u32 code);
58u32 camss_format_find_code(u32 *code, unsigned int n_code, unsigned int index, u32 req_code);
59int 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
353 writel_relaxed(status0, vfe->base + VFE_IRQ_CLEAR_0);353 writel_relaxed(status0, vfe->base + VFE_IRQ_CLEAR_0);
354 writel_relaxed(status1, vfe->base + VFE_IRQ_CLEAR_1);354 writel_relaxed(status1, vfe->base + VFE_IRQ_CLEAR_1);
355 355
356 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) {356 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) {
357 vfe_bus_status[i] = readl_relaxed(vfe->base + VFE_BUS_IRQ_STATUS(i));357 vfe_bus_status[i] = readl_relaxed(vfe->base + VFE_BUS_IRQ_STATUS(i));
358 writel_relaxed(vfe_bus_status[i], vfe->base + VFE_BUS_IRQ_CLEAR(i));358 writel_relaxed(vfe_bus_status[i], vfe->base + VFE_BUS_IRQ_CLEAR(i));
359 }359 }
@@ -367,11 +367,11 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 7 unmodified lines
367 if (status0 & STATUS_0_RESET_ACK)367 if (status0 & STATUS_0_RESET_ACK)
368 vfe->isr_ops.reset_ack(vfe);368 vfe->isr_ops.reset_ack(vfe);
369 369
370 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++)370 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)
371 if (status0 & STATUS_0_RDI_REG_UPDATE(i))371 if (status0 & STATUS_0_RDI_REG_UPDATE(i))
372 vfe->isr_ops.reg_update(vfe, i);372 vfe->isr_ops.reg_update(vfe, i);
373 373
374 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++)374 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)
375 if (status0 & STATUS_1_RDI_SOF(i))375 if (status0 & STATUS_1_RDI_SOF(i))
376 vfe->isr_ops.sof(vfe, i);376 vfe->isr_ops.sof(vfe, i);
377 377
@@ -442,7 +442,7 @@ static int vfe_enable_output(struct vfe_line *line) · 64 unmodified lines
442{442{
443 struct vfe_device *vfe = to_vfe(line);443 struct vfe_device *vfe = to_vfe(line);
444 struct vfe_output *output = &line->output;444 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;
446 struct media_entity *sensor;446 struct media_entity *sensor;
447 unsigned long flags;447 unsigned long flags;
448 unsigned int frame_skip = 0;448 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
560 unsigned long flags;560 unsigned long flags;
561 561
562 spin_lock_irqsave(&vfe->output_lock, flags);562 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);
564 564
565 output = &vfe->line[line_id].output;565 output = &vfe->line[line_id].output;
566 566
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
892 u32 value0, value1;892 u32 value0, value1;
893 int i, j;893 int i, j;
894 894
895 vfe->ops->isr_read(vfe, &value0, &value1);895 vfe->res->hw_ops->isr_read(vfe, &value0, &value1);
896 896
897 dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",897 dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",
898 value0, value1);898 value0, value1);
@@ -901,7 +901,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 2 unmodified lines
901 vfe->isr_ops.reset_ack(vfe);901 vfe->isr_ops.reset_ack(vfe);
902 902
903 if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)903 if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
904 vfe->ops->violation_read(vfe);904 vfe->res->hw_ops->violation_read(vfe);
905 905
906 if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)906 if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
907 vfe->isr_ops.halt_ack(vfe);907 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
1050 u32 value0, value1;1050 u32 value0, value1;
1051 int i, j;1051 int i, j;
1052 1052
1053 vfe->ops->isr_read(vfe, &value0, &value1);1053 vfe->res->hw_ops->isr_read(vfe, &value0, &value1);
1054 1054
1055 dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",1055 dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n",
1056 value0, value1);1056 value0, value1);
@@ -1059,12 +1059,12 @@ static irqreturn_t vfe_isr(int irq, void *dev) · 2 unmodified lines
1059 vfe->isr_ops.reset_ack(vfe);1059 vfe->isr_ops.reset_ack(vfe);
1060 1060
1061 if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)1061 if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION)
1062 vfe->ops->violation_read(vfe);1062 vfe->res->hw_ops->violation_read(vfe);
1063 1063
1064 if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)1064 if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK)
1065 vfe->isr_ops.halt_ack(vfe);1065 vfe->isr_ops.halt_ack(vfe);
1066 1066
1067 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++)1067 for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++)
1068 if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))1068 if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i))
1069 vfe->isr_ops.reg_update(vfe, i);1069 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.