History

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

Pull media updates from Mauro Carvalho Chehab: - Removal of some old unused sensor drivers: ad9389b, m5mols, mt9m032, mt9t001, noon010pc30, s5k6aa, sr030pc30 and vs6624 - New i.MX8 image sensor interface driver - Some new RC keymaps - lots of cleanups at atomisp driver to make it support standard features present on other webcam drivers - the cx18 and saa7146 now uses VB2 - lots of cleanups and driver improvements * tag 'media/v6.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (460 commits) media: ov5670: Fix probe on ACPI media: nxp: imx8-isi: Remove 300ms sleep after enabling channel media: nxp: imx8-isi: Replace udelay() with fsleep() media: nxp: imx8-isi: Drop partial support for i.MX8QM and i.MX8QXP media: nxp: Add i.MX8 ISI driver media: dt-bindings: media: Add i.MX8 ISI DT bindings media: atomisp: gmin_platform: Add Lenovo Ideapad Miix 310 gmin_vars media: atomisp: gmin_platform: Make DMI quirks take precedence over the _DSM table media: atomisp: Remove struct atomisp_sub_device index field media: atomisp: Drop support for streaming from 2 sensors at once media: atomisp: Remove atomisp_try_fmt() call from atomisp_set_fmt() media: atomisp: Remove unused ATOM_ISP_MAX_WIDTH_TMP and ATOM_ISP_MAX_HEIGHT_TMP media: atomisp: Remove snr_mbus_fmt local var from atomisp_try_fmt() media: atomisp: Remove custom V4L2_CID_FMT_AUTO control media: atomisp: Remove continuous mode related code from atomisp_set_fmt() media: atomisp: Remove duplicate atomisp_[start|stop]_streaming() prototypes media: atomisp: gc0310: Switch over to ACPI powermanagement media: atomisp: gc0310: Use devm_kzalloc() for data struct media: atomisp: gc0310: Add runtime-pm support media: atomisp: gc0310: Delay power-on till streaming is started ...

Linus Torvalds committed 3 years ago

Commit 4ea95692 parents c8cc58e 73b41dc442 files · +15626 −21778Browse files

Unified · Split

442 files
  1. Documentation/admin-guide/media/cec.rst +45 −34
  2. Documentation/admin-guide/media/i2c-cardlist.rst +0 −8
  3. Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml +1 −1
  4. Documentation/devicetree/bindings/media/allwinner,sun50i-h6-vpu-g2.yaml +2 −2
  5. Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml +2 −2
  6. Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml +2 −2
  7. Documentation/devicetree/bindings/media/amlogic,meson-ir-tx.yaml +2 −2
  8. Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml +47 −0
  9. Documentation/devicetree/bindings/media/exynos-fimc-lite.txt +0 −16
  10. Documentation/devicetree/bindings/media/exynos4-fimc-is.txt +0 −50
  11. Documentation/devicetree/bindings/media/gpio-ir-receiver.yaml +3 −0
  12. Documentation/devicetree/bindings/media/i2c/chrontel,ch7322.yaml +2 −2
  13. Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml +3 −3
  14. Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml +1 −1
  15. Documentation/devicetree/bindings/media/i2c/ov2685.txt +0 −41
  16. Documentation/devicetree/bindings/media/i2c/ov8856.yaml +1 −1
  17. Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml +1 −1
  18. Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml +101 −0
  19. Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml +101 −0
  20. Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml +98 −0
  21. Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml +18 −7
  22. Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml +1 −1
  23. Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml +1 −1
  24. Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml +46 −71
  25. Documentation/devicetree/bindings/media/meson-ir.txt +0 −20
  26. Documentation/devicetree/bindings/media/microchip,sama5d4-vdec.yaml +2 −2
  27. Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml +173 −0
  28. Documentation/devicetree/bindings/media/nxp,imx8mq-vpu.yaml +2 −2
  29. Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml +2 −2
  30. Documentation/devicetree/bindings/media/qcom,msm8916-venus.yaml +29 −57
  31. Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml +2 −2
  32. Documentation/devicetree/bindings/media/qcom,msm8996-venus.yaml +63 −83
  33. Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml +38 −59
  34. Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml +54 −78
  35. Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml +2 −2
  36. Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml +58 −86
  37. Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml +2 −2
  38. Documentation/devicetree/bindings/media/qcom,sdm845-venus-v2.yaml +42 −66
  39. Documentation/devicetree/bindings/media/qcom,sdm845-venus.yaml +38 −66
  40. Documentation/devicetree/bindings/media/qcom,sm8250-camss.yaml +2 −2
  41. Documentation/devicetree/bindings/media/qcom,sm8250-venus.yaml +49 −73
  42. Documentation/devicetree/bindings/media/qcom,venus-common.yaml +73 −0
  43. Documentation/devicetree/bindings/media/rc.yaml +3 −1
  44. Documentation/devicetree/bindings/media/renesas,csi2.yaml +1 −0
  45. Documentation/devicetree/bindings/media/renesas,fcp.yaml +40 −5
  46. Documentation/devicetree/bindings/media/renesas,isp.yaml +1 −0
  47. Documentation/devicetree/bindings/media/renesas,vin.yaml +1 −0
  48. Documentation/devicetree/bindings/media/renesas,vsp1.yaml +9 −4
  49. Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml +2 −2
  50. Documentation/devicetree/bindings/media/rockchip-isp1.yaml +13 −6
  51. Documentation/devicetree/bindings/media/rockchip-vpu.yaml +2 −2
  52. Documentation/devicetree/bindings/media/samsung,exynos4210-csis.yaml +170 −0
  53. Documentation/devicetree/bindings/media/samsung,exynos4210-fimc.yaml +152 −0
  54. Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml +220 −0
  55. Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-lite.yaml +63 −0
  56. Documentation/devicetree/bindings/media/samsung,fimc.yaml +279 −0
  57. Documentation/devicetree/bindings/media/samsung,s5c73m3.yaml +165 −0
  58. Documentation/devicetree/bindings/media/samsung-fimc.txt +0 −209
  59. Documentation/devicetree/bindings/media/samsung-mipi-csis.txt +0 −81
  60. Documentation/devicetree/bindings/media/samsung-s5c73m3.txt +0 −97
  61. Documentation/devicetree/bindings/media/samsung-s5k5baf.txt +0 −58
  62. Documentation/devicetree/bindings/media/samsung-s5k6a3.txt +0 −33
  63. Documentation/devicetree/bindings/media/si470x.txt +0 −26
  64. Documentation/devicetree/bindings/media/silabs,si470x.yaml +48 −0
  65. Documentation/devicetree/bindings/media/st,stm32-cec.yaml +0 −53
  66. Documentation/devicetree/bindings/media/ti,cal.yaml +1 −1
  67. Documentation/driver-api/media/drivers/ccs/ccs.rst +22 −0
  68. Documentation/userspace-api/media/v4l/dev-overlay.rst +8 −2
  69. Documentation/userspace-api/media/v4l/pixfmt-compressed.rst +25 −0
  70. Documentation/userspace-api/media/v4l/pixfmt-packed-yuv.rst +28 −0
  71. Documentation/userspace-api/media/v4l/pixfmt-rgb.rst +42 −0
  72. Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst +15 −0
  73. Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst +94 −0
  74. Documentation/userspace-api/media/v4l/user-func.rst +1 −0
  75. Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +10 −0
  76. Documentation/userspace-api/media/v4l/vidioc-g-fbuf.rst +16 −36
  77. Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-size.rst +29 −15
  78. Documentation/userspace-api/media/v4l/vidioc-subdev-enum-mbus-code.rst +27 −12
  79. Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst +83 −0
  80. MAINTAINERS +17 −31
  81. drivers/media/cec/core/cec-adap.c +5 −2
  82. drivers/media/cec/platform/cec-gpio/cec-gpio.c +2 −3
  83. drivers/media/cec/platform/cros-ec/cros-ec-cec.c +14 −8
  84. drivers/media/cec/platform/meson/ao-cec-g12a.c +2 −4
  85. drivers/media/cec/platform/meson/ao-cec.c +2 −4
  86. drivers/media/cec/platform/s5p/s5p_cec.c +2 −3
  87. drivers/media/cec/platform/seco/seco-cec.c +2 −4
  88. drivers/media/cec/platform/sti/stih-cec.c +2 −4
  89. drivers/media/cec/platform/stm32/stm32-cec.c +2 −4
  90. drivers/media/cec/platform/tegra/tegra_cec.c +2 −4
  91. drivers/media/common/btcx-risc.h +0 −29
  92. drivers/media/common/saa7146/Kconfig +1 −1
  93. drivers/media/common/saa7146/saa7146_core.c +14 −26
  94. drivers/media/common/saa7146/saa7146_fops.c +75 −298
  95. drivers/media/common/saa7146/saa7146_hlp.c +40 −315
  96. drivers/media/common/saa7146/saa7146_vbi.c +118 −169
  97. drivers/media/common/saa7146/saa7146_video.c +199 −760
  98. drivers/media/common/videobuf2/videobuf2-v4l2.c +3 −2
  99. drivers/media/dvb-frontends/drx39xyj/drxj.c +1 −1
  100. drivers/media/dvb-frontends/drxk_hard.c +1 −1
  101. drivers/media/dvb-frontends/rtl2832_sdr.c +2 −4
  102. drivers/media/dvb-frontends/zd1301_demod.c +2 −4
  103. drivers/media/i2c/Kconfig +1 −67
  104. drivers/media/i2c/Makefile +0 −8
  105. drivers/media/i2c/ad9389b.c +0 −1215
  106. drivers/media/i2c/adv748x/adv748x-hdmi.c +15 −6
  107. drivers/media/i2c/adv7604.c +4 −1
  108. drivers/media/i2c/ccs/ccs-core.c +83 −74
  109. drivers/media/i2c/ccs/ccs.h +0 −14
  110. drivers/media/i2c/hi556.c +148 −2
  111. drivers/media/i2c/hi846.c +8 −3
  112. drivers/media/i2c/imx258.c +24 −9
  113. drivers/media/i2c/imx290.c +477 −119
  114. drivers/media/i2c/imx296.c +1 −10
  115. drivers/media/i2c/imx334.c +294 −28
  116. drivers/media/i2c/m5mols/Kconfig +0 −8
  117. drivers/media/i2c/m5mols/Makefile +0 −4
  118. drivers/media/i2c/m5mols/m5mols.h +0 −349
  119. drivers/media/i2c/m5mols/m5mols_capture.c +0 −158
  120. drivers/media/i2c/m5mols/m5mols_controls.c +0 −625
  121. drivers/media/i2c/m5mols/m5mols_core.c +0 −1051
  122. drivers/media/i2c/m5mols/m5mols_reg.h +0 −359
  123. drivers/media/i2c/max9286.c +1 −0
  124. drivers/media/i2c/mt9m032.c +0 −891
  125. drivers/media/i2c/mt9t001.c +0 −992
  126. drivers/media/i2c/noon010pc30.c +0 −821
  127. drivers/media/i2c/ov13b10.c +47 −28
  128. drivers/media/i2c/ov2685.c +77 −3
  129. drivers/media/i2c/ov5647.c +43 −13
  130. drivers/media/i2c/ov5670.c +79 −37
  131. drivers/media/i2c/ov7670.c +3 −8
  132. drivers/media/i2c/ov8856.c +0 −40
  133. drivers/media/i2c/s5k6aa.c +0 −1652
  134. drivers/media/i2c/sr030pc30.c +0 −762
  135. drivers/media/i2c/st-vgxy61.c +11 −12
  136. drivers/media/i2c/tc358746.c +2 −2
  137. drivers/media/i2c/vs6624.c +0 −854
  138. drivers/media/i2c/vs6624_regs.h +0 −325
  139. drivers/media/mc/mc-device.c +1 −2
  140. drivers/media/pci/bt8xx/Kconfig +1 −1
  141. drivers/media/pci/bt8xx/btcx-risc.c +0 −153
  142. drivers/media/pci/bt8xx/btcx-risc.h +0 −9
  143. drivers/media/pci/bt8xx/bttv-cards.c +0 −15
  144. drivers/media/pci/bt8xx/bttv-driver.c +9 −427
  145. drivers/media/pci/bt8xx/bttv-risc.c +0 −131
  146. drivers/media/pci/bt8xx/bttvp.h +1 −27
  147. drivers/media/pci/cobalt/cobalt-v4l2.c +13 −8
  148. drivers/media/pci/cx18/Kconfig +1 −1
  149. drivers/media/pci/cx18/cx18-driver.c +2 −2
  150. drivers/media/pci/cx18/cx18-driver.h +12 −12
  151. drivers/media/pci/cx18/cx18-fileops.c +16 −69
  152. drivers/media/pci/cx18/cx18-fileops.h +2 −1
  153. drivers/media/pci/cx18/cx18-ioctl.c +159 −232
  154. drivers/media/pci/cx18/cx18-mailbox.c +14 −13
  155. drivers/media/pci/cx18/cx18-streams.c +145 −133
  156. drivers/media/pci/cx23885/cx23885-core.c +3 −1
  157. drivers/media/pci/cx23885/cx23885-video.c +7 −6
  158. drivers/media/pci/dm1105/dm1105.c +1 −0
  159. drivers/media/pci/intel/ipu3/cio2-bridge.c +19 −4
  160. drivers/media/pci/intel/ipu3/cio2-bridge.h +2 −1
  161. drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +1 −0
  162. drivers/media/pci/saa7134/saa7134-cards.c +0 −1
  163. drivers/media/pci/saa7134/saa7134-core.c +0 −32
  164. drivers/media/pci/saa7134/saa7134-empress.c +2 −2
  165. drivers/media/pci/saa7134/saa7134-ts.c +1 −0
  166. drivers/media/pci/saa7134/saa7134-vbi.c +1 −0
  167. drivers/media/pci/saa7134/saa7134-video.c +5 −407
  168. drivers/media/pci/saa7134/saa7134.h +0 −13
  169. drivers/media/pci/saa7146/hexium_gemini.c +12 −11
  170. drivers/media/pci/saa7146/hexium_orion.c +13 −11
  171. drivers/media/pci/saa7146/mxb.c +29 −24
  172. drivers/media/pci/ttpci/budget-av.c +3 −2
  173. drivers/media/pci/tw68/tw68-video.c +9 −7
  174. drivers/media/pci/zoran/zoran_device.h +0 −2
  175. drivers/media/platform/allegro-dvt/allegro-core.c +2 −4
  176. drivers/media/platform/amlogic/meson-ge2d/ge2d.c +2 −4
  177. drivers/media/platform/amphion/vdec.c +53 −0
  178. drivers/media/platform/amphion/vpu_codec.h +2 −1
  179. drivers/media/platform/amphion/vpu_core.c +2 −4
  180. drivers/media/platform/amphion/vpu_drv.c +2 −4
  181. drivers/media/platform/amphion/vpu_malone.c +44 −1
  182. drivers/media/platform/amphion/vpu_malone.h +1 −0
  183. drivers/media/platform/aspeed/aspeed-video.c +2 −4
  184. drivers/media/platform/atmel/atmel-isi.c +4 −6
  185. drivers/media/platform/cadence/cdns-csi2rx.c +2 −4
  186. drivers/media/platform/cadence/cdns-csi2tx.c +2 −4
  187. drivers/media/platform/chips-media/coda-common.c +2 −3
  188. drivers/media/platform/intel/pxa_camera.c +4 −6
  189. drivers/media/platform/m2m-deinterlace.c +2 −4
  190. drivers/media/platform/marvell/mcam-core.c +2 −2
  191. drivers/media/platform/marvell/mmp-driver.c +3 −13
  192. drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c +84 −56
  193. drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h +12 −16
  194. drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c +13 −30
  195. drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c +8 −30
  196. drivers/media/platform/mediatek/mdp/mtk_mdp_core.c +2 −3
  197. drivers/media/platform/mediatek/mdp3/Makefile +1 −1
  198. drivers/media/platform/mediatek/mdp3/mdp_cfg_data.c +453 −0
  199. drivers/media/platform/mediatek/mdp3/mdp_sm_mt8183.h +144 −0
  200. drivers/media/platform/mediatek/mdp3/mtk-img-ipi.h +24 −165
  201. drivers/media/platform/mediatek/mdp3/mtk-mdp3-cfg.h +20 −0
  202. drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c +101 −47
  203. drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c +346 −193
  204. drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.h +22 −2
  205. drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c +13 −40
  206. drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.h +16 −2
  207. drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c +19 −17
  208. drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.h +0 −1
  209. drivers/media/platform/mediatek/mdp3/mtk-mdp3-regs.c +27 −266
  210. drivers/media/platform/mediatek/mdp3/mtk-mdp3-regs.h +109 −105
  211. drivers/media/platform/mediatek/mdp3/mtk-mdp3-type.h +53 −0
  212. drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c +83 −110
  213. drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.h +7 −22
  214. drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c +10 −21
  215. drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c +5 −5
  216. drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c +8 −0
  217. drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateful.c +11 −1
  218. drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c +8 −6
  219. drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c +1 −1
  220. drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c +15 −8
  221. drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c +1 −1
  222. drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c +1 −1
  223. drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c +82 −13
  224. drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h +12 −0
  225. drivers/media/platform/mediatek/vpu/mtk_vpu.c +2 −4
  226. drivers/media/platform/microchip/microchip-csi2dc.c +2 −4
  227. drivers/media/platform/microchip/microchip-isc-base.c +3 −2
  228. drivers/media/platform/microchip/microchip-sama5d2-isc.c +2 −4
  229. drivers/media/platform/microchip/microchip-sama7g5-isc.c +2 −4
  230. drivers/media/platform/nvidia/tegra-vde/vde.c +2 −4
  231. drivers/media/platform/nxp/Kconfig +2 −0
  232. drivers/media/platform/nxp/Makefile +1 −0
  233. drivers/media/platform/nxp/dw100/dw100.c +3 −7
  234. drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c +15 −4
  235. drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h +3 −2
  236. drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c +316 −28
  237. drivers/media/platform/nxp/imx-mipi-csis.c +2 −4
  238. drivers/media/platform/nxp/imx-pxp.c +2 −4
  239. drivers/media/platform/nxp/imx7-media-csi.c +19 −14
  240. drivers/media/platform/nxp/imx8-isi/Kconfig +22 −0
  241. drivers/media/platform/nxp/imx8-isi/Makefile +8 −0
  242. drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c +539 −0
  243. drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h +394 −0
  244. drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c +529 −0
  245. drivers/media/platform/nxp/imx8-isi/imx8-isi-debug.c +109 −0
  246. drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c +650 −0
  247. drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c +858 −0
  248. drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c +867 −0
  249. drivers/media/platform/nxp/imx8-isi/imx8-isi-regs.h +418 −0
  250. drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c +1512 −0
  251. drivers/media/platform/nxp/mx2_emmaprp.c +2 −4
  252. drivers/media/platform/qcom/camss/camss-csid-gen2.c +34 −20
  253. drivers/media/platform/qcom/camss/camss-csid.c +31 −13
  254. drivers/media/platform/qcom/camss/camss-csid.h +9 −2
  255. drivers/media/platform/qcom/camss/camss-vfe-170.c +2 −2
  256. drivers/media/platform/qcom/camss/camss-vfe-480.c +40 −21
  257. drivers/media/platform/qcom/camss/camss-vfe-gen1.c +2 −2
  258. drivers/media/platform/qcom/camss/camss-vfe.c +1 −0
  259. drivers/media/platform/qcom/camss/camss-video.c +21 −5
  260. drivers/media/platform/qcom/camss/camss.c +3 −5
  261. drivers/media/platform/qcom/venus/core.c +2 −4
  262. drivers/media/platform/qcom/venus/core.h +9 −1
  263. drivers/media/platform/qcom/venus/helpers.c +2 −2
  264. drivers/media/platform/qcom/venus/hfi_cmds.c +23 −0
  265. drivers/media/platform/qcom/venus/hfi_helper.h +18 −0
  266. drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c +2 −2
  267. drivers/media/platform/qcom/venus/vdec.c +20 −9
  268. drivers/media/platform/qcom/venus/venc.c +103 −12
  269. drivers/media/platform/renesas/rcar-fcp.c +2 −4
  270. drivers/media/platform/renesas/rcar-isp.c +3 −8
  271. drivers/media/platform/renesas/rcar-vin/rcar-core.c +2 −40
  272. drivers/media/platform/renesas/rcar-vin/rcar-csi2.c +5 −16
  273. drivers/media/platform/renesas/rcar_drif.c +3 −5
  274. drivers/media/platform/renesas/rcar_fdp1.c +10 −11
  275. drivers/media/platform/renesas/rcar_jpu.c +2 −4
  276. drivers/media/platform/renesas/renesas-ceu.c +4 −6
  277. drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c +2 −4
  278. drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c +2 −4
  279. drivers/media/platform/renesas/sh_vou.c +2 −3
  280. drivers/media/platform/renesas/vsp1/vsp1_drm.c +15 −11
  281. drivers/media/platform/renesas/vsp1/vsp1_drv.c +12 −5
  282. drivers/media/platform/renesas/vsp1/vsp1_entity.c +5 −6
  283. drivers/media/platform/renesas/vsp1/vsp1_entity.h +0 −2
  284. drivers/media/platform/renesas/vsp1/vsp1_pipe.h +2 −0
  285. drivers/media/platform/renesas/vsp1/vsp1_regs.h +2 −0
  286. drivers/media/platform/renesas/vsp1/vsp1_video.c +4 −3
  287. drivers/media/platform/rockchip/rga/rga.c +2 −4
  288. drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c +52 −0
  289. drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +2 −4
  290. drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c +7 −7
  291. drivers/media/platform/samsung/exynos-gsc/gsc-core.c +2 −3
  292. drivers/media/platform/samsung/exynos4-is/fimc-capture.c +11 −7
  293. drivers/media/platform/samsung/exynos4-is/fimc-core.c +2 −3
  294. drivers/media/platform/samsung/exynos4-is/fimc-is-errno.c +1 −1
  295. drivers/media/platform/samsung/exynos4-is/fimc-is-errno.h +1 −1
  296. drivers/media/platform/samsung/exynos4-is/fimc-is-i2c.c +2 −4
  297. drivers/media/platform/samsung/exynos4-is/fimc-is.c +2 −4
  298. drivers/media/platform/samsung/exynos4-is/fimc-isp-video.c +7 −3
  299. drivers/media/platform/samsung/exynos4-is/fimc-lite.c +8 −6
  300. drivers/media/platform/samsung/exynos4-is/media-dev.c +9 −9
  301. drivers/media/platform/samsung/exynos4-is/mipi-csis.c +2 −4
  302. drivers/media/platform/samsung/s3c-camif/camif-capture.c +3 −2
  303. drivers/media/platform/samsung/s3c-camif/camif-core.c +5 −6
  304. drivers/media/platform/samsung/s5p-g2d/g2d.c +2 −3
  305. drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c +2 −4
  306. drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +2 −3
  307. drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c +4 −4
  308. drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +2 −4
  309. drivers/media/platform/st/sti/delta/delta-v4l2.c +2 −4
  310. drivers/media/platform/st/sti/hva/hva-v4l2.c +2 −4
  311. drivers/media/platform/st/stm32/dma2d/dma2d.c +3 −8
  312. drivers/media/platform/st/stm32/dma2d/dma2d.h +0 −2
  313. drivers/media/platform/st/stm32/stm32-dcmi.c +3 −4
  314. drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c +2 −4
  315. drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c +2 −4
  316. drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c +2 −4
  317. drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c +2 −4
  318. drivers/media/platform/sunxi/sun8i-di/sun8i-di.c +2 −4
  319. drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c +2 −4
  320. drivers/media/platform/ti/am437x/am437x-vpfe.c +21 −20
  321. drivers/media/platform/ti/cal/cal-video.c +20 −17
  322. drivers/media/platform/ti/cal/cal.c +2 −4
  323. drivers/media/platform/ti/davinci/vpif.c +2 −4
  324. drivers/media/platform/ti/davinci/vpif_capture.c +2 −3
  325. drivers/media/platform/ti/davinci/vpif_display.c +2 −4
  326. drivers/media/platform/ti/omap/omap_vout.c +2 −3
  327. drivers/media/platform/ti/omap3isp/isp.c +2 −4
  328. drivers/media/platform/ti/omap3isp/ispccdc.c +3 −2
  329. drivers/media/platform/ti/omap3isp/ispvideo.c +12 −8
  330. drivers/media/platform/ti/vpe/vpe.c +2 −4
  331. drivers/media/platform/verisilicon/hantro_drv.c +41 −15
  332. drivers/media/platform/verisilicon/hantro_postproc.c +1 −1
  333. drivers/media/platform/verisilicon/hantro_v4l2.c +45 −55
  334. drivers/media/platform/verisilicon/hantro_v4l2.h +2 −1
  335. drivers/media/platform/verisilicon/imx8m_vpu_hw.c +2 −0
  336. drivers/media/platform/via/via-camera.c +7 −6
  337. drivers/media/platform/video-mux.c +2 −4
  338. drivers/media/platform/xilinx/xilinx-csi2rxss.c +2 −4
  339. drivers/media/platform/xilinx/xilinx-dma.c +3 −2
  340. drivers/media/platform/xilinx/xilinx-tpg.c +2 −4
  341. drivers/media/platform/xilinx/xilinx-vipp.c +2 −4
  342. drivers/media/platform/xilinx/xilinx-vtc.c +3 −5
  343. drivers/media/radio/radio-si476x.c +2 −4
  344. drivers/media/radio/radio-timb.c +2 −3
  345. drivers/media/radio/radio-wl1273.c +2 −4
  346. drivers/media/radio/si4713/radio-platform-si4713.c +2 −4
  347. drivers/media/rc/gpio-ir-recv.c +4 −4
  348. drivers/media/rc/img-ir/img-ir-core.c +2 −3
  349. drivers/media/rc/ir-hix5hd2.c +2 −3
  350. drivers/media/rc/keymaps/Makefile +2 −0
  351. drivers/media/rc/keymaps/rc-beelink-mxiii.c +57 −0
  352. drivers/media/rc/keymaps/rc-dreambox.c +151 −0
  353. drivers/media/rc/meson-ir-tx.c +2 −4
  354. drivers/media/rc/meson-ir.c +2 −4
  355. drivers/media/rc/mtk-cir.c +2 −4
  356. drivers/media/rc/st_rc.c +2 −3
  357. drivers/media/rc/sunxi-cir.c +2 −4
  358. drivers/media/test-drivers/vicodec/vicodec-core.c +2 −4
  359. drivers/media/test-drivers/vidtv/vidtv_bridge.c +2 −4
  360. drivers/media/test-drivers/vim2m.c +2 −4
  361. drivers/media/test-drivers/vimc/vimc-common.c +4 −4
  362. drivers/media/test-drivers/vimc/vimc-core.c +2 −4
  363. drivers/media/test-drivers/visl/visl-core.c +2 −4
  364. drivers/media/test-drivers/vivid/vivid-core.c +8 −46
  365. drivers/media/test-drivers/vivid/vivid-core.h +0 −19
  366. drivers/media/test-drivers/vivid/vivid-kthread-cap.c +1 −130
  367. drivers/media/test-drivers/vivid/vivid-vid-cap.c +0 −272
  368. drivers/media/test-drivers/vivid/vivid-vid-cap.h +0 −3
  369. drivers/media/test-drivers/vivid/vivid-vid-out.c +0 −74
  370. drivers/media/tuners/it913x.c +2 −4
  371. drivers/media/tuners/mxl5005s.c +8 −4
  372. drivers/media/usb/au0828/au0828-core.c +3 −8
  373. drivers/media/usb/au0828/au0828-dvb.c +2 −2
  374. drivers/media/usb/dvb-usb/cxusb-analog.c +7 −7
  375. drivers/media/usb/dvb-usb/pctv452e.c +2 −0
  376. drivers/media/usb/pvrusb2/Kconfig +1 −1
  377. drivers/media/usb/usbtv/usbtv-core.c +1 −1
  378. drivers/media/v4l2-core/v4l2-async.c +8 −5
  379. drivers/media/v4l2-core/v4l2-common.c +6 −0
  380. drivers/media/v4l2-core/v4l2-compat-ioctl32.c +12 −73
  381. drivers/media/v4l2-core/v4l2-dev.c +3 −2
  382. drivers/media/v4l2-core/v4l2-ioctl.c +34 −52
  383. drivers/media/v4l2-core/v4l2-mc.c +6 −9
  384. drivers/media/v4l2-core/v4l2-subdev.c +166 −34
  385. drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +218 −785
  386. drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +8 −25
  387. drivers/staging/media/atomisp/i2c/gc0310.h +165 −251
  388. drivers/staging/media/atomisp/i2c/ov2680.h +0 −1
  389. drivers/staging/media/atomisp/include/linux/atomisp.h +0 −28
  390. drivers/staging/media/atomisp/include/linux/atomisp_platform.h +5 −6
  391. drivers/staging/media/atomisp/pci/atomisp_cmd.c +142 −936
  392. drivers/staging/media/atomisp/pci/atomisp_cmd.h +0 −9
  393. drivers/staging/media/atomisp/pci/atomisp_compat.h +1 −10
  394. drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +66 −354
  395. drivers/staging/media/atomisp/pci/atomisp_fops.c +5 −114
  396. drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +270 −19
  397. drivers/staging/media/atomisp/pci/atomisp_internal.h +2 −39
  398. drivers/staging/media/atomisp/pci/atomisp_ioctl.c +21 −205
  399. drivers/staging/media/atomisp/pci/atomisp_ioctl.h +0 −6
  400. drivers/staging/media/atomisp/pci/atomisp_subdev.c +39 −150
  401. drivers/staging/media/atomisp/pci/atomisp_subdev.h +0 −22
  402. drivers/staging/media/atomisp/pci/atomisp_v4l2.c +15 −60
  403. drivers/staging/media/av7110/av7110.c +4 −2
  404. drivers/staging/media/av7110/av7110_av.c +2 −2
  405. drivers/staging/media/av7110/av7110_hw.c +2 −1
  406. drivers/staging/media/av7110/av7110_v4l.c +76 −72
  407. drivers/staging/media/deprecated/atmel/atmel-isc-base.c +5 −4
  408. drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c +3 −7
  409. drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c +3 −7
  410. drivers/staging/media/imx/imx-media-capture.c +22 −18
  411. drivers/staging/media/imx/imx-media-csi.c +2 −4
  412. drivers/staging/media/imx/imx-media-dev-common.c +0 −14
  413. drivers/staging/media/imx/imx-media-dev.c +2 −4
  414. drivers/staging/media/imx/imx-media-of.c +2 −3
  415. drivers/staging/media/imx/imx-media-utils.c +4 −72
  416. drivers/staging/media/imx/imx-media.h +0 −13
  417. drivers/staging/media/imx/imx6-mipi-csi2.c +2 −4
  418. drivers/staging/media/imx/imx8mq-mipi-csi2.c +60 −98
  419. drivers/staging/media/meson/vdec/vdec.c +2 −4
  420. drivers/staging/media/omap4iss/iss.c +2 −4
  421. drivers/staging/media/omap4iss/iss_video.c +9 −7
  422. drivers/staging/media/rkvdec/rkvdec.c +4 −3
  423. drivers/staging/media/sunxi/cedrus/cedrus.c +3 −4
  424. drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c +2 −4
  425. drivers/staging/media/tegra-video/vi.c +6 −4
  426. include/media/drv-intf/saa7146_vv.h +10 −55
  427. include/media/dvb_net.h +2 −4
  428. include/media/i2c/ad9389b.h +0 −37
  429. include/media/i2c/m5mols.h +0 −25
  430. include/media/i2c/mt9m032.h +0 −22
  431. include/media/i2c/mt9t001.h +0 −10
  432. include/media/i2c/noon010pc30.h +0 −21
  433. include/media/i2c/s5k6aa.h +0 −48
  434. include/media/i2c/sr030pc30.h +0 −17
  435. include/media/media-device.h +2 −3
  436. include/media/rc-map.h +2 −0
  437. include/media/tveeprom.h +1 −1
  438. include/media/v4l2-ctrls.h +1 −1
  439. include/media/v4l2-mc.h +4 −4
  440. include/media/v4l2-subdev.h +28 −5
  441. include/uapi/linux/v4l2-subdev.h +21 −0
  442. include/uapi/linux/videodev2.h +13 −0
Documentation/admin-guide/media/cec.rst+45−34
@@ -55,6 +55,15 @@ Miscellaneous: · 54 unmodified lines
55 you can control the CEC line through this driver. This supports error55 you can control the CEC line through this driver. This supports error
56 injection as well.56 injection as well.
57 57
58- cec-gpio and Allwinner A10 (or any other driver that uses the CEC pin
59 framework to drive the CEC pin directly): the CEC pin framework uses
60 high-resolution timers. These timers are affected by NTP daemons that
61 speed up or slow down the clock to sync with the official time. The
62 chronyd server will by default increase or decrease the clock by
63 1/12th. This will cause the CEC timings to go out of spec. To fix this,
64 add a 'maxslewrate 40000' line to chronyd.conf. This limits the clock
65 frequency change to 1/25th, which keeps the CEC timings within spec.
66
58 67
59Utilities68Utilities
60=========69=========
@@ -296,69 +305,71 @@ broadcast messages twice to reduce the chance of them being lost. Specifically · 235 unmodified lines
296Making a CEC debugger305Making a CEC debugger
297=====================306=====================
298 307
299By using a Raspberry Pi 2B/3/4 and some cheap components you can make308By using a Raspberry Pi 4B and some cheap components you can make
300your own low-level CEC debugger.309your own low-level CEC debugger.
301 310
302Here is a picture of my setup:311The critical component is one of these HDMI female-female passthrough connectors
303 312(full soldering type 1):
304https://hverkuil.home.xs4all.nl/rpi3-cec.jpg
305
306It's a Raspberry Pi 3 together with a breadboard and some breadboard wires:
307
308http://www.dx.com/p/diy-40p-male-to-female-male-to-male-female-to-female-dupont-line-wire-3pcs-356089#.WYLOOXWGN7I
309
310Finally on of these HDMI female-female passthrough connectors (full soldering type 1):
311 313
312https://elabbay.myshopify.com/collections/camera/products/hdmi-af-af-v1a-hdmi-type-a-female-to-hdmi-type-a-female-pass-through-adapter-breakout-board?variant=45533926147314https://elabbay.myshopify.com/collections/camera/products/hdmi-af-af-v1a-hdmi-type-a-female-to-hdmi-type-a-female-pass-through-adapter-breakout-board?variant=45533926147
313 315
314We've tested this and it works up to 4kp30 (297 MHz). The quality is not high316The video quality is variable and certainly not enough to pass-through 4kp60
315enough to pass-through 4kp60 (594 MHz).317(594 MHz) video. You might be able to support 4kp30, but more likely you will
316 318be limited to 1080p60 (148.5 MHz). But for CEC testing that is fine.
317I also added an RTC and a breakout shield:
318
319https://www.amazon.com/Makerfire%C2%AE-Raspberry-Module-DS1307-Battery/dp/B00ZOXWHK4
320 319
321https://www.dx.com/p/raspberry-pi-gpio-expansion-board-breadboard-easy-multiplexing-board-one-to-three-with-screw-for-raspberry-pi-2-3-b-b-2729992.html#.YGRCG0MzZ7I320You need a breadboard and some breadboard wires:
322 321
323These two are not needed but they make life a bit easier.322http://www.dx.com/p/diy-40p-male-to-female-male-to-male-female-to-female-dupont-line-wire-3pcs-356089#.WYLOOXWGN7I
324 323
325If you want to monitor the HPD line as well, then you need one of these324If you want to monitor the HPD and/or 5V lines as well, then you need one of
326level shifters:325these 5V to 3.3V level shifters:
327 326
328https://www.adafruit.com/product/757327https://www.adafruit.com/product/757
329 328
330(This is just where I got these components, there are many other places you329(This is just where I got these components, there are many other places you
331can get similar things).330can get similar things).
332 331
332The ground pin of the HDMI connector needs to be connected to a ground
333pin of the Raspberry Pi, of course.
334
333The CEC pin of the HDMI connector needs to be connected to these pins:335The CEC pin of the HDMI connector needs to be connected to these pins:
334CE0/IO8 and CE1/IO7 (pull-up GPIOs). The (optional) HPD pin of the HDMI336GPIO 6 and GPIO 7. The optional HPD pin of the HDMI connector should
335connector should be connected (via a level shifter to convert the 5V337be connected via the level shifter to these pins: GPIO 23 and GPIO 12.
336to 3.3V) to these pins: IO17 and IO27. The (optional) 5V pin of the HDMI338The optional 5V pin of the HDMI connector should be connected via the
337connector should be connected (via a level shifter) to these pins: IO22339level shifter to these pins: GPIO 25 and GPIO 22. Monitoring the HPD and
338and IO24. Monitoring the HPD an 5V lines is not necessary, but it is helpful.3405V lines is not necessary, but it is helpful.
339 341
340This kernel patch will hook up the cec-gpio driver correctly to342This device tree addition in ``arch/arm/boot/dts/bcm2711-rpi-4-b.dts``
341e.g. ``arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts``::343will hook up the cec-gpio driver correctly::
344
345 cec@6 {
346 compatible = "cec-gpio";
347 cec-gpios = <&gpio 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
348 hpd-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
349 v5-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
350 };
342 351
343 cec@7 {352 cec@7 {
344 compatible = "cec-gpio";353 compatible = "cec-gpio";
345 cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;354 cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
346 hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;355 hpd-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
347 v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;356 v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
348 };357 };
349 358
350 cec@8 {359If you haven't hooked up the HPD and/or 5V lines, then just delete those
351 compatible = "cec-gpio";360lines.
352 cec-gpios = <&gpio 8 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
353 hpd-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
354 v5-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
355 };
356 361
357This dts change will enable two cec GPIO devices: I typically use one to362This dts change will enable two cec GPIO devices: I typically use one to
358send/receive CEC commands and the other to monitor. If you monitor using363send/receive CEC commands and the other to monitor. If you monitor using
359an unconfigured CEC adapter then it will use GPIO interrupts which makes364an unconfigured CEC adapter then it will use GPIO interrupts which makes
360monitoring very accurate.365monitoring very accurate.
361 366
367If you just want to monitor traffic, then a single instance is sufficient.
368The minimum configuration is one HDMI female-female passthrough connector
369and two female-female breadboard wires: one for connecting the HDMI ground
370pin to a ground pin on the Raspberry Pi, and the other to connect the HDMI
371CEC pin to GPIO 6 on the Raspberry Pi.
372
362The documentation on how to use the error injection is here: :ref:`cec_pin_error_inj`.373The documentation on how to use the error injection is here: :ref:`cec_pin_error_inj`.
363 374
364``cec-ctl --monitor-pin`` will do low-level CEC bus sniffing and analysis.375``cec-ctl --monitor-pin`` will do low-level CEC bus sniffing and analysis.
Documentation/admin-guide/media/i2c-cardlist.rst+0−8
@@ -72,17 +72,13 @@ imx319 Sony IMX319 sensor · 71 unmodified lines
72imx334 Sony IMX334 sensor72imx334 Sony IMX334 sensor
73imx355 Sony IMX355 sensor73imx355 Sony IMX355 sensor
74imx412 Sony IMX412 sensor74imx412 Sony IMX412 sensor
75m5mols Fujitsu M-5MOLS 8MP sensor
76mt9m001 mt9m00175mt9m001 mt9m001
77mt9m032 MT9M032 camera sensor
78mt9m111 mt9m111, mt9m112 and mt9m13176mt9m111 mt9m111, mt9m112 and mt9m131
79mt9p031 Aptina MT9P03177mt9p031 Aptina MT9P031
80mt9t001 Aptina MT9T001
81mt9t112 Aptina MT9T111/MT9T11278mt9t112 Aptina MT9T111/MT9T112
82mt9v011 Micron mt9v011 sensor79mt9v011 Micron mt9v011 sensor
83mt9v032 Micron MT9V032 sensor80mt9v032 Micron MT9V032 sensor
84mt9v111 Aptina MT9V111 sensor81mt9v111 Aptina MT9V111 sensor
85noon010pc30 Siliconfile NOON010PC30 sensor
86ov13858 OmniVision OV13858 sensor82ov13858 OmniVision OV13858 sensor
87ov13b10 OmniVision OV13B10 sensor83ov13b10 OmniVision OV13B10 sensor
88ov2640 OmniVision OV2640 sensor84ov2640 OmniVision OV2640 sensor
@@ -109,9 +105,6 @@ s5c73m3 Samsung S5C73M3 sensor · 20 unmodified lines
109s5k4ecgx Samsung S5K4ECGX sensor105s5k4ecgx Samsung S5K4ECGX sensor
110s5k5baf Samsung S5K5BAF sensor106s5k5baf Samsung S5K5BAF sensor
111s5k6a3 Samsung S5K6A3 sensor107s5k6a3 Samsung S5K6A3 sensor
112s5k6aa Samsung S5K6AAFX sensor
113sr030pc30 Siliconfile SR030PC30 sensor
114vs6624 ST VS6624 sensor
115============ ==========================================================108============ ==========================================================
116 109
117Flash devices110Flash devices
@@ -222,7 +215,6 @@ Video encoders · 104 unmodified lines
222============ ==========================================================215============ ==========================================================
223Driver Name216Driver Name
224============ ==========================================================217============ ==========================================================
225ad9389b Analog Devices AD9389B encoder
226adv7170 Analog Devices ADV7170 video encoder218adv7170 Analog Devices ADV7170 video encoder
227adv7175 Analog Devices ADV7175 video encoder219adv7175 Analog Devices ADV7175 video encoder
228adv7343 ADV7343 video encoder220adv7343 ADV7343 video encoder
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml+1−1
@@ -11,7 +11,7 @@ maintainers: · 10 unmodified lines
11 - Maxime Ripard <mripard@kernel.org>11 - Maxime Ripard <mripard@kernel.org>
12 12
13allOf:13allOf:
14 - $ref: "rc.yaml#"14 - $ref: rc.yaml#
15 15
16properties:16properties:
17 compatible:17 compatible:
Documentation/devicetree/bindings/media/allwinner,sun50i-h6-vpu-g2.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/allwinner,sun50i-h6-vpu-g2.yaml#"5$id: http://devicetree.org/schemas/media/allwinner,sun50i-h6-vpu-g2.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Hantro G2 VPU codec implemented on Allwinner H6 SoC8title: Hantro G2 VPU codec implemented on Allwinner H6 SoC
9 9
Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2# Copyright 2020 BayLibre, SAS2# Copyright 2020 BayLibre, SAS
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/amlogic,axg-ge2d.yaml#"5$id: http://devicetree.org/schemas/media/amlogic,axg-ge2d.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Amlogic GE2D Acceleration Unit8title: Amlogic GE2D Acceleration Unit
9 9
Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2# Copyright 2019 BayLibre, SAS2# Copyright 2019 BayLibre, SAS
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/amlogic,gx-vdec.yaml#"5$id: http://devicetree.org/schemas/media/amlogic,gx-vdec.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Amlogic Video Decoder8title: Amlogic Video Decoder
9 9
Documentation/devicetree/bindings/media/amlogic,meson-ir-tx.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml#"5$id: http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Amlogic Meson IR transmitter8title: Amlogic Meson IR transmitter
9 9
Documentation/devicetree/bindings/media/amlogic,meson6-ir.yaml+47−0
@@ -0,0 +1,47 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/amlogic,meson6-ir.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Amlogic Meson IR remote control receiver
8
9maintainers:
10 - Neil Armstrong <neil.armstrong@linaro.org>
11
12allOf:
13 - $ref: rc.yaml#
14
15properties:
16 compatible:
17 oneOf:
18 - enum:
19 - amlogic,meson6-ir
20 - amlogic,meson8b-ir
21 - amlogic,meson-gxbb-ir
22 - items:
23 - const: amlogic,meson-gx-ir
24 - const: amlogic,meson-gxbb-ir
25
26 reg:
27 maxItems: 1
28
29 interrupts:
30 maxItems: 1
31
32required:
33 - compatible
34 - reg
35 - interrupts
36
37unevaluatedProperties: false
38
39examples:
40 - |
41 #include <dt-bindings/interrupt-controller/irq.h>
42 #include <dt-bindings/interrupt-controller/arm-gic.h>
43 ir-receiver@c8100480 {
44 compatible = "amlogic,meson6-ir";
45 reg = <0xc8100480 0x20>;
46 interrupts = <GIC_SPI 15 IRQ_TYPE_EDGE_RISING>;
47 };
Documentation/devicetree/bindings/media/exynos-fimc-lite.txt+0−16
@@ -1,16 +0,0 @@
1Exynos4x12/Exynos5 SoC series camera host interface (FIMC-LITE)
2
3Required properties:
4
5- compatible : should be one of:
6 "samsung,exynos4212-fimc-lite" for Exynos4212/4412 SoCs,
7 "samsung,exynos5250-fimc-lite" for Exynos5250 compatible
8 devices;
9- reg : physical base address and size of the device memory mapped
10 registers;
11- interrupts : should contain FIMC-LITE interrupt;
12- clocks : FIMC LITE gate clock should be specified in this property.
13- clock-names : should contain "flite" entry.
14
15Each FIMC device should have an alias in the aliases node, in the form of
16fimc-lite<n>, where <n> is an integer specifying the IP block instance.
Documentation/devicetree/bindings/media/exynos4-fimc-is.txt+0−50
@@ -1,50 +0,0 @@
1Exynos4x12 SoC series Imaging Subsystem (FIMC-IS)
2
3The FIMC-IS is a subsystem for processing image signal from an image sensor.
4The Exynos4x12 SoC series FIMC-IS V1.5 comprises of a dedicated ARM Cortex-A5
5processor, ISP, DRC and FD IP blocks and peripheral devices such as UART, I2C
6and SPI bus controllers, PWM and ADC.
7
8fimc-is node
9------------
10
11Required properties:
12- compatible : should be "samsung,exynos4212-fimc-is" for Exynos4212 and
13 Exynos4412 SoCs;
14- reg : physical base address and length of the registers set;
15- interrupts : must contain two FIMC-IS interrupts, in order: ISP0, ISP1;
16- clocks : list of clock specifiers, corresponding to entries in
17 clock-names property;
18- clock-names : must contain "ppmuispx", "ppmuispx", "lite0", "lite1"
19 "mpll", "sysreg", "isp", "drc", "fd", "mcuisp", "gicisp",
20 "pwm_isp", "mcuctl_isp", "uart", "ispdiv0", "ispdiv1",
21 "mcuispdiv0", "mcuispdiv1", "aclk200", "div_aclk200",
22 "aclk400mcuisp", "div_aclk400mcuisp" entries,
23 matching entries in the clocks property.
24pmu subnode
25-----------
26
27Required properties:
28 - reg : must contain PMU physical base address and size of the register set.
29
30The following are the FIMC-IS peripheral device nodes and can be specified
31either standalone or as the fimc-is node child nodes.
32
33i2c-isp (ISP I2C bus controller) nodes
34------------------------------------------
35
36Required properties:
37
38- compatible : should be "samsung,exynos4212-i2c-isp" for Exynos4212 and
39 Exynos4412 SoCs;
40- reg : physical base address and length of the registers set;
41- clocks : must contain gate clock specifier for this controller;
42- clock-names : must contain "i2c_isp" entry.
43
44For the above nodes it is required to specify a pinctrl state named "default",
45according to the pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt.
46
47Device tree nodes of the image sensors' controlled directly by the FIMC-IS
48firmware must be child nodes of their corresponding ISP I2C bus controller node.
49The data link of these image sensors must be specified using the common video
50interfaces bindings, defined in video-interfaces.txt.
Documentation/devicetree/bindings/media/gpio-ir-receiver.yaml+3−0
@@ -23,6 +23,9 @@ properties: · 22 unmodified lines
23 description: autosuspend delay time in milliseconds23 description: autosuspend delay time in milliseconds
24 $ref: /schemas/types.yaml#/definitions/uint3224 $ref: /schemas/types.yaml#/definitions/uint32
25 25
26 wakeup-source:
27 description: IR receiver can wake-up the system.
28
26required:29required:
27 - compatible30 - compatible
28 - gpios31 - gpios
Documentation/devicetree/bindings/media/i2c/chrontel,ch7322.yaml+2−2
@@ -1,8 +1,8 @@
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/chrontel,ch7322.yaml#"4$id: http://devicetree.org/schemas/media/i2c/chrontel,ch7322.yaml#
5$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
6 6
7title: Chrontel HDMI-CEC Controller7title: Chrontel HDMI-CEC Controller
8 8
Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml+3−3
@@ -38,7 +38,7 @@ properties: · 37 unmodified lines
38 dongwoon,aac-mode:38 dongwoon,aac-mode:
39 description:39 description:
40 Indication of AAC mode select.40 Indication of AAC mode select.
41 $ref: "/schemas/types.yaml#/definitions/uint32"41 $ref: /schemas/types.yaml#/definitions/uint32
42 enum:42 enum:
43 - 1 # AAC2 mode(operation time# 0.48 x Tvib)43 - 1 # AAC2 mode(operation time# 0.48 x Tvib)
44 - 2 # AAC3 mode(operation time# 0.70 x Tvib)44 - 2 # AAC3 mode(operation time# 0.70 x Tvib)
@@ -50,7 +50,7 @@ properties: · 5 unmodified lines
50 description:50 description:
51 Number of AAC Timing count that controlled by one 6-bit period of51 Number of AAC Timing count that controlled by one 6-bit period of
52 vibration register AACT[5:0], the unit of which is 100 us.52 vibration register AACT[5:0], the unit of which is 100 us.
53 $ref: "/schemas/types.yaml#/definitions/uint32"53 $ref: /schemas/types.yaml#/definitions/uint32
54 default: 0x2054 default: 0x20
55 minimum: 0x0055 minimum: 0x00
56 maximum: 0x3f56 maximum: 0x3f
@@ -59,7 +59,7 @@ properties: · 2 unmodified lines
59 description:59 description:
60 Indication of VCM internal clock dividing rate select, as one multiple60 Indication of VCM internal clock dividing rate select, as one multiple
61 factor to calculate VCM ring periodic time Tvib.61 factor to calculate VCM ring periodic time Tvib.
62 $ref: "/schemas/types.yaml#/definitions/uint32"62 $ref: /schemas/types.yaml#/definitions/uint32
63 enum:63 enum:
64 - 0 # Dividing Rate - 264 - 0 # Dividing Rate - 2
65 - 1 # Dividing Rate - 165 - 1 # Dividing Rate - 1
Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml+1−1
@@ -86,7 +86,7 @@ properties: · 85 unmodified lines
86 is 100000 micro volts86 is 100000 micro volts
87 87
88 maxim,gpio-poc:88 maxim,gpio-poc:
89 $ref: '/schemas/types.yaml#/definitions/uint32-array'89 $ref: /schemas/types.yaml#/definitions/uint32-array
90 minItems: 290 minItems: 2
91 maxItems: 291 maxItems: 2
92 description: |92 description: |
Documentation/devicetree/bindings/media/i2c/ov2685.txt+0−41
@@ -1,41 +0,0 @@
1* Omnivision OV2685 MIPI CSI-2 sensor
2
3Required Properties:
4- compatible: shall be "ovti,ov2685"
5- clocks: reference to the xvclk input clock
6- clock-names: shall be "xvclk"
7- avdd-supply: Analog voltage supply, 2.8 volts
8- dovdd-supply: Digital I/O voltage supply, 1.8 volts
9- dvdd-supply: Digital core voltage supply, 1.8 volts
10- reset-gpios: Low active reset gpio
11
12The device node shall contain one 'port' child node with an
13'endpoint' subnode for its digital output video port,
14in accordance with the video interface bindings defined in
15Documentation/devicetree/bindings/media/video-interfaces.txt.
16The endpoint optional property 'data-lanes' shall be "<1>".
17
18Example:
19&i2c7 {
20 ov2685: camera-sensor@3c {
21 compatible = "ovti,ov2685";
22 reg = <0x3c>;
23 pinctrl-names = "default";
24 pinctrl-0 = <&clk_24m_cam>;
25
26 clocks = <&cru SCLK_TESTCLKOUT1>;
27 clock-names = "xvclk";
28
29 avdd-supply = <&pp2800_cam>;
30 dovdd-supply = <&pp1800>;
31 dvdd-supply = <&pp1800>;
32 reset-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
33
34 port {
35 ucam_out: endpoint {
36 remote-endpoint = <&mipi_in_ucam>;
37 data-lanes = <1>;
38 };
39 };
40 };
41};
Documentation/devicetree/bindings/media/i2c/ov8856.yaml+1−1
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 7 unmodified lines
8title: Omnivision OV8856 CMOS Sensor8title: Omnivision OV8856 CMOS Sensor
9 9
10maintainers:10maintainers:
11 - Dongchun Zhu <dongchun.zhu@mediatek.com>11 - Sakari Ailus <sakari.ailus@linux.intel.com>
12 12
13description: |-13description: |-
14 The Omnivision OV8856 is a high performance, 1/4-inch, 8 megapixel, CMOS14 The Omnivision OV8856 is a high performance, 1/4-inch, 8 megapixel, CMOS
Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml+1−1
@@ -88,7 +88,7 @@ properties: · 87 unmodified lines
88 properties:88 properties:
89 link-frequencies: true89 link-frequencies: true
90 ovti,mipi-clock-voltage:90 ovti,mipi-clock-voltage:
91 $ref: "/schemas/types.yaml#/definitions/uint32"91 $ref: /schemas/types.yaml#/definitions/uint32
92 description:92 description:
93 Definition of MIPI clock voltage unit. This entry corresponds to93 Definition of MIPI clock voltage unit. This entry corresponds to
94 the link speed defined by the 'link-frequencies' property.94 the link speed defined by the 'link-frequencies' property.
Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml+101−0
@@ -0,0 +1,101 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/i2c/ovti,ov2685.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: OmniVision OV2685 Image Sensor
8
9maintainers:
10 - Shunqian Zheng <zhengsq@rock-chips.com>
11
12properties:
13 compatible:
14 const: ovti,ov2685
15
16 reg:
17 maxItems: 1
18
19 clocks:
20 items:
21 - description: XVCLK clock
22
23 clock-names:
24 items:
25 - const: xvclk
26
27 dvdd-supply:
28 description: Digital Domain Power Supply
29
30 avdd-supply:
31 description: Analog Domain Power Supply
32
33 dovdd-supply:
34 description: I/O Domain Power Supply
35
36 reset-gpios:
37 maxItems: 1
38 description: Reset Pin GPIO Control (active low)
39
40 port:
41 description: MIPI CSI-2 transmitter port
42 $ref: /schemas/graph.yaml#/$defs/port-base
43 additionalProperties: false
44
45 properties:
46 endpoint:
47 $ref: /schemas/media/video-interfaces.yaml#
48 unevaluatedProperties: false
49
50 properties:
51 data-lanes:
52 maxItems: 2
53
54 required:
55 - data-lanes
56
57required:
58 - compatible
59 - reg
60 - clocks
61 - clock-names
62 - dvdd-supply
63 - avdd-supply
64 - dovdd-supply
65 - port
66
67additionalProperties: false
68
69examples:
70 - |
71 #include <dt-bindings/clock/rk3399-cru.h>
72 #include <dt-bindings/gpio/gpio.h>
73
74 i2c {
75 #address-cells = <1>;
76 #size-cells = <0>;
77
78 ov2685: camera-sensor@3c {
79 compatible = "ovti,ov2685";
80 reg = <0x3c>;
81 pinctrl-names = "default";
82 pinctrl-0 = <&clk_24m_cam>;
83
84 clocks = <&cru SCLK_TESTCLKOUT1>;
85 clock-names = "xvclk";
86
87 avdd-supply = <&pp2800_cam>;
88 dovdd-supply = <&pp1800>;
89 dvdd-supply = <&pp1800>;
90 reset-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
91
92 port {
93 ucam_out: endpoint {
94 remote-endpoint = <&mipi_in_ucam>;
95 data-lanes = <1>;
96 };
97 };
98 };
99 };
100
101...
Documentation/devicetree/bindings/media/i2c/samsung,s5k5baf.yaml+101−0
@@ -0,0 +1,101 @@
1# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/i2c/samsung,s5k5baf.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung S5K5BAF UXGA 1/5" 2M CMOS Image Sensor with embedded SoC ISP
8
9maintainers:
10 - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
11
12properties:
13 compatible:
14 const: samsung,s5k5baf
15
16 reg:
17 maxItems: 1
18
19 clocks:
20 maxItems: 1
21
22 clock-names:
23 items:
24 - const: mclk
25
26 clock-frequency:
27 default: 24000000
28 description: mclk clock frequency
29
30 rstn-gpios:
31 maxItems: 1
32 description: RSTN pin
33
34 stbyn-gpios:
35 maxItems: 1
36 description: STDBYN pin
37
38 vdda-supply:
39 description: Analog power supply 2.8V (2.6V to 3.0V)
40
41 vddio-supply:
42 description: I/O power supply 1.8V (1.65V to 1.95V) or 2.8V (2.5V to 3.1V)
43
44 vddreg-supply:
45 description:
46 Regulator input power supply 1.8V (1.7V to 1.9V) or 2.8V (2.6V to 3.0)
47
48 port:
49 $ref: /schemas/graph.yaml#/$defs/port-base
50 additionalProperties: false
51
52 properties:
53 endpoint:
54 $ref: /schemas/media/video-interfaces.yaml#
55 unevaluatedProperties: false
56
57 properties:
58 data-lanes:
59 items:
60 - const: 1
61
62required:
63 - compatible
64 - clocks
65 - clock-names
66 - rstn-gpios
67 - stbyn-gpios
68 - vdda-supply
69 - vddio-supply
70 - vddreg-supply
71
72additionalProperties: false
73
74examples:
75 - |
76 #include <dt-bindings/gpio/gpio.h>
77
78 i2c {
79 #address-cells = <1>;
80 #size-cells = <0>;
81
82 sensor@2d {
83 compatible = "samsung,s5k5baf";
84 reg = <0x2d>;
85 clocks = <&camera 0>;
86 clock-names = "mclk";
87 clock-frequency = <24000000>;
88 rstn-gpios = <&gpl2 1 GPIO_ACTIVE_LOW>;
89 stbyn-gpios = <&gpl2 0 GPIO_ACTIVE_LOW>;
90 vdda-supply = <&cam_io_en_reg>;
91 vddio-supply = <&vtcam_reg>;
92 vddreg-supply = <&vt_core_15v_reg>;
93
94 port {
95 endpoint {
96 remote-endpoint = <&csis1_ep>;
97 data-lanes = <1>;
98 };
99 };
100 };
101 };
Documentation/devicetree/bindings/media/i2c/samsung,s5k6a3.yaml+98−0
@@ -0,0 +1,98 @@
1# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/i2c/samsung,s5k6a3.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung S5K6A3(YX) raw image sensor
8
9maintainers:
10 - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
11
12description:
13 S5K6A3(YX) is a raw image sensor with MIPI CSI-2 and CCP2 image data
14 interfaces and CCI (I2C compatible) control bus.
15
16properties:
17 compatible:
18 const: samsung,s5k6a3
19
20 reg:
21 maxItems: 1
22
23 clocks:
24 maxItems: 1
25
26 clock-names:
27 items:
28 - const: extclk
29
30 clock-frequency:
31 default: 24000000
32 description: extclk clock frequency
33
34 gpios:
35 maxItems: 1
36 description: GPIO connected to the RESET pin
37
38 afvdd-supply:
39 description: AF (actuator) voltage supply
40
41 svdda-supply:
42 description: Core voltage supply
43
44 svddio-supply:
45 description: I/O voltage supply
46
47 port:
48 $ref: /schemas/graph.yaml#/$defs/port-base
49 additionalProperties: false
50
51 properties:
52 endpoint:
53 $ref: /schemas/media/video-interfaces.yaml#
54 unevaluatedProperties: false
55
56 properties:
57 data-lanes:
58 items:
59 - const: 1
60
61required:
62 - compatible
63 - clocks
64 - clock-names
65 - gpios
66 - afvdd-supply
67 - svdda-supply
68 - svddio-supply
69
70additionalProperties: false
71
72examples:
73 - |
74 #include <dt-bindings/gpio/gpio.h>
75
76 i2c {
77 #address-cells = <1>;
78 #size-cells = <0>;
79
80 sensor@10 {
81 compatible = "samsung,s5k6a3";
82 reg = <0x10>;
83 clock-frequency = <24000000>;
84 clocks = <&camera 1>;
85 clock-names = "extclk";
86 gpios = <&gpm1 6 GPIO_ACTIVE_LOW>;
87 afvdd-supply = <&ldo19_reg>;
88 svdda-supply = <&cam_io_reg>;
89 svddio-supply = <&ldo19_reg>;
90
91 port {
92 endpoint {
93 remote-endpoint = <&csis1_ep>;
94 data-lanes = <1>;
95 };
96 };
97 };
98 };
Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml+18−7
@@ -12,15 +12,26 @@ maintainers: · 11 unmodified lines
12 12
13description: |-13description: |-
14 The Sony IMX290 is a 1/2.8-Inch CMOS Solid-state image sensor with Square14 The Sony IMX290 is a 1/2.8-Inch CMOS Solid-state image sensor with Square
15 Pixel for Color Cameras. It is programmable through I2C and 4-wire15 Pixel, available in either mono or colour variants. It is programmable
16 interfaces. The sensor output is available via CMOS logic parallel SDR16 through I2C and 4-wire interfaces.
17 output, Low voltage LVDS DDR output and CSI-2 serial data output. The CSI-217
18 bus is the default. No bindings have been defined for the other busses.18 The sensor output is available via CMOS logic parallel SDR output, Low voltage
19 LVDS DDR output and CSI-2 serial data output. The CSI-2 bus is the default.
20 No bindings have been defined for the other busses.
21
22 imx290lqr is the full model identifier for the colour variant. "sony,imx290"
23 is treated the same as this as it was the original compatible string.
24 imx290llr is the mono version of the sensor.
19 25
20properties:26properties:
21 compatible:27 compatible:
22 enum:28 oneOf:
23 - sony,imx29029 - enum:
30 - sony,imx290lqr # Colour
31 - sony,imx290llr # Monochrome
32 - sony,imx327lqr # Colour
33 - const: sony,imx290
34 deprecated: true
24 35
25 reg:36 reg:
26 maxItems: 137 maxItems: 1
@@ -101,7 +112,7 @@ examples: · 74 unmodified lines
101 #size-cells = <0>;112 #size-cells = <0>;
102 113
103 imx290: camera-sensor@1a {114 imx290: camera-sensor@1a {
104 compatible = "sony,imx290";115 compatible = "sony,imx290lqr";
105 reg = <0x1a>;116 reg = <0x1a>;
106 117
107 pinctrl-names = "default";118 pinctrl-names = "default";
Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml+1−1
@@ -82,7 +82,7 @@ examples: · 81 unmodified lines
82 imx334: endpoint {82 imx334: endpoint {
83 remote-endpoint = <&cam>;83 remote-endpoint = <&cam>;
84 data-lanes = <1 2 3 4>;84 data-lanes = <1 2 3 4>;
85 link-frequencies = /bits/ 64 <891000000>;85 link-frequencies = /bits/ 64 <891000000 445500000>;
86 };86 };
87 };87 };
88 };88 };
Documentation/devicetree/bindings/media/mediatek,mdp3-rdma.yaml+1−1
@@ -27,7 +27,7 @@ properties: · 26 unmodified lines
27 maxItems: 127 maxItems: 1
28 28
29 mediatek,gce-client-reg:29 mediatek,gce-client-reg:
30 $ref: '/schemas/types.yaml#/definitions/phandle-array'30 $ref: /schemas/types.yaml#/definitions/phandle-array
31 items:31 items:
32 items:32 items:
33 - description: phandle of GCE33 - description: phandle of GCE
Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml+46−71
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/mediatek,vcodec-subdev-decoder.yaml#"5$id: http://devicetree.org/schemas/media/mediatek,vcodec-subdev-decoder.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Mediatek Video Decode Accelerator With Multi Hardware8title: Mediatek Video Decode Accelerator With Multi Hardware
9 9
@@ -61,7 +61,10 @@ properties: · 51 unmodified lines
61 - mediatek,mt8195-vcodec-dec61 - mediatek,mt8195-vcodec-dec
62 62
63 reg:63 reg:
64 maxItems: 164 minItems: 1
65 items:
66 - description: VDEC_SYS register space
67 - description: VDEC_RACING_CTRL register space
65 68
66 iommus:69 iommus:
67 minItems: 170 minItems: 1
@@ -76,11 +79,6 @@ properties: · 8 unmodified lines
76 The node of system control processor (SCP), using79 The node of system control processor (SCP), using
77 the remoteproc & rpmsg framework.80 the remoteproc & rpmsg framework.
78 81
79 dma-ranges:
80 maxItems: 1
81 description: |
82 Describes the physical address space of IOMMU maps to memory.
83
84 "#address-cells":82 "#address-cells":
85 const: 283 const: 2
86 84
@@ -91,17 +89,19 @@ properties: · 4 unmodified lines
91 89
92# Required child node:90# Required child node:
93patternProperties:91patternProperties:
94 '^vcodec-lat@[0-9a-f]+$':92 '^video-codec@[0-9a-f]+$':
95 type: object93 type: object
96 94
97 properties:95 properties:
98 compatible:96 compatible:
99 enum:97 enum:
98 - mediatek,mtk-vcodec-core
100 - mediatek,mtk-vcodec-lat99 - mediatek,mtk-vcodec-lat
101 - mediatek,mtk-vcodec-lat-soc100 - mediatek,mtk-vcodec-lat-soc
102 101
103 reg:102 reg:
104 maxItems: 1103 maxItems: 1
104 description: VDEC_MISC register space
105 105
106 interrupts:106 interrupts:
107 maxItems: 1107 maxItems: 1
@@ -114,68 +114,13 @@ patternProperties: · 6 unmodified lines
114 Refer to bindings/iommu/mediatek,iommu.yaml.114 Refer to bindings/iommu/mediatek,iommu.yaml.
115 115
116 clocks:116 clocks:
117 minItems: 4
117 maxItems: 5118 maxItems: 5
118 119
119 clock-names:120 clock-names:
120 items:121 minItems: 4
121 - const: sel
122 - const: soc-vdec
123 - const: soc-lat
124 - const: vdec
125 - const: top
126
127 assigned-clocks:
128 maxItems: 1
129
130 assigned-clock-parents:
131 maxItems: 1
132
133 power-domains:
134 maxItems: 1
135
136 required:
137 - compatible
138 - reg
139 - iommus
140 - clocks
141 - clock-names
142 - assigned-clocks
143 - assigned-clock-parents
144 - power-domains
145
146 additionalProperties: false
147
148 '^vcodec-core@[0-9a-f]+$':
149 type: object
150
151 properties:
152 compatible:
153 const: mediatek,mtk-vcodec-core
154
155 reg:
156 maxItems: 1
157
158 interrupts:
159 maxItems: 1
160
161 iommus:
162 minItems: 1
163 maxItems: 32
164 description: |
165 List of the hardware port in respective IOMMU block for current Socs.
166 Refer to bindings/iommu/mediatek,iommu.yaml.
167
168 clocks:
169 maxItems: 5122 maxItems: 5
170 123
171 clock-names:
172 items:
173 - const: sel
174 - const: soc-vdec
175 - const: soc-lat
176 - const: vdec
177 - const: top
178
179 assigned-clocks:124 assigned-clocks:
180 maxItems: 1125 maxItems: 1
181 126
@@ -188,7 +133,6 @@ patternProperties: · 6 unmodified lines
188 required:133 required:
189 - compatible134 - compatible
190 - reg135 - reg
191 - interrupts
192 - iommus136 - iommus
193 - clocks137 - clocks
194 - clock-names138 - clock-names
@@ -203,7 +147,6 @@ required: · 8 unmodified lines
203 - reg147 - reg
204 - iommus148 - iommus
205 - mediatek,scp149 - mediatek,scp
206 - dma-ranges
207 - ranges150 - ranges
208 151
209if:152if:
@@ -211,12 +154,45 @@ if: · 1 unmodified line
211 compatible:154 compatible:
212 contains:155 contains:
213 enum:156 enum:
157 - mediatek,mtk-vcodec-core
214 - mediatek,mtk-vcodec-lat158 - mediatek,mtk-vcodec-lat
215 159
216then:160then:
217 required:161 required:
218 - interrupts162 - interrupts
219 163
164allOf:
165 - if:
166 properties:
167 compatible:
168 contains:
169 enum:
170 - mediatek,mt8192-vcodec-dec
171 then:
172 properties:
173 clock-names:
174 items:
175 - const: sel
176 - const: soc-vdec
177 - const: soc-lat
178 - const: vdec
179 - const: top
180
181 - if:
182 properties:
183 compatible:
184 contains:
185 enum:
186 - mediatek,mt8195-vcodec-dec
187 then:
188 properties:
189 clock-names:
190 items:
191 - const: sel
192 - const: vdec
193 - const: lat
194 - const: top
195
220additionalProperties: false196additionalProperties: false
221 197
222examples:198examples:
@@ -236,12 +212,11 @@ examples: · 13 unmodified lines
236 compatible = "mediatek,mt8192-vcodec-dec";212 compatible = "mediatek,mt8192-vcodec-dec";
237 mediatek,scp = <&scp>;213 mediatek,scp = <&scp>;
238 iommus = <&iommu0 M4U_PORT_L4_VDEC_MC_EXT>;214 iommus = <&iommu0 M4U_PORT_L4_VDEC_MC_EXT>;
239 dma-ranges = <0x1 0x0 0x0 0x40000000 0x0 0xfff00000>;
240 #address-cells = <2>;215 #address-cells = <2>;
241 #size-cells = <2>;216 #size-cells = <2>;
242 ranges = <0 0 0 0x16000000 0 0x40000>;217 ranges = <0 0 0 0x16000000 0 0x40000>;
243 reg = <0 0x16000000 0 0x1000>; /* VDEC_SYS */218 reg = <0 0x16000000 0 0x1000>; /* VDEC_SYS */
244 vcodec-lat@10000 {219 video-codec@10000 {
245 compatible = "mediatek,mtk-vcodec-lat";220 compatible = "mediatek,mtk-vcodec-lat";
246 reg = <0 0x10000 0 0x800>;221 reg = <0 0x10000 0 0x800>;
247 interrupts = <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH 0>;222 interrupts = <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH 0>;
@@ -264,7 +239,7 @@ examples: · 16 unmodified lines
264 power-domains = <&spm MT8192_POWER_DOMAIN_VDEC>;239 power-domains = <&spm MT8192_POWER_DOMAIN_VDEC>;
265 };240 };
266 241
267 vcodec-core@25000 {242 video-codec@25000 {
268 compatible = "mediatek,mtk-vcodec-core";243 compatible = "mediatek,mtk-vcodec-core";
269 reg = <0 0x25000 0 0x1000>;244 reg = <0 0x25000 0 0x1000>;
270 interrupts = <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH 0>;245 interrupts = <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH 0>;
Documentation/devicetree/bindings/media/meson-ir.txt+0−20
@@ -1,20 +0,0 @@
1* Amlogic Meson IR remote control receiver
2
3Required properties:
4 - compatible : depending on the platform this should be one of:
5 - "amlogic,meson6-ir"
6 - "amlogic,meson8b-ir"
7 - "amlogic,meson-gxbb-ir"
8 - reg : physical base address and length of the device registers
9 - interrupts : a single specifier for the interrupt from the device
10
11Optional properties:
12 - linux,rc-map-name: see rc.txt file in the same directory.
13
14Example:
15
16 ir-receiver@c8100480 {
17 compatible= "amlogic,meson6-ir";
18 reg = <0xc8100480 0x20>;
19 interrupts = <0 15 1>;
20 };
Documentation/devicetree/bindings/media/microchip,sama5d4-vdec.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/microchip,sama5d4-vdec.yaml#"5$id: http://devicetree.org/schemas/media/microchip,sama5d4-vdec.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Hantro G1 VPU codec implemented on Microchip SAMA5D4 SoCs8title: Hantro G1 VPU codec implemented on Microchip SAMA5D4 SoCs
9 9
Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml+173−0
@@ -0,0 +1,173 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/nxp,imx8-isi.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: i.MX8 Image Sensing Interface
8
9maintainers:
10 - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11
12description: |
13 The Image Sensing Interface (ISI) combines image processing pipelines with
14 DMA engines to process and capture frames originating from a variety of
15 sources. The inputs to the ISI go through Pixel Link interfaces, and their
16 number and nature is SoC-dependent. They cover both capture interfaces (MIPI
17 CSI-2 RX, HDMI RX, ...) and display engine outputs for writeback support.
18
19properties:
20 compatible:
21 enum:
22 - fsl,imx8mn-isi
23 - fsl,imx8mp-isi
24
25 reg:
26 maxItems: 1
27
28 clocks:
29 items:
30 - description: The AXI clock
31 - description: The APB clock
32 # TODO: Check if the per-channel ipg_proc_clk clocks need to be specified
33 # as well, in case some SoCs have the ability to control them separately.
34 # This may be the case of the i.MX8[DQ]X(P)
35
36 clock-names:
37 items:
38 - const: axi
39 - const: apb
40
41 fsl,blk-ctrl:
42 $ref: /schemas/types.yaml#/definitions/phandle
43 description:
44 A phandle referencing the block control that contains the CSIS to ISI
45 gasket.
46
47 interrupts:
48 description: Processing pipeline interrupts, one per pipeline
49 minItems: 1
50 maxItems: 2
51
52 power-domains:
53 maxItems: 1
54
55 ports:
56 $ref: /schemas/graph.yaml#/properties/ports
57 description: |
58 Ports represent the Pixel Link inputs to the ISI. Their number and
59 assignment are model-dependent. Each port shall have a single endpoint.
60
61required:
62 - compatible
63 - reg
64 - interrupts
65 - clocks
66 - clock-names
67 - fsl,blk-ctrl
68 - ports
69
70allOf:
71 - if:
72 properties:
73 compatible:
74 contains:
75 const: fsl,imx8mn-isi
76 then:
77 properties:
78 interrupts:
79 maxItems: 1
80 ports:
81 properties:
82 port@0:
83 description: MIPI CSI-2 RX
84 required:
85 - port@0
86
87 - if:
88 properties:
89 compatible:
90 contains:
91 const: fsl,imx8mp-isi
92 then:
93 properties:
94 interrupts:
95 maxItems: 2
96 ports:
97 properties:
98 port@0:
99 description: MIPI CSI-2 RX 0
100 port@1:
101 description: MIPI CSI-2 RX 1
102 required:
103 - port@0
104 - port@1
105
106additionalProperties: false
107
108examples:
109 - |
110 #include <dt-bindings/clock/imx8mn-clock.h>
111 #include <dt-bindings/interrupt-controller/arm-gic.h>
112 #include <dt-bindings/interrupt-controller/irq.h>
113 #include <dt-bindings/power/imx8mn-power.h>
114
115 isi@32e20000 {
116 compatible = "fsl,imx8mn-isi";
117 reg = <0x32e20000 0x100>;
118 interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
119 clocks = <&clk IMX8MN_CLK_DISP_AXI_ROOT>,
120 <&clk IMX8MN_CLK_DISP_APB_ROOT>;
121 clock-names = "axi", "apb";
122 fsl,blk-ctrl = <&disp_blk_ctrl>;
123 power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_ISI>;
124
125 ports {
126 #address-cells = <1>;
127 #size-cells = <0>;
128
129 port@0 {
130 reg = <0>;
131 isi_in: endpoint {
132 remote-endpoint = <&mipi_csi_out>;
133 };
134 };
135 };
136 };
137
138 - |
139 #include <dt-bindings/clock/imx8mp-clock.h>
140 #include <dt-bindings/interrupt-controller/arm-gic.h>
141 #include <dt-bindings/interrupt-controller/irq.h>
142
143 isi@32e00000 {
144 compatible = "fsl,imx8mp-isi";
145 reg = <0x32e00000 0x4000>;
146 interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
147 <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
148 clocks = <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>,
149 <&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
150 clock-names = "axi", "apb";
151 fsl,blk-ctrl = <&media_blk_ctrl>;
152 power-domains = <&mediamix_pd>;
153
154 ports {
155 #address-cells = <1>;
156 #size-cells = <0>;
157
158 port@0 {
159 reg = <0>;
160 isi_in_0: endpoint {
161 remote-endpoint = <&mipi_csi_0_out>;
162 };
163 };
164
165 port@1 {
166 reg = <1>;
167 isi_in_1: endpoint {
168 remote-endpoint = <&mipi_csi_1_out>;
169 };
170 };
171 };
172 };
173...
Documentation/devicetree/bindings/media/nxp,imx8mq-vpu.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/nxp,imx8mq-vpu.yaml#"5$id: http://devicetree.org/schemas/media/nxp,imx8mq-vpu.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Hantro G1/G2 VPU codecs implemented on i.MX8M SoCs8title: Hantro G1/G2 VPU codecs implemented on i.MX8M SoCs
9 9
Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/qcom,msm8916-camss.yaml#"5$id: http://devicetree.org/schemas/media/qcom,msm8916-camss.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Qualcomm CAMSS ISP8title: Qualcomm CAMSS ISP
9 9
Documentation/devicetree/bindings/media/qcom,msm8916-venus.yaml+29−57
@@ -1,11 +1,10 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2
3%YAML 1.22%YAML 1.2
4---3---
5$id: "http://devicetree.org/schemas/media/qcom,msm8916-venus.yaml#"4$id: http://devicetree.org/schemas/media/qcom,msm8916-venus.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
7 6
8title: Qualcomm Venus video encode and decode accelerators7title: Qualcomm MSM8916 Venus video encode and decode accelerators
9 8
10maintainers:9maintainers:
11 - Stanimir Varbanov <stanimir.varbanov@linaro.org>10 - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: | · 2 unmodified lines
14 The Venus IP is a video encode and decode accelerator present13 The Venus IP is a video encode and decode accelerator present
15 on Qualcomm platforms14 on Qualcomm platforms
16 15
16allOf:
17 - $ref: qcom,venus-common.yaml#
18
17properties:19properties:
18 compatible:20 compatible:
19 const: qcom,msm8916-venus21 const: qcom,msm8916-venus
20 22
21 reg:
22 maxItems: 1
23
24 interrupts:
25 maxItems: 1
26
27 power-domains:23 power-domains:
28 maxItems: 124 maxItems: 1
29 25
@@ -39,9 +35,6 @@ properties: · 9 unmodified lines
39 iommus:35 iommus:
40 maxItems: 136 maxItems: 1
41 37
42 memory-region:
43 maxItems: 1
44
45 video-decoder:38 video-decoder:
46 type: object39 type: object
47 40
@@ -66,57 +59,36 @@ properties: · 18 unmodified lines
66 59
67 additionalProperties: false60 additionalProperties: false
68 61
69 video-firmware:
70 type: object
71 additionalProperties: false
72
73 description: |
74 Firmware subnode is needed when the platform does not
75 have TrustZone.
76
77 properties:
78 iommus:
79 maxItems: 1
80
81 required:
82 - iommus
83
84required:62required:
85 - compatible63 - compatible
86 - reg
87 - interrupts
88 - power-domains
89 - clocks
90 - clock-names
91 - iommus64 - iommus
92 - memory-region
93 - video-decoder65 - video-decoder
94 - video-encoder66 - video-encoder
95 67
96additionalProperties: false68unevaluatedProperties: false
97 69
98examples:70examples:
99 - |71 - |
100 #include <dt-bindings/interrupt-controller/arm-gic.h>72 #include <dt-bindings/interrupt-controller/arm-gic.h>
101 #include <dt-bindings/clock/qcom,gcc-msm8916.h>73 #include <dt-bindings/clock/qcom,gcc-msm8916.h>
102 74
103 video-codec@1d00000 {75 video-codec@1d00000 {
104 compatible = "qcom,msm8916-venus";76 compatible = "qcom,msm8916-venus";
105 reg = <0x01d00000 0xff000>;77 reg = <0x01d00000 0xff000>;
106 interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;78 interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
107 clocks = <&gcc GCC_VENUS0_VCODEC0_CLK>,79 clocks = <&gcc GCC_VENUS0_VCODEC0_CLK>,
108 <&gcc GCC_VENUS0_AHB_CLK>,80 <&gcc GCC_VENUS0_AHB_CLK>,
109 <&gcc GCC_VENUS0_AXI_CLK>;81 <&gcc GCC_VENUS0_AXI_CLK>;
110 clock-names = "core", "iface", "bus";82 clock-names = "core", "iface", "bus";
111 power-domains = <&gcc VENUS_GDSC>;83 power-domains = <&gcc VENUS_GDSC>;
112 iommus = <&apps_iommu 5>;84 iommus = <&apps_iommu 5>;
113 memory-region = <&venus_mem>;85 memory-region = <&venus_mem>;
114 86
115 video-decoder {87 video-decoder {
116 compatible = "venus-decoder";88 compatible = "venus-decoder";
117 };89 };
118 90
119 video-encoder {91 video-encoder {
120 compatible = "venus-encoder";92 compatible = "venus-encoder";
121 };
122 };93 };
94 };
Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/qcom,msm8996-camss.yaml#"5$id: http://devicetree.org/schemas/media/qcom,msm8996-camss.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Qualcomm CAMSS ISP8title: Qualcomm CAMSS ISP
9 9
Documentation/devicetree/bindings/media/qcom,msm8996-venus.yaml+63−83
@@ -1,11 +1,10 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2
3%YAML 1.22%YAML 1.2
4---3---
5$id: "http://devicetree.org/schemas/media/qcom,msm8996-venus.yaml#"4$id: http://devicetree.org/schemas/media/qcom,msm8996-venus.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
7 6
8title: Qualcomm Venus video encode and decode accelerators7title: Qualcomm MSM8996 Venus video encode and decode accelerators
9 8
10maintainers:9maintainers:
11 - Stanimir Varbanov <stanimir.varbanov@linaro.org>10 - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: | · 2 unmodified lines
14 The Venus IP is a video encode and decode accelerator present13 The Venus IP is a video encode and decode accelerator present
15 on Qualcomm platforms14 on Qualcomm platforms
16 15
16allOf:
17 - $ref: qcom,venus-common.yaml#
18
17properties:19properties:
18 compatible:20 compatible:
19 const: qcom,msm8996-venus21 const: qcom,msm8996-venus
20 22
21 reg:
22 maxItems: 1
23
24 interrupts:
25 maxItems: 1
26
27 power-domains:23 power-domains:
28 maxItems: 124 maxItems: 1
29 25
@@ -37,12 +33,17 @@ properties: · 7 unmodified lines
37 - const: bus33 - const: bus
38 - const: mbus34 - const: mbus
39 35
36 interconnects:
37 maxItems: 2
38
39 interconnect-names:
40 items:
41 - const: video-mem
42 - const: cpu-cfg
43
40 iommus:44 iommus:
41 maxItems: 2045 maxItems: 20
42 46
43 memory-region:
44 maxItems: 1
45
46 video-decoder:47 video-decoder:
47 type: object48 type: object
48 49
@@ -93,83 +94,62 @@ properties: · 44 unmodified lines
93 94
94 additionalProperties: false95 additionalProperties: false
95 96
96 video-firmware:
97 type: object
98 additionalProperties: false
99
100 description: |
101 Firmware subnode is needed when the platform does not
102 have TrustZone.
103
104 properties:
105 iommus:
106 maxItems: 1
107
108 required:
109 - iommus
110
111required:97required:
112 - compatible98 - compatible
113 - reg
114 - interrupts
115 - power-domains
116 - clocks
117 - clock-names
118 - iommus99 - iommus
119 - memory-region
120 - video-decoder100 - video-decoder
121 - video-encoder101 - video-encoder
122 102
123additionalProperties: false103unevaluatedProperties: false
124 104
125examples:105examples:
126 - |106 - |
127 #include <dt-bindings/interrupt-controller/arm-gic.h>107 #include <dt-bindings/interrupt-controller/arm-gic.h>
128 #include <dt-bindings/clock/qcom,mmcc-msm8996.h>108 #include <dt-bindings/clock/qcom,mmcc-msm8996.h>
129 109
130 video-codec@c00000 {110 video-codec@c00000 {
131 compatible = "qcom,msm8996-venus";111 compatible = "qcom,msm8996-venus";
132 reg = <0x00c00000 0xff000>;112 reg = <0x00c00000 0xff000>;
133 interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;113 interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
134 clocks = <&mmcc VIDEO_CORE_CLK>,114 clocks = <&mmcc VIDEO_CORE_CLK>,
135 <&mmcc VIDEO_AHB_CLK>,115 <&mmcc VIDEO_AHB_CLK>,
136 <&mmcc VIDEO_AXI_CLK>,116 <&mmcc VIDEO_AXI_CLK>,
137 <&mmcc VIDEO_MAXI_CLK>;117 <&mmcc VIDEO_MAXI_CLK>;
138 clock-names = "core", "iface", "bus", "mbus";118 clock-names = "core", "iface", "bus", "mbus";
139 power-domains = <&mmcc VENUS_GDSC>;119 power-domains = <&mmcc VENUS_GDSC>;
140 iommus = <&venus_smmu 0x00>,120 iommus = <&venus_smmu 0x00>,
141 <&venus_smmu 0x01>,121 <&venus_smmu 0x01>,
142 <&venus_smmu 0x0a>,122 <&venus_smmu 0x0a>,
143 <&venus_smmu 0x07>,123 <&venus_smmu 0x07>,
144 <&venus_smmu 0x0e>,124 <&venus_smmu 0x0e>,
145 <&venus_smmu 0x0f>,125 <&venus_smmu 0x0f>,
146 <&venus_smmu 0x08>,126 <&venus_smmu 0x08>,
147 <&venus_smmu 0x09>,127 <&venus_smmu 0x09>,
148 <&venus_smmu 0x0b>,128 <&venus_smmu 0x0b>,
149 <&venus_smmu 0x0c>,129 <&venus_smmu 0x0c>,
150 <&venus_smmu 0x0d>,130 <&venus_smmu 0x0d>,
151 <&venus_smmu 0x10>,131 <&venus_smmu 0x10>,
152 <&venus_smmu 0x11>,132 <&venus_smmu 0x11>,
153 <&venus_smmu 0x21>,133 <&venus_smmu 0x21>,
154 <&venus_smmu 0x28>,134 <&venus_smmu 0x28>,
155 <&venus_smmu 0x29>,135 <&venus_smmu 0x29>,
156 <&venus_smmu 0x2b>,136 <&venus_smmu 0x2b>,
157 <&venus_smmu 0x2c>,137 <&venus_smmu 0x2c>,
158 <&venus_smmu 0x2d>,138 <&venus_smmu 0x2d>,
159 <&venus_smmu 0x31>;139 <&venus_smmu 0x31>;
160 memory-region = <&venus_mem>;140 memory-region = <&venus_mem>;
161 141
162 video-decoder {142 video-decoder {
163 compatible = "venus-decoder";143 compatible = "venus-decoder";
164 clocks = <&mmcc VIDEO_SUBCORE0_CLK>;144 clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
165 clock-names = "core";145 clock-names = "core";
166 power-domains = <&mmcc VENUS_CORE0_GDSC>;146 power-domains = <&mmcc VENUS_CORE0_GDSC>;
167 };147 };
168 148
169 video-encoder {149 video-encoder {
170 compatible = "venus-encoder";150 compatible = "venus-encoder";
171 clocks = <&mmcc VIDEO_SUBCORE1_CLK>;151 clocks = <&mmcc VIDEO_SUBCORE1_CLK>;
172 clock-names = "core";152 clock-names = "core";
173 power-domains = <&mmcc VENUS_CORE1_GDSC>;153 power-domains = <&mmcc VENUS_CORE1_GDSC>;
174 };
175 };154 };
155 };
Documentation/devicetree/bindings/media/qcom,sc7180-venus.yaml+38−59
@@ -1,11 +1,10 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2
3%YAML 1.22%YAML 1.2
4---3---
5$id: "http://devicetree.org/schemas/media/qcom,sc7180-venus.yaml#"4$id: http://devicetree.org/schemas/media/qcom,sc7180-venus.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
7 6
8title: Qualcomm Venus video encode and decode accelerators7title: Qualcomm SC7180 Venus video encode and decode accelerators
9 8
10maintainers:9maintainers:
11 - Stanimir Varbanov <stanimir.varbanov@linaro.org>10 - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: | · 2 unmodified lines
14 The Venus IP is a video encode and decode accelerator present13 The Venus IP is a video encode and decode accelerator present
15 on Qualcomm platforms14 on Qualcomm platforms
16 15
16allOf:
17 - $ref: qcom,venus-common.yaml#
18
17properties:19properties:
18 compatible:20 compatible:
19 const: qcom,sc7180-venus21 const: qcom,sc7180-venus
20 22
21 reg:
22 maxItems: 1
23
24 interrupts:
25 maxItems: 1
26
27 power-domains:23 power-domains:
28 minItems: 224 minItems: 2
29 maxItems: 325 maxItems: 3
@@ -60,6 +56,10 @@ properties: · 30 unmodified lines
60 - const: video-mem56 - const: video-mem
61 - const: cpu-cfg57 - const: cpu-cfg
62 58
59 operating-points-v2: true
60 opp-table:
61 type: object
62
63 video-decoder:63 video-decoder:
64 type: object64 type: object
65 65
@@ -84,63 +84,42 @@ properties: · 18 unmodified lines
84 84
85 additionalProperties: false85 additionalProperties: false
86 86
87 video-firmware:
88 type: object
89 additionalProperties: false
90
91 description: |
92 Firmware subnode is needed when the platform does not
93 have TrustZone.
94
95 properties:
96 iommus:
97 maxItems: 1
98
99 required:
100 - iommus
101
102required:87required:
103 - compatible88 - compatible
104 - reg
105 - interrupts
106 - power-domains
107 - power-domain-names89 - power-domain-names
108 - clocks
109 - clock-names
110 - iommus90 - iommus
111 - memory-region
112 - video-decoder91 - video-decoder
113 - video-encoder92 - video-encoder
114 93
115additionalProperties: false94unevaluatedProperties: false
116 95
117examples:96examples:
118 - |97 - |
119 #include <dt-bindings/interrupt-controller/arm-gic.h>98 #include <dt-bindings/interrupt-controller/arm-gic.h>
120 #include <dt-bindings/clock/qcom,videocc-sc7180.h>99 #include <dt-bindings/clock/qcom,videocc-sc7180.h>
121 100
122 venus: video-codec@aa00000 {101 venus: video-codec@aa00000 {
123 compatible = "qcom,sc7180-venus";102 compatible = "qcom,sc7180-venus";
124 reg = <0x0aa00000 0xff000>;103 reg = <0x0aa00000 0xff000>;
125 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;104 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
126 power-domains = <&videocc VENUS_GDSC>,105 power-domains = <&videocc VENUS_GDSC>,
127 <&videocc VCODEC0_GDSC>;106 <&videocc VCODEC0_GDSC>;
128 power-domain-names = "venus", "vcodec0";107 power-domain-names = "venus", "vcodec0";
129 clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,108 clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
130 <&videocc VIDEO_CC_VENUS_AHB_CLK>,109 <&videocc VIDEO_CC_VENUS_AHB_CLK>,
131 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,110 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,
132 <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,111 <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
133 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;112 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;
134 clock-names = "core", "iface", "bus",113 clock-names = "core", "iface", "bus",
135 "vcodec0_core", "vcodec0_bus";114 "vcodec0_core", "vcodec0_bus";
136 iommus = <&apps_smmu 0x0c00 0x60>;115 iommus = <&apps_smmu 0x0c00 0x60>;
137 memory-region = <&venus_mem>;116 memory-region = <&venus_mem>;
138 117
139 video-decoder {118 video-decoder {
140 compatible = "venus-decoder";119 compatible = "venus-decoder";
141 };120 };
142 121
143 video-encoder {122 video-encoder {
144 compatible = "venus-encoder";123 compatible = "venus-encoder";
145 };
146 };124 };
125 };
Documentation/devicetree/bindings/media/qcom,sc7280-venus.yaml+54−78
@@ -1,11 +1,10 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2
3%YAML 1.22%YAML 1.2
4---3---
5$id: "http://devicetree.org/schemas/media/qcom,sc7280-venus.yaml#"4$id: http://devicetree.org/schemas/media/qcom,sc7280-venus.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
7 6
8title: Qualcomm Venus video encode and decode accelerators7title: Qualcomm SC7280 Venus video encode and decode accelerators
9 8
10maintainers:9maintainers:
11 - Stanimir Varbanov <stanimir.varbanov@linaro.org>10 - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: | · 2 unmodified lines
14 The Venus Iris2 IP is a video encode and decode accelerator present13 The Venus Iris2 IP is a video encode and decode accelerator present
15 on Qualcomm platforms14 on Qualcomm platforms
16 15
16allOf:
17 - $ref: qcom,venus-common.yaml#
18
17properties:19properties:
18 compatible:20 compatible:
19 const: qcom,sc7280-venus21 const: qcom,sc7280-venus
20 22
21 reg:
22 maxItems: 1
23
24 interrupts:
25 maxItems: 1
26
27 power-domains:23 power-domains:
28 minItems: 224 minItems: 2
29 maxItems: 325 maxItems: 3
@@ -49,9 +45,6 @@ properties: · 19 unmodified lines
49 iommus:45 iommus:
50 maxItems: 246 maxItems: 2
51 47
52 memory-region:
53 maxItems: 1
54
55 interconnects:48 interconnects:
56 maxItems: 249 maxItems: 2
57 50
@@ -60,6 +53,10 @@ properties: · 2 unmodified lines
60 - const: cpu-cfg53 - const: cpu-cfg
61 - const: video-mem54 - const: video-mem
62 55
56 operating-points-v2: true
57 opp-table:
58 type: object
59
63 video-decoder:60 video-decoder:
64 type: object61 type: object
65 62
@@ -84,79 +81,58 @@ properties: · 18 unmodified lines
84 81
85 additionalProperties: false82 additionalProperties: false
86 83
87 video-firmware:
88 type: object
89 additionalProperties: false
90
91 description: |
92 Firmware subnode is needed when the platform does not
93 have TrustZone.
94
95 properties:
96 iommus:
97 maxItems: 1
98
99 required:
100 - iommus
101
102required:84required:
103 - compatible85 - compatible
104 - reg
105 - interrupts
106 - power-domains
107 - power-domain-names86 - power-domain-names
108 - clocks
109 - clock-names
110 - iommus87 - iommus
111 - memory-region
112 - video-decoder88 - video-decoder
113 - video-encoder89 - video-encoder
114 90
115additionalProperties: false91unevaluatedProperties: false
116 92
117examples:93examples:
118 - |94 - |
119 #include <dt-bindings/interrupt-controller/arm-gic.h>95 #include <dt-bindings/interrupt-controller/arm-gic.h>
120 #include <dt-bindings/clock/qcom,videocc-sc7280.h>96 #include <dt-bindings/clock/qcom,videocc-sc7280.h>
121 #include <dt-bindings/interconnect/qcom,sc7280.h>97 #include <dt-bindings/interconnect/qcom,sc7280.h>
122 #include <dt-bindings/power/qcom-rpmpd.h>98 #include <dt-bindings/power/qcom-rpmpd.h>
123 99
124 venus: video-codec@aa00000 {100 venus: video-codec@aa00000 {
125 compatible = "qcom,sc7280-venus";101 compatible = "qcom,sc7280-venus";
126 reg = <0x0aa00000 0xd0600>;102 reg = <0x0aa00000 0xd0600>;
127 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;103 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
128 104
129 clocks = <&videocc VIDEO_CC_MVSC_CORE_CLK>,105 clocks = <&videocc VIDEO_CC_MVSC_CORE_CLK>,
130 <&videocc VIDEO_CC_MVSC_CTL_AXI_CLK>,106 <&videocc VIDEO_CC_MVSC_CTL_AXI_CLK>,
131 <&videocc VIDEO_CC_VENUS_AHB_CLK>,107 <&videocc VIDEO_CC_VENUS_AHB_CLK>,
132 <&videocc VIDEO_CC_MVS0_CORE_CLK>,108 <&videocc VIDEO_CC_MVS0_CORE_CLK>,
133 <&videocc VIDEO_CC_MVS0_AXI_CLK>;109 <&videocc VIDEO_CC_MVS0_AXI_CLK>;
134 clock-names = "core", "bus", "iface",110 clock-names = "core", "bus", "iface",
135 "vcodec_core", "vcodec_bus";111 "vcodec_core", "vcodec_bus";
136 112
137 power-domains = <&videocc MVSC_GDSC>,113 power-domains = <&videocc MVSC_GDSC>,
138 <&videocc MVS0_GDSC>,114 <&videocc MVS0_GDSC>,
139 <&rpmhpd SC7280_CX>;115 <&rpmhpd SC7280_CX>;
140 power-domain-names = "venus", "vcodec0", "cx";116 power-domain-names = "venus", "vcodec0", "cx";
141 117
142 interconnects = <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_VENUS_CFG 0>,118 interconnects = <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_VENUS_CFG 0>,
143 <&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI1 0>;119 <&mmss_noc MASTER_VIDEO_P0 0 &mc_virt SLAVE_EBI1 0>;
144 interconnect-names = "cpu-cfg", "video-mem";120 interconnect-names = "cpu-cfg", "video-mem";
145 121
146 iommus = <&apps_smmu 0x2180 0x20>,122 iommus = <&apps_smmu 0x2180 0x20>,
147 <&apps_smmu 0x2184 0x20>;123 <&apps_smmu 0x2184 0x20>;
148 124
149 memory-region = <&video_mem>;125 memory-region = <&video_mem>;
150 126
151 video-decoder {127 video-decoder {
152 compatible = "venus-decoder";128 compatible = "venus-decoder";
153 };129 };
154 130
155 video-encoder {131 video-encoder {
156 compatible = "venus-encoder";132 compatible = "venus-encoder";
157 };133 };
158 134
159 video-firmware {135 video-firmware {
160 iommus = <&apps_smmu 0x21a2 0x0>;136 iommus = <&apps_smmu 0x21a2 0x0>;
161 };
162 };137 };
138 };
Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/qcom,sdm660-camss.yaml#"5$id: http://devicetree.org/schemas/media/qcom,sdm660-camss.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Qualcomm CAMSS ISP8title: Qualcomm CAMSS ISP
9 9
Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml+58−86
@@ -1,11 +1,10 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2
3%YAML 1.22%YAML 1.2
4---3---
5$id: "http://devicetree.org/schemas/media/qcom,sdm660-venus.yaml#"4$id: http://devicetree.org/schemas/media/qcom,sdm660-venus.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
7 6
8title: Qualcomm Venus video encode and decode accelerators7title: Qualcomm SDM660 Venus video encode and decode accelerators
9 8
10maintainers:9maintainers:
11 - Stanimir Varbanov <stanimir.varbanov@linaro.org>10 - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -15,13 +14,13 @@ description: | · 3 unmodified lines
15 The Venus IP is a video encode and decode accelerator present14 The Venus IP is a video encode and decode accelerator present
16 on Qualcomm platforms15 on Qualcomm platforms
17 16
17allOf:
18 - $ref: qcom,venus-common.yaml#
19
18properties:20properties:
19 compatible:21 compatible:
20 const: qcom,sdm660-venus22 const: qcom,sdm660-venus
21 23
22 reg:
23 maxItems: 1
24
25 clocks:24 clocks:
26 maxItems: 425 maxItems: 4
27 26
@@ -40,15 +39,9 @@ properties: · 12 unmodified lines
40 - const: cpu-cfg39 - const: cpu-cfg
41 - const: video-mem40 - const: video-mem
42 41
43 interrupts:
44 maxItems: 1
45
46 iommus:42 iommus:
47 maxItems: 2043 maxItems: 20
48 44
49 memory-region:
50 maxItems: 1
51
52 power-domains:45 power-domains:
53 maxItems: 146 maxItems: 1
54 47
@@ -102,86 +95,65 @@ properties: · 47 unmodified lines
102 95
103 additionalProperties: false96 additionalProperties: false
104 97
105 video-firmware:
106 type: object
107 additionalProperties: false
108
109 description: |
110 Firmware subnode is needed when the platform does not
111 have TrustZone.
112
113 properties:
114 iommus:
115 maxItems: 1
116
117 required:
118 - iommus
119
120required:98required:
121 - compatible99 - compatible
122 - reg
123 - clocks
124 - clock-names
125 - interrupts
126 - iommus100 - iommus
127 - memory-region
128 - power-domains
129 - video-decoder101 - video-decoder
130 - video-encoder102 - video-encoder
131 103
132additionalProperties: false104unevaluatedProperties: false
133 105
134examples:106examples:
135 - |107 - |
136 #include <dt-bindings/clock/qcom,mmcc-sdm660.h>108 #include <dt-bindings/clock/qcom,mmcc-sdm660.h>
137 #include <dt-bindings/interrupt-controller/arm-gic.h>109 #include <dt-bindings/interrupt-controller/arm-gic.h>
138 110
139 video-codec@cc00000 {111 video-codec@cc00000 {
140 compatible = "qcom,sdm660-venus";112 compatible = "qcom,sdm660-venus";
141 reg = <0x0cc00000 0xff000>;113 reg = <0x0cc00000 0xff000>;
142 clocks = <&mmcc VIDEO_CORE_CLK>,114 clocks = <&mmcc VIDEO_CORE_CLK>,
143 <&mmcc VIDEO_AHB_CLK>,115 <&mmcc VIDEO_AHB_CLK>,
144 <&mmcc VIDEO_AXI_CLK>,116 <&mmcc VIDEO_AXI_CLK>,
145 <&mmcc THROTTLE_VIDEO_AXI_CLK>;117 <&mmcc THROTTLE_VIDEO_AXI_CLK>;
146 clock-names = "core", "iface", "bus", "bus_throttle";118 clock-names = "core", "iface", "bus", "bus_throttle";
147 interconnects = <&gnoc 0 &mnoc 13>,119 interconnects = <&gnoc 0 &mnoc 13>,
148 <&mnoc 4 &bimc 5>;120 <&mnoc 4 &bimc 5>;
149 interconnect-names = "cpu-cfg", "video-mem";121 interconnect-names = "cpu-cfg", "video-mem";
150 interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;122 interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
151 iommus = <&mmss_smmu 0x400>,123 iommus = <&mmss_smmu 0x400>,
152 <&mmss_smmu 0x401>,124 <&mmss_smmu 0x401>,
153 <&mmss_smmu 0x40a>,125 <&mmss_smmu 0x40a>,
154 <&mmss_smmu 0x407>,126 <&mmss_smmu 0x407>,
155 <&mmss_smmu 0x40e>,127 <&mmss_smmu 0x40e>,
156 <&mmss_smmu 0x40f>,128 <&mmss_smmu 0x40f>,
157 <&mmss_smmu 0x408>,129 <&mmss_smmu 0x408>,
158 <&mmss_smmu 0x409>,130 <&mmss_smmu 0x409>,
159 <&mmss_smmu 0x40b>,131 <&mmss_smmu 0x40b>,
160 <&mmss_smmu 0x40c>,132 <&mmss_smmu 0x40c>,
161 <&mmss_smmu 0x40d>,133 <&mmss_smmu 0x40d>,
162 <&mmss_smmu 0x410>,134 <&mmss_smmu 0x410>,
163 <&mmss_smmu 0x421>,135 <&mmss_smmu 0x421>,
164 <&mmss_smmu 0x428>,136 <&mmss_smmu 0x428>,
165 <&mmss_smmu 0x429>,137 <&mmss_smmu 0x429>,
166 <&mmss_smmu 0x42b>,138 <&mmss_smmu 0x42b>,
167 <&mmss_smmu 0x42c>,139 <&mmss_smmu 0x42c>,
168 <&mmss_smmu 0x42d>,140 <&mmss_smmu 0x42d>,
169 <&mmss_smmu 0x411>,141 <&mmss_smmu 0x411>,
170 <&mmss_smmu 0x431>;142 <&mmss_smmu 0x431>;
171 memory-region = <&venus_region>;143 memory-region = <&venus_region>;
172 power-domains = <&mmcc VENUS_GDSC>;144 power-domains = <&mmcc VENUS_GDSC>;
173 145
174 video-decoder {146 video-decoder {
175 compatible = "venus-decoder";147 compatible = "venus-decoder";
176 clocks = <&mmcc VIDEO_SUBCORE0_CLK>;148 clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
177 clock-names = "vcodec0_core";149 clock-names = "vcodec0_core";
178 power-domains = <&mmcc VENUS_CORE0_GDSC>;150 power-domains = <&mmcc VENUS_CORE0_GDSC>;
179 };151 };
180 152
181 video-encoder {153 video-encoder {
182 compatible = "venus-encoder";154 compatible = "venus-encoder";
183 clocks = <&mmcc VIDEO_SUBCORE0_CLK>;155 clocks = <&mmcc VIDEO_SUBCORE0_CLK>;
184 clock-names = "vcodec0_core";156 clock-names = "vcodec0_core";
185 power-domains = <&mmcc VENUS_CORE0_GDSC>;157 power-domains = <&mmcc VENUS_CORE0_GDSC>;
186 };
187 };158 };
159 };
Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/qcom,sdm845-camss.yaml#"5$id: http://devicetree.org/schemas/media/qcom,sdm845-camss.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Qualcomm CAMSS ISP8title: Qualcomm CAMSS ISP
9 9
Documentation/devicetree/bindings/media/qcom,sdm845-venus-v2.yaml+42−66
@@ -1,11 +1,10 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2
3%YAML 1.22%YAML 1.2
4---3---
5$id: "http://devicetree.org/schemas/media/qcom,sdm845-venus-v2.yaml#"4$id: http://devicetree.org/schemas/media/qcom,sdm845-venus-v2.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
7 6
8title: Qualcomm Venus video encode and decode accelerators7title: Qualcomm SDM845 Venus v2 video encode and decode accelerators
9 8
10maintainers:9maintainers:
11 - Stanimir Varbanov <stanimir.varbanov@linaro.org>10 - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: | · 2 unmodified lines
14 The Venus IP is a video encode and decode accelerator present13 The Venus IP is a video encode and decode accelerator present
15 on Qualcomm platforms14 on Qualcomm platforms
16 15
16allOf:
17 - $ref: qcom,venus-common.yaml#
18
17properties:19properties:
18 compatible:20 compatible:
19 const: qcom,sdm845-venus-v221 const: qcom,sdm845-venus-v2
20 22
21 reg:
22 maxItems: 1
23
24 interrupts:
25 maxItems: 1
26
27 power-domains:23 power-domains:
28 minItems: 324 minItems: 3
29 maxItems: 425 maxItems: 4
@@ -52,8 +48,9 @@ properties: · 22 unmodified lines
52 iommus:48 iommus:
53 maxItems: 249 maxItems: 2
54 50
55 memory-region:51 operating-points-v2: true
56 maxItems: 152 opp-table:
53 type: object
57 54
58 video-core0:55 video-core0:
59 type: object56 type: object
@@ -79,68 +76,47 @@ properties: · 19 unmodified lines
79 76
80 additionalProperties: false77 additionalProperties: false
81 78
82 video-firmware:
83 type: object
84 additionalProperties: false
85
86 description: |
87 Firmware subnode is needed when the platform does not
88 have TrustZone.
89
90 properties:
91 iommus:
92 maxItems: 1
93
94 required:
95 - iommus
96
97required:79required:
98 - compatible80 - compatible
99 - reg
100 - interrupts
101 - power-domains
102 - power-domain-names81 - power-domain-names
103 - clocks
104 - clock-names
105 - iommus82 - iommus
106 - memory-region
107 - video-core083 - video-core0
108 - video-core184 - video-core1
109 85
110additionalProperties: false86unevaluatedProperties: false
111 87
112examples:88examples:
113 - |89 - |
114 #include <dt-bindings/interrupt-controller/arm-gic.h>90 #include <dt-bindings/interrupt-controller/arm-gic.h>
115 #include <dt-bindings/clock/qcom,videocc-sdm845.h>91 #include <dt-bindings/clock/qcom,videocc-sdm845.h>
116 92
117 video-codec@aa00000 {93 video-codec@aa00000 {
118 compatible = "qcom,sdm845-venus-v2";94 compatible = "qcom,sdm845-venus-v2";
119 reg = <0x0aa00000 0xff000>;95 reg = <0x0aa00000 0xff000>;
120 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;96 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
121 clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,97 clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
122 <&videocc VIDEO_CC_VENUS_AHB_CLK>,98 <&videocc VIDEO_CC_VENUS_AHB_CLK>,
123 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,99 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,
124 <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,100 <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
125 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>,101 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>,
126 <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,102 <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,
127 <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;103 <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;
128 clock-names = "core", "iface", "bus",104 clock-names = "core", "iface", "bus",
129 "vcodec0_core", "vcodec0_bus",105 "vcodec0_core", "vcodec0_bus",
130 "vcodec1_core", "vcodec1_bus";106 "vcodec1_core", "vcodec1_bus";
131 power-domains = <&videocc VENUS_GDSC>,107 power-domains = <&videocc VENUS_GDSC>,
132 <&videocc VCODEC0_GDSC>,108 <&videocc VCODEC0_GDSC>,
133 <&videocc VCODEC1_GDSC>;109 <&videocc VCODEC1_GDSC>;
134 power-domain-names = "venus", "vcodec0", "vcodec1";110 power-domain-names = "venus", "vcodec0", "vcodec1";
135 iommus = <&apps_smmu 0x10a0 0x8>,111 iommus = <&apps_smmu 0x10a0 0x8>,
136 <&apps_smmu 0x10b0 0x0>;112 <&apps_smmu 0x10b0 0x0>;
137 memory-region = <&venus_mem>;113 memory-region = <&venus_mem>;
138 114
139 video-core0 {115 video-core0 {
140 compatible = "venus-decoder";116 compatible = "venus-decoder";
141 };117 };
142 118
143 video-core1 {119 video-core1 {
144 compatible = "venus-encoder";120 compatible = "venus-encoder";
145 };
146 };121 };
122 };
Documentation/devicetree/bindings/media/qcom,sdm845-venus.yaml+38−66
@@ -1,11 +1,10 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2
3%YAML 1.22%YAML 1.2
4---3---
5$id: "http://devicetree.org/schemas/media/qcom,sdm845-venus.yaml#"4$id: http://devicetree.org/schemas/media/qcom,sdm845-venus.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
7 6
8title: Qualcomm Venus video encode and decode accelerators7title: Qualcomm SDM845 Venus video encode and decode accelerators
9 8
10maintainers:9maintainers:
11 - Stanimir Varbanov <stanimir.varbanov@linaro.org>10 - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: | · 2 unmodified lines
14 The Venus IP is a video encode and decode accelerator present13 The Venus IP is a video encode and decode accelerator present
15 on Qualcomm platforms14 on Qualcomm platforms
16 15
16allOf:
17 - $ref: qcom,venus-common.yaml#
18
17properties:19properties:
18 compatible:20 compatible:
19 const: qcom,sdm845-venus21 const: qcom,sdm845-venus
20 22
21 reg:
22 maxItems: 1
23
24 interrupts:
25 maxItems: 1
26
27 power-domains:23 power-domains:
28 maxItems: 124 maxItems: 1
29 25
@@ -39,9 +35,6 @@ properties: · 9 unmodified lines
39 iommus:35 iommus:
40 maxItems: 236 maxItems: 2
41 37
42 memory-region:
43 maxItems: 1
44
45 video-core0:38 video-core0:
46 type: object39 type: object
47 40
@@ -94,66 +87,45 @@ properties: · 46 unmodified lines
94 87
95 additionalProperties: false88 additionalProperties: false
96 89
97 video-firmware:
98 type: object
99 additionalProperties: false
100
101 description: |
102 Firmware subnode is needed when the platform does not
103 have TrustZone.
104
105 properties:
106 iommus:
107 maxItems: 1
108
109 required:
110 - iommus
111
112required:90required:
113 - compatible91 - compatible
114 - reg
115 - interrupts
116 - power-domains
117 - clocks
118 - clock-names
119 - iommus92 - iommus
120 - memory-region
121 - video-core093 - video-core0
122 - video-core194 - video-core1
123 95
124additionalProperties: false96unevaluatedProperties: false
125 97
126examples:98examples:
127 - |99 - |
128 #include <dt-bindings/interrupt-controller/arm-gic.h>100 #include <dt-bindings/interrupt-controller/arm-gic.h>
129 #include <dt-bindings/clock/qcom,videocc-sdm845.h>101 #include <dt-bindings/clock/qcom,videocc-sdm845.h>
130 102
131 video-codec@aa00000 {103 video-codec@aa00000 {
132 compatible = "qcom,sdm845-venus";104 compatible = "qcom,sdm845-venus";
133 reg = <0x0aa00000 0xff000>;105 reg = <0x0aa00000 0xff000>;
134 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;106 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
135 clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,107 clocks = <&videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
136 <&videocc VIDEO_CC_VENUS_AHB_CLK>,108 <&videocc VIDEO_CC_VENUS_AHB_CLK>,
137 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>;109 <&videocc VIDEO_CC_VENUS_CTL_AXI_CLK>;
138 clock-names = "core", "iface", "bus";110 clock-names = "core", "iface", "bus";
139 power-domains = <&videocc VENUS_GDSC>;111 power-domains = <&videocc VENUS_GDSC>;
140 iommus = <&apps_smmu 0x10a0 0x8>,112 iommus = <&apps_smmu 0x10a0 0x8>,
141 <&apps_smmu 0x10b0 0x0>;113 <&apps_smmu 0x10b0 0x0>;
142 memory-region = <&venus_mem>;114 memory-region = <&venus_mem>;
143 115
144 video-core0 {116 video-core0 {
145 compatible = "venus-decoder";117 compatible = "venus-decoder";
146 clocks = <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,118 clocks = <&videocc VIDEO_CC_VCODEC0_CORE_CLK>,
147 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;119 <&videocc VIDEO_CC_VCODEC0_AXI_CLK>;
148 clock-names = "core", "bus";120 clock-names = "core", "bus";
149 power-domains = <&videocc VCODEC0_GDSC>;121 power-domains = <&videocc VCODEC0_GDSC>;
150 };122 };
151 123
152 video-core1 {124 video-core1 {
153 compatible = "venus-encoder";125 compatible = "venus-encoder";
154 clocks = <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,126 clocks = <&videocc VIDEO_CC_VCODEC1_CORE_CLK>,
155 <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;127 <&videocc VIDEO_CC_VCODEC1_AXI_CLK>;
156 clock-names = "core", "bus";128 clock-names = "core", "bus";
157 power-domains = <&videocc VCODEC1_GDSC>;129 power-domains = <&videocc VCODEC1_GDSC>;
158 };
159 };130 };
131 };
Documentation/devicetree/bindings/media/qcom,sm8250-camss.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/qcom,sm8250-camss.yaml#"5$id: http://devicetree.org/schemas/media/qcom,sm8250-camss.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Qualcomm CAMSS ISP8title: Qualcomm CAMSS ISP
9 9
Documentation/devicetree/bindings/media/qcom,sm8250-venus.yaml+49−73
@@ -1,11 +1,10 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2
3%YAML 1.22%YAML 1.2
4---3---
5$id: "http://devicetree.org/schemas/media/qcom,sm8250-venus.yaml#"4$id: http://devicetree.org/schemas/media/qcom,sm8250-venus.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"5$schema: http://devicetree.org/meta-schemas/core.yaml#
7 6
8title: Qualcomm Venus video encode and decode accelerators7title: Qualcomm SM8250 Venus video encode and decode accelerators
9 8
10maintainers:9maintainers:
11 - Stanimir Varbanov <stanimir.varbanov@linaro.org>10 - Stanimir Varbanov <stanimir.varbanov@linaro.org>
@@ -14,16 +13,13 @@ description: | · 2 unmodified lines
14 The Venus IP is a video encode and decode accelerator present13 The Venus IP is a video encode and decode accelerator present
15 on Qualcomm platforms14 on Qualcomm platforms
16 15
16allOf:
17 - $ref: qcom,venus-common.yaml#
18
17properties:19properties:
18 compatible:20 compatible:
19 const: qcom,sm8250-venus21 const: qcom,sm8250-venus
20 22
21 reg:
22 maxItems: 1
23
24 interrupts:
25 maxItems: 1
26
27 power-domains:23 power-domains:
28 minItems: 224 minItems: 2
29 maxItems: 325 maxItems: 3
@@ -47,9 +43,6 @@ properties: · 17 unmodified lines
47 iommus:43 iommus:
48 maxItems: 144 maxItems: 1
49 45
50 memory-region:
51 maxItems: 1
52
53 interconnects:46 interconnects:
54 maxItems: 247 maxItems: 2
55 48
@@ -58,6 +51,10 @@ properties: · 2 unmodified lines
58 - const: cpu-cfg51 - const: cpu-cfg
59 - const: video-mem52 - const: video-mem
60 53
54 operating-points-v2: true
55 opp-table:
56 type: object
57
61 resets:58 resets:
62 maxItems: 259 maxItems: 2
63 60
@@ -90,78 +87,57 @@ properties: · 26 unmodified lines
90 87
91 additionalProperties: false88 additionalProperties: false
92 89
93 video-firmware:
94 type: object
95 additionalProperties: false
96
97 description: |
98 Firmware subnode is needed when the platform does not
99 have TrustZone.
100
101 properties:
102 iommus:
103 maxItems: 1
104
105 required:
106 - iommus
107
108required:90required:
109 - compatible91 - compatible
110 - reg
111 - interrupts
112 - power-domains
113 - power-domain-names92 - power-domain-names
114 - clocks
115 - clock-names
116 - interconnects93 - interconnects
117 - interconnect-names94 - interconnect-names
118 - iommus95 - iommus
119 - memory-region
120 - resets96 - resets
121 - reset-names97 - reset-names
122 - video-decoder98 - video-decoder
123 - video-encoder99 - video-encoder
124 100
125additionalProperties: false101unevaluatedProperties: false
126 102
127examples:103examples:
128 - |104 - |
129 #include <dt-bindings/interrupt-controller/arm-gic.h>105 #include <dt-bindings/interrupt-controller/arm-gic.h>
130 #include <dt-bindings/clock/qcom,videocc-sm8250.h>106 #include <dt-bindings/clock/qcom,videocc-sm8250.h>
131 #include <dt-bindings/interconnect/qcom,sm8250.h>107 #include <dt-bindings/interconnect/qcom,sm8250.h>
132 #include <dt-bindings/clock/qcom,gcc-sm8250.h>108 #include <dt-bindings/clock/qcom,gcc-sm8250.h>
133 #include <dt-bindings/power/qcom-rpmpd.h>109 #include <dt-bindings/power/qcom-rpmpd.h>
134 110
135 venus: video-codec@aa00000 {111 venus: video-codec@aa00000 {
136 compatible = "qcom,sm8250-venus";112 compatible = "qcom,sm8250-venus";
137 reg = <0x0aa00000 0xff000>;113 reg = <0x0aa00000 0xff000>;
138 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;114 interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
139 power-domains = <&videocc MVS0C_GDSC>,115 power-domains = <&videocc MVS0C_GDSC>,
140 <&videocc MVS0_GDSC>,116 <&videocc MVS0_GDSC>,
141 <&rpmhpd SM8250_MX>;117 <&rpmhpd SM8250_MX>;
142 power-domain-names = "venus", "vcodec0", "mx";118 power-domain-names = "venus", "vcodec0", "mx";
143 119
144 clocks = <&gcc GCC_VIDEO_AXI0_CLK>,120 clocks = <&gcc GCC_VIDEO_AXI0_CLK>,
145 <&videocc VIDEO_CC_MVS0C_CLK>,121 <&videocc VIDEO_CC_MVS0C_CLK>,
146 <&videocc VIDEO_CC_MVS0_CLK>;122 <&videocc VIDEO_CC_MVS0_CLK>;
147 clock-names = "iface", "core", "vcodec0_core";123 clock-names = "iface", "core", "vcodec0_core";
148 124
149 interconnects = <&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_VENUS_CFG>,125 interconnects = <&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_VENUS_CFG>,
150 <&mmss_noc MASTER_VIDEO_P0 &mc_virt SLAVE_EBI_CH0>;126 <&mmss_noc MASTER_VIDEO_P0 &mc_virt SLAVE_EBI_CH0>;
151 interconnect-names = "cpu-cfg", "video-mem";127 interconnect-names = "cpu-cfg", "video-mem";
152 128
153 iommus = <&apps_smmu 0x2100 0x0400>;129 iommus = <&apps_smmu 0x2100 0x0400>;
154 memory-region = <&video_mem>;130 memory-region = <&video_mem>;
155 131
156 resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>,132 resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>,
157 <&videocc VIDEO_CC_MVS0C_CLK_ARES>;133 <&videocc VIDEO_CC_MVS0C_CLK_ARES>;
158 reset-names = "bus", "core";134 reset-names = "bus", "core";
159 135
160 video-decoder {136 video-decoder {
161 compatible = "venus-decoder";137 compatible = "venus-decoder";
162 };138 };
163 139
164 video-encoder {140 video-encoder {
165 compatible = "venus-encoder";141 compatible = "venus-encoder";
166 };
167 };142 };
143 };
Documentation/devicetree/bindings/media/qcom,venus-common.yaml+73−0
@@ -0,0 +1,73 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/qcom,venus-common.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Qualcomm SoC Venus Video Encode and Decode Accelerators Common Properties
8
9maintainers:
10 - Stanimir Varbanov <stanimir.k.varbanov@gmail.com>
11 - Vikash Garodia <quic_vgarodia@quicinc.com>
12
13description: |
14 The Venus IP is a video encode and decode accelerator present
15 on Qualcomm platforms
16
17properties:
18 reg:
19 maxItems: 1
20
21 clocks:
22 minItems: 3
23 maxItems: 7
24
25 clock-names:
26 minItems: 3
27 maxItems: 7
28
29 firmware-name:
30 maxItems: 1
31
32 interrupts:
33 maxItems: 1
34
35 iommus:
36 minItems: 1
37 maxItems: 20
38
39 memory-region:
40 maxItems: 1
41
42 power-domains:
43 minItems: 1
44 maxItems: 4
45
46 power-domain-names:
47 minItems: 1
48 maxItems: 4
49
50 video-firmware:
51 type: object
52 additionalProperties: false
53
54 description: |
55 Firmware subnode is needed when the platform does not
56 have TrustZone.
57
58 properties:
59 iommus:
60 maxItems: 1
61
62 required:
63 - iommus
64
65required:
66 - reg
67 - clocks
68 - clock-names
69 - interrupts
70 - memory-region
71 - power-domains
72
73additionalProperties: true
Documentation/devicetree/bindings/media/rc.yaml+3−1
@@ -18,7 +18,7 @@ properties: · 17 unmodified lines
18 description:18 description:
19 Specifies the scancode/key mapping table defined in-kernel for19 Specifies the scancode/key mapping table defined in-kernel for
20 the remote controller.20 the remote controller.
21 $ref: '/schemas/types.yaml#/definitions/string'21 $ref: /schemas/types.yaml#/definitions/string
22 enum:22 enum:
23 - rc-adstech-dvb-t-pci23 - rc-adstech-dvb-t-pci
24 - rc-alink-dtu-m24 - rc-alink-dtu-m
@@ -39,6 +39,7 @@ properties: · 14 unmodified lines
39 - rc-avertv-30339 - rc-avertv-303
40 - rc-azurewave-ad-tu70040 - rc-azurewave-ad-tu700
41 - rc-beelink-gs141 - rc-beelink-gs1
42 - rc-beelink-mxiii
42 - rc-behold43 - rc-behold
43 - rc-behold-columbus44 - rc-behold-columbus
44 - rc-budget-ci-old45 - rc-budget-ci-old
@@ -55,6 +56,7 @@ properties: · 10 unmodified lines
55 - rc-dm1105-nec56 - rc-dm1105-nec
56 - rc-dntv-live-dvb-t57 - rc-dntv-live-dvb-t
57 - rc-dntv-live-dvbt-pro58 - rc-dntv-live-dvbt-pro
59 - rc-dreambox
58 - rc-dtt200u60 - rc-dtt200u
59 - rc-dvbsky61 - rc-dvbsky
60 - rc-dvico-mce62 - rc-dvico-mce
Documentation/devicetree/bindings/media/renesas,csi2.yaml+1−0
@@ -31,6 +31,7 @@ properties: · 30 unmodified lines
31 - renesas,r8a77980-csi2 # R-Car V3H31 - renesas,r8a77980-csi2 # R-Car V3H
32 - renesas,r8a77990-csi2 # R-Car E332 - renesas,r8a77990-csi2 # R-Car E3
33 - renesas,r8a779a0-csi2 # R-Car V3U33 - renesas,r8a779a0-csi2 # R-Car V3U
34 - renesas,r8a779g0-csi2 # R-Car V4H
34 35
35 reg:36 reg:
36 maxItems: 137 maxItems: 1
Documentation/devicetree/bindings/media/renesas,fcp.yaml+40−5
@@ -21,15 +21,22 @@ description: | · 20 unmodified lines
21 21
22properties:22properties:
23 compatible:23 compatible:
24 enum:24 oneOf:
25 - renesas,fcpv # FCP for VSP25 - enum:
26 - renesas,fcpf # FCP for FDP26 - renesas,fcpv # FCP for VSP
27 - renesas,fcpf # FCP for FDP
28 - items:
29 - enum:
30 - renesas,r9a07g044-fcpvd # RZ/G2{L,LC}
31 - renesas,r9a07g054-fcpvd # RZ/V2L
32 - const: renesas,fcpv # Generic FCP for VSP fallback
27 33
28 reg:34 reg:
29 maxItems: 135 maxItems: 1
30 36
31 clocks:37 clocks: true
32 maxItems: 138
39 clock-names: true
33 40
34 iommus:41 iommus:
35 maxItems: 142 maxItems: 1
@@ -49,6 +56,34 @@ required: · 13 unmodified lines
49 56
50additionalProperties: false57additionalProperties: false
51 58
59allOf:
60 - if:
61 properties:
62 compatible:
63 contains:
64 enum:
65 - renesas,r9a07g044-fcpvd
66 - renesas,r9a07g054-fcpvd
67 then:
68 properties:
69 clocks:
70 items:
71 - description: Main clock
72 - description: Register access clock
73 - description: Video clock
74 clock-names:
75 items:
76 - const: aclk
77 - const: pclk
78 - const: vclk
79 required:
80 - clock-names
81 else:
82 properties:
83 clocks:
84 maxItems: 1
85 clock-names: false
86
52examples:87examples:
53 # R8A7795 (R-Car H3) FCP for VSP-D188 # R8A7795 (R-Car H3) FCP for VSP-D1
54 - |89 - |
Documentation/devicetree/bindings/media/renesas,isp.yaml+1−0
@@ -21,6 +21,7 @@ properties: · 20 unmodified lines
21 items:21 items:
22 - enum:22 - enum:
23 - renesas,r8a779a0-isp # V3U23 - renesas,r8a779a0-isp # V3U
24 - renesas,r8a779g0-isp # V4H
24 reg:25 reg:
25 maxItems: 126 maxItems: 1
26 27
Documentation/devicetree/bindings/media/renesas,vin.yaml+1−0
@@ -53,6 +53,7 @@ properties: · 52 unmodified lines
53 - renesas,vin-r8a77990 # R-Car E353 - renesas,vin-r8a77990 # R-Car E3
54 - renesas,vin-r8a77995 # R-Car D354 - renesas,vin-r8a77995 # R-Car D3
55 - renesas,vin-r8a779a0 # R-Car V3U55 - renesas,vin-r8a779a0 # R-Car V3U
56 - renesas,vin-r8a779g0 # R-Car V4H
56 57
57 reg:58 reg:
58 maxItems: 159 maxItems: 1
Documentation/devicetree/bindings/media/renesas,vsp1.yaml+9−4
@@ -16,10 +16,15 @@ description: · 15 unmodified lines
16 16
17properties:17properties:
18 compatible:18 compatible:
19 enum:19 oneOf:
20 - renesas,r9a07g044-vsp2 # RZ/G2L20 - enum:
21 - renesas,vsp1 # R-Car Gen2 and RZ/G121 - renesas,r9a07g044-vsp2 # RZ/G2L
22 - renesas,vsp2 # R-Car Gen3 and RZ/G222 - renesas,vsp1 # R-Car Gen2 and RZ/G1
23 - renesas,vsp2 # R-Car Gen3 and RZ/G2
24 - items:
25 - enum:
26 - renesas,r9a07g054-vsp2 # RZ/V2L
27 - const: renesas,r9a07g044-vsp2 # RZ/G2L fallback
23 28
24 reg:29 reg:
25 maxItems: 130 maxItems: 1
Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/rockchip,rk3568-vepu.yaml#"5$id: http://devicetree.org/schemas/media/rockchip,rk3568-vepu.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Hantro G1 VPU encoders implemented on Rockchip SoCs8title: Hantro G1 VPU encoders implemented on Rockchip SoCs
9 9
Documentation/devicetree/bindings/media/rockchip-isp1.yaml+13−6
@@ -212,12 +212,19 @@ examples: · 211 unmodified lines
212 compatible = "ovti,ov2685";212 compatible = "ovti,ov2685";
213 reg = <0x3c>;213 reg = <0x3c>;
214 214
215 port {215 clocks = <&cru SCLK_TESTCLKOUT1>;
216 ucam_out: endpoint {216 clock-names = "xvclk";
217 remote-endpoint = <&mipi_in_ucam>;217
218 data-lanes = <1>;218 avdd-supply = <&pp2800_cam>;
219 };219 dovdd-supply = <&pp1800>;
220 };220 dvdd-supply = <&pp1800>;
221
222 port {
223 ucam_out: endpoint {
224 remote-endpoint = <&mipi_in_ucam>;
225 data-lanes = <1>;
226 };
227 };
221 };228 };
222 };229 };
223 };230 };
Documentation/devicetree/bindings/media/rockchip-vpu.yaml+2−2
@@ -2,8 +2,8 @@ · 1 unmodified line
2 2
3%YAML 1.23%YAML 1.2
4---4---
5$id: "http://devicetree.org/schemas/media/rockchip-vpu.yaml#"5$id: http://devicetree.org/schemas/media/rockchip-vpu.yaml#
6$schema: "http://devicetree.org/meta-schemas/core.yaml#"6$schema: http://devicetree.org/meta-schemas/core.yaml#
7 7
8title: Hantro G1 VPU codecs implemented on Rockchip SoCs8title: Hantro G1 VPU codecs implemented on Rockchip SoCs
9 9
Documentation/devicetree/bindings/media/samsung,exynos4210-csis.yaml+170−0
@@ -0,0 +1,170 @@
1# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/samsung,exynos4210-csis.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung S5P/Exynos SoC series MIPI CSI-2 receiver (MIPI CSIS)
8
9maintainers:
10 - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
11 - Sylwester Nawrocki <s.nawrocki@samsung.com>
12
13properties:
14 compatible:
15 enum:
16 - samsung,s5pv210-csis
17 - samsung,exynos4210-csis
18 - samsung,exynos4212-csis
19 - samsung,exynos5250-csis
20
21 reg:
22 maxItems: 1
23
24 '#address-cells':
25 const: 1
26
27 '#size-cells':
28 const: 0
29
30 bus-width:
31 $ref: /schemas/types.yaml#/definitions/uint32
32 enum: [2, 4]
33 description:
34 Number of data lines supported.
35
36 clocks:
37 maxItems: 2
38
39 clock-names:
40 items:
41 - const: csis
42 - const: sclk_csis
43
44 clock-frequency:
45 default: 166000000
46 description:
47 The IP's main (system bus) clock frequency in Hz.
48
49 interrupts:
50 maxItems: 1
51
52 phys:
53 maxItems: 1
54
55 phy-names:
56 items:
57 - const: csis
58
59 power-domains:
60 maxItems: 1
61
62 vddio-supply:
63 description: MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V).
64
65 vddcore-supply:
66 description: MIPI CSIS Core voltage supply (e.g. 1.1V).
67
68patternProperties:
69 "^port@[34]$":
70 $ref: /schemas/graph.yaml#/$defs/port-base
71 additionalProperties: false
72 description:
73 Camera input port.
74
75 properties:
76 reg:
77 enum: [3, 4]
78
79 endpoint:
80 $ref: video-interfaces.yaml#
81 unevaluatedProperties: false
82
83 properties:
84 data-lanes:
85 minItems: 1
86 maxItems: 4
87
88 samsung,csis-hs-settle:
89 $ref: /schemas/types.yaml#/definitions/uint32
90 description: Differential receiver (HS-RX) settle time.
91
92 samsung,csis-wclk:
93 type: boolean
94 description:
95 CSI-2 wrapper clock selection. If this property is present external clock
96 from CMU will be used, or the bus clock if it's not specified.
97
98 required:
99 - data-lanes
100
101 required:
102 - reg
103
104required:
105 - compatible
106 - reg
107 - bus-width
108 - clocks
109 - clock-names
110 - interrupts
111 - vddio-supply
112 - vddcore-supply
113
114anyOf:
115 - required:
116 - port@3
117 - required:
118 - port@4
119
120allOf:
121 - if:
122 required:
123 - samsung,isp-wb
124 then:
125 required:
126 - samsung,sysreg
127
128additionalProperties: false
129
130examples:
131 - |
132 #include <dt-bindings/clock/exynos4.h>
133 #include <dt-bindings/interrupt-controller/arm-gic.h>
134
135 csis@11890000 {
136 compatible = "samsung,exynos4210-csis";
137 reg = <0x11890000 0x4000>;
138 clocks = <&clock CLK_CSIS1>,
139 <&clock CLK_SCLK_CSIS1>;
140 clock-names = "csis", "sclk_csis";
141 assigned-clocks = <&clock CLK_MOUT_CSIS1>,
142 <&clock CLK_SCLK_CSIS1>;
143 assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
144 assigned-clock-rates = <0>, <176000000>;
145
146 interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
147
148 bus-width = <2>;
149 power-domains = <&pd_cam>;
150 phys = <&mipi_phy 2>;
151 phy-names = "csis";
152
153 vddcore-supply = <&ldo8_reg>;
154 vddio-supply = <&ldo10_reg>;
155
156 #address-cells = <1>;
157 #size-cells = <0>;
158
159 /* Camera D (4) MIPI CSI-2 (CSIS1) */
160 port@4 {
161 reg = <4>;
162
163 endpoint {
164 remote-endpoint = <&is_s5k6a3_ep>;
165 data-lanes = <1>;
166 samsung,csis-hs-settle = <18>;
167 samsung,csis-wclk;
168 };
169 };
170 };
Documentation/devicetree/bindings/media/samsung,exynos4210-fimc.yaml+152−0
@@ -0,0 +1,152 @@
1# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/samsung,exynos4210-fimc.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung S5P/Exynos SoC Fully Integrated Mobile Camera
8
9maintainers:
10 - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
11 - Sylwester Nawrocki <s.nawrocki@samsung.com>
12
13description:
14 Each FIMC device should have an alias in the aliases node, in the form of
15 fimc<n>, where <n> is an integer specifying the IP block instance.
16
17properties:
18 compatible:
19 enum:
20 - samsung,exynos4210-fimc
21 - samsung,exynos4212-fimc
22 - samsung,s5pv210-fimc
23
24 reg:
25 maxItems: 1
26
27 clocks:
28 maxItems: 2
29
30 clock-names:
31 items:
32 - const: fimc
33 - const: sclk_fimc
34
35 clock-frequency:
36 description:
37 Maximum FIMC local clock (LCLK) frequency.
38
39 interrupts:
40 maxItems: 1
41
42 iommus:
43 maxItems: 1
44
45 power-domains:
46 maxItems: 1
47
48 samsung,cam-if:
49 type: boolean
50 description:
51 The FIMC IP block includes the camera input interface.
52
53 samsung,isp-wb:
54 type: boolean
55 description: |
56 The FIMC IP block has the ISP writeback input.
57
58 samsung,lcd-wb:
59 type: boolean
60 description: |
61 The FIMC IP block has the LCD writeback input.
62
63 samsung,mainscaler-ext:
64 type: boolean
65 description:
66 FIMC IP supports extended image size and has CIEXTEN register.
67
68 samsung,min-pix-alignment:
69 $ref: /schemas/types.yaml#/definitions/uint32-array
70 items:
71 - description: Minimum supported image height alignment.
72 - description: Horizontal image offset.
73 description:
74 The values are in pixels and default is <2 1>.
75
76 samsung,min-pix-sizes:
77 $ref: /schemas/types.yaml#/definitions/uint32-array
78 maxItems: 2
79 description: |
80 An array specyfing minimum image size in pixels at the FIMC input and
81 output DMA, in the first and second cell respectively. Default value
82 is <16 16>.
83
84 samsung,pix-limits:
85 $ref: /schemas/types.yaml#/definitions/uint32-array
86 maxItems: 4
87 description: |
88 An array of maximum supported image sizes in pixels, for details refer to
89 Table 2-1 in the S5PV210 SoC User Manual. The meaning of each cell is as
90 follows:
91 0 - scaler input horizontal size
92 1 - input horizontal size for the scaler bypassed
93 2 - REAL_WIDTH without input rotation
94 3 - REAL_HEIGHT with input rotation
95
96 samsung,rotators:
97 $ref: /schemas/types.yaml#/definitions/uint32
98 default: 0x11
99 description: |
100 A bitmask specifying whether this IP has the input and the output
101 rotator. Bits 4 and 0 correspond to input and output rotator
102 respectively. If a rotator is present its corresponding bit should be
103 set.
104
105 samsung,sysreg:
106 $ref: /schemas/types.yaml#/definitions/phandle
107 description:
108 System Registers (SYSREG) node.
109
110required:
111 - compatible
112 - reg
113 - clocks
114 - clock-names
115 - samsung,pix-limits
116
117allOf:
118 - if:
119 required:
120 - samsung,isp-wb
121 then:
122 required:
123 - samsung,sysreg
124
125additionalProperties: false
126
127examples:
128 - |
129 #include <dt-bindings/clock/exynos4.h>
130 #include <dt-bindings/interrupt-controller/arm-gic.h>
131
132 fimc@11800000 {
133 compatible = "samsung,exynos4212-fimc";
134 reg = <0x11800000 0x1000>;
135 clocks = <&clock CLK_FIMC0>,
136 <&clock CLK_SCLK_FIMC0>;
137 clock-names = "fimc", "sclk_fimc";
138 interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
139 iommus = <&sysmmu_fimc0>;
140 power-domains = <&pd_cam>;
141 samsung,sysreg = <&sys_reg>;
142
143 samsung,pix-limits = <4224 8192 1920 4224>;
144 samsung,mainscaler-ext;
145 samsung,isp-wb;
146 samsung,cam-if;
147
148 assigned-clocks = <&clock CLK_MOUT_FIMC0>,
149 <&clock CLK_SCLK_FIMC0>;
150 assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
151 assigned-clock-rates = <0>, <176000000>;
152 };
Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml+220−0
@@ -0,0 +1,220 @@
1# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/samsung,exynos4212-fimc-is.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung Exynos4212/4412 SoC Imaging Subsystem (FIMC-IS)
8
9maintainers:
10 - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
11 - Sylwester Nawrocki <s.nawrocki@samsung.com>
12
13description:
14 The FIMC-IS is a subsystem for processing image signal from an image sensor.
15 The Exynos4x12 SoC series FIMC-IS V1.5 comprises of a dedicated ARM Cortex-A5
16 processor, ISP, DRC and FD IP blocks and peripheral devices such as UART, I2C
17 and SPI bus controllers, PWM and ADC.
18
19properties:
20 compatible:
21 enum:
22 - samsung,exynos4212-fimc-is
23
24 reg:
25 maxItems: 1
26
27 ranges: true
28
29 '#address-cells':
30 const: 1
31
32 '#size-cells':
33 const: 1
34
35 clocks:
36 maxItems: 21
37
38 clock-names:
39 items:
40 - const: lite0
41 - const: lite1
42 - const: ppmuispx
43 - const: ppmuispmx
44 - const: isp
45 - const: drc
46 - const: fd
47 - const: mcuisp
48 - const: gicisp
49 - const: mcuctl_isp
50 - const: pwm_isp
51 - const: ispdiv0
52 - const: ispdiv1
53 - const: mcuispdiv0
54 - const: mcuispdiv1
55 - const: mpll
56 - const: aclk200
57 - const: aclk400mcuisp
58 - const: div_aclk200
59 - const: div_aclk400mcuisp
60 - const: uart
61
62 interrupts:
63 maxItems: 2
64
65 iommus:
66 maxItems: 4
67
68 iommu-names:
69 items:
70 - const: isp
71 - const: drc
72 - const: fd
73 - const: mcuctl
74
75 power-domains:
76 maxItems: 1
77
78patternProperties:
79 "^pmu@[0-9a-f]+$":
80 type: object
81 additionalProperties: false
82 description:
83 Node representing the SoC's Power Management Unit (duplicated with the
84 correct PMU node in the SoC).
85
86 properties:
87 reg:
88 maxItems: 1
89
90 required:
91 - reg
92
93 "^i2c-isp@[0-9a-f]+$":
94 type: object
95 $ref: /schemas/i2c/i2c-controller.yaml#
96 unevaluatedProperties: false
97 description:
98 ISP I2C bus controller
99
100 properties:
101 compatible:
102 const: samsung,exynos4212-i2c-isp
103
104 reg:
105 maxItems: 1
106
107
108 clocks:
109 maxItems: 1
110
111 clock-names:
112 items:
113 - const: i2c_isp
114
115 pinctrl-0: true
116 pinctrl-names:
117 items:
118 - const: default
119
120 required:
121 - compatible
122 - reg
123 - clocks
124 - clock-names
125
126required:
127 - compatible
128 - reg
129 - '#address-cells'
130 - clocks
131 - clock-names
132 - interrupts
133 - ranges
134 - '#size-cells'
135
136additionalProperties: false
137
138examples:
139 - |
140 #include <dt-bindings/clock/exynos4.h>
141 #include <dt-bindings/gpio/gpio.h>
142 #include <dt-bindings/interrupt-controller/arm-gic.h>
143
144 fimc-is@12000000 {
145 compatible = "samsung,exynos4212-fimc-is";
146 reg = <0x12000000 0x260000>;
147 interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
148 <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
149 clocks = <&isp_clock CLK_ISP_FIMC_LITE0>,
150 <&isp_clock CLK_ISP_FIMC_LITE1>,
151 <&isp_clock CLK_ISP_PPMUISPX>,
152 <&isp_clock CLK_ISP_PPMUISPMX>,
153 <&isp_clock CLK_ISP_FIMC_ISP>,
154 <&isp_clock CLK_ISP_FIMC_DRC>,
155 <&isp_clock CLK_ISP_FIMC_FD>,
156 <&isp_clock CLK_ISP_MCUISP>,
157 <&isp_clock CLK_ISP_GICISP>,
158 <&isp_clock CLK_ISP_MCUCTL_ISP>,
159 <&isp_clock CLK_ISP_PWM_ISP>,
160 <&isp_clock CLK_ISP_DIV_ISP0>,
161 <&isp_clock CLK_ISP_DIV_ISP1>,
162 <&isp_clock CLK_ISP_DIV_MCUISP0>,
163 <&isp_clock CLK_ISP_DIV_MCUISP1>,
164 <&clock CLK_MOUT_MPLL_USER_T>,
165 <&clock CLK_ACLK200>,
166 <&clock CLK_ACLK400_MCUISP>,
167 <&clock CLK_DIV_ACLK200>,
168 <&clock CLK_DIV_ACLK400_MCUISP>,
169 <&clock CLK_UART_ISP_SCLK>;
170 clock-names = "lite0", "lite1", "ppmuispx",
171 "ppmuispmx", "isp",
172 "drc", "fd", "mcuisp",
173 "gicisp", "mcuctl_isp", "pwm_isp",
174 "ispdiv0", "ispdiv1", "mcuispdiv0",
175 "mcuispdiv1", "mpll", "aclk200",
176 "aclk400mcuisp", "div_aclk200",
177 "div_aclk400mcuisp", "uart";
178 iommus = <&sysmmu_fimc_isp>, <&sysmmu_fimc_drc>,
179 <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>;
180 iommu-names = "isp", "drc", "fd", "mcuctl";
181 power-domains = <&pd_isp>;
182
183 #address-cells = <1>;
184 #size-cells = <1>;
185 ranges;
186
187 pmu@10020000 {
188 reg = <0x10020000 0x3000>;
189 };
190
191 i2c-isp@12140000 {
192 compatible = "samsung,exynos4212-i2c-isp";
193 reg = <0x12140000 0x100>;
194 clocks = <&isp_clock CLK_ISP_I2C1_ISP>;
195 clock-names = "i2c_isp";
196 pinctrl-0 = <&fimc_is_i2c1>;
197 pinctrl-names = "default";
198 #address-cells = <1>;
199 #size-cells = <0>;
200
201 image-sensor@10 {
202 compatible = "samsung,s5k6a3";
203 reg = <0x10>;
204 svdda-supply = <&cam_io_reg>;
205 svddio-supply = <&ldo19_reg>;
206 afvdd-supply = <&ldo19_reg>;
207 clock-frequency = <24000000>;
208 clocks = <&camera 1>;
209 clock-names = "extclk";
210 gpios = <&gpm1 6 GPIO_ACTIVE_LOW>;
211
212 port {
213 endpoint {
214 remote-endpoint = <&csis1_ep>;
215 data-lanes = <1>;
216 };
217 };
218 };
219 };
220 };
Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-lite.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/samsung,exynos4212-fimc-lite.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung Exynos SoC series camera host interface (FIMC-LITE)
8
9maintainers:
10 - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
11 - Sylwester Nawrocki <s.nawrocki@samsung.com>
12
13description:
14 Each FIMC device should have an alias in the aliases node, in the form of
15 fimc-lite<n>, where <n> is an integer specifying the IP block instance.
16
17properties:
18 compatible:
19 enum:
20 - samsung,exynos4212-fimc-lite
21 - samsung,exynos5250-fimc-lite
22
23 reg:
24 maxItems: 1
25
26 clocks:
27 maxItems: 1
28
29 clock-names:
30 items:
31 - const: flite
32
33 interrupts:
34 maxItems: 1
35
36 iommus:
37 maxItems: 1
38
39 power-domains:
40 maxItems: 1
41
42required:
43 - compatible
44 - reg
45 - clocks
46 - clock-names
47 - interrupts
48
49additionalProperties: false
50
51examples:
52 - |
53 #include <dt-bindings/clock/exynos4.h>
54 #include <dt-bindings/interrupt-controller/arm-gic.h>
55 fimc-lite@12390000 {
56 compatible = "samsung,exynos4212-fimc-lite";
57 reg = <0x12390000 0x1000>;
58 clocks = <&isp_clock CLK_ISP_FIMC_LITE0>;
59 clock-names = "flite";
60 interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
61 power-domains = <&pd_isp>;
62 iommus = <&sysmmu_fimc_lite0>;
63 };
Documentation/devicetree/bindings/media/samsung,fimc.yaml+279−0
@@ -0,0 +1,279 @@
1# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/samsung,fimc.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung S5P/Exynos SoC Camera Subsystem (FIMC)
8
9maintainers:
10 - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
11 - Sylwester Nawrocki <s.nawrocki@samsung.com>
12
13description: |
14 The S5P/Exynos SoC Camera subsystem comprises of multiple sub-devices
15 represented by separate device tree nodes. Currently this includes: Fully
16 Integrated Mobile Camera (FIMC, in the S5P SoCs series known as CAMIF), MIPI
17 CSIS, FIMC-LITE and FIMC-IS (ISP).
18
19properties:
20 compatible:
21 const: samsung,fimc
22
23 ranges: true
24
25 '#address-cells':
26 const: 1
27
28 '#size-cells':
29 const: 1
30
31 '#clock-cells':
32 const: 1
33 description: |
34 The clock specifier cell stores an index of a clock: 0, 1 for
35 CAM_A_CLKOUT, CAM_B_CLKOUT clocks respectively.
36
37 clocks:
38 minItems: 2
39 maxItems: 4
40
41 clock-names:
42 minItems: 2
43 items:
44 - const: sclk_cam0
45 - const: sclk_cam1
46 - const: pxl_async0
47 - const: pxl_async1
48
49 clock-output-names:
50 maxItems: 2
51
52 parallel-ports:
53 $ref: /schemas/graph.yaml#/properties/ports
54 description:
55 Active parallel video input ports.
56
57 patternProperties:
58 "^port@[01]$":
59 $ref: /schemas/graph.yaml#/$defs/port-base
60 description:
61 Camera A and camera B inputs.
62
63 properties:
64 endpoint:
65 $ref: /schemas/media/video-interfaces.yaml#
66 unevaluatedProperties: false
67
68 pinctrl-names:
69 minItems: 1
70 items:
71 - const: default
72 - const: idle
73 - const: active_a
74 - const: active_b
75
76patternProperties:
77 "^csis@[0-9a-f]+$":
78 type: object
79 $ref: samsung,exynos4210-csis.yaml#
80 description: MIPI CSI-2 receiver.
81
82 "^fimc@[0-9a-f]+$":
83 type: object
84 $ref: samsung,exynos4210-fimc.yaml#
85 description: Fully Integrated Mobile Camera.
86
87 "^fimc-is@[0-9a-f]+$":
88 type: object
89 $ref: samsung,exynos4212-fimc-is.yaml#
90 description: Imaging Subsystem (FIMC-IS).
91
92 "^fimc-lite@[0-9a-f]+$":
93 type: object
94 $ref: samsung,exynos4212-fimc-lite.yaml#
95 description: Camera host interface (FIMC-LITE).
96
97required:
98 - compatible
99 - '#address-cells'
100 - '#clock-cells'
101 - clocks
102 - clock-names
103 - clock-output-names
104 - ranges
105 - '#size-cells'
106
107additionalProperties: false
108
109examples:
110 - |
111 #include <dt-bindings/clock/exynos4.h>
112 #include <dt-bindings/gpio/gpio.h>
113 #include <dt-bindings/interrupt-controller/arm-gic.h>
114
115 camera@11800000 {
116 compatible = "samsung,fimc";
117 #clock-cells = <1>;
118 #address-cells = <1>;
119 #size-cells = <1>;
120 ranges = <0x0 0x0 0x18000000>;
121
122 clocks = <&clock CLK_SCLK_CAM0>, <&clock CLK_SCLK_CAM1>,
123 <&clock CLK_PIXELASYNCM0>, <&clock CLK_PIXELASYNCM1>;
124 clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0", "pxl_async1";
125 clock-output-names = "cam_a_clkout", "cam_b_clkout";
126
127 assigned-clocks = <&clock CLK_MOUT_CAM0>,
128 <&clock CLK_MOUT_CAM1>;
129 assigned-clock-parents = <&clock CLK_XUSBXTI>,
130 <&clock CLK_XUSBXTI>;
131
132 pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>;
133 pinctrl-names = "default";
134
135 fimc@11800000 {
136 compatible = "samsung,exynos4212-fimc";
137 reg = <0x11800000 0x1000>;
138 interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
139 clocks = <&clock CLK_FIMC0>,
140 <&clock CLK_SCLK_FIMC0>;
141 clock-names = "fimc", "sclk_fimc";
142 power-domains = <&pd_cam>;
143 samsung,sysreg = <&sys_reg>;
144 iommus = <&sysmmu_fimc0>;
145
146 samsung,pix-limits = <4224 8192 1920 4224>;
147 samsung,mainscaler-ext;
148 samsung,isp-wb;
149 samsung,cam-if;
150 };
151
152 /* ... FIMC 1-3 */
153
154 csis@11880000 {
155 compatible = "samsung,exynos4210-csis";
156 reg = <0x11880000 0x4000>;
157 interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
158 clocks = <&clock CLK_CSIS0>,
159 <&clock CLK_SCLK_CSIS0>;
160 clock-names = "csis", "sclk_csis";
161 assigned-clocks = <&clock CLK_MOUT_CSIS0>,
162 <&clock CLK_SCLK_CSIS0>;
163 assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
164 assigned-clock-rates = <0>, <176000000>;
165
166 bus-width = <4>;
167 power-domains = <&pd_cam>;
168 phys = <&mipi_phy 0>;
169 phy-names = "csis";
170 #address-cells = <1>;
171 #size-cells = <0>;
172
173 vddcore-supply = <&ldo8_reg>;
174 vddio-supply = <&ldo10_reg>;
175
176 /* Camera C (3) MIPI CSI-2 (CSIS0) */
177 port@3 {
178 reg = <3>;
179 endpoint {
180 remote-endpoint = <&s5c73m3_ep>;
181 data-lanes = <1 2 3 4>;
182 samsung,csis-hs-settle = <12>;
183 };
184 };
185 };
186
187 /* ... CSIS 1 */
188
189 fimc-lite@12390000 {
190 compatible = "samsung,exynos4212-fimc-lite";
191 reg = <0x12390000 0x1000>;
192 interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
193 power-domains = <&pd_isp>;
194 clocks = <&isp_clock CLK_ISP_FIMC_LITE0>;
195 clock-names = "flite";
196 iommus = <&sysmmu_fimc_lite0>;
197 };
198
199 /* ... FIMC-LITE 1 */
200
201 fimc-is@12000000 {
202 compatible = "samsung,exynos4212-fimc-is";
203 reg = <0x12000000 0x260000>;
204 interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
205 <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
206 clocks = <&isp_clock CLK_ISP_FIMC_LITE0>,
207 <&isp_clock CLK_ISP_FIMC_LITE1>,
208 <&isp_clock CLK_ISP_PPMUISPX>,
209 <&isp_clock CLK_ISP_PPMUISPMX>,
210 <&isp_clock CLK_ISP_FIMC_ISP>,
211 <&isp_clock CLK_ISP_FIMC_DRC>,
212 <&isp_clock CLK_ISP_FIMC_FD>,
213 <&isp_clock CLK_ISP_MCUISP>,
214 <&isp_clock CLK_ISP_GICISP>,
215 <&isp_clock CLK_ISP_MCUCTL_ISP>,
216 <&isp_clock CLK_ISP_PWM_ISP>,
217 <&isp_clock CLK_ISP_DIV_ISP0>,
218 <&isp_clock CLK_ISP_DIV_ISP1>,
219 <&isp_clock CLK_ISP_DIV_MCUISP0>,
220 <&isp_clock CLK_ISP_DIV_MCUISP1>,
221 <&clock CLK_MOUT_MPLL_USER_T>,
222 <&clock CLK_ACLK200>,
223 <&clock CLK_ACLK400_MCUISP>,
224 <&clock CLK_DIV_ACLK200>,
225 <&clock CLK_DIV_ACLK400_MCUISP>,
226 <&clock CLK_UART_ISP_SCLK>;
227 clock-names = "lite0", "lite1", "ppmuispx",
228 "ppmuispmx", "isp",
229 "drc", "fd", "mcuisp",
230 "gicisp", "mcuctl_isp", "pwm_isp",
231 "ispdiv0", "ispdiv1", "mcuispdiv0",
232 "mcuispdiv1", "mpll", "aclk200",
233 "aclk400mcuisp", "div_aclk200",
234 "div_aclk400mcuisp", "uart";
235 iommus = <&sysmmu_fimc_isp>, <&sysmmu_fimc_drc>,
236 <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>;
237 iommu-names = "isp", "drc", "fd", "mcuctl";
238 power-domains = <&pd_isp>;
239
240 #address-cells = <1>;
241 #size-cells = <1>;
242 ranges;
243
244 pmu@10020000 {
245 reg = <0x10020000 0x3000>;
246 };
247
248 i2c-isp@12140000 {
249 compatible = "samsung,exynos4212-i2c-isp";
250 reg = <0x12140000 0x100>;
251 clocks = <&isp_clock CLK_ISP_I2C1_ISP>;
252 clock-names = "i2c_isp";
253 pinctrl-0 = <&fimc_is_i2c1>;
254 pinctrl-names = "default";
255 #address-cells = <1>;
256 #size-cells = <0>;
257
258 image-sensor@10 {
259 compatible = "samsung,s5k6a3";
260 reg = <0x10>;
261 svdda-supply = <&cam_io_reg>;
262 svddio-supply = <&ldo19_reg>;
263 afvdd-supply = <&ldo19_reg>;
264 clock-frequency = <24000000>;
265 /* CAM_B_CLKOUT */
266 clocks = <&camera 1>;
267 clock-names = "extclk";
268 gpios = <&gpm1 6 GPIO_ACTIVE_LOW>;
269
270 port {
271 endpoint {
272 remote-endpoint = <&csis1_ep>;
273 data-lanes = <1>;
274 };
275 };
276 };
277 };
278 };
279 };
Documentation/devicetree/bindings/media/samsung,s5c73m3.yaml+165−0
@@ -0,0 +1,165 @@
1# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/samsung,s5c73m3.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Samsung S5C73M3 8Mp camera ISP
8
9maintainers:
10 - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
11 - Sylwester Nawrocki <s.nawrocki@samsung.com>
12
13description:
14 The S5C73M3 camera ISP supports MIPI CSI-2 and parallel (ITU-R BT.656)
15 video data busses. The I2C bus is the main control bus and additionally the
16 SPI bus is used, mostly for transferring the firmware to and from the
17 device. Two slave device nodes corresponding to these control bus
18 interfaces are required and should be placed under respective bus
19 controller nodes.
20
21properties:
22 compatible:
23 const: samsung,s5c73m3
24
25 reg:
26 maxItems: 1
27
28 clocks:
29 maxItems: 1
30
31 clock-names:
32 items:
33 - const: cis_extclk
34
35 clock-frequency:
36 default: 24000000
37 description: cis_extclk clock frequency.
38
39 standby-gpios:
40 maxItems: 1
41 description: STANDBY pin.
42
43 vdda-supply:
44 description: Analog power supply (1.2V).
45
46 vdd-af-supply:
47 description: lens power supply (2.8V).
48
49 vddio-cis-supply:
50 description: CIS I/O power supply (1.2V to 1.8V).
51
52 vddio-host-supply:
53 description: Host I/O power supply (1.8V to 2.8V).
54
55 vdd-int-supply:
56 description: Digital power supply (1.2V).
57
58 vdd-reg-supply:
59 description: Regulator input power supply (2.8V).
60
61 xshutdown-gpios:
62 maxItems: 1
63 description: XSHUTDOWN pin.
64
65 port:
66 $ref: /schemas/graph.yaml#/$defs/port-base
67 additionalProperties: false
68
69 properties:
70 endpoint:
71 $ref: /schemas/media/video-interfaces.yaml#
72 unevaluatedProperties: false
73
74 properties:
75 data-lanes:
76 items:
77 - const: 1
78 - const: 2
79 - const: 3
80 - const: 4
81
82required:
83 - compatible
84 - reg
85
86allOf:
87 - $ref: /schemas/spi/spi-peripheral-props.yaml#
88 - if:
89 required:
90 - spi-max-frequency
91 then:
92 properties:
93 # The SPI node is simplified firmware-transfer interface only
94 clocks: false
95 clock-names: false
96 standby-gpios: false
97 vdda-supply: false
98 vdd-af-supply: false
99 vddio-cis-supply: false
100 vddio-host-supply: false
101 vdd-int-supply: false
102 vdd-reg-supply: false
103 xshutdown-gpios: false
104 port: false
105 else:
106 required:
107 - clocks
108 - clock-names
109 - standby-gpios
110 - vdda-supply
111 - vdd-af-supply
112 - vddio-cis-supply
113 - vddio-host-supply
114 - vdd-int-supply
115 - vdd-reg-supply
116 - xshutdown-gpios
117 - port
118
119unevaluatedProperties: false
120
121examples:
122 - |
123 #include <dt-bindings/gpio/gpio.h>
124
125 i2c {
126 #address-cells = <1>;
127 #size-cells = <0>;
128
129 image-sensor@3c {
130 compatible = "samsung,s5c73m3";
131 reg = <0x3c>;
132 clock-frequency = <24000000>;
133 clocks = <&camera 0>;
134 clock-names = "cis_extclk";
135 standby-gpios = <&gpm0 6 GPIO_ACTIVE_LOW>;
136 vdda-supply = <&cam_vdda_reg>;
137 vdd-af-supply = <&cam_af_reg>;
138 vddio-cis-supply = <&ldo9_reg>;
139 vddio-host-supply = <&ldo18_reg>;
140 vdd-int-supply = <&buck9_reg>;
141 vdd-reg-supply = <&cam_io_reg>;
142 xshutdown-gpios = <&gpf1 3 GPIO_ACTIVE_LOW>; /* ISP_RESET */
143
144 port {
145 s5c73m3_ep: endpoint {
146 remote-endpoint = <&csis0_ep>;
147 data-lanes = <1 2 3 4>;
148 };
149 };
150 };
151 };
152
153 spi {
154 #address-cells = <1>;
155 #size-cells = <0>;
156
157 image-sensor@0 {
158 compatible = "samsung,s5c73m3";
159 reg = <0>;
160 spi-max-frequency = <50000000>;
161 controller-data {
162 samsung,spi-feedback-delay = <2>;
163 };
164 };
165 };
Documentation/devicetree/bindings/media/samsung-fimc.txt+0−209
@@ -1,209 +0,0 @@
1Samsung S5P/Exynos SoC Camera Subsystem (FIMC)
2----------------------------------------------
3
4The S5P/Exynos SoC Camera subsystem comprises of multiple sub-devices
5represented by separate device tree nodes. Currently this includes: FIMC (in
6the S5P SoCs series known as CAMIF), MIPI CSIS, FIMC-LITE and FIMC-IS (ISP).
7
8The sub-subdevices are defined as child nodes of the common 'camera' node which
9also includes common properties of the whole subsystem not really specific to
10any single sub-device, like common camera port pins or the CAMCLK clock outputs
11for external image sensors attached to an SoC.
12
13Common 'camera' node
14--------------------
15
16Required properties:
17
18- compatible: must be "samsung,fimc", "simple-bus"
19- clocks: list of clock specifiers, corresponding to entries in
20 the clock-names property;
21- clock-names : must contain "sclk_cam0", "sclk_cam1", "pxl_async0",
22 "pxl_async1" entries, matching entries in the clocks property.
23
24- #clock-cells: from the common clock bindings (../clock/clock-bindings.txt),
25 must be 1. A clock provider is associated with the 'camera' node and it should
26 be referenced by external sensors that use clocks provided by the SoC on
27 CAM_*_CLKOUT pins. The clock specifier cell stores an index of a clock.
28 The indices are 0, 1 for CAM_A_CLKOUT, CAM_B_CLKOUT clocks respectively.
29
30- clock-output-names: from the common clock bindings, should contain names of
31 clocks registered by the camera subsystem corresponding to CAM_A_CLKOUT,
32 CAM_B_CLKOUT output clocks respectively.
33
34The pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt must be used
35to define a required pinctrl state named "default" and optional pinctrl states:
36"idle", "active-a", active-b". These optional states can be used to switch the
37camera port pinmux at runtime. The "idle" state should configure both the camera
38ports A and B into high impedance state, especially the CAMCLK clock output
39should be inactive. For the "active-a" state the camera port A must be activated
40and the port B deactivated and for the state "active-b" it should be the other
41way around.
42
43The 'camera' node must include at least one 'fimc' child node.
44
45
46'fimc' device nodes
47-------------------
48
49Required properties:
50
51- compatible: "samsung,s5pv210-fimc" for S5PV210, "samsung,exynos4210-fimc"
52 for Exynos4210 and "samsung,exynos4212-fimc" for Exynos4x12 SoCs;
53- reg: physical base address and length of the registers set for the device;
54- interrupts: should contain FIMC interrupt;
55- clocks: list of clock specifiers, must contain an entry for each required
56 entry in clock-names;
57- clock-names: must contain "fimc", "sclk_fimc" entries.
58- samsung,pix-limits: an array of maximum supported image sizes in pixels, for
59 details refer to Table 2-1 in the S5PV210 SoC User Manual; The meaning of
60 each cell is as follows:
61 0 - scaler input horizontal size,
62 1 - input horizontal size for the scaler bypassed,
63 2 - REAL_WIDTH without input rotation,
64 3 - REAL_HEIGHT with input rotation,
65- samsung,sysreg: a phandle to the SYSREG node.
66
67Each FIMC device should have an alias in the aliases node, in the form of
68fimc<n>, where <n> is an integer specifying the IP block instance.
69
70Optional properties:
71
72- clock-frequency: maximum FIMC local clock (LCLK) frequency;
73- samsung,min-pix-sizes: an array specyfing minimum image size in pixels at
74 the FIMC input and output DMA, in the first and second cell respectively.
75 Default value when this property is not present is <16 16>;
76- samsung,min-pix-alignment: minimum supported image height alignment (first
77 cell) and the horizontal image offset (second cell). The values are in pixels
78 and default to <2 1> when this property is not present;
79- samsung,mainscaler-ext: a boolean property indicating whether the FIMC IP
80 supports extended image size and has CIEXTEN register;
81- samsung,rotators: a bitmask specifying whether this IP has the input and
82 the output rotator. Bits 4 and 0 correspond to input and output rotator
83 respectively. If a rotator is present its corresponding bit should be set.
84 Default value when this property is not specified is 0x11.
85- samsung,cam-if: a bolean property indicating whether the IP block includes
86 the camera input interface.
87- samsung,isp-wb: this property must be present if the IP block has the ISP
88 writeback input.
89- samsung,lcd-wb: this property must be present if the IP block has the LCD
90 writeback input.
91
92
93'parallel-ports' node
94---------------------
95
96This node should contain child 'port' nodes specifying active parallel video
97input ports. It includes camera A and camera B inputs. 'reg' property in the
98port nodes specifies data input - 1, 2 indicates input A, B respectively.
99
100Optional properties
101
102- samsung,camclk-out (deprecated) : specifies clock output for remote sensor,
103 0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT;
104
105Image sensor nodes
106------------------
107
108The sensor device nodes should be added to their control bus controller (e.g.
109I2C0) nodes and linked to a port node in the csis or the parallel-ports node,
110using the common video interfaces bindings, defined in video-interfaces.txt.
111
112Example:
113
114 aliases {
115 fimc0 = &fimc_0;
116 };
117
118 /* Parallel bus IF sensor */
119 i2c_0: i2c@13860000 {
120 s5k6aa: sensor@3c {
121 compatible = "samsung,s5k6aafx";
122 reg = <0x3c>;
123 vddio-supply = <...>;
124
125 clock-frequency = <24000000>;
126 clocks = <&camera 1>;
127 clock-names = "mclk";
128
129 port {
130 s5k6aa_ep: endpoint {
131 remote-endpoint = <&fimc0_ep>;
132 bus-width = <8>;
133 hsync-active = <0>;
134 vsync-active = <1>;
135 pclk-sample = <1>;
136 };
137 };
138 };
139
140 /* MIPI CSI-2 bus IF sensor */
141 s5c73m3: sensor@1a {
142 compatible = "samsung,s5c73m3";
143 reg = <0x1a>;
144 vddio-supply = <...>;
145
146 clock-frequency = <24000000>;
147 clocks = <&camera 0>;
148 clock-names = "mclk";
149
150 port {
151 s5c73m3_1: endpoint {
152 data-lanes = <1 2 3 4>;
153 remote-endpoint = <&csis0_ep>;
154 };
155 };
156 };
157 };
158
159 camera {
160 compatible = "samsung,fimc", "simple-bus";
161 clocks = <&clock 132>, <&clock 133>, <&clock 351>,
162 <&clock 352>;
163 clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0",
164 "pxl_async1";
165 #clock-cells = <1>;
166 clock-output-names = "cam_a_clkout", "cam_b_clkout";
167 pinctrl-names = "default";
168 pinctrl-0 = <&cam_port_a_clk_active>;
169 #address-cells = <1>;
170 #size-cells = <1>;
171
172 /* parallel camera ports */
173 parallel-ports {
174 /* camera A input */
175 port@1 {
176 reg = <1>;
177 fimc0_ep: endpoint {
178 remote-endpoint = <&s5k6aa_ep>;
179 bus-width = <8>;
180 hsync-active = <0>;
181 vsync-active = <1>;
182 pclk-sample = <1>;
183 };
184 };
185 };
186
187 fimc_0: fimc@11800000 {
188 compatible = "samsung,exynos4210-fimc";
189 reg = <0x11800000 0x1000>;
190 interrupts = <0 85 0>;
191 };
192
193 csis_0: csis@11880000 {
194 compatible = "samsung,exynos4210-csis";
195 reg = <0x11880000 0x1000>;
196 interrupts = <0 78 0>;
197 /* camera C input */
198 port@3 {
199 reg = <3>;
200 csis0_ep: endpoint {
201 remote-endpoint = <&s5c73m3_ep>;
202 data-lanes = <1 2 3 4>;
203 samsung,csis-hs-settle = <12>;
204 };
205 };
206 };
207 };
208
209The MIPI-CSIS device binding is defined in samsung-mipi-csis.txt.
Documentation/devicetree/bindings/media/samsung-mipi-csis.txt+0−81
@@ -1,81 +0,0 @@
1Samsung S5P/Exynos SoC series MIPI CSI-2 receiver (MIPI CSIS)
2-------------------------------------------------------------
3
4Required properties:
5
6- compatible : "samsung,s5pv210-csis" for S5PV210 (S5PC110),
7 "samsung,exynos4210-csis" for Exynos4210 (S5PC210),
8 "samsung,exynos4212-csis" for Exynos4212/Exynos4412,
9 "samsung,exynos5250-csis" for Exynos5250;
10- reg : offset and length of the register set for the device;
11- interrupts : should contain MIPI CSIS interrupt; the format of the
12 interrupt specifier depends on the interrupt controller;
13- bus-width : maximum number of data lanes supported (SoC specific);
14- vddio-supply : MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V);
15- vddcore-supply : MIPI CSIS Core voltage supply (e.g. 1.1V);
16- clocks : list of clock specifiers, corresponding to entries in
17 clock-names property;
18- clock-names : must contain "csis", "sclk_csis" entries, matching entries
19 in the clocks property.
20
21Optional properties:
22
23- clock-frequency : The IP's main (system bus) clock frequency in Hz, default
24 value when this property is not specified is 166 MHz;
25- samsung,csis-wclk : CSI-2 wrapper clock selection. If this property is present
26 external clock from CMU will be used, or the bus clock if
27 if it's not specified.
28
29The device node should contain one 'port' child node with one child 'endpoint'
30node, according to the bindings defined in Documentation/devicetree/bindings/
31media/video-interfaces.txt. The following are properties specific to those nodes.
32
33port node
34---------
35
36- reg : (required) must be 3 for camera C input (CSIS0) or 4 for
37 camera D input (CSIS1);
38
39endpoint node
40-------------
41
42- data-lanes : (required) an array specifying active physical MIPI-CSI2
43 data input lanes and their mapping to logical lanes; the
44 array's content is unused, only its length is meaningful;
45
46- samsung,csis-hs-settle : (optional) differential receiver (HS-RX) settle time;
47
48
49Example:
50
51 reg0: regulator@0 {
52 };
53
54 reg1: regulator@1 {
55 };
56
57/* SoC properties */
58
59 csis_0: csis@11880000 {
60 compatible = "samsung,exynos4210-csis";
61 reg = <0x11880000 0x1000>;
62 interrupts = <0 78 0>;
63 #address-cells = <1>;
64 #size-cells = <0>;
65 };
66
67/* Board properties */
68
69 csis_0: csis@11880000 {
70 clock-frequency = <166000000>;
71 vddio-supply = <&reg0>;
72 vddcore-supply = <&reg1>;
73 port {
74 reg = <3>; /* 3 - CSIS0, 4 - CSIS1 */
75 csis0_ep: endpoint {
76 remote-endpoint = <...>;
77 data-lanes = <1>, <2>;
78 samsung,csis-hs-settle = <12>;
79 };
80 };
81 };
Documentation/devicetree/bindings/media/samsung-s5c73m3.txt+0−97
@@ -1,97 +0,0 @@
1Samsung S5C73M3 8Mp camera ISP
2------------------------------
3
4The S5C73M3 camera ISP supports MIPI CSI-2 and parallel (ITU-R BT.656) video
5data busses. The I2C bus is the main control bus and additionally the SPI bus
6is used, mostly for transferring the firmware to and from the device. Two
7slave device nodes corresponding to these control bus interfaces are required
8and should be placed under respective bus controller nodes.
9
10I2C slave device node
11---------------------
12
13Required properties:
14
15- compatible : "samsung,s5c73m3";
16- reg : I2C slave address of the sensor;
17- vdd-int-supply : digital power supply (1.2V);
18- vdda-supply : analog power supply (1.2V);
19- vdd-reg-supply : regulator input power supply (2.8V);
20- vddio-host-supply : host I/O power supply (1.8V to 2.8V);
21- vddio-cis-supply : CIS I/O power supply (1.2V to 1.8V);
22- vdd-af-supply : lens power supply (2.8V);
23- xshutdown-gpios : specifier of GPIO connected to the XSHUTDOWN pin;
24- standby-gpios : specifier of GPIO connected to the STANDBY pin;
25- clocks : should contain list of phandle and clock specifier pairs
26 according to common clock bindings for the clocks described
27 in the clock-names property;
28- clock-names : should contain "cis_extclk" entry for the CIS_EXTCLK clock;
29
30Optional properties:
31
32- clock-frequency : the frequency at which the "cis_extclk" clock should be
33 configured to operate, in Hz; if this property is not
34 specified default 24 MHz value will be used.
35
36The common video interfaces bindings (see video-interfaces.txt) should be used
37to specify link from the S5C73M3 to an external image data receiver. The S5C73M3
38device node should contain one 'port' child node with an 'endpoint' subnode for
39this purpose. The data link from a raw image sensor to the S5C73M3 can be
40similarly specified, but it is optional since the S5C73M3 ISP and a raw image
41sensor are usually inseparable and form a hybrid module.
42
43Following properties are valid for the endpoint node(s):
44
45endpoint subnode
46----------------
47
48- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
49 video-interfaces.txt. This sensor doesn't support data lane remapping
50 and physical lane indexes in subsequent elements of the array should
51 be only consecutive ascending values.
52
53SPI device node
54---------------
55
56Required properties:
57
58- compatible : "samsung,s5c73m3";
59
60For more details see description of the SPI busses bindings
61(../spi/spi-bus.txt) and bindings of a specific bus controller.
62
63Example:
64
65i2c@138a000000 {
66 ...
67 s5c73m3@3c {
68 compatible = "samsung,s5c73m3";
69 reg = <0x3c>;
70 vdd-int-supply = <&buck9_reg>;
71 vdda-supply = <&ldo17_reg>;
72 vdd-reg-supply = <&cam_io_reg>;
73 vddio-host-supply = <&ldo18_reg>;
74 vddio-cis-supply = <&ldo9_reg>;
75 vdd-af-supply = <&cam_af_reg>;
76 clock-frequency = <24000000>;
77 clocks = <&clk 0>;
78 clock-names = "cis_extclk";
79 xshutdown-gpios = <&gpf1 3 1>;
80 standby-gpios = <&gpm0 1 1>;
81 port {
82 s5c73m3_ep: endpoint {
83 remote-endpoint = <&csis0_ep>;
84 data-lanes = <1 2 3 4>;
85 };
86 };
87 };
88};
89
90spi@1392000 {
91 ...
92 s5c73m3_spi: s5c73m3@0 {
93 compatible = "samsung,s5c73m3";
94 reg = <0>;
95 ...
96 };
97};
Documentation/devicetree/bindings/media/samsung-s5k5baf.txt+0−58
@@ -1,58 +0,0 @@
1Samsung S5K5BAF UXGA 1/5" 2M CMOS Image Sensor with embedded SoC ISP
2--------------------------------------------------------------------
3
4Required properties:
5
6- compatible : "samsung,s5k5baf";
7- reg : I2C slave address of the sensor;
8- vdda-supply : analog power supply 2.8V (2.6V to 3.0V);
9- vddreg-supply : regulator input power supply 1.8V (1.7V to 1.9V)
10 or 2.8V (2.6V to 3.0);
11- vddio-supply : I/O power supply 1.8V (1.65V to 1.95V)
12 or 2.8V (2.5V to 3.1V);
13- stbyn-gpios : GPIO connected to STDBYN pin;
14- rstn-gpios : GPIO connected to RSTN pin;
15- clocks : list of phandle and clock specifier pairs
16 according to common clock bindings for the
17 clocks described in clock-names;
18- clock-names : should include "mclk" for the sensor's master clock;
19
20Optional properties:
21
22- clock-frequency : the frequency at which the "mclk" clock should be
23 configured to operate, in Hz; if this property is not
24 specified default 24 MHz value will be used.
25
26The device node should contain one 'port' child node with one child 'endpoint'
27node, according to the bindings defined in Documentation/devicetree/bindings/
28media/video-interfaces.txt. The following are properties specific to those
29nodes.
30
31endpoint node
32-------------
33
34- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
35 video-interfaces.txt. If present it should be <1> - the device
36 supports only one data lane without re-mapping.
37
38Example:
39
40s5k5bafx@2d {
41 compatible = "samsung,s5k5baf";
42 reg = <0x2d>;
43 vdda-supply = <&cam_io_en_reg>;
44 vddreg-supply = <&vt_core_15v_reg>;
45 vddio-supply = <&vtcam_reg>;
46 stbyn-gpios = <&gpl2 0 1>;
47 rstn-gpios = <&gpl2 1 1>;
48 clock-names = "mclk";
49 clocks = <&clock_cam 0>;
50 clock-frequency = <24000000>;
51
52 port {
53 s5k5bafx_ep: endpoint {
54 remote-endpoint = <&csis1_ep>;
55 data-lanes = <1>;
56 };
57 };
58};
Documentation/devicetree/bindings/media/samsung-s5k6a3.txt+0−33
@@ -1,33 +0,0 @@
1Samsung S5K6A3(YX) raw image sensor
2---------------------------------
3
4S5K6A3(YX) is a raw image sensor with MIPI CSI-2 and CCP2 image data interfaces
5and CCI (I2C compatible) control bus.
6
7Required properties:
8
9- compatible : "samsung,s5k6a3";
10- reg : I2C slave address of the sensor;
11- svdda-supply : core voltage supply;
12- svddio-supply : I/O voltage supply;
13- afvdd-supply : AF (actuator) voltage supply;
14- gpios : specifier of a GPIO connected to the RESET pin;
15- clocks : should contain list of phandle and clock specifier pairs
16 according to common clock bindings for the clocks described
17 in the clock-names property;
18- clock-names : should contain "extclk" entry for the sensor's EXTCLK clock;
19
20Optional properties:
21
22- clock-frequency : the frequency at which the "extclk" clock should be
23 configured to operate, in Hz; if this property is not
24 specified default 24 MHz value will be used.
25
26The common video interfaces bindings (see video-interfaces.txt) should be
27used to specify link to the image data receiver. The S5K6A3(YX) device
28node should contain one 'port' child node with an 'endpoint' subnode.
29
30Following properties are valid for the endpoint node:
31
32- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
33 video-interfaces.txt. The sensor supports only one data lane.
Documentation/devicetree/bindings/media/si470x.txt+0−26
@@ -1,26 +0,0 @@
1* Silicon Labs FM Radio receiver
2
3The Silicon Labs Si470x is family of FM radio receivers with receive power scan
4supporting 76-108 MHz, programmable through an I2C interface.
5Some of them includes an RDS encoder.
6
7Required Properties:
8- compatible: Should contain "silabs,si470x"
9- reg: the I2C address of the device
10
11Optional Properties:
12- interrupts : The interrupt number
13- reset-gpios: GPIO specifier for the chips reset line
14
15Example:
16
17&i2c2 {
18 si470x@63 {
19 compatible = "silabs,si470x";
20 reg = <0x63>;
21
22 interrupt-parent = <&gpj2>;
23 interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
24 reset-gpios = <&gpj2 5 GPIO_ACTIVE_HIGH>;
25 };
26};
Documentation/devicetree/bindings/media/silabs,si470x.yaml+48−0
@@ -0,0 +1,48 @@
1# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/silabs,si470x.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Silicon Labs Si470x FM Radio Receiver
8
9maintainers:
10 - Hans Verkuil <hverkuil@xs4all.nl>
11 - Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>
12
13properties:
14 compatible:
15 const: silabs,si470x
16
17 reg:
18 maxItems: 1
19
20 interrupts:
21 maxItems: 1
22
23 reset-gpios:
24 maxItems: 1
25
26required:
27 - compatible
28 - reg
29
30additionalProperties: false
31
32examples:
33 - |
34 #include <dt-bindings/gpio/gpio.h>
35 #include <dt-bindings/interrupt-controller/irq.h>
36
37 i2c {
38 #address-cells = <1>;
39 #size-cells = <0>;
40
41 fmradio@10 {
42 compatible = "silabs,si470x";
43 reg = <0x10>;
44 interrupt-parent = <&gpj2>;
45 interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
46 reset-gpios = <&gpj2 5 GPIO_ACTIVE_HIGH>;
47 };
48 };
Documentation/devicetree/bindings/media/st,stm32-cec.yaml+0−53
@@ -1,53 +0,0 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/media/st,stm32-cec.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: STMicroelectronics STM32 CEC
8
9maintainers:
10 - Yannick Fertre <yannick.fertre@foss.st.com>
11
12properties:
13 compatible:
14 const: st,stm32-cec
15
16 reg:
17 maxItems: 1
18
19 interrupts:
20 maxItems: 1
21
22 clocks:
23 items:
24 - description: Module Clock
25 - description: Bus Clock
26
27 clock-names:
28 items:
29 - const: cec
30 - const: hdmi-cec
31
32required:
33 - compatible
34 - reg
35 - interrupts
36 - clocks
37 - clock-names
38
39additionalProperties: false
40
41examples:
42 - |
43 #include <dt-bindings/interrupt-controller/arm-gic.h>
44 #include <dt-bindings/clock/stm32mp1-clks.h>
45 cec: cec@40006c00 {
46 compatible = "st,stm32-cec";
47 reg = <0x40006c00 0x400>;
48 interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
49 clocks = <&rcc CEC_K>, <&clk_lse>;
50 clock-names = "cec", "hdmi-cec";
51 };
52
53...
Documentation/devicetree/bindings/media/ti,cal.yaml+1−1
@@ -47,7 +47,7 @@ properties: · 46 unmodified lines
47 maxItems: 147 maxItems: 1
48 48
49 ti,camerrx-control:49 ti,camerrx-control:
50 $ref: "/schemas/types.yaml#/definitions/phandle-array"50 $ref: /schemas/types.yaml#/definitions/phandle-array
51 items:51 items:
52 - items:52 - items:
53 - description: phandle to device control module53 - description: phandle to device control module
Documentation/driver-api/media/drivers/ccs/ccs.rst+22−0
@@ -56,6 +56,28 @@ analogue data is never read from the pixel matrix that are outside the · 55 unmodified lines
56configured selection rectangle that designates crop. The difference has an56configured selection rectangle that designates crop. The difference has an
57effect in device timing and likely also in power consumption.57effect in device timing and likely also in power consumption.
58 58
59CCS static data
60---------------
61
62The MIPI CCS driver supports CCS static data for all compliant devices,
63including not just those compliant with CCS 1.1 but also CCS 1.0 and SMIA(++).
64For CCS the file names are formed as
65
66 ccs/ccs-sensor-vvvv-mmmm-rrrr.fw (sensor) and
67 ccs/ccs-module-vvvv-mmmm-rrrr.fw (module).
68
69For SMIA++ compliant devices the corresponding file names are
70
71 ccs/smiapp-sensor-vv-mmmm-rr.fw (sensor) and
72 ccs/smiapp-module-vv-mmmm-rrrr.fw (module).
73
74For SMIA (non-++) compliant devices the static data file name is
75
76 ccs/smia-sensor-vv-mmmm-rr.fw (sensor).
77
78vvvv or vv denotes MIPI and SMIA manufacturer IDs respectively, mmmm model ID
79and rrrr or rr revision number.
80
59Register definition generator81Register definition generator
60-----------------------------82-----------------------------
61 83
Documentation/userspace-api/media/v4l/dev-overlay.rst+8−2
@@ -67,6 +67,7 @@ ioctls must be supported by all video overlay devices. · 66 unmodified lines
67Setup67Setup
68=====68=====
69 69
70*Note: support for this has been removed.*
70Before overlay can commence applications must program the driver with71Before overlay can commence applications must program the driver with
71frame buffer parameters, namely the address and size of the frame buffer72frame buffer parameters, namely the address and size of the frame buffer
72and the image format, for example RGB 5:6:5. The73and the image format, for example RGB 5:6:5. The
@@ -92,11 +93,13 @@ A driver may support any (or none) of five clipping/blending methods: · 19 unmodified lines
921. Chroma-keying displays the overlaid image only where pixels in the931. Chroma-keying displays the overlaid image only where pixels in the
93 primary graphics surface assume a certain color.94 primary graphics surface assume a certain color.
94 95
952. A bitmap can be specified where each bit corresponds to a pixel in962. *Note: support for this has been removed.*
97 A bitmap can be specified where each bit corresponds to a pixel in
96 the overlaid image. When the bit is set, the corresponding video98 the overlaid image. When the bit is set, the corresponding video
97 pixel is displayed, otherwise a pixel of the graphics surface.99 pixel is displayed, otherwise a pixel of the graphics surface.
98 100
993. A list of clipping rectangles can be specified. In these regions *no*1013. *Note: support for this has been removed.*
102 A list of clipping rectangles can be specified. In these regions *no*
100 video is displayed, so the graphics surface can be seen here.103 video is displayed, so the graphics surface can be seen here.
101 104
1024. The framebuffer has an alpha channel that can be used to clip or1054. The framebuffer has an alpha channel that can be used to clip or
@@ -185,6 +188,7 @@ struct v4l2_window · 82 unmodified lines
185 be 0xRRGGBB on a little endian, 0xBBGGRR on a big endian host.188 be 0xRRGGBB on a little endian, 0xBBGGRR on a big endian host.
186 189
187``struct v4l2_clip * clips``190``struct v4l2_clip * clips``
191 *Note: support for this has been removed.*
188 When chroma-keying has *not* been negotiated and192 When chroma-keying has *not* been negotiated and
189 :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` indicated this capability,193 :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` indicated this capability,
190 applications can set this field to point to an array of clipping194 applications can set this field to point to an array of clipping
@@ -201,6 +205,7 @@ struct v4l2_window · 10 unmodified lines
201 are undefined.205 are undefined.
202 206
203``__u32 clipcount``207``__u32 clipcount``
208 *Note: support for this has been removed.*
204 When the application set the ``clips`` field, this field must209 When the application set the ``clips`` field, this field must
205 contain the number of clipping rectangles in the list. When clip210 contain the number of clipping rectangles in the list. When clip
206 lists are not supported the driver ignores this field, its contents211 lists are not supported the driver ignores this field, its contents
@@ -208,6 +213,7 @@ struct v4l2_window · 1 unmodified line
208 supported but no clipping is desired this field must be set to zero.213 supported but no clipping is desired this field must be set to zero.
209 214
210``void * bitmap``215``void * bitmap``
216 *Note: support for this has been removed.*
211 When chroma-keying has *not* been negotiated and217 When chroma-keying has *not* been negotiated and
212 :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` indicated this capability,218 :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` indicated this capability,
213 applications can set this field to point to a clipping bit mask.219 applications can set this field to point to a clipping bit mask.
Documentation/userspace-api/media/v4l/pixfmt-compressed.rst+25−0
@@ -88,6 +88,11 @@ Compressed Formats · 87 unmodified lines
88 - ``V4L2_PIX_FMT_H263``88 - ``V4L2_PIX_FMT_H263``
89 - 'H263'89 - 'H263'
90 - H263 video elementary stream.90 - H263 video elementary stream.
91 * .. _V4L2-PIX-FMT-SPK:
92
93 - ``V4L2_PIX_FMT_SPK``
94 - 'SPK0'
95 - Sorenson Spark is an implementation of H.263 for use in Flash Video and Adobe Flash files
91 * .. _V4L2-PIX-FMT-MPEG1:96 * .. _V4L2-PIX-FMT-MPEG1:
92 97
93 - ``V4L2_PIX_FMT_MPEG1``98 - ``V4L2_PIX_FMT_MPEG1``
@@ -232,6 +237,26 @@ Compressed Formats · 138 unmodified lines
232 Metadata associated with the frame to decode is required to be passed237 Metadata associated with the frame to decode is required to be passed
233 through the ``V4L2_CID_STATELESS_FWHT_PARAMS`` control.238 through the ``V4L2_CID_STATELESS_FWHT_PARAMS`` control.
234 See the :ref:`associated Codec Control ID <codec-stateless-fwht>`.239 See the :ref:`associated Codec Control ID <codec-stateless-fwht>`.
240 * .. _V4L2-PIX-FMT-RV30:
241
242 - ``V4L2_PIX_FMT_RV30``
243 - 'RV30'
244 - RealVideo, or also spelled as Real Video, is a suite of
245 proprietary video compression formats developed by
246 RealNetworks - the specific format changes with the version.
247 RealVideo codecs are identified by four-character codes.
248 RV30 corresponds to RealVideo 8, suspected to be based
249 largely on an early draft of H.264
250 * .. _V4L2-PIX-FMT-RV40:
251
252 - ``V4L2_PIX_FMT_RV40``
253 - 'RV40'
254 - RV40 represents RealVideo 9 and RealVideo 10.
255 RealVideo 9, suspected to be based on H.264.
256 RealVideo 10, aka RV9 EHQ, This refers to an improved encoder
257 for the RV9 format that is fully backwards compatible with
258 RV9 players - the format and decoder did not change, only
259 the encoder did. As a result, it uses the same FourCC.
235 260
236.. raw:: latex261.. raw:: latex
237 262
Documentation/userspace-api/media/v4l/pixfmt-packed-yuv.rst+28−0
@@ -257,6 +257,34 @@ the second byte and Y'\ :sub:`7-0` in the third byte. · 256 unmodified lines
257 - The padding bits contain undefined values that must be ignored by all257 - The padding bits contain undefined values that must be ignored by all
258 applications and drivers.258 applications and drivers.
259 259
260The next table lists the packed YUV 4:4:4 formats with 12 bits per component.
261Expand the bits per component to 16 bits, data in the high bits, zeros in the low bits,
262arranged in little endian order, storing 1 pixel in 6 bytes.
263
264.. flat-table:: Packed YUV 4:4:4 Image Formats (12bpc)
265 :header-rows: 1
266 :stub-columns: 0
267
268 * - Identifier
269 - Code
270 - Byte 1-0
271 - Byte 3-2
272 - Byte 5-4
273 - Byte 7-6
274 - Byte 9-8
275 - Byte 11-10
276
277 * .. _V4L2-PIX-FMT-YUV48-12:
278
279 - ``V4L2_PIX_FMT_YUV48_12``
280 - 'Y312'
281
282 - Y'\ :sub:`0`
283 - Cb\ :sub:`0`
284 - Cr\ :sub:`0`
285 - Y'\ :sub:`1`
286 - Cb\ :sub:`1`
287 - Cr\ :sub:`1`
260 288
2614:2:2 Subsampling2894:2:2 Subsampling
262=================290=================
Documentation/userspace-api/media/v4l/pixfmt-rgb.rst+42−0
@@ -953,6 +953,48 @@ number of bits for each component. · 952 unmodified lines
953 953
954 \endgroup954 \endgroup
955 955
95612 Bits Per Component
957==============================
958
959These formats store an RGB triplet in six or eight bytes, with 12 bits per component.
960Expand the bits per component to 16 bits, data in the high bits, zeros in the low bits,
961arranged in little endian order.
962
963.. raw:: latex
964
965 \small
966
967.. flat-table:: RGB Formats With 12 Bits Per Component
968 :header-rows: 1
969
970 * - Identifier
971 - Code
972 - Byte 1-0
973 - Byte 3-2
974 - Byte 5-4
975 - Byte 7-6
976 * .. _V4L2-PIX-FMT-BGR48-12:
977
978 - ``V4L2_PIX_FMT_BGR48_12``
979 - 'B312'
980
981 - B\ :sub:`15-4`
982 - G\ :sub:`15-4`
983 - R\ :sub:`15-4`
984 -
985 * .. _V4L2-PIX-FMT-ABGR64-12:
986
987 - ``V4L2_PIX_FMT_ABGR64_12``
988 - 'B412'
989
990 - B\ :sub:`15-4`
991 - G\ :sub:`15-4`
992 - R\ :sub:`15-4`
993 - A\ :sub:`15-4`
994
995.. raw:: latex
996
997 \normalsize
956 998
957Deprecated RGB Formats999Deprecated RGB Formats
958======================1000======================
Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst+15−0
@@ -103,6 +103,17 @@ are often referred to as greyscale formats. · 102 unmodified lines
103 - ...103 - ...
104 - ...104 - ...
105 105
106 * .. _V4L2-PIX-FMT-Y012:
107
108 - ``V4L2_PIX_FMT_Y012``
109 - 'Y012'
110
111 - Y'\ :sub:`0`\ [3:0] `0000`
112 - Y'\ :sub:`0`\ [11:4]
113 - ...
114 - ...
115 - ...
116
106 * .. _V4L2-PIX-FMT-Y14:117 * .. _V4L2-PIX-FMT-Y14:
107 118
108 - ``V4L2_PIX_FMT_Y14``119 - ``V4L2_PIX_FMT_Y14``
@@ -146,3 +157,7 @@ are often referred to as greyscale formats. · 37 unmodified lines
146 than 16 bits. For example, 10 bits per pixel uses values in the range 0 to157 than 16 bits. For example, 10 bits per pixel uses values in the range 0 to
147 1023. For the IPU3_Y10 format 25 pixels are packed into 32 bytes, which158 1023. For the IPU3_Y10 format 25 pixels are packed into 32 bytes, which
148 leaves the 6 most significant bits of the last byte padded with 0.159 leaves the 6 most significant bits of the last byte padded with 0.
160
161 For Y012 and Y12 formats, Y012 places its data in the 12 high bits, with
162 padding zeros in the 4 low bits, in contrast to the Y12 format, which has
163 its padding located in the most significant bits of the 16 bit word.
Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst+94−0
@@ -123,6 +123,20 @@ All components are stored with the same number of bits per component. · 122 unmodified lines
123 - Cb, Cr123 - Cb, Cr
124 - Yes124 - Yes
125 - 4x4 tiles125 - 4x4 tiles
126 * - V4L2_PIX_FMT_P012
127 - 'P012'
128 - 12
129 - 4:2:0
130 - Cb, Cr
131 - Yes
132 - Linear
133 * - V4L2_PIX_FMT_P012M
134 - 'PM12'
135 - 12
136 - 4:2:0
137 - Cb, Cr
138 - No
139 - Linear
126 * - V4L2_PIX_FMT_NV16140 * - V4L2_PIX_FMT_NV16
127 - 'NV16'141 - 'NV16'
128 - 8142 - 8
@@ -586,6 +600,86 @@ Data in the 10 high bits, zeros in the 6 low bits, arranged in little endian ord · 457 unmodified lines
586 - Cb\ :sub:`11`600 - Cb\ :sub:`11`
587 - Cr\ :sub:`11`601 - Cr\ :sub:`11`
588 602
603.. _V4L2-PIX-FMT-P012:
604.. _V4L2-PIX-FMT-P012M:
605
606P012 and P012M
607--------------
608
609P012 is like NV12 with 12 bits per component, expanded to 16 bits.
610Data in the 12 high bits, zeros in the 4 low bits, arranged in little endian order.
611
612.. flat-table:: Sample 4x4 P012 Image
613 :header-rows: 0
614 :stub-columns: 0
615
616 * - start + 0:
617 - Y'\ :sub:`00`
618 - Y'\ :sub:`01`
619 - Y'\ :sub:`02`
620 - Y'\ :sub:`03`
621 * - start + 8:
622 - Y'\ :sub:`10`
623 - Y'\ :sub:`11`
624 - Y'\ :sub:`12`
625 - Y'\ :sub:`13`
626 * - start + 16:
627 - Y'\ :sub:`20`
628 - Y'\ :sub:`21`
629 - Y'\ :sub:`22`
630 - Y'\ :sub:`23`
631 * - start + 24:
632 - Y'\ :sub:`30`
633 - Y'\ :sub:`31`
634 - Y'\ :sub:`32`
635 - Y'\ :sub:`33`
636 * - start + 32:
637 - Cb\ :sub:`00`
638 - Cr\ :sub:`00`
639 - Cb\ :sub:`01`
640 - Cr\ :sub:`01`
641 * - start + 40:
642 - Cb\ :sub:`10`
643 - Cr\ :sub:`10`
644 - Cb\ :sub:`11`
645 - Cr\ :sub:`11`
646
647.. flat-table:: Sample 4x4 P012M Image
648 :header-rows: 0
649 :stub-columns: 0
650
651 * - start0 + 0:
652 - Y'\ :sub:`00`
653 - Y'\ :sub:`01`
654 - Y'\ :sub:`02`
655 - Y'\ :sub:`03`
656 * - start0 + 8:
657 - Y'\ :sub:`10`
658 - Y'\ :sub:`11`
659 - Y'\ :sub:`12`
660 - Y'\ :sub:`13`
661 * - start0 + 16:
662 - Y'\ :sub:`20`
663 - Y'\ :sub:`21`
664 - Y'\ :sub:`22`
665 - Y'\ :sub:`23`
666 * - start0 + 24:
667 - Y'\ :sub:`30`
668 - Y'\ :sub:`31`
669 - Y'\ :sub:`32`
670 - Y'\ :sub:`33`
671 * -
672 * - start1 + 0:
673 - Cb\ :sub:`00`
674 - Cr\ :sub:`00`
675 - Cb\ :sub:`01`
676 - Cr\ :sub:`01`
677 * - start1 + 8:
678 - Cb\ :sub:`10`
679 - Cr\ :sub:`10`
680 - Cb\ :sub:`11`
681 - Cr\ :sub:`11`
682
589 683
590Fully Planar YUV Formats684Fully Planar YUV Formats
591========================685========================
Documentation/userspace-api/media/v4l/user-func.rst+1−0
@@ -72,6 +72,7 @@ Function Reference · 71 unmodified lines
72 vidioc-subdev-g-frame-interval72 vidioc-subdev-g-frame-interval
73 vidioc-subdev-g-routing73 vidioc-subdev-g-routing
74 vidioc-subdev-g-selection74 vidioc-subdev-g-selection
75 vidioc-subdev-g-client-cap
75 vidioc-subdev-querycap76 vidioc-subdev-querycap
76 vidioc-subscribe-event77 vidioc-subscribe-event
77 func-mmap78 func-mmap
Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst+10−0
@@ -185,6 +185,16 @@ still cause this situation. · 184 unmodified lines
185 - ``p_u32``185 - ``p_u32``
186 - A pointer to a matrix control of unsigned 32-bit values. Valid if186 - A pointer to a matrix control of unsigned 32-bit values. Valid if
187 this control is of type ``V4L2_CTRL_TYPE_U32``.187 this control is of type ``V4L2_CTRL_TYPE_U32``.
188 * - __u32 *
189 - ``p_s32``
190 - A pointer to a matrix control of signed 32-bit values. Valid if
191 this control is of type ``V4L2_CTRL_TYPE_INTEGER`` and
192 ``V4L2_CTRL_FLAG_HAS_PAYLOAD`` is set.
193 * - __u32 *
194 - ``p_s64``
195 - A pointer to a matrix control of signed 64-bit values. Valid if
196 this control is of type ``V4L2_CTRL_TYPE_INTEGER64`` and
197 ``V4L2_CTRL_FLAG_HAS_PAYLOAD`` is set.
188 * - struct :c:type:`v4l2_area` *198 * - struct :c:type:`v4l2_area` *
189 - ``p_area``199 - ``p_area``
190 - A pointer to a struct :c:type:`v4l2_area`. Valid if this control is200 - A pointer to a struct :c:type:`v4l2_area`. Valid if this control is
Documentation/userspace-api/media/v4l/vidioc-g-fbuf.rst+16−36
@@ -49,6 +49,9 @@ of a graphics card. A non-destructive overlay blends video images into a · 48 unmodified lines
49VGA signal or graphics into a video signal. *Video Output Overlays* are49VGA signal or graphics into a video signal. *Video Output Overlays* are
50always non-destructive.50always non-destructive.
51 51
52Destructive overlay support has been removed: with modern GPUs and CPUs
53this is no longer needed, and it was always a very dangerous feature.
54
52To get the current parameters applications call the :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`55To get the current parameters applications call the :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`
53ioctl with a pointer to a struct :c:type:`v4l2_framebuffer`56ioctl with a pointer to a struct :c:type:`v4l2_framebuffer`
54structure. The driver fills all fields of the structure or returns an57structure. The driver fills all fields of the structure or returns an
@@ -63,18 +66,12 @@ this structure, the driver prepares for the overlay and returns the · 8 unmodified lines
63framebuffer parameters as :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` does, or it returns an error66framebuffer parameters as :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>` does, or it returns an error
64code.67code.
65 68
66To set the parameters for a *non-destructive Video Overlay*,69To set the parameters for a *Video Capture Overlay*
67applications must initialize the ``flags`` field, the ``fmt``70applications must initialize the ``flags`` field, the ``fmt``
68substructure, and call :ref:`VIDIOC_S_FBUF <VIDIOC_G_FBUF>`. Again the driver prepares for71substructure, and call :ref:`VIDIOC_S_FBUF <VIDIOC_G_FBUF>`. Again the driver prepares for
69the overlay and returns the framebuffer parameters as :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`72the overlay and returns the framebuffer parameters as :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`
70does, or it returns an error code.73does, or it returns an error code.
71 74
72For a *destructive Video Overlay* applications must additionally provide
73a ``base`` address. Setting up a DMA to a random memory location can
74jeopardize the system security, its stability or even damage the
75hardware, therefore only the superuser can set the parameters for a
76destructive video overlay.
77
78.. tabularcolumns:: |p{3.5cm}|p{3.5cm}|p{3.5cm}|p{6.6cm}|75.. tabularcolumns:: |p{3.5cm}|p{3.5cm}|p{3.5cm}|p{6.6cm}|
79 76
80.. c:type:: v4l2_framebuffer77.. c:type:: v4l2_framebuffer
@@ -100,17 +97,14 @@ destructive video overlay. · 19 unmodified lines
100 - ``base``97 - ``base``
101 -98 -
102 - Physical base address of the framebuffer, that is the address of99 - Physical base address of the framebuffer, that is the address of
103 the pixel in the top left corner of the framebuffer. [#f1]_100 the pixel in the top left corner of the framebuffer.
104 * -101 For :ref:`VIDIOC_S_FBUF <VIDIOC_G_FBUF>` this field is no longer supported
105 -102 and the kernel will always set this to NULL.
106 -103 For *Video Output Overlays*
107 - This field is irrelevant to *non-destructive Video Overlays*. For104 the driver will return a valid base address, so applications can
108 *destructive Video Overlays* applications must provide a base
109 address. The driver may accept only base addresses which are a
110 multiple of two, four or eight bytes. For *Video Output Overlays*
111 the driver must return a valid base address, so applications can
112 find the corresponding Linux framebuffer device (see105 find the corresponding Linux framebuffer device (see
113 :ref:`osd`).106 :ref:`osd`). For *Video Capture Overlays* this field will always be
107 NULL.
114 * - struct108 * - struct
115 - ``fmt``109 - ``fmt``
116 -110 -
@@ -136,8 +130,7 @@ destructive video overlay. · 19 unmodified lines
136 * -130 * -
137 -131 -
138 -132 -
139 - For *destructive Video Overlays* applications must initialize this133 - For *Video Output Overlays* the driver must return a valid
140 field. For *Video Output Overlays* the driver must return a valid
141 format.134 format.
142 * -135 * -
143 -136 -
@@ -165,13 +158,6 @@ destructive video overlay. · 21 unmodified lines
165 158
166 This field is irrelevant to *non-destructive Video Overlays*.159 This field is irrelevant to *non-destructive Video Overlays*.
167 160
168 For *destructive Video Overlays* both applications and drivers can
169 set this field to request padding bytes at the end of each line.
170 Drivers however may ignore the requested value, returning
171 ``width`` times bytes-per-pixel or a larger value required by the
172 hardware. That implies applications can just set this field to
173 zero to get a reasonable default.
174
175 For *Video Output Overlays* the driver must return a valid value.161 For *Video Output Overlays* the driver must return a valid value.
176 162
177 Video hardware may access padding bytes, therefore they must163 Video hardware may access padding bytes, therefore they must
@@ -190,9 +176,8 @@ destructive video overlay. · 12 unmodified lines
190 * -176 * -
191 - __u32177 - __u32
192 - ``sizeimage``178 - ``sizeimage``
193 - This field is irrelevant to *non-destructive Video Overlays*. For179 - This field is irrelevant to *non-destructive Video Overlays*.
194 *destructive Video Overlays* applications must initialize this180 For *Video Output Overlays* the driver must return a valid
195 field. For *Video Output Overlays* the driver must return a valid
196 format.181 format.
197 182
198 Together with ``base`` it defines the framebuffer memory183 Together with ``base`` it defines the framebuffer memory
@@ -232,9 +217,11 @@ destructive video overlay. · 33 unmodified lines
232 * - ``V4L2_FBUF_CAP_LIST_CLIPPING``217 * - ``V4L2_FBUF_CAP_LIST_CLIPPING``
233 - 0x0004218 - 0x0004
234 - The device supports clipping using a list of clip rectangles.219 - The device supports clipping using a list of clip rectangles.
220 Note that this is no longer supported.
235 * - ``V4L2_FBUF_CAP_BITMAP_CLIPPING``221 * - ``V4L2_FBUF_CAP_BITMAP_CLIPPING``
236 - 0x0008222 - 0x0008
237 - The device supports clipping using a bit mask.223 - The device supports clipping using a bit mask.
224 Note that this is no longer supported.
238 * - ``V4L2_FBUF_CAP_LOCAL_ALPHA``225 * - ``V4L2_FBUF_CAP_LOCAL_ALPHA``
239 - 0x0010226 - 0x0010
240 - The device supports clipping/blending using the alpha channel of227 - The device supports clipping/blending using the alpha channel of
@@ -342,10 +329,3 @@ EPERM · 101 unmodified lines
342 329
343EINVAL330EINVAL
344 The :ref:`VIDIOC_S_FBUF <VIDIOC_G_FBUF>` parameters are unsuitable.331 The :ref:`VIDIOC_S_FBUF <VIDIOC_G_FBUF>` parameters are unsuitable.
345
346.. [#f1]
347 A physical base address may not suit all platforms. GK notes in
348 theory we should pass something like PCI device + memory region +
349 offset instead. If you encounter problems please discuss on the
350 linux-media mailing list:
351 `https://linuxtv.org/lists.php <https://linuxtv.org/lists.php>`__.
Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-size.rst+29−15
@@ -31,18 +31,30 @@ Arguments · 30 unmodified lines
31Description31Description
32===========32===========
33 33
34This ioctl allows applications to enumerate all frame sizes supported by34This ioctl allows applications to access the enumeration of frame sizes
35a sub-device on the given pad for the given media bus format. Supported35supported by a sub-device on the specified pad
36formats can be retrieved with the36for the specified media bus format.
37Supported formats can be retrieved with the
37:ref:`VIDIOC_SUBDEV_ENUM_MBUS_CODE`38:ref:`VIDIOC_SUBDEV_ENUM_MBUS_CODE`
38ioctl.39ioctl.
39 40
40To enumerate frame sizes applications initialize the ``pad``, ``which``41The enumerations are defined by the driver, and indexed using the ``index`` field
41, ``code`` and ``index`` fields of the struct42of the struct :c:type:`v4l2_subdev_frame_size_enum`.
42:c:type:`v4l2_subdev_mbus_code_enum` and43Each pair of ``pad`` and ``code`` correspond to a separate enumeration.
43call the :ref:`VIDIOC_SUBDEV_ENUM_FRAME_SIZE` ioctl with a pointer to the44Each enumeration starts with the ``index`` of 0, and
44structure. Drivers fill the minimum and maximum frame sizes or return an45the lowest invalid index marks the end of the enumeration.
45EINVAL error code if one of the input parameters is invalid.46
47Therefore, to enumerate frame sizes allowed on the specified pad
48and using the specified mbus format, initialize the
49``pad``, ``which``, and ``code`` fields to desired values,
50and set ``index`` to 0.
51Then call the :ref:`VIDIOC_SUBDEV_ENUM_FRAME_SIZE` ioctl with a pointer to the
52structure.
53
54A successful call will return with minimum and maximum frame sizes filled in.
55Repeat with increasing ``index`` until ``EINVAL`` is received.
56``EINVAL`` means that either no more entries are available in the enumeration,
57or that an input parameter was invalid.
46 58
47Sub-devices that only support discrete frame sizes (such as most59Sub-devices that only support discrete frame sizes (such as most
48sensors) will return one or more frame sizes with identical minimum and60sensors) will return one or more frame sizes with identical minimum and
@@ -72,26 +84,28 @@ information about try formats. · 23 unmodified lines
72 84
73 * - __u3285 * - __u32
74 - ``index``86 - ``index``
75 - Number of the format in the enumeration, set by the application.87 - Index of the frame size in the enumeration belonging to the given pad
88 and format. Filled in by the application.
76 * - __u3289 * - __u32
77 - ``pad``90 - ``pad``
78 - Pad number as reported by the media controller API.91 - Pad number as reported by the media controller API.
92 Filled in by the application.
79 * - __u3293 * - __u32
80 - ``code``94 - ``code``
81 - The media bus format code, as defined in95 - The media bus format code, as defined in
82 :ref:`v4l2-mbus-format`.96 :ref:`v4l2-mbus-format`. Filled in by the application.
83 * - __u3297 * - __u32
84 - ``min_width``98 - ``min_width``
85 - Minimum frame width, in pixels.99 - Minimum frame width, in pixels. Filled in by the driver.
86 * - __u32100 * - __u32
87 - ``max_width``101 - ``max_width``
88 - Maximum frame width, in pixels.102 - Maximum frame width, in pixels. Filled in by the driver.
89 * - __u32103 * - __u32
90 - ``min_height``104 - ``min_height``
91 - Minimum frame height, in pixels.105 - Minimum frame height, in pixels. Filled in by the driver.
92 * - __u32106 * - __u32
93 - ``max_height``107 - ``max_height``
94 - Maximum frame height, in pixels.108 - Maximum frame height, in pixels. Filled in by the driver.
95 * - __u32109 * - __u32
96 - ``which``110 - ``which``
97 - Frame sizes to be enumerated, from enum111 - Frame sizes to be enumerated, from enum
Documentation/userspace-api/media/v4l/vidioc-subdev-enum-mbus-code.rst+27−12
@@ -31,15 +31,28 @@ Arguments · 30 unmodified lines
31Description31Description
32===========32===========
33 33
34To enumerate media bus formats available at a given sub-device pad34This call is used by the application to access the enumeration
35applications initialize the ``pad``, ``which`` and ``index`` fields of35of media bus formats for the selected pad.
36struct36
37:c:type:`v4l2_subdev_mbus_code_enum` and37The enumerations are defined by the driver, and indexed using the ``index`` field
38call the :ref:`VIDIOC_SUBDEV_ENUM_MBUS_CODE` ioctl with a pointer to this38of struct :c:type:`v4l2_subdev_mbus_code_enum`.
39structure. Drivers fill the rest of the structure or return an ``EINVAL``39Each enumeration starts with the ``index`` of 0, and
40error code if either the ``pad`` or ``index`` are invalid. All media bus40the lowest invalid index marks the end of enumeration.
41formats are enumerable by beginning at index zero and incrementing by41
42one until ``EINVAL`` is returned.42Therefore, to enumerate media bus formats available at a given sub-device pad,
43initialize the ``pad``, and ``which`` fields to desired values,
44and set ``index`` to 0.
45Then call the :ref:`VIDIOC_SUBDEV_ENUM_MBUS_CODE` ioctl
46with a pointer to this structure.
47
48A successful call will return with the ``code`` field filled in
49with a mbus code value.
50Repeat with increasing ``index`` until ``EINVAL`` is received.
51``EINVAL`` means that either ``pad`` is invalid,
52or that there are no more codes available at this pad.
53
54The driver must not return the same value of ``code`` for different indices
55at the same pad.
43 56
44Available media bus formats may depend on the current 'try' formats at57Available media bus formats may depend on the current 'try' formats at
45other pads of the sub-device, as well as on the current active links.58other pads of the sub-device, as well as on the current active links.
@@ -57,14 +70,16 @@ information about the try formats. · 11 unmodified lines
57 70
58 * - __u3271 * - __u32
59 - ``pad``72 - ``pad``
60 - Pad number as reported by the media controller API.73 - Pad number as reported by the media controller API. Filled in by the
74 application.
61 * - __u3275 * - __u32
62 - ``index``76 - ``index``
63 - Number of the format in the enumeration, set by the application.77 - Index of the mbus code in the enumeration belonging to the given pad.
78 Filled in by the application.
64 * - __u3279 * - __u32
65 - ``code``80 - ``code``
66 - The media bus format code, as defined in81 - The media bus format code, as defined in
67 :ref:`v4l2-mbus-format`.82 :ref:`v4l2-mbus-format`. Filled in by the driver.
68 * - __u3283 * - __u32
69 - ``which``84 - ``which``
70 - Media bus format codes to be enumerated, from enum85 - Media bus format codes to be enumerated, from enum
Documentation/userspace-api/media/v4l/vidioc-subdev-g-client-cap.rst+83−0
@@ -0,0 +1,83 @@
1.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
2.. c:namespace:: V4L
3
4.. _VIDIOC_SUBDEV_G_CLIENT_CAP:
5
6************************************************************
7ioctl VIDIOC_SUBDEV_G_CLIENT_CAP, VIDIOC_SUBDEV_S_CLIENT_CAP
8************************************************************
9
10Name
11====
12
13VIDIOC_SUBDEV_G_CLIENT_CAP - VIDIOC_SUBDEV_S_CLIENT_CAP - Get or set client
14capabilities.
15
16Synopsis
17========
18
19.. c:macro:: VIDIOC_SUBDEV_G_CLIENT_CAP
20
21``int ioctl(int fd, VIDIOC_SUBDEV_G_CLIENT_CAP, struct v4l2_subdev_client_capability *argp)``
22
23.. c:macro:: VIDIOC_SUBDEV_S_CLIENT_CAP
24
25``int ioctl(int fd, VIDIOC_SUBDEV_S_CLIENT_CAP, struct v4l2_subdev_client_capability *argp)``
26
27Arguments
28=========
29
30``fd``
31 File descriptor returned by :ref:`open() <func-open>`.
32
33``argp``
34 Pointer to struct :c:type:`v4l2_subdev_client_capability`.
35
36Description
37===========
38
39These ioctls are used to get and set the client (the application using the
40subdevice ioctls) capabilities. The client capabilities are stored in the file
41handle of the opened subdev device node, and the client must set the
42capabilities for each opened subdev separately.
43
44By default no client capabilities are set when a subdev device node is opened.
45
46The purpose of the client capabilities are to inform the kernel of the behavior
47of the client, mainly related to maintaining compatibility with different
48kernel and userspace versions.
49
50The ``VIDIOC_SUBDEV_G_CLIENT_CAP`` ioctl returns the current client capabilities
51associated with the file handle ``fd``.
52
53The ``VIDIOC_SUBDEV_S_CLIENT_CAP`` ioctl sets client capabilities for the file
54handle ``fd``. The new capabilities fully replace the current capabilities, the
55ioctl can therefore also be used to remove capabilities that have previously
56been set.
57
58``VIDIOC_SUBDEV_S_CLIENT_CAP`` modifies the struct
59:c:type:`v4l2_subdev_client_capability` to reflect the capabilities that have
60been accepted. A common case for the kernel not accepting a capability is that
61the kernel is older than the headers the userspace uses, and thus the capability
62is unknown to the kernel.
63
64.. flat-table:: Client Capabilities
65 :header-rows: 1
66
67 * - Capability
68 - Description
69 * - ``V4L2_SUBDEV_CLIENT_CAP_STREAMS``
70 - The client is aware of streams. Setting this flag enables the use
71 of 'stream' fields (referring to the stream number) with various
72 ioctls. If this is not set (which is the default), the 'stream' fields
73 will be forced to 0 by the kernel.
74
75Return Value
76============
77
78On success 0 is returned, on error -1 and the ``errno`` variable is set
79appropriately. The generic error codes are described at the
80:ref:`Generic Error Codes <gen-errors>` chapter.
81
82ENOIOCTLCMD
83 The kernel does not support this ioctl.
MAINTAINERS+17−31
@@ -1227,12 +1227,6 @@ F: Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml · 1226 unmodified lines
1227F: drivers/iio/addac/ad74413r.c1227F: drivers/iio/addac/ad74413r.c
1228F: include/dt-bindings/iio/addac/adi,ad74413r.h1228F: include/dt-bindings/iio/addac/adi,ad74413r.h
1229 1229
1230ANALOG DEVICES INC AD9389B DRIVER
1231M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
1232L: linux-media@vger.kernel.org
1233S: Maintained
1234F: drivers/media/i2c/ad9389b*
1235
1236ANALOG DEVICES INC ADA4250 DRIVER1230ANALOG DEVICES INC ADA4250 DRIVER
1237M: Antoniu Miclaus <antoniu.miclaus@analog.com>1231M: Antoniu Miclaus <antoniu.miclaus@analog.com>
1238L: linux-iio@vger.kernel.org1232L: linux-iio@vger.kernel.org
@@ -8441,14 +8435,6 @@ L: platform-driver-x86@vger.kernel.org · 7202 unmodified lines
8441S: Maintained8435S: Maintained
8442F: drivers/platform/x86/fujitsu-laptop.c8436F: drivers/platform/x86/fujitsu-laptop.c
8443 8437
8444FUJITSU M-5MO LS CAMERA ISP DRIVER
8445M: Kyungmin Park <kyungmin.park@samsung.com>
8446M: Heungjun Kim <riverful.kim@samsung.com>
8447L: linux-media@vger.kernel.org
8448S: Maintained
8449F: drivers/media/i2c/m5mols/
8450F: include/media/i2c/m5mols.h
8451
8452FUJITSU TABLET EXTRAS8438FUJITSU TABLET EXTRAS
8453M: Robert Gerlach <khnz@gmx.de>8439M: Robert Gerlach <khnz@gmx.de>
8454L: platform-driver-x86@vger.kernel.org8440L: platform-driver-x86@vger.kernel.org
@@ -14206,14 +14192,6 @@ L: linux-mtd@lists.infradead.org · 5751 unmodified lines
14206S: Maintained14192S: Maintained
14207F: drivers/mtd/devices/docg3*14193F: drivers/mtd/devices/docg3*
14208 14194
14209MT9M032 APTINA SENSOR DRIVER
14210M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
14211L: linux-media@vger.kernel.org
14212S: Maintained
14213T: git git://linuxtv.org/media_tree.git
14214F: drivers/media/i2c/mt9m032.c
14215F: include/media/i2c/mt9m032.h
14216
14217MT9P031 APTINA CAMERA SENSOR14195MT9P031 APTINA CAMERA SENSOR
14218M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>14196M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
14219L: linux-media@vger.kernel.org14197L: linux-media@vger.kernel.org
@@ -14223,14 +14201,6 @@ F: Documentation/devicetree/bindings/media/i2c/aptina,mt9p031.yaml · 3 unmodified lines
14223F: drivers/media/i2c/mt9p031.c14201F: drivers/media/i2c/mt9p031.c
14224F: include/media/i2c/mt9p031.h14202F: include/media/i2c/mt9p031.h
14225 14203
14226MT9T001 APTINA CAMERA SENSOR
14227M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
14228L: linux-media@vger.kernel.org
14229S: Maintained
14230T: git git://linuxtv.org/media_tree.git
14231F: drivers/media/i2c/mt9t001.c
14232F: include/media/i2c/mt9t001.h
14233
14234MT9T112 APTINA CAMERA SENSOR14204MT9T112 APTINA CAMERA SENSOR
14235M: Jacopo Mondi <jacopo@jmondi.org>14205M: Jacopo Mondi <jacopo@jmondi.org>
14236L: linux-media@vger.kernel.org14206L: linux-media@vger.kernel.org
@@ -14983,6 +14953,13 @@ F: Documentation/devicetree/bindings/clock/imx* · 746 unmodified lines
14983F: drivers/clk/imx/14953F: drivers/clk/imx/
14984F: include/dt-bindings/clock/imx*14954F: include/dt-bindings/clock/imx*
14985 14955
14956NXP i.MX 8M ISI DRIVER
14957M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
14958L: linux-media@vger.kernel.org
14959S: Maintained
14960F: Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml
14961F: drivers/media/platform/nxp/imx8-isi/
14962
14986NXP i.MX 8MQ DCSS DRIVER14963NXP i.MX 8MQ DCSS DRIVER
14987M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>14964M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
14988R: Lucas Stach <l.stach@pengutronix.de>14965R: Lucas Stach <l.stach@pengutronix.de>
@@ -15410,6 +15387,7 @@ M: Shunqian Zheng <zhengsq@rock-chips.com> · 421 unmodified lines
15410L: linux-media@vger.kernel.org15387L: linux-media@vger.kernel.org
15411S: Maintained15388S: Maintained
15412T: git git://linuxtv.org/media_tree.git15389T: git git://linuxtv.org/media_tree.git
15390F: Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml
15413F: drivers/media/i2c/ov2685.c15391F: drivers/media/i2c/ov2685.c
15414 15392
15415OMNIVISION OV2740 SENSOR DRIVER15393OMNIVISION OV2740 SENSOR DRIVER
@@ -15501,7 +15479,7 @@ F: Documentation/devicetree/bindings/media/i2c/ov7740.txt · 85 unmodified lines
15501F: drivers/media/i2c/ov7740.c15479F: drivers/media/i2c/ov7740.c
15502 15480
15503OMNIVISION OV8856 SENSOR DRIVER15481OMNIVISION OV8856 SENSOR DRIVER
15504M: Dongchun Zhu <dongchun.zhu@mediatek.com>15482M: Sakari Ailus <sakari.ailus@linux.intel.com>
15505L: linux-media@vger.kernel.org15483L: linux-media@vger.kernel.org
15506S: Maintained15484S: Maintained
15507T: git git://linuxtv.org/media_tree.git15485T: git git://linuxtv.org/media_tree.git
@@ -17260,6 +17238,7 @@ F: drivers/net/wwan/qcom_bam_dmux.c · 1752 unmodified lines
17260QUALCOMM CAMERA SUBSYSTEM DRIVER17238QUALCOMM CAMERA SUBSYSTEM DRIVER
17261M: Robert Foss <rfoss@kernel.org>17239M: Robert Foss <rfoss@kernel.org>
17262M: Todor Tomov <todor.too@gmail.com>17240M: Todor Tomov <todor.too@gmail.com>
17241M: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
17263L: linux-media@vger.kernel.org17242L: linux-media@vger.kernel.org
17264S: Maintained17243S: Maintained
17265F: Documentation/admin-guide/media/qcom_camss.rst17244F: Documentation/admin-guide/media/qcom_camss.rst
@@ -18536,6 +18515,7 @@ M: Sylwester Nawrocki <s.nawrocki@samsung.com> · 1270 unmodified lines
18536M: Andrzej Hajda <andrzej.hajda@intel.com>18515M: Andrzej Hajda <andrzej.hajda@intel.com>
18537L: linux-media@vger.kernel.org18516L: linux-media@vger.kernel.org
18538S: Supported18517S: Supported
18518F: Documentation/devicetree/bindings/media/samsung,s5c73m3.yaml
18539F: drivers/media/i2c/s5c73m3/*18519F: drivers/media/i2c/s5c73m3/*
18540 18520
18541SAMSUNG S5K5BAF CAMERA DRIVER18521SAMSUNG S5K5BAF CAMERA DRIVER
@@ -18560,6 +18540,11 @@ M: Sylwester Nawrocki <s.nawrocki@samsung.com> · 18 unmodified lines
18560L: linux-media@vger.kernel.org18540L: linux-media@vger.kernel.org
18561S: Supported18541S: Supported
18562Q: https://patchwork.linuxtv.org/project/linux-media/list/18542Q: https://patchwork.linuxtv.org/project/linux-media/list/
18543F: Documentation/devicetree/bindings/media/samsung,exynos4210-csis.yaml
18544F: Documentation/devicetree/bindings/media/samsung,exynos4210-fimc.yaml
18545F: Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml
18546F: Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-lite.yaml
18547F: Documentation/devicetree/bindings/media/samsung,fimc.yaml
18563F: drivers/media/platform/samsung/exynos4-is/18548F: drivers/media/platform/samsung/exynos4-is/
18564 18549
18565SAMSUNG SOC CLOCK DRIVERS18550SAMSUNG SOC CLOCK DRIVERS
@@ -19038,6 +19023,7 @@ L: linux-media@vger.kernel.org · 472 unmodified lines
19038S: Odd Fixes19023S: Odd Fixes
19039W: https://linuxtv.org19024W: https://linuxtv.org
19040T: git git://linuxtv.org/media_tree.git19025T: git git://linuxtv.org/media_tree.git
19026F: Documentation/devicetree/bindings/media/silabs,si470x.yaml
19041F: drivers/media/radio/si470x/radio-si470x-i2c.c19027F: drivers/media/radio/si470x/radio-si470x-i2c.c
19042 19028
19043SI470X FM RADIO RECEIVER USB DRIVER19029SI470X FM RADIO RECEIVER USB DRIVER
drivers/media/cec/core/cec-adap.c+5−2
@@ -1052,6 +1052,7 @@ void cec_received_msg_ts(struct cec_adapter *adap, · 1051 unmodified lines
1052 u8 cmd = msg->msg[1];1052 u8 cmd = msg->msg[1];
1053 bool is_reply = false;1053 bool is_reply = false;
1054 bool valid_la = true;1054 bool valid_la = true;
1055 bool monitor_valid_la = true;
1055 u8 min_len = 0;1056 u8 min_len = 0;
1056 1057
1057 if (WARN_ON(!msg->len || msg->len > CEC_MAX_MSG_SIZE))1058 if (WARN_ON(!msg->len || msg->len > CEC_MAX_MSG_SIZE))
@@ -1093,8 +1094,10 @@ void cec_received_msg_ts(struct cec_adapter *adap, · 35 unmodified lines
1093 adap->last_initiator = 0xff;1094 adap->last_initiator = 0xff;
1094 1095
1095 /* Check if this message was for us (directed or broadcast). */1096 /* Check if this message was for us (directed or broadcast). */
1096 if (!cec_msg_is_broadcast(msg))1097 if (!cec_msg_is_broadcast(msg)) {
1097 valid_la = cec_has_log_addr(adap, msg_dest);1098 valid_la = cec_has_log_addr(adap, msg_dest);
1099 monitor_valid_la = valid_la;
1100 }
1098 1101
1099 /*1102 /*
1100 * Check if the length is not too short or if the message is a1103 * Check if the length is not too short or if the message is a
@@ -1227,7 +1230,7 @@ void cec_received_msg_ts(struct cec_adapter *adap, · 126 unmodified lines
1227 mutex_unlock(&adap->lock);1230 mutex_unlock(&adap->lock);
1228 1231
1229 /* Pass the message on to any monitoring filehandles */1232 /* Pass the message on to any monitoring filehandles */
1230 cec_queue_msg_monitor(adap, msg, valid_la);1233 cec_queue_msg_monitor(adap, msg, monitor_valid_la);
1231 1234
1232 /* We're done if it is not for us or a poll message */1235 /* We're done if it is not for us or a poll message */
1233 if (!valid_la || msg->len <= 1)1236 if (!valid_la || msg->len <= 1)
drivers/media/cec/platform/cec-gpio/cec-gpio.c+2−3
@@ -269,13 +269,12 @@ del_adap: · 268 unmodified lines
269 return ret;269 return ret;
270}270}
271 271
272static int cec_gpio_remove(struct platform_device *pdev)272static void cec_gpio_remove(struct platform_device *pdev)
273{273{
274 struct cec_gpio *cec = platform_get_drvdata(pdev);274 struct cec_gpio *cec = platform_get_drvdata(pdev);
275 275
276 cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);276 cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
277 cec_unregister_adapter(cec->adap);277 cec_unregister_adapter(cec->adap);
278 return 0;
279}278}
280 279
281static const struct of_device_id cec_gpio_match[] = {280static const struct of_device_id cec_gpio_match[] = {
@@ -288,7 +287,7 @@ MODULE_DEVICE_TABLE(of, cec_gpio_match); · 6 unmodified lines
288 287
289static struct platform_driver cec_gpio_pdrv = {288static struct platform_driver cec_gpio_pdrv = {
290 .probe = cec_gpio_probe,289 .probe = cec_gpio_probe,
291 .remove = cec_gpio_remove,290 .remove_new = cec_gpio_remove,
292 .driver = {291 .driver = {
293 .name = "cec-gpio",292 .name = "cec-gpio",
294 .of_match_table = cec_gpio_match,293 .of_match_table = cec_gpio_match,
drivers/media/cec/platform/cros-ec/cros-ec-cec.c+14−8
@@ -225,6 +225,12 @@ static const struct cec_dmi_match cec_dmi_match_table[] = { · 224 unmodified lines
225 { "Google", "Kinox", "0000:00:02.0", "Port B" },225 { "Google", "Kinox", "0000:00:02.0", "Port B" },
226 /* Google Kuldax */226 /* Google Kuldax */
227 { "Google", "Kuldax", "0000:00:02.0", "Port B" },227 { "Google", "Kuldax", "0000:00:02.0", "Port B" },
228 /* Google Aurash */
229 { "Google", "Aurash", "0000:00:02.0", "Port B" },
230 /* Google Gladios */
231 { "Google", "Gladios", "0000:00:02.0", "Port B" },
232 /* Google Lisbon */
233 { "Google", "Lisbon", "0000:00:02.0", "Port B" },
228};234};
229 235
230static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,236static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,
@@ -326,31 +332,31 @@ out_probe_adapter: · 95 unmodified lines
326 return ret;332 return ret;
327}333}
328 334
329static int cros_ec_cec_remove(struct platform_device *pdev)335static void cros_ec_cec_remove(struct platform_device *pdev)
330{336{
331 struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev);337 struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev);
332 struct device *dev = &pdev->dev;338 struct device *dev = &pdev->dev;
333 int ret;339 int ret;
334 340
341 /*
342 * blocking_notifier_chain_unregister() only fails if the notifier isn't
343 * in the list. We know it was added to it by .probe(), so there should
344 * be no need for error checking. Be cautious and still check.
345 */
335 ret = blocking_notifier_chain_unregister(346 ret = blocking_notifier_chain_unregister(
336 &cros_ec_cec->cros_ec->event_notifier,347 &cros_ec_cec->cros_ec->event_notifier,
337 &cros_ec_cec->notifier);348 &cros_ec_cec->notifier);
338 349 if (ret)
339 if (ret) {
340 dev_err(dev, "failed to unregister notifier\n");350 dev_err(dev, "failed to unregister notifier\n");
341 return ret;
342 }
343 351
344 cec_notifier_cec_adap_unregister(cros_ec_cec->notify,352 cec_notifier_cec_adap_unregister(cros_ec_cec->notify,
345 cros_ec_cec->adap);353 cros_ec_cec->adap);
346 cec_unregister_adapter(cros_ec_cec->adap);354 cec_unregister_adapter(cros_ec_cec->adap);
347
348 return 0;
349}355}
350 356
351static struct platform_driver cros_ec_cec_driver = {357static struct platform_driver cros_ec_cec_driver = {
352 .probe = cros_ec_cec_probe,358 .probe = cros_ec_cec_probe,
353 .remove = cros_ec_cec_remove,359 .remove_new = cros_ec_cec_remove,
354 .driver = {360 .driver = {
355 .name = DRV_NAME,361 .name = DRV_NAME,
356 .pm = &cros_ec_cec_pm_ops,362 .pm = &cros_ec_cec_pm_ops,
drivers/media/cec/platform/meson/ao-cec-g12a.c+2−4
@@ -744,7 +744,7 @@ out_probe_adapter: · 743 unmodified lines
744 return ret;744 return ret;
745}745}
746 746
747static int meson_ao_cec_g12a_remove(struct platform_device *pdev)747static void meson_ao_cec_g12a_remove(struct platform_device *pdev)
748{748{
749 struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev);749 struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev);
750 750
@@ -753,8 +753,6 @@ static int meson_ao_cec_g12a_remove(struct platform_device *pdev) · 2 unmodified lines
753 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);753 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
754 754
755 cec_unregister_adapter(ao_cec->adap);755 cec_unregister_adapter(ao_cec->adap);
756
757 return 0;
758}756}
759 757
760static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = {758static const struct meson_ao_cec_g12a_data ao_cec_g12a_data = {
@@ -780,7 +778,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match); · 19 unmodified lines
780 778
781static struct platform_driver meson_ao_cec_g12a_driver = {779static struct platform_driver meson_ao_cec_g12a_driver = {
782 .probe = meson_ao_cec_g12a_probe,780 .probe = meson_ao_cec_g12a_probe,
783 .remove = meson_ao_cec_g12a_remove,781 .remove_new = meson_ao_cec_g12a_remove,
784 .driver = {782 .driver = {
785 .name = "meson-ao-cec-g12a",783 .name = "meson-ao-cec-g12a",
786 .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),784 .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match),
drivers/media/cec/platform/meson/ao-cec.c+2−4
@@ -696,7 +696,7 @@ out_probe_adapter: · 695 unmodified lines
696 return ret;696 return ret;
697}697}
698 698
699static int meson_ao_cec_remove(struct platform_device *pdev)699static void meson_ao_cec_remove(struct platform_device *pdev)
700{700{
701 struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);701 struct meson_ao_cec_device *ao_cec = platform_get_drvdata(pdev);
702 702
@@ -704,8 +704,6 @@ static int meson_ao_cec_remove(struct platform_device *pdev) · 1 unmodified line
704 704
705 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);705 cec_notifier_cec_adap_unregister(ao_cec->notify, ao_cec->adap);
706 cec_unregister_adapter(ao_cec->adap);706 cec_unregister_adapter(ao_cec->adap);
707
708 return 0;
709}707}
710 708
711static const struct of_device_id meson_ao_cec_of_match[] = {709static const struct of_device_id meson_ao_cec_of_match[] = {
@@ -716,7 +714,7 @@ MODULE_DEVICE_TABLE(of, meson_ao_cec_of_match); · 4 unmodified lines
716 714
717static struct platform_driver meson_ao_cec_driver = {715static struct platform_driver meson_ao_cec_driver = {
718 .probe = meson_ao_cec_probe,716 .probe = meson_ao_cec_probe,
719 .remove = meson_ao_cec_remove,717 .remove_new = meson_ao_cec_remove,
720 .driver = {718 .driver = {
721 .name = "meson-ao-cec",719 .name = "meson-ao-cec",
722 .of_match_table = of_match_ptr(meson_ao_cec_of_match),720 .of_match_table = of_match_ptr(meson_ao_cec_of_match),
drivers/media/cec/platform/s5p/s5p_cec.c+2−3
@@ -249,14 +249,13 @@ err_delete_adapter: · 248 unmodified lines
249 return ret;249 return ret;
250}250}
251 251
252static int s5p_cec_remove(struct platform_device *pdev)252static void s5p_cec_remove(struct platform_device *pdev)
253{253{
254 struct s5p_cec_dev *cec = platform_get_drvdata(pdev);254 struct s5p_cec_dev *cec = platform_get_drvdata(pdev);
255 255
256 cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);256 cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
257 cec_unregister_adapter(cec->adap);257 cec_unregister_adapter(cec->adap);
258 pm_runtime_disable(&pdev->dev);258 pm_runtime_disable(&pdev->dev);
259 return 0;
260}259}
261 260
262static int __maybe_unused s5p_cec_runtime_suspend(struct device *dev)261static int __maybe_unused s5p_cec_runtime_suspend(struct device *dev)
@@ -295,7 +294,7 @@ MODULE_DEVICE_TABLE(of, s5p_cec_match); · 32 unmodified lines
295 294
296static struct platform_driver s5p_cec_pdrv = {295static struct platform_driver s5p_cec_pdrv = {
297 .probe = s5p_cec_probe,296 .probe = s5p_cec_probe,
298 .remove = s5p_cec_remove,297 .remove_new = s5p_cec_remove,
299 .driver = {298 .driver = {
300 .name = CEC_NAME,299 .name = CEC_NAME,
301 .of_match_table = s5p_cec_match,300 .of_match_table = s5p_cec_match,
drivers/media/cec/platform/seco/seco-cec.c+2−4
@@ -668,7 +668,7 @@ err: · 667 unmodified lines
668 return ret;668 return ret;
669}669}
670 670
671static int secocec_remove(struct platform_device *pdev)671static void secocec_remove(struct platform_device *pdev)
672{672{
673 struct secocec_data *secocec = platform_get_drvdata(pdev);673 struct secocec_data *secocec = platform_get_drvdata(pdev);
674 u16 val;674 u16 val;
@@ -686,8 +686,6 @@ static int secocec_remove(struct platform_device *pdev) · 11 unmodified lines
686 release_region(BRA_SMB_BASE_ADDR, 7);686 release_region(BRA_SMB_BASE_ADDR, 7);
687 687
688 dev_dbg(&pdev->dev, "CEC device removed\n");688 dev_dbg(&pdev->dev, "CEC device removed\n");
689
690 return 0;
691}689}
692 690
693#ifdef CONFIG_PM_SLEEP691#ifdef CONFIG_PM_SLEEP
@@ -780,7 +778,7 @@ static struct platform_driver secocec_driver = { · 86 unmodified lines
780 .pm = SECOCEC_PM_OPS,778 .pm = SECOCEC_PM_OPS,
781 },779 },
782 .probe = secocec_probe,780 .probe = secocec_probe,
783 .remove = secocec_remove,781 .remove_new = secocec_remove,
784};782};
785 783
786module_platform_driver(secocec_driver);784module_platform_driver(secocec_driver);
drivers/media/cec/platform/sti/stih-cec.c+2−4
@@ -364,14 +364,12 @@ err_delete_adapter: · 363 unmodified lines
364 return ret;364 return ret;
365}365}
366 366
367static int stih_cec_remove(struct platform_device *pdev)367static void stih_cec_remove(struct platform_device *pdev)
368{368{
369 struct stih_cec *cec = platform_get_drvdata(pdev);369 struct stih_cec *cec = platform_get_drvdata(pdev);
370 370
371 cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);371 cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
372 cec_unregister_adapter(cec->adap);372 cec_unregister_adapter(cec->adap);
373
374 return 0;
375}373}
376 374
377static const struct of_device_id stih_cec_match[] = {375static const struct of_device_id stih_cec_match[] = {
@@ -384,7 +382,7 @@ MODULE_DEVICE_TABLE(of, stih_cec_match); · 6 unmodified lines
384 382
385static struct platform_driver stih_cec_pdrv = {383static struct platform_driver stih_cec_pdrv = {
386 .probe = stih_cec_probe,384 .probe = stih_cec_probe,
387 .remove = stih_cec_remove,385 .remove_new = stih_cec_remove,
388 .driver = {386 .driver = {
389 .name = CEC_NAME,387 .name = CEC_NAME,
390 .of_match_table = stih_cec_match,388 .of_match_table = stih_cec_match,
drivers/media/cec/platform/stm32/stm32-cec.c+2−4
@@ -344,7 +344,7 @@ err_unprepare_cec_clk: · 343 unmodified lines
344 return ret;344 return ret;
345}345}
346 346
347static int stm32_cec_remove(struct platform_device *pdev)347static void stm32_cec_remove(struct platform_device *pdev)
348{348{
349 struct stm32_cec *cec = platform_get_drvdata(pdev);349 struct stm32_cec *cec = platform_get_drvdata(pdev);
350 350
@@ -352,8 +352,6 @@ static int stm32_cec_remove(struct platform_device *pdev) · 1 unmodified line
352 clk_unprepare(cec->clk_hdmi_cec);352 clk_unprepare(cec->clk_hdmi_cec);
353 353
354 cec_unregister_adapter(cec->adap);354 cec_unregister_adapter(cec->adap);
355
356 return 0;
357}355}
358 356
359static const struct of_device_id stm32_cec_of_match[] = {357static const struct of_device_id stm32_cec_of_match[] = {
@@ -364,7 +362,7 @@ MODULE_DEVICE_TABLE(of, stm32_cec_of_match); · 4 unmodified lines
364 362
365static struct platform_driver stm32_cec_driver = {363static struct platform_driver stm32_cec_driver = {
366 .probe = stm32_cec_probe,364 .probe = stm32_cec_probe,
367 .remove = stm32_cec_remove,365 .remove_new = stm32_cec_remove,
368 .driver = {366 .driver = {
369 .name = CEC_NAME,367 .name = CEC_NAME,
370 .of_match_table = stm32_cec_of_match,368 .of_match_table = stm32_cec_of_match,
drivers/media/cec/platform/tegra/tegra_cec.c+2−4
@@ -421,7 +421,7 @@ err_clk: · 420 unmodified lines
421 return ret;421 return ret;
422}422}
423 423
424static int tegra_cec_remove(struct platform_device *pdev)424static void tegra_cec_remove(struct platform_device *pdev)
425{425{
426 struct tegra_cec *cec = platform_get_drvdata(pdev);426 struct tegra_cec *cec = platform_get_drvdata(pdev);
427 427
@@ -429,8 +429,6 @@ static int tegra_cec_remove(struct platform_device *pdev) · 1 unmodified line
429 429
430 cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);430 cec_notifier_cec_adap_unregister(cec->notifier, cec->adap);
431 cec_unregister_adapter(cec->adap);431 cec_unregister_adapter(cec->adap);
432
433 return 0;
434}432}
435 433
436#ifdef CONFIG_PM434#ifdef CONFIG_PM
@@ -467,7 +465,7 @@ static struct platform_driver tegra_cec_driver = { · 30 unmodified lines
467 .of_match_table = of_match_ptr(tegra_cec_of_match),465 .of_match_table = of_match_ptr(tegra_cec_of_match),
468 },466 },
469 .probe = tegra_cec_probe,467 .probe = tegra_cec_probe,
470 .remove = tegra_cec_remove,468 .remove_new = tegra_cec_remove,
471 469
472#ifdef CONFIG_PM470#ifdef CONFIG_PM
473 .suspend = tegra_cec_suspend,471 .suspend = tegra_cec_suspend,
drivers/media/common/btcx-risc.h+0−29
@@ -1,29 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 */
4struct btcx_riscmem {
5 unsigned int size;
6 __le32 *cpu;
7 __le32 *jmp;
8 dma_addr_t dma;
9};
10
11struct btcx_skiplist {
12 int start;
13 int end;
14};
15
16int btcx_riscmem_alloc(struct pci_dev *pci,
17 struct btcx_riscmem *risc,
18 unsigned int size);
19void btcx_riscmem_free(struct pci_dev *pci,
20 struct btcx_riscmem *risc);
21
22int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
23 struct v4l2_clip *clips, unsigned int n);
24int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
25 unsigned int n, int mask);
26void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
27void btcx_calc_skips(int line, int width, int *maxy,
28 struct btcx_skiplist *skips, unsigned int *nskips,
29 const struct v4l2_clip *clips, unsigned int nclips);
drivers/media/common/saa7146/Kconfig+1−1
@@ -6,5 +6,5 @@ config VIDEO_SAA7146 · 5 unmodified lines
6config VIDEO_SAA7146_VV6config VIDEO_SAA7146_VV
7 tristate7 tristate
8 depends on VIDEO_DEV8 depends on VIDEO_DEV
9 select VIDEOBUF_DMA_SG9 select VIDEOBUF2_DMA_SG
10 select VIDEO_SAA714610 select VIDEO_SAA7146
drivers/media/common/saa7146/saa7146_core.c+14−26
@@ -37,7 +37,8 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) · 36 unmodified lines
37{37{
38 u32 value = 0;38 u32 value = 0;
39 39
40 BUG_ON(port > 3);40 if (WARN_ON(port > 3))
41 return;
41 42
42 value = saa7146_read(dev, GPIO_CTRL);43 value = saa7146_read(dev, GPIO_CTRL);
43 value &= ~(0xff << (8*port));44 value &= ~(0xff << (8*port));
@@ -148,7 +149,8 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) · 104 unmodified lines
148 pg = vmalloc_to_page(virt);149 pg = vmalloc_to_page(virt);
149 if (NULL == pg)150 if (NULL == pg)
150 goto err;151 goto err;
151 BUG_ON(PageHighMem(pg));152 if (WARN_ON(PageHighMem(pg)))
153 return NULL;
152 sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);154 sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
153 }155 }
154 return sglist;156 return sglist;
@@ -233,46 +235,32 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) · 78 unmodified lines
233}235}
234 236
235int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,237int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
236 struct scatterlist *list, int sglen )238 struct scatterlist *list, int sglen)
237{239{
240 struct sg_dma_page_iter dma_iter;
238 __le32 *ptr, fill;241 __le32 *ptr, fill;
239 int nr_pages = 0;242 int nr_pages = 0;
240 int i,p;243 int i;
241 244
242 BUG_ON(0 == sglen);245 if (WARN_ON(!sglen) ||
243 BUG_ON(list->offset > PAGE_SIZE);246 WARN_ON(list->offset > PAGE_SIZE))
247 return -EIO;
244 248
245 /* if we have a user buffer, the first page may not be249 /* if we have a user buffer, the first page may not be
246 aligned to a page boundary. */250 aligned to a page boundary. */
247 pt->offset = list->offset;251 pt->offset = list->offset;
248 252
249 ptr = pt->cpu;253 ptr = pt->cpu;
250 for (i = 0; i < sglen; i++, list++) {254 for_each_sg_dma_page(list, &dma_iter, sglen, 0) {
251/*255 *ptr++ = cpu_to_le32(sg_page_iter_dma_address(&dma_iter));
252 pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",256 nr_pages++;
253 i, sg_dma_address(list), sg_dma_len(list),
254 list->offset);
255*/
256 for (p = 0; p * 4096 < sg_dma_len(list); p++, ptr++) {
257 *ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
258 nr_pages++;
259 }
260 }257 }
261 258
262 259
263 /* safety; fill the page table up with the last valid page */260 /* safety; fill the page table up with the last valid page */
264 fill = *(ptr-1);261 fill = *(ptr-1);
265 for(i=nr_pages;i<1024;i++) {262 for (i = nr_pages; i < 1024; i++)
266 *ptr++ = fill;263 *ptr++ = fill;
267 }
268
269/*
270 ptr = pt->cpu;
271 pr_debug("offset: %d\n", pt->offset);
272 for(i=0;i<5;i++) {
273 pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
274 }
275*/
276 return 0;264 return 0;
277}265}
278 266
drivers/media/common/saa7146/saa7146_fops.c+75−298
@@ -7,12 +7,11 @@ · 6 unmodified lines
7/****************************************************************************/7/****************************************************************************/
8/* resource management functions, shamelessly stolen from saa7134 driver */8/* resource management functions, shamelessly stolen from saa7134 driver */
9 9
10int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)10int saa7146_res_get(struct saa7146_dev *dev, unsigned int bit)
11{11{
12 struct saa7146_dev *dev = fh->dev;
13 struct saa7146_vv *vv = dev->vv_data;12 struct saa7146_vv *vv = dev->vv_data;
14 13
15 if (fh->resources & bit) {14 if (vv->resources & bit) {
16 DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",15 DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
17 bit, vv->resources);16 bit, vv->resources);
18 /* have it already allocated */17 /* have it already allocated */
@@ -27,41 +26,22 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) · 8 unmodified lines
27 return 0;26 return 0;
28 }27 }
29 /* it's free, grab it */28 /* it's free, grab it */
30 fh->resources |= bit;
31 vv->resources |= bit;29 vv->resources |= bit;
32 DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);30 DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
33 return 1;31 return 1;
34}32}
35 33
36void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)34void saa7146_res_free(struct saa7146_dev *dev, unsigned int bits)
37{35{
38 struct saa7146_dev *dev = fh->dev;
39 struct saa7146_vv *vv = dev->vv_data;36 struct saa7146_vv *vv = dev->vv_data;
40 37
41 BUG_ON((fh->resources & bits) != bits);38 WARN_ON((vv->resources & bits) != bits);
42 39
43 fh->resources &= ~bits;
44 vv->resources &= ~bits;40 vv->resources &= ~bits;
45 DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);41 DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
46}42}
47 43
48 44
49/********************************************************************************/
50/* common dma functions */
51
52void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
53 struct saa7146_buf *buf)
54{
55 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
56 DEB_EE("dev:%p, buf:%p\n", dev, buf);
57
58 videobuf_waiton(q, &buf->vb, 0, 0);
59 videobuf_dma_unmap(q->dev, dma);
60 videobuf_dma_free(dma);
61 buf->vb.state = VIDEOBUF_NEEDS_INIT;
62}
63
64
65/********************************************************************************/45/********************************************************************************/
66/* common buffer functions */46/* common buffer functions */
67 47
@@ -72,15 +52,15 @@ int saa7146_buffer_queue(struct saa7146_dev *dev, · 4 unmodified lines
72 assert_spin_locked(&dev->slock);52 assert_spin_locked(&dev->slock);
73 DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);53 DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
74 54
75 BUG_ON(!q);55 if (WARN_ON(!q))
56 return -EIO;
76 57
77 if (NULL == q->curr) {58 if (NULL == q->curr) {
78 q->curr = buf;59 q->curr = buf;
79 DEB_D("immediately activating buffer %p\n", buf);60 DEB_D("immediately activating buffer %p\n", buf);
80 buf->activate(dev,buf,NULL);61 buf->activate(dev,buf,NULL);
81 } else {62 } else {
82 list_add_tail(&buf->vb.queue,&q->queue);63 list_add_tail(&buf->list, &q->queue);
83 buf->vb.state = VIDEOBUF_QUEUED;
84 DEB_D("adding buffer %p to queue. (active buffer present)\n",64 DEB_D("adding buffer %p to queue. (active buffer present)\n",
85 buf);65 buf);
86 }66 }
@@ -91,21 +71,31 @@ void saa7146_buffer_finish(struct saa7146_dev *dev, · 4 unmodified lines
91 struct saa7146_dmaqueue *q,71 struct saa7146_dmaqueue *q,
92 int state)72 int state)
93{73{
74 struct saa7146_vv *vv = dev->vv_data;
75 struct saa7146_buf *buf = q->curr;
76
94 assert_spin_locked(&dev->slock);77 assert_spin_locked(&dev->slock);
95 DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);78 DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
96 DEB_EE("q->curr:%p\n", q->curr);79 DEB_EE("q->curr:%p\n", q->curr);
97 80
98 /* finish current buffer */81 /* finish current buffer */
99 if (NULL == q->curr) {82 if (!buf) {
100 DEB_D("aiii. no current buffer\n");83 DEB_D("aiii. no current buffer\n");
101 return;84 return;
102 }85 }
103 86
104 q->curr->vb.state = state;
105 q->curr->vb.ts = ktime_get_ns();
106 wake_up(&q->curr->vb.done);
107
108 q->curr = NULL;87 q->curr = NULL;
88 buf->vb.vb2_buf.timestamp = ktime_get_ns();
89 if (vv->video_fmt.field == V4L2_FIELD_ALTERNATE)
90 buf->vb.field = vv->last_field;
91 else if (vv->video_fmt.field == V4L2_FIELD_ANY)
92 buf->vb.field = (vv->video_fmt.height > vv->standard->v_max_out / 2)
93 ? V4L2_FIELD_INTERLACED
94 : V4L2_FIELD_BOTTOM;
95 else
96 buf->vb.field = vv->video_fmt.field;
97 buf->vb.sequence = vv->seqnr++;
98 vb2_buffer_done(&buf->vb.vb2_buf, state);
109}99}
110 100
111void saa7146_buffer_next(struct saa7146_dev *dev,101void saa7146_buffer_next(struct saa7146_dev *dev,
@@ -113,17 +103,18 @@ void saa7146_buffer_next(struct saa7146_dev *dev, · 1 unmodified line
113{103{
114 struct saa7146_buf *buf,*next = NULL;104 struct saa7146_buf *buf,*next = NULL;
115 105
116 BUG_ON(!q);106 if (WARN_ON(!q))
107 return;
117 108
118 DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);109 DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
119 110
120 assert_spin_locked(&dev->slock);111 assert_spin_locked(&dev->slock);
121 if (!list_empty(&q->queue)) {112 if (!list_empty(&q->queue)) {
122 /* activate next one from queue */113 /* activate next one from queue */
123 buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue);114 buf = list_entry(q->queue.next, struct saa7146_buf, list);
124 list_del(&buf->vb.queue);115 list_del(&buf->list);
125 if (!list_empty(&q->queue))116 if (!list_empty(&q->queue))
126 next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);117 next = list_entry(q->queue.next, struct saa7146_buf, list);
127 q->curr = buf;118 q->curr = buf;
128 DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",119 DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
129 buf, q->queue.prev, q->queue.next);120 buf, q->queue.prev, q->queue.next);
@@ -171,7 +162,7 @@ void saa7146_buffer_timeout(struct timer_list *t) · 41 unmodified lines
171 spin_lock_irqsave(&dev->slock,flags);162 spin_lock_irqsave(&dev->slock,flags);
172 if (q->curr) {163 if (q->curr) {
173 DEB_D("timeout on %p\n", q->curr);164 DEB_D("timeout on %p\n", q->curr);
174 saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);165 saa7146_buffer_finish(dev, q, VB2_BUF_STATE_ERROR);
175 }166 }
176 167
177 /* we don't restart the transfer here like other drivers do. when168 /* we don't restart the transfer here like other drivers do. when
@@ -180,256 +171,39 @@ void saa7146_buffer_timeout(struct timer_list *t) · 2 unmodified lines
180 we mess up our capture logic. if a timeout occurs on another buffer,171 we mess up our capture logic. if a timeout occurs on another buffer,
181 then something is seriously broken before, so no need to buffer the172 then something is seriously broken before, so no need to buffer the
182 next capture IMHO... */173 next capture IMHO... */
183/*174
184 saa7146_buffer_next(dev,q);175 saa7146_buffer_next(dev, q, 0);
185*/176
186 spin_unlock_irqrestore(&dev->slock,flags);177 spin_unlock_irqrestore(&dev->slock,flags);
187}178}
188 179
189/********************************************************************************/180/********************************************************************************/
190/* file operations */181/* file operations */
191 182
192static int fops_open(struct file *file)183static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
193{184{
194 struct video_device *vdev = video_devdata(file);185 struct video_device *vdev = video_devdata(file);
195 struct saa7146_dev *dev = video_drvdata(file);186 struct saa7146_dev *dev = video_drvdata(file);
196 struct saa7146_fh *fh = NULL;187 int ret;
197 int result = 0;
198
199 DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
200
201 if (mutex_lock_interruptible(vdev->lock))
202 return -ERESTARTSYS;
203
204 DEB_D("using: %p\n", dev);
205
206 /* check if an extension is registered */
207 if( NULL == dev->ext ) {
208 DEB_S("no extension registered for this device\n");
209 result = -ENODEV;
210 goto out;
211 }
212
213 /* allocate per open data */
214 fh = kzalloc(sizeof(*fh),GFP_KERNEL);
215 if (NULL == fh) {
216 DEB_S("cannot allocate memory for per open data\n");
217 result = -ENOMEM;
218 goto out;
219 }
220
221 v4l2_fh_init(&fh->fh, vdev);
222
223 file->private_data = &fh->fh;
224 fh->dev = dev;
225
226 if (vdev->vfl_type == VFL_TYPE_VBI) {
227 DEB_S("initializing vbi...\n");
228 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
229 result = saa7146_vbi_uops.open(dev,file);
230 if (dev->ext_vv_data->vbi_fops.open)
231 dev->ext_vv_data->vbi_fops.open(file);
232 } else {
233 DEB_S("initializing video...\n");
234 result = saa7146_video_uops.open(dev,file);
235 }
236
237 if (0 != result) {
238 goto out;
239 }
240
241 if( 0 == try_module_get(dev->ext->module)) {
242 result = -EINVAL;
243 goto out;
244 }
245
246 result = 0;
247 v4l2_fh_add(&fh->fh);
248out:
249 if (fh && result != 0) {
250 kfree(fh);
251 file->private_data = NULL;
252 }
253 mutex_unlock(vdev->lock);
254 return result;
255}
256
257static int fops_release(struct file *file)
258{
259 struct video_device *vdev = video_devdata(file);
260 struct saa7146_fh *fh = file->private_data;
261 struct saa7146_dev *dev = fh->dev;
262
263 DEB_EE("file:%p\n", file);
264
265 mutex_lock(vdev->lock);
266
267 if (vdev->vfl_type == VFL_TYPE_VBI) {
268 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
269 saa7146_vbi_uops.release(dev,file);
270 if (dev->ext_vv_data->vbi_fops.release)
271 dev->ext_vv_data->vbi_fops.release(file);
272 } else {
273 saa7146_video_uops.release(dev,file);
274 }
275
276 v4l2_fh_del(&fh->fh);
277 v4l2_fh_exit(&fh->fh);
278 module_put(dev->ext->module);
279 file->private_data = NULL;
280 kfree(fh);
281
282 mutex_unlock(vdev->lock);
283
284 return 0;
285}
286
287static int fops_mmap(struct file *file, struct vm_area_struct * vma)
288{
289 struct video_device *vdev = video_devdata(file);
290 struct saa7146_fh *fh = file->private_data;
291 struct videobuf_queue *q;
292 int res;
293
294 switch (vdev->vfl_type) {
295 case VFL_TYPE_VIDEO: {
296 DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
297 file, vma);
298 q = &fh->video_q;
299 break;
300 }
301 case VFL_TYPE_VBI: {
302 DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
303 file, vma);
304 if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
305 return -ENODEV;
306 q = &fh->vbi_q;
307 break;
308 }
309 default:
310 BUG();
311 }
312 188
189 if (vdev->vfl_type != VFL_TYPE_VBI || !dev->ext_vv_data->vbi_fops.write)
190 return -EINVAL;
313 if (mutex_lock_interruptible(vdev->lock))191 if (mutex_lock_interruptible(vdev->lock))
314 return -ERESTARTSYS;192 return -ERESTARTSYS;
315 res = videobuf_mmap_mapper(q, vma);193 ret = dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
316 mutex_unlock(vdev->lock);194 mutex_unlock(vdev->lock);
317 return res;195 return ret;
318}
319
320static __poll_t __fops_poll(struct file *file, struct poll_table_struct *wait)
321{
322 struct video_device *vdev = video_devdata(file);
323 struct saa7146_fh *fh = file->private_data;
324 struct videobuf_buffer *buf = NULL;
325 struct videobuf_queue *q;
326 __poll_t res = v4l2_ctrl_poll(file, wait);
327
328 DEB_EE("file:%p, poll:%p\n", file, wait);
329
330 if (vdev->vfl_type == VFL_TYPE_VBI) {
331 if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
332 return res | EPOLLOUT | EPOLLWRNORM;
333 if( 0 == fh->vbi_q.streaming )
334 return res | videobuf_poll_stream(file, &fh->vbi_q, wait);
335 q = &fh->vbi_q;
336 } else {
337 DEB_D("using video queue\n");
338 q = &fh->video_q;
339 }
340
341 if (!list_empty(&q->stream))
342 buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
343
344 if (!buf) {
345 DEB_D("buf == NULL!\n");
346 return res | EPOLLERR;
347 }
348
349 poll_wait(file, &buf->done, wait);
350 if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
351 DEB_D("poll succeeded!\n");
352 return res | EPOLLIN | EPOLLRDNORM;
353 }
354
355 DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
356 return res;
357}
358
359static __poll_t fops_poll(struct file *file, struct poll_table_struct *wait)
360{
361 struct video_device *vdev = video_devdata(file);
362 __poll_t res;
363
364 mutex_lock(vdev->lock);
365 res = __fops_poll(file, wait);
366 mutex_unlock(vdev->lock);
367 return res;
368}
369
370static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
371{
372 struct video_device *vdev = video_devdata(file);
373 struct saa7146_fh *fh = file->private_data;
374 int ret;
375
376 switch (vdev->vfl_type) {
377 case VFL_TYPE_VIDEO:
378/*
379 DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
380 file, data, (unsigned long)count);
381*/
382 return saa7146_video_uops.read(file,data,count,ppos);
383 case VFL_TYPE_VBI:
384/*
385 DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
386 file, data, (unsigned long)count);
387*/
388 if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) {
389 if (mutex_lock_interruptible(vdev->lock))
390 return -ERESTARTSYS;
391 ret = saa7146_vbi_uops.read(file, data, count, ppos);
392 mutex_unlock(vdev->lock);
393 return ret;
394 }
395 return -EINVAL;
396 default:
397 BUG();
398 }
399}
400
401static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
402{
403 struct video_device *vdev = video_devdata(file);
404 struct saa7146_fh *fh = file->private_data;
405 int ret;
406
407 switch (vdev->vfl_type) {
408 case VFL_TYPE_VIDEO:
409 return -EINVAL;
410 case VFL_TYPE_VBI:
411 if (fh->dev->ext_vv_data->vbi_fops.write) {
412 if (mutex_lock_interruptible(vdev->lock))
413 return -ERESTARTSYS;
414 ret = fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
415 mutex_unlock(vdev->lock);
416 return ret;
417 }
418 return -EINVAL;
419 default:
420 BUG();
421 }
422}196}
423 197
424static const struct v4l2_file_operations video_fops =198static const struct v4l2_file_operations video_fops =
425{199{
426 .owner = THIS_MODULE,200 .owner = THIS_MODULE,
427 .open = fops_open,201 .open = v4l2_fh_open,
428 .release = fops_release,202 .release = vb2_fop_release,
429 .read = fops_read,203 .read = vb2_fop_read,
430 .write = fops_write,204 .write = fops_write,
431 .poll = fops_poll,205 .poll = vb2_fop_poll,
432 .mmap = fops_mmap,206 .mmap = vb2_fop_mmap,
433 .unlocked_ioctl = video_ioctl2,207 .unlocked_ioctl = video_ioctl2,
434};208};
435 209
@@ -516,33 +290,15 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) · 80 unmodified lines
516 configuration data) */290 configuration data) */
517 dev->ext_vv_data = ext_vv;291 dev->ext_vv_data = ext_vv;
518 292
519 vv->d_clipping.cpu_addr =
520 dma_alloc_coherent(&dev->pci->dev, SAA7146_CLIPPING_MEM,
521 &vv->d_clipping.dma_handle, GFP_KERNEL);
522 if( NULL == vv->d_clipping.cpu_addr ) {
523 ERR("out of memory. aborting.\n");
524 kfree(vv);
525 v4l2_ctrl_handler_free(hdl);
526 v4l2_device_unregister(&dev->v4l2_dev);
527 return -ENOMEM;
528 }
529
530 saa7146_video_uops.init(dev,vv);293 saa7146_video_uops.init(dev,vv);
531 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)294 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
532 saa7146_vbi_uops.init(dev,vv);295 saa7146_vbi_uops.init(dev,vv);
533 296
534 vv->ov_fb.fmt.width = vv->standard->h_max_out;
535 vv->ov_fb.fmt.height = vv->standard->v_max_out;
536 vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
537 vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width;
538 vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height;
539 vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB;
540
541 fmt = &vv->video_fmt;297 fmt = &vv->video_fmt;
542 fmt->width = 384;298 fmt->width = 384;
543 fmt->height = 288;299 fmt->height = 288;
544 fmt->pixelformat = V4L2_PIX_FMT_BGR24;300 fmt->pixelformat = V4L2_PIX_FMT_BGR24;
545 fmt->field = V4L2_FIELD_ANY;301 fmt->field = V4L2_FIELD_INTERLACED;
546 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;302 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
547 fmt->bytesperline = 3 * fmt->width;303 fmt->bytesperline = 3 * fmt->width;
548 fmt->sizeimage = fmt->bytesperline * fmt->height;304 fmt->sizeimage = fmt->bytesperline * fmt->height;
@@ -561,8 +317,6 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) · 12 unmodified lines
561 317
562 timer_setup(&vv->vbi_read_timeout, NULL, 0);318 timer_setup(&vv->vbi_read_timeout, NULL, 0);
563 319
564 vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING;
565 vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY;
566 dev->vv_data = vv;320 dev->vv_data = vv;
567 dev->vv_callback = &vv_callback;321 dev->vv_callback = &vv_callback;
568 322
@@ -577,8 +331,6 @@ int saa7146_vv_release(struct saa7146_dev* dev) · 8 unmodified lines
577 DEB_EE("dev:%p\n", dev);331 DEB_EE("dev:%p\n", dev);
578 332
579 v4l2_device_unregister(&dev->v4l2_dev);333 v4l2_device_unregister(&dev->v4l2_dev);
580 dma_free_coherent(&dev->pci->dev, SAA7146_CLIPPING_MEM,
581 vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
582 v4l2_ctrl_handler_free(&dev->ctrl_handler);334 v4l2_ctrl_handler_free(&dev->ctrl_handler);
583 kfree(vv);335 kfree(vv);
584 dev->vv_data = NULL;336 dev->vv_data = NULL;
@@ -591,16 +343,20 @@ EXPORT_SYMBOL_GPL(saa7146_vv_release); · 6 unmodified lines
591int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,343int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,
592 char *name, int type)344 char *name, int type)
593{345{
346 struct vb2_queue *q;
594 int err;347 int err;
595 int i;348 int i;
596 349
597 DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);350 DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
598 351
599 vfd->fops = &video_fops;352 vfd->fops = &video_fops;
600 if (type == VFL_TYPE_VIDEO)353 if (type == VFL_TYPE_VIDEO) {
601 vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;354 vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;
602 else355 q = &dev->vv_data->video_dmaq.q;
356 } else {
603 vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;357 vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
358 q = &dev->vv_data->vbi_dmaq.q;
359 }
604 vfd->release = video_device_release_empty;360 vfd->release = video_device_release_empty;
605 vfd->lock = &dev->v4l2_lock;361 vfd->lock = &dev->v4l2_lock;
606 vfd->v4l2_dev = &dev->v4l2_dev;362 vfd->v4l2_dev = &dev->v4l2_dev;
@@ -608,15 +364,36 @@ int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev, · 1 unmodified line
608 for (i = 0; i < dev->ext_vv_data->num_stds; i++)364 for (i = 0; i < dev->ext_vv_data->num_stds; i++)
609 vfd->tvnorms |= dev->ext_vv_data->stds[i].id;365 vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
610 strscpy(vfd->name, name, sizeof(vfd->name));366 strscpy(vfd->name, name, sizeof(vfd->name));
611 vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |367 vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE |
612 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;368 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
613 vfd->device_caps |= dev->ext_vv_data->capabilities;369 vfd->device_caps |= dev->ext_vv_data->capabilities;
614 if (type == VFL_TYPE_VIDEO)370 if (type == VFL_TYPE_VIDEO) {
615 vfd->device_caps &=371 vfd->device_caps &=
616 ~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);372 ~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);
617 else373 } else if (vfd->device_caps & V4L2_CAP_SLICED_VBI_OUTPUT) {
618 vfd->device_caps &=374 vfd->vfl_dir = VFL_DIR_TX;
619 ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO);375 vfd->device_caps &= ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
376 V4L2_CAP_AUDIO | V4L2_CAP_TUNER);
377 } else {
378 vfd->device_caps &= ~V4L2_CAP_VIDEO_CAPTURE;
379 }
380
381 q->type = type == VFL_TYPE_VIDEO ? V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VBI_CAPTURE;
382 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
383 q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
384 q->ops = type == VFL_TYPE_VIDEO ? &video_qops : &vbi_qops;
385 q->mem_ops = &vb2_dma_sg_memops;
386 q->drv_priv = dev;
387 q->gfp_flags = __GFP_DMA32;
388 q->buf_struct_size = sizeof(struct saa7146_buf);
389 q->lock = &dev->v4l2_lock;
390 q->min_buffers_needed = 2;
391 q->dev = &dev->pci->dev;
392 err = vb2_queue_init(q);
393 if (err)
394 return err;
395 vfd->queue = q;
396
620 video_set_drvdata(vfd, dev);397 video_set_drvdata(vfd, dev);
621 398
622 err = video_register_device(vfd, type, -1);399 err = video_register_device(vfd, type, -1);
drivers/media/common/saa7146/saa7146_hlp.c+40−315
@@ -306,221 +306,6 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field · 305 unmodified lines
306}306}
307 307
308/* simple bubble-sort algorithm with duplicate elimination */308/* simple bubble-sort algorithm with duplicate elimination */
309static int sort_and_eliminate(u32* values, int* count)
310{
311 int low = 0, high = 0, top = 0;
312 int cur = 0, next = 0;
313
314 /* sanity checks */
315 if( (0 > *count) || (NULL == values) ) {
316 return -EINVAL;
317 }
318
319 /* bubble sort the first @count items of the array @values */
320 for( top = *count; top > 0; top--) {
321 for( low = 0, high = 1; high < top; low++, high++) {
322 if( values[low] > values[high] )
323 swap(values[low], values[high]);
324 }
325 }
326
327 /* remove duplicate items */
328 for( cur = 0, next = 1; next < *count; next++) {
329 if( values[cur] != values[next])
330 values[++cur] = values[next];
331 }
332
333 *count = cur + 1;
334
335 return 0;
336}
337
338static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh,
339 struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
340{
341 struct saa7146_vv *vv = dev->vv_data;
342 __le32 *clipping = vv->d_clipping.cpu_addr;
343
344 int width = vv->ov.win.w.width;
345 int height = vv->ov.win.w.height;
346 int clipcount = vv->ov.nclips;
347
348 u32 line_list[32];
349 u32 pixel_list[32];
350 int numdwords = 0;
351
352 int i = 0, j = 0;
353 int cnt_line = 0, cnt_pixel = 0;
354
355 int x[32], y[32], w[32], h[32];
356
357 /* clear out memory */
358 memset(&line_list[0], 0x00, sizeof(u32)*32);
359 memset(&pixel_list[0], 0x00, sizeof(u32)*32);
360 memset(clipping, 0x00, SAA7146_CLIPPING_MEM);
361
362 /* fill the line and pixel-lists */
363 for(i = 0; i < clipcount; i++) {
364 int l = 0, r = 0, t = 0, b = 0;
365
366 x[i] = vv->ov.clips[i].c.left;
367 y[i] = vv->ov.clips[i].c.top;
368 w[i] = vv->ov.clips[i].c.width;
369 h[i] = vv->ov.clips[i].c.height;
370
371 if( w[i] < 0) {
372 x[i] += w[i]; w[i] = -w[i];
373 }
374 if( h[i] < 0) {
375 y[i] += h[i]; h[i] = -h[i];
376 }
377 if( x[i] < 0) {
378 w[i] += x[i]; x[i] = 0;
379 }
380 if( y[i] < 0) {
381 h[i] += y[i]; y[i] = 0;
382 }
383 if( 0 != vv->vflip ) {
384 y[i] = height - y[i] - h[i];
385 }
386
387 l = x[i];
388 r = x[i]+w[i];
389 t = y[i];
390 b = y[i]+h[i];
391
392 /* insert left/right coordinates */
393 pixel_list[ 2*i ] = min_t(int, l, width);
394 pixel_list[(2*i)+1] = min_t(int, r, width);
395 /* insert top/bottom coordinates */
396 line_list[ 2*i ] = min_t(int, t, height);
397 line_list[(2*i)+1] = min_t(int, b, height);
398 }
399
400 /* sort and eliminate lists */
401 cnt_line = cnt_pixel = 2*clipcount;
402 sort_and_eliminate( &pixel_list[0], &cnt_pixel );
403 sort_and_eliminate( &line_list[0], &cnt_line );
404
405 /* calculate the number of used u32s */
406 numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2;
407 numdwords = max_t(int, 4, numdwords);
408 numdwords = min_t(int, 64, numdwords);
409
410 /* fill up cliptable */
411 for(i = 0; i < cnt_pixel; i++) {
412 clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16);
413 }
414 for(i = 0; i < cnt_line; i++) {
415 clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16);
416 }
417
418 /* fill up cliptable with the display infos */
419 for(j = 0; j < clipcount; j++) {
420
421 for(i = 0; i < cnt_pixel; i++) {
422
423 if( x[j] < 0)
424 x[j] = 0;
425
426 if( pixel_list[i] < (x[j] + w[j])) {
427
428 if ( pixel_list[i] >= x[j] ) {
429 clipping[2*i] |= cpu_to_le32(1 << j);
430 }
431 }
432 }
433 for(i = 0; i < cnt_line; i++) {
434
435 if( y[j] < 0)
436 y[j] = 0;
437
438 if( line_list[i] < (y[j] + h[j]) ) {
439
440 if( line_list[i] >= y[j] ) {
441 clipping[(2*i)+1] |= cpu_to_le32(1 << j);
442 }
443 }
444 }
445 }
446
447 /* adjust arbitration control register */
448 *arbtr_ctrl &= 0xffff00ff;
449 *arbtr_ctrl |= 0x00001c00;
450
451 vdma2->base_even = vv->d_clipping.dma_handle;
452 vdma2->base_odd = vv->d_clipping.dma_handle;
453 vdma2->prot_addr = vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords));
454 vdma2->base_page = 0x04;
455 vdma2->pitch = 0x00;
456 vdma2->num_line_byte = (0 << 16 | (sizeof(u32))*(numdwords-1) );
457
458 /* set clipping-mode. this depends on the field(s) used */
459 *clip_format &= 0xfffffff7;
460 if (V4L2_FIELD_HAS_BOTH(field)) {
461 *clip_format |= 0x00000008;
462 } else {
463 *clip_format |= 0x00000000;
464 }
465}
466
467/* disable clipping */
468static void saa7146_disable_clipping(struct saa7146_dev *dev)
469{
470 u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
471
472 /* mask out relevant bits (=lower word)*/
473 clip_format &= MASK_W1;
474
475 /* upload clipping-registers*/
476 saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
477 saa7146_write(dev, MC2, (MASK_05 | MASK_21));
478
479 /* disable video dma2 */
480 saa7146_write(dev, MC1, MASK_21);
481}
482
483static void saa7146_set_clipping_rect(struct saa7146_fh *fh)
484{
485 struct saa7146_dev *dev = fh->dev;
486 struct saa7146_vv *vv = dev->vv_data;
487 enum v4l2_field field = vv->ov.win.field;
488 struct saa7146_video_dma vdma2;
489 u32 clip_format;
490 u32 arbtr_ctrl;
491
492 /* check clipcount, disable clipping if clipcount == 0*/
493 if (vv->ov.nclips == 0) {
494 saa7146_disable_clipping(dev);
495 return;
496 }
497
498 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
499 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
500
501 calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field);
502
503 /* set clipping format */
504 clip_format &= 0xffff0008;
505 clip_format |= (SAA7146_CLIPPING_RECT << 4);
506
507 /* prepare video dma2 */
508 saa7146_write(dev, BASE_EVEN2, vdma2.base_even);
509 saa7146_write(dev, BASE_ODD2, vdma2.base_odd);
510 saa7146_write(dev, PROT_ADDR2, vdma2.prot_addr);
511 saa7146_write(dev, BASE_PAGE2, vdma2.base_page);
512 saa7146_write(dev, PITCH2, vdma2.pitch);
513 saa7146_write(dev, NUM_LINE_BYTE2, vdma2.num_line_byte);
514
515 /* prepare the rest */
516 saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
517 saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
518
519 /* upload clip_control-register, clipping-registers, enable video dma2 */
520 saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19));
521 saa7146_write(dev, MC1, (MASK_05 | MASK_21));
522}
523
524static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field)309static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field)
525{310{
526 struct saa7146_vv *vv = dev->vv_data;311 struct saa7146_vv *vv = dev->vv_data;
@@ -556,62 +341,6 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e · 29 unmodified lines
556 saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );341 saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );
557}342}
558 343
559/* calculate the new memory offsets for a desired position */
560static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
561{
562 struct saa7146_vv *vv = dev->vv_data;
563 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);
564
565 int b_depth = vv->ov_fmt->depth;
566 int b_bpl = vv->ov_fb.fmt.bytesperline;
567 /* The unsigned long cast is to remove a 64-bit compile warning since
568 it looks like a 64-bit address is cast to a 32-bit value, even
569 though the base pointer is really a 32-bit physical address that
570 goes into a 32-bit DMA register.
571 FIXME: might not work on some 64-bit platforms, but see the FIXME
572 in struct v4l2_framebuffer (videodev2.h) for that.
573 */
574 u32 base = (u32)(unsigned long)vv->ov_fb.base;
575
576 struct saa7146_video_dma vdma1;
577
578 /* calculate memory offsets for picture, look if we shall top-down-flip */
579 vdma1.pitch = 2*b_bpl;
580 if ( 0 == vv->vflip ) {
581 vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
582 vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2);
583 vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
584 }
585 else {
586 vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
587 vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2);
588 vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
589 }
590
591 if (V4L2_FIELD_HAS_BOTH(field)) {
592 } else if (field == V4L2_FIELD_ALTERNATE) {
593 /* fixme */
594 vdma1.base_odd = vdma1.prot_addr;
595 vdma1.pitch /= 2;
596 } else if (field == V4L2_FIELD_TOP) {
597 vdma1.base_odd = vdma1.prot_addr;
598 vdma1.pitch /= 2;
599 } else if (field == V4L2_FIELD_BOTTOM) {
600 vdma1.base_odd = vdma1.base_even;
601 vdma1.base_even = vdma1.prot_addr;
602 vdma1.pitch /= 2;
603 }
604
605 if ( 0 != vv->vflip ) {
606 vdma1.pitch *= -1;
607 }
608
609 vdma1.base_page = sfmt->swap;
610 vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
611
612 saa7146_write_out_dma(dev, 1, &vdma1);
613}
614
615static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette)344static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette)
616{345{
617 u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);346 u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
@@ -645,30 +374,6 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy · 27 unmodified lines
645}374}
646EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);375EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
647 376
648int saa7146_enable_overlay(struct saa7146_fh *fh)
649{
650 struct saa7146_dev *dev = fh->dev;
651 struct saa7146_vv *vv = dev->vv_data;
652
653 saa7146_set_window(dev, vv->ov.win.w.width, vv->ov.win.w.height, vv->ov.win.field);
654 saa7146_set_position(dev, vv->ov.win.w.left, vv->ov.win.w.top, vv->ov.win.w.height, vv->ov.win.field, vv->ov_fmt->pixelformat);
655 saa7146_set_output_format(dev, vv->ov_fmt->trans);
656 saa7146_set_clipping_rect(fh);
657
658 /* enable video dma1 */
659 saa7146_write(dev, MC1, (MASK_06 | MASK_22));
660 return 0;
661}
662
663void saa7146_disable_overlay(struct saa7146_fh *fh)
664{
665 struct saa7146_dev *dev = fh->dev;
666
667 /* disable clipping + video dma1 */
668 saa7146_disable_clipping(dev);
669 saa7146_write(dev, MC1, MASK_22);
670}
671
672void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)377void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)
673{378{
674 int where = 0;379 int where = 0;
@@ -702,14 +407,14 @@ void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_vi · 27 unmodified lines
702static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf)407static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf)
703{408{
704 struct saa7146_vv *vv = dev->vv_data;409 struct saa7146_vv *vv = dev->vv_data;
410 struct v4l2_pix_format *pix = &vv->video_fmt;
705 struct saa7146_video_dma vdma1;411 struct saa7146_video_dma vdma1;
412 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
706 413
707 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);414 int width = pix->width;
708 415 int height = pix->height;
709 int width = buf->fmt->width;416 int bytesperline = pix->bytesperline;
710 int height = buf->fmt->height;417 enum v4l2_field field = pix->field;
711 int bytesperline = buf->fmt->bytesperline;
712 enum v4l2_field field = buf->fmt->field;
713 418
714 int depth = sfmt->depth;419 int depth = sfmt->depth;
715 420
@@ -764,8 +469,9 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71 · 48 unmodified lines
764 469
765static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)470static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
766{471{
767 int height = buf->fmt->height;472 struct v4l2_pix_format *pix = &vv->video_fmt;
768 int width = buf->fmt->width;473 int height = pix->height;
474 int width = pix->width;
769 475
770 vdma2->pitch = width;476 vdma2->pitch = width;
771 vdma3->pitch = width;477 vdma3->pitch = width;
@@ -795,8 +501,9 @@ static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struc · 23 unmodified lines
795 501
796static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)502static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
797{503{
798 int height = buf->fmt->height;504 struct v4l2_pix_format *pix = &vv->video_fmt;
799 int width = buf->fmt->width;505 int height = pix->height;
506 int width = pix->width;
800 507
801 vdma2->pitch = width/2;508 vdma2->pitch = width/2;
802 vdma3->pitch = width/2;509 vdma3->pitch = width/2;
@@ -825,19 +532,20 @@ static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struc · 22 unmodified lines
825static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf)532static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf)
826{533{
827 struct saa7146_vv *vv = dev->vv_data;534 struct saa7146_vv *vv = dev->vv_data;
535 struct v4l2_pix_format *pix = &vv->video_fmt;
828 struct saa7146_video_dma vdma1;536 struct saa7146_video_dma vdma1;
829 struct saa7146_video_dma vdma2;537 struct saa7146_video_dma vdma2;
830 struct saa7146_video_dma vdma3;538 struct saa7146_video_dma vdma3;
539 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
831 540
832 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);541 int width = pix->width;
542 int height = pix->height;
543 enum v4l2_field field = pix->field;
833 544
834 int width = buf->fmt->width;545 if (WARN_ON(!buf->pt[0].dma) ||
835 int height = buf->fmt->height;546 WARN_ON(!buf->pt[1].dma) ||
836 enum v4l2_field field = buf->fmt->field;547 WARN_ON(!buf->pt[2].dma))
837 548 return -1;
838 BUG_ON(0 == buf->pt[0].dma);
839 BUG_ON(0 == buf->pt[1].dma);
840 BUG_ON(0 == buf->pt[2].dma);
841 549
842 DEB_CAP("[size=%dx%d,fields=%s]\n",550 DEB_CAP("[size=%dx%d,fields=%s]\n",
843 width, height, v4l2_field_names[field]);551 width, height, v4l2_field_names[field]);
@@ -994,10 +702,27 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar) · 150 unmodified lines
994 WRITE_RPS0(CMD_STOP);702 WRITE_RPS0(CMD_STOP);
995}703}
996 704
705/* disable clipping */
706static void saa7146_disable_clipping(struct saa7146_dev *dev)
707{
708 u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
709
710 /* mask out relevant bits (=lower word)*/
711 clip_format &= MASK_W1;
712
713 /* upload clipping-registers*/
714 saa7146_write(dev, CLIP_FORMAT_CTRL, clip_format);
715 saa7146_write(dev, MC2, (MASK_05 | MASK_21));
716
717 /* disable video dma2 */
718 saa7146_write(dev, MC1, MASK_21);
719}
720
997void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)721void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
998{722{
999 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
1000 struct saa7146_vv *vv = dev->vv_data;723 struct saa7146_vv *vv = dev->vv_data;
724 struct v4l2_pix_format *pix = &vv->video_fmt;
725 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
1001 u32 vdma1_prot_addr;726 u32 vdma1_prot_addr;
1002 727
1003 DEB_CAP("buf:%p, next:%p\n", buf, next);728 DEB_CAP("buf:%p, next:%p\n", buf, next);
@@ -1009,7 +734,7 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc · 5 unmodified lines
1009 saa7146_write(dev, MC2, MASK_27 );734 saa7146_write(dev, MC2, MASK_27 );
1010 }735 }
1011 736
1012 saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field);737 saa7146_set_window(dev, pix->width, pix->height, pix->field);
1013 saa7146_set_output_format(dev, sfmt->trans);738 saa7146_set_output_format(dev, sfmt->trans);
1014 saa7146_disable_clipping(dev);739 saa7146_disable_clipping(dev);
1015 740
drivers/media/common/saa7146/saa7146_vbi.c+118−169
@@ -207,7 +207,6 @@ static int buffer_activate(struct saa7146_dev *dev, · 206 unmodified lines
207 struct saa7146_buf *next)207 struct saa7146_buf *next)
208{208{
209 struct saa7146_vv *vv = dev->vv_data;209 struct saa7146_vv *vv = dev->vv_data;
210 buf->vb.state = VIDEOBUF_ACTIVE;
211 210
212 DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);211 DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
213 saa7146_set_vbi_capture(dev,buf,next);212 saa7146_set_vbi_capture(dev,buf,next);
@@ -216,114 +215,101 @@ static int buffer_activate(struct saa7146_dev *dev, · 2 unmodified lines
216 return 0;215 return 0;
217}216}
218 217
219static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field)218/* ------------------------------------------------------------------ */
220{
221 struct file *file = q->priv_data;
222 struct saa7146_fh *fh = file->private_data;
223 struct saa7146_dev *dev = fh->dev;
224 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
225 219
226 int err = 0;220static int queue_setup(struct vb2_queue *q,
227 int lines, llength, size;221 unsigned int *num_buffers, unsigned int *num_planes,
222 unsigned int sizes[], struct device *alloc_devs[])
223{
224 unsigned int size = 16 * 2 * vbi_pixel_to_capture;
228 225
229 lines = 16 * 2 ; /* 2 fields */226 if (*num_planes)
230 llength = vbi_pixel_to_capture;227 return sizes[0] < size ? -EINVAL : 0;
231 size = lines * llength;228 *num_planes = 1;
229 sizes[0] = size;
232 230
233 DEB_VBI("vb:%p\n", vb);231 return 0;
232}
234 233
235 if (0 != buf->vb.baddr && buf->vb.bsize < size) {234static void buf_queue(struct vb2_buffer *vb)
236 DEB_VBI("size mismatch\n");235{
237 return -EINVAL;236 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
238 }237 struct vb2_queue *vq = vb->vb2_queue;
238 struct saa7146_dev *dev = vb2_get_drv_priv(vq);
239 struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
240 unsigned long flags;
239 241
240 if (buf->vb.size != size)242 spin_lock_irqsave(&dev->slock, flags);
241 saa7146_dma_free(dev,q,buf);
242 243
243 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {244 saa7146_buffer_queue(dev, &dev->vv_data->vbi_dmaq, buf);
244 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);245 spin_unlock_irqrestore(&dev->slock, flags);
246}
245 247
246 buf->vb.width = llength;248static int buf_init(struct vb2_buffer *vb)
247 buf->vb.height = lines;249{
248 buf->vb.size = size;250 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
249 buf->vb.field = field; // FIXME: check this251 struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
252 struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
253 struct scatterlist *list = sgt->sgl;
254 int length = sgt->nents;
255 struct vb2_queue *vq = vb->vb2_queue;
256 struct saa7146_dev *dev = vb2_get_drv_priv(vq);
257 int ret;
250 258
251 saa7146_pgtable_free(dev->pci, &buf->pt[2]);
252 saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
253
254 err = videobuf_iolock(q,&buf->vb, NULL);
255 if (err)
256 goto oops;
257 err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
258 dma->sglist, dma->sglen);
259 if (0 != err)
260 return err;
261 }
262 buf->vb.state = VIDEOBUF_PREPARED;
263 buf->activate = buffer_activate;259 buf->activate = buffer_activate;
264 260
265 return 0;261 saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
266
267 oops:
268 DEB_VBI("error out\n");
269 saa7146_dma_free(dev,q,buf);
270 262
271 return err;263 ret = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
264 list, length);
265 if (ret)
266 saa7146_pgtable_free(dev->pci, &buf->pt[2]);
267 return ret;
272}268}
273 269
274static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)270static int buf_prepare(struct vb2_buffer *vb)
275{271{
276 int llength,lines;272 unsigned int size = 16 * 2 * vbi_pixel_to_capture;
277
278 lines = 16 * 2 ; /* 2 fields */
279 llength = vbi_pixel_to_capture;
280
281 *size = lines * llength;
282 *count = 2;
283
284 DEB_VBI("count:%d, size:%d\n", *count, *size);
285 273
274 if (vb2_plane_size(vb, 0) < size)
275 return -EINVAL;
276 vb2_set_plane_payload(vb, 0, size);
286 return 0;277 return 0;
287}278}
288 279
289static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)280static void buf_cleanup(struct vb2_buffer *vb)
290{281{
291 struct file *file = q->priv_data;282 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
292 struct saa7146_fh *fh = file->private_data;283 struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
293 struct saa7146_dev *dev = fh->dev;284 struct vb2_queue *vq = vb->vb2_queue;
294 struct saa7146_vv *vv = dev->vv_data;285 struct saa7146_dev *dev = vb2_get_drv_priv(vq);
295 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
296 286
297 DEB_VBI("vb:%p\n", vb);287 saa7146_pgtable_free(dev->pci, &buf->pt[2]);
298 saa7146_buffer_queue(dev, &vv->vbi_dmaq, buf);
299}288}
300 289
301static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)290static void return_buffers(struct vb2_queue *q, int state)
302{291{
303 struct file *file = q->priv_data;292 struct saa7146_dev *dev = vb2_get_drv_priv(q);
304 struct saa7146_fh *fh = file->private_data;293 struct saa7146_dmaqueue *dq = &dev->vv_data->vbi_dmaq;
305 struct saa7146_dev *dev = fh->dev;294 struct saa7146_buf *buf;
306 struct saa7146_buf *buf = (struct saa7146_buf *)vb;295
307 296 if (dq->curr) {
308 DEB_VBI("vb:%p\n", vb);297 buf = dq->curr;
309 saa7146_dma_free(dev,q,buf);298 dq->curr = NULL;
299 vb2_buffer_done(&buf->vb.vb2_buf, state);
300 }
301 while (!list_empty(&dq->queue)) {
302 buf = list_entry(dq->queue.next, struct saa7146_buf, list);
303 list_del(&buf->list);
304 vb2_buffer_done(&buf->vb.vb2_buf, state);
305 }
310}306}
311 307
312static const struct videobuf_queue_ops vbi_qops = {308static void vbi_stop(struct saa7146_dev *dev)
313 .buf_setup = buffer_setup,
314 .buf_prepare = buffer_prepare,
315 .buf_queue = buffer_queue,
316 .buf_release = buffer_release,
317};
318
319/* ------------------------------------------------------------------ */
320
321static void vbi_stop(struct saa7146_fh *fh, struct file *file)
322{309{
323 struct saa7146_dev *dev = fh->dev;
324 struct saa7146_vv *vv = dev->vv_data;310 struct saa7146_vv *vv = dev->vv_data;
325 unsigned long flags;311 unsigned long flags;
326 DEB_VBI("dev:%p, fh:%p\n", dev, fh);312 DEB_VBI("dev:%p\n", dev);
327 313
328 spin_lock_irqsave(&dev->slock,flags);314 spin_lock_irqsave(&dev->slock,flags);
329 315
@@ -336,13 +322,6 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file) · 6 unmodified lines
336 /* shut down dma 3 transfers */322 /* shut down dma 3 transfers */
337 saa7146_write(dev, MC1, MASK_20);323 saa7146_write(dev, MC1, MASK_20);
338 324
339 if (vv->vbi_dmaq.curr)
340 saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE);
341
342 videobuf_queue_cancel(&fh->vbi_q);
343
344 vv->vbi_streaming = NULL;
345
346 del_timer(&vv->vbi_dmaq.timeout);325 del_timer(&vv->vbi_dmaq.timeout);
347 del_timer(&vv->vbi_read_timeout);326 del_timer(&vv->vbi_read_timeout);
348 327
@@ -352,38 +331,22 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file) · 3 unmodified lines
352static void vbi_read_timeout(struct timer_list *t)331static void vbi_read_timeout(struct timer_list *t)
353{332{
354 struct saa7146_vv *vv = from_timer(vv, t, vbi_read_timeout);333 struct saa7146_vv *vv = from_timer(vv, t, vbi_read_timeout);
355 struct file *file = vv->vbi_read_timeout_file;334 struct saa7146_dev *dev = vv->vbi_dmaq.dev;
356 struct saa7146_fh *fh = file->private_data;
357 struct saa7146_dev *dev = fh->dev;
358
359 DEB_VBI("dev:%p, fh:%p\n", dev, fh);
360 335
361 vbi_stop(fh, file);
362}
363
364static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
365{
366 DEB_VBI("dev:%p\n", dev);336 DEB_VBI("dev:%p\n", dev);
367 337
368 INIT_LIST_HEAD(&vv->vbi_dmaq.queue);338 vbi_stop(dev);
369
370 timer_setup(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout, 0);
371 vv->vbi_dmaq.dev = dev;
372
373 init_waitqueue_head(&vv->vbi_wq);
374}339}
375 340
376static int vbi_open(struct saa7146_dev *dev, struct file *file)341static int vbi_begin(struct saa7146_dev *dev)
377{342{
378 struct saa7146_fh *fh = file->private_data;343 struct saa7146_vv *vv = dev->vv_data;
379 struct saa7146_vv *vv = fh->dev->vv_data;
380
381 u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);344 u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
382 int ret = 0;345 int ret = 0;
383 346
384 DEB_VBI("dev:%p, fh:%p\n", dev, fh);347 DEB_VBI("dev:%p\n", dev);
385 348
386 ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);349 ret = saa7146_res_get(dev, RESOURCE_DMA3_BRS);
387 if (0 == ret) {350 if (0 == ret) {
388 DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");351 DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
389 return -EBUSY;352 return -EBUSY;
@@ -395,15 +358,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) · 5 unmodified lines
395 saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);358 saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
396 saa7146_write(dev, MC2, (MASK_04|MASK_20));359 saa7146_write(dev, MC2, (MASK_04|MASK_20));
397 360
398 videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
399 &dev->pci->dev, &dev->slock,
400 V4L2_BUF_TYPE_VBI_CAPTURE,
401 V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
402 sizeof(struct saa7146_buf),
403 file, &dev->v4l2_lock);
404
405 vv->vbi_read_timeout.function = vbi_read_timeout;361 vv->vbi_read_timeout.function = vbi_read_timeout;
406 vv->vbi_read_timeout_file = file;
407 362
408 /* initialize the brs */363 /* initialize the brs */
409 if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {364 if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
@@ -422,16 +377,52 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) · 12 unmodified lines
422 return 0;377 return 0;
423}378}
424 379
425static void vbi_close(struct saa7146_dev *dev, struct file *file)380static int start_streaming(struct vb2_queue *q, unsigned int count)
426{381{
427 struct saa7146_fh *fh = file->private_data;382 struct saa7146_dev *dev = vb2_get_drv_priv(q);
428 struct saa7146_vv *vv = dev->vv_data;383 int ret;
429 DEB_VBI("dev:%p, fh:%p\n", dev, fh);384
385 if (!vb2_is_streaming(&dev->vv_data->vbi_dmaq.q))
386 dev->vv_data->seqnr = 0;
387 ret = vbi_begin(dev);
388 if (ret)
389 return_buffers(q, VB2_BUF_STATE_QUEUED);
390 return ret;
391}
430 392
431 if( fh == vv->vbi_streaming ) {393static void stop_streaming(struct vb2_queue *q)
432 vbi_stop(fh, file);394{
433 }395 struct saa7146_dev *dev = vb2_get_drv_priv(q);
434 saa7146_res_free(fh, RESOURCE_DMA3_BRS);396
397 vbi_stop(dev);
398 return_buffers(q, VB2_BUF_STATE_ERROR);
399 saa7146_res_free(dev, RESOURCE_DMA3_BRS);
400}
401
402const struct vb2_ops vbi_qops = {
403 .queue_setup = queue_setup,
404 .buf_queue = buf_queue,
405 .buf_init = buf_init,
406 .buf_prepare = buf_prepare,
407 .buf_cleanup = buf_cleanup,
408 .start_streaming = start_streaming,
409 .stop_streaming = stop_streaming,
410 .wait_prepare = vb2_ops_wait_prepare,
411 .wait_finish = vb2_ops_wait_finish,
412};
413
414/* ------------------------------------------------------------------ */
415
416static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
417{
418 DEB_VBI("dev:%p\n", dev);
419
420 INIT_LIST_HEAD(&vv->vbi_dmaq.queue);
421
422 timer_setup(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout, 0);
423 vv->vbi_dmaq.dev = dev;
424
425 init_waitqueue_head(&vv->vbi_wq);
435}426}
436 427
437static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)428static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
@@ -441,10 +432,7 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status) · 3 unmodified lines
441 432
442 if (vv->vbi_dmaq.curr) {433 if (vv->vbi_dmaq.curr) {
443 DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_dmaq.curr);434 DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_dmaq.curr);
444 /* this must be += 2, one count for each field */435 saa7146_buffer_finish(dev, &vv->vbi_dmaq, VB2_BUF_STATE_DONE);
445 vv->vbi_fieldcount+=2;
446 vv->vbi_dmaq.curr->vb.field_count = vv->vbi_fieldcount;
447 saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE);
448 } else {436 } else {
449 DEB_VBI("dev:%p\n", dev);437 DEB_VBI("dev:%p\n", dev);
450 }438 }
@@ -453,46 +441,7 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status) · 2 unmodified lines
453 spin_unlock(&dev->slock);441 spin_unlock(&dev->slock);
454}442}
455 443
456static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
457{
458 struct saa7146_fh *fh = file->private_data;
459 struct saa7146_dev *dev = fh->dev;
460 struct saa7146_vv *vv = dev->vv_data;
461 ssize_t ret = 0;
462
463 DEB_VBI("dev:%p, fh:%p\n", dev, fh);
464
465 if( NULL == vv->vbi_streaming ) {
466 // fixme: check if dma3 is available
467 // fixme: activate vbi engine here if necessary. (really?)
468 vv->vbi_streaming = fh;
469 }
470
471 if( fh != vv->vbi_streaming ) {
472 DEB_VBI("open %p is already using vbi capture\n",
473 vv->vbi_streaming);
474 return -EBUSY;
475 }
476
477 mod_timer(&vv->vbi_read_timeout, jiffies+BUFFER_TIMEOUT);
478 ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1,
479 file->f_flags & O_NONBLOCK);
480/*
481 printk("BASE_ODD3: 0x%08x\n", saa7146_read(dev, BASE_ODD3));
482 printk("BASE_EVEN3: 0x%08x\n", saa7146_read(dev, BASE_EVEN3));
483 printk("PROT_ADDR3: 0x%08x\n", saa7146_read(dev, PROT_ADDR3));
484 printk("PITCH3: 0x%08x\n", saa7146_read(dev, PITCH3));
485 printk("BASE_PAGE3: 0x%08x\n", saa7146_read(dev, BASE_PAGE3));
486 printk("NUM_LINE_BYTE3: 0x%08x\n", saa7146_read(dev, NUM_LINE_BYTE3));
487 printk("BRS_CTRL: 0x%08x\n", saa7146_read(dev, BRS_CTRL));
488*/
489 return ret;
490}
491
492const struct saa7146_use_ops saa7146_vbi_uops = {444const struct saa7146_use_ops saa7146_vbi_uops = {
493 .init = vbi_init,445 .init = vbi_init,
494 .open = vbi_open,
495 .release = vbi_close,
496 .irq_done = vbi_irq_done,446 .irq_done = vbi_irq_done,
497 .read = vbi_read,
498};447};
drivers/media/common/saa7146/saa7146_video.c+199−760
@@ -6,17 +6,6 @@ · 5 unmodified lines
6#include <linux/module.h>6#include <linux/module.h>
7#include <linux/kernel.h>7#include <linux/kernel.h>
8 8
9static int max_memory = 32;
10
11module_param(max_memory, int, 0644);
12MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)");
13
14#define IS_CAPTURE_ACTIVE(fh) \
15 (((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh))
16
17#define IS_OVERLAY_ACTIVE(fh) \
18 (((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh))
19
20/* format descriptions for capture and preview */9/* format descriptions for capture and preview */
21static struct saa7146_format formats[] = {10static struct saa7146_format formats[] = {
22 {11 {
@@ -54,7 +43,7 @@ static struct saa7146_format formats[] = { · 31 unmodified lines
54 .pixelformat = V4L2_PIX_FMT_YUV422P,43 .pixelformat = V4L2_PIX_FMT_YUV422P,
55 .trans = YUV422_DECOMPOSED,44 .trans = YUV422_DECOMPOSED,
56 .depth = 16,45 .depth = 16,
57 .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,46 .flags = FORMAT_IS_PLANAR,
58 }, {47 }, {
59 .pixelformat = V4L2_PIX_FMT_YVU420,48 .pixelformat = V4L2_PIX_FMT_YVU420,
60 .trans = YUV420_DECOMPOSED,49 .trans = YUV420_DECOMPOSED,
@@ -91,115 +80,18 @@ struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fou · 30 unmodified lines
91 return NULL;80 return NULL;
92}81}
93 82
94static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f);
95
96int saa7146_start_preview(struct saa7146_fh *fh)
97{
98 struct saa7146_dev *dev = fh->dev;
99 struct saa7146_vv *vv = dev->vv_data;
100 struct v4l2_format fmt;
101 int ret = 0, err = 0;
102
103 DEB_EE("dev:%p, fh:%p\n", dev, fh);
104
105 /* check if we have overlay information */
106 if (vv->ov.fh == NULL) {
107 DEB_D("no overlay data available. try S_FMT first.\n");
108 return -EAGAIN;
109 }
110
111 /* check if streaming capture is running */
112 if (IS_CAPTURE_ACTIVE(fh) != 0) {
113 DEB_D("streaming capture is active\n");
114 return -EBUSY;
115 }
116
117 /* check if overlay is running */
118 if (IS_OVERLAY_ACTIVE(fh) != 0) {
119 if (vv->video_fh == fh) {
120 DEB_D("overlay is already active\n");
121 return 0;
122 }
123 DEB_D("overlay is already active in another open\n");
124 return -EBUSY;
125 }
126
127 if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
128 DEB_D("cannot get necessary overlay resources\n");
129 return -EBUSY;
130 }
131
132 fmt.fmt.win = vv->ov.win;
133 err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt);
134 if (0 != err) {
135 saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
136 return -EBUSY;
137 }
138 vv->ov.win = fmt.fmt.win;
139
140 DEB_D("%dx%d+%d+%d 0x%08x field=%s\n",
141 vv->ov.win.w.width, vv->ov.win.w.height,
142 vv->ov.win.w.left, vv->ov.win.w.top,
143 vv->ov_fmt->pixelformat, v4l2_field_names[vv->ov.win.field]);
144
145 if (0 != (ret = saa7146_enable_overlay(fh))) {
146 DEB_D("enabling overlay failed: %d\n", ret);
147 saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
148 return ret;
149 }
150
151 vv->video_status = STATUS_OVERLAY;
152 vv->video_fh = fh;
153
154 return 0;
155}
156EXPORT_SYMBOL_GPL(saa7146_start_preview);
157
158int saa7146_stop_preview(struct saa7146_fh *fh)
159{
160 struct saa7146_dev *dev = fh->dev;
161 struct saa7146_vv *vv = dev->vv_data;
162
163 DEB_EE("dev:%p, fh:%p\n", dev, fh);
164
165 /* check if streaming capture is running */
166 if (IS_CAPTURE_ACTIVE(fh) != 0) {
167 DEB_D("streaming capture is active\n");
168 return -EBUSY;
169 }
170
171 /* check if overlay is running at all */
172 if ((vv->video_status & STATUS_OVERLAY) == 0) {
173 DEB_D("no active overlay\n");
174 return 0;
175 }
176
177 if (vv->video_fh != fh) {
178 DEB_D("overlay is active, but in another open\n");
179 return -EBUSY;
180 }
181
182 vv->video_status = 0;
183 vv->video_fh = NULL;
184
185 saa7146_disable_overlay(fh);
186
187 saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
188
189 return 0;
190}
191EXPORT_SYMBOL_GPL(saa7146_stop_preview);
192
193/********************************************************************************/83/********************************************************************************/
194/* common pagetable functions */84/* common pagetable functions */
195 85
196static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)86static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
197{87{
88 struct saa7146_vv *vv = dev->vv_data;
198 struct pci_dev *pci = dev->pci;89 struct pci_dev *pci = dev->pci;
199 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);90 struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
200 struct scatterlist *list = dma->sglist;91 struct scatterlist *list = sgt->sgl;
201 int length = dma->sglen;92 int length = sgt->nents;
202 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);93 struct v4l2_pix_format *pix = &vv->video_fmt;
94 struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
203 95
204 DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);96 DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
205 97
@@ -207,31 +99,32 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu · 1 unmodified line
207 struct saa7146_pgtable *pt1 = &buf->pt[0];99 struct saa7146_pgtable *pt1 = &buf->pt[0];
208 struct saa7146_pgtable *pt2 = &buf->pt[1];100 struct saa7146_pgtable *pt2 = &buf->pt[1];
209 struct saa7146_pgtable *pt3 = &buf->pt[2];101 struct saa7146_pgtable *pt3 = &buf->pt[2];
102 struct sg_dma_page_iter dma_iter;
210 __le32 *ptr1, *ptr2, *ptr3;103 __le32 *ptr1, *ptr2, *ptr3;
211 __le32 fill;104 __le32 fill;
212 105
213 int size = buf->fmt->width*buf->fmt->height;106 int size = pix->width * pix->height;
214 int i,p,m1,m2,m3,o1,o2;107 int i, m1, m2, m3, o1, o2;
215 108
216 switch( sfmt->depth ) {109 switch( sfmt->depth ) {
217 case 12: {110 case 12: {
218 /* create some offsets inside the page table */111 /* create some offsets inside the page table */
219 m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;112 m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
220 m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1;113 m2 = ((size + (size / 4) + PAGE_SIZE) / PAGE_SIZE) - 1;
221 m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;114 m3 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
222 o1 = size%PAGE_SIZE;115 o1 = size % PAGE_SIZE;
223 o2 = (size+(size/4))%PAGE_SIZE;116 o2 = (size + (size / 4)) % PAGE_SIZE;
224 DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",117 DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
225 size, m1, m2, m3, o1, o2);118 size, m1, m2, m3, o1, o2);
226 break;119 break;
227 }120 }
228 case 16: {121 case 16: {
229 /* create some offsets inside the page table */122 /* create some offsets inside the page table */
230 m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;123 m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
231 m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;124 m2 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
232 m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;125 m3 = ((2 * size + PAGE_SIZE) / PAGE_SIZE) - 1;
233 o1 = size%PAGE_SIZE;126 o1 = size % PAGE_SIZE;
234 o2 = (size+(size/2))%PAGE_SIZE;127 o2 = (size + (size / 2)) % PAGE_SIZE;
235 DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",128 DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
236 size, m1, m2, m3, o1, o2);129 size, m1, m2, m3, o1, o2);
237 break;130 break;
@@ -245,64 +138,37 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu · 7 unmodified lines
245 ptr2 = pt2->cpu;138 ptr2 = pt2->cpu;
246 ptr3 = pt3->cpu;139 ptr3 = pt3->cpu;
247 140
248 /* walk all pages, copy all page addresses to ptr1 */141 for_each_sg_dma_page(list, &dma_iter, length, 0)
249 for (i = 0; i < length; i++, list++) {142 *ptr1++ = cpu_to_le32(sg_page_iter_dma_address(&dma_iter) - list->offset);
250 for (p = 0; p * 4096 < sg_dma_len(list); p++, ptr1++)
251 *ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset);
252 }
253/*
254 ptr1 = pt1->cpu;
255 for(j=0;j<40;j++) {
256 printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
257 }
258*/
259 143
260 /* if we have a user buffer, the first page may not be144 /* if we have a user buffer, the first page may not be
261 aligned to a page boundary. */145 aligned to a page boundary. */
262 pt1->offset = dma->sglist->offset;146 pt1->offset = sgt->sgl->offset;
263 pt2->offset = pt1->offset+o1;147 pt2->offset = pt1->offset + o1;
264 pt3->offset = pt1->offset+o2;148 pt3->offset = pt1->offset + o2;
265 149
266 /* create video-dma2 page table */150 /* create video-dma2 page table */
267 ptr1 = pt1->cpu;151 ptr1 = pt1->cpu;
268 for(i = m1; i <= m2 ; i++, ptr2++) {152 for (i = m1; i <= m2; i++, ptr2++)
269 *ptr2 = ptr1[i];153 *ptr2 = ptr1[i];
270 }154 fill = *(ptr2 - 1);
271 fill = *(ptr2-1);155 for (; i < 1024; i++, ptr2++)
272 for(;i<1024;i++,ptr2++) {
273 *ptr2 = fill;156 *ptr2 = fill;
274 }
275 /* create video-dma3 page table */157 /* create video-dma3 page table */
276 ptr1 = pt1->cpu;158 ptr1 = pt1->cpu;
277 for(i = m2; i <= m3; i++,ptr3++) {159 for (i = m2; i <= m3; i++, ptr3++)
278 *ptr3 = ptr1[i];160 *ptr3 = ptr1[i];
279 }161 fill = *(ptr3 - 1);
280 fill = *(ptr3-1);162 for (; i < 1024; i++, ptr3++)
281 for(;i<1024;i++,ptr3++) {
282 *ptr3 = fill;163 *ptr3 = fill;
283 }
284 /* finally: finish up video-dma1 page table */164 /* finally: finish up video-dma1 page table */
285 ptr1 = pt1->cpu+m1;165 ptr1 = pt1->cpu + m1;
286 fill = pt1->cpu[m1];166 fill = pt1->cpu[m1];
287 for(i=m1;i<1024;i++,ptr1++) {167 for (i = m1; i < 1024; i++, ptr1++)
288 *ptr1 = fill;168 *ptr1 = fill;
289 }
290/*
291 ptr1 = pt1->cpu;
292 ptr2 = pt2->cpu;
293 ptr3 = pt3->cpu;
294 for(j=0;j<40;j++) {
295 printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
296 }
297 for(j=0;j<40;j++) {
298 printk("ptr2 %d: 0x%08x\n",j,ptr2[j]);
299 }
300 for(j=0;j<40;j++) {
301 printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);
302 }
303*/
304 } else {169 } else {
305 struct saa7146_pgtable *pt = &buf->pt[0];170 struct saa7146_pgtable *pt = &buf->pt[0];
171
306 return saa7146_pgtable_build_single(pci, pt, list, length);172 return saa7146_pgtable_build_single(pci, pt, list, length);
307 }173 }
308 174
@@ -313,34 +179,14 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu · 4 unmodified lines
313/********************************************************************************/179/********************************************************************************/
314/* file operations */180/* file operations */
315 181
316static int video_begin(struct saa7146_fh *fh)182static int video_begin(struct saa7146_dev *dev)
317{183{
318 struct saa7146_dev *dev = fh->dev;
319 struct saa7146_vv *vv = dev->vv_data;184 struct saa7146_vv *vv = dev->vv_data;
320 struct saa7146_format *fmt = NULL;185 struct saa7146_format *fmt = NULL;
321 unsigned int resource;186 unsigned int resource;
322 int ret = 0, err = 0;187 int ret = 0;
323
324 DEB_EE("dev:%p, fh:%p\n", dev, fh);
325
326 if ((vv->video_status & STATUS_CAPTURE) != 0) {
327 if (vv->video_fh == fh) {
328 DEB_S("already capturing\n");
329 return 0;
330 }
331 DEB_S("already capturing in another open\n");
332 return -EBUSY;
333 }
334 188
335 if ((vv->video_status & STATUS_OVERLAY) != 0) {189 DEB_EE("dev:%p\n", dev);
336 DEB_S("warning: suspending overlay video for streaming capture\n");
337 vv->ov_suspend = vv->video_fh;
338 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
339 if (0 != err) {
340 DEB_D("suspending video failed. aborting\n");
341 return err;
342 }
343 }
344 190
345 fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);191 fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
346 /* we need to have a valid format set here */192 /* we need to have a valid format set here */
@@ -353,13 +199,9 @@ static int video_begin(struct saa7146_fh *fh) · 6 unmodified lines
353 resource = RESOURCE_DMA1_HPS;199 resource = RESOURCE_DMA1_HPS;
354 }200 }
355 201
356 ret = saa7146_res_get(fh, resource);202 ret = saa7146_res_get(dev, resource);
357 if (0 == ret) {203 if (0 == ret) {
358 DEB_S("cannot get capture resource %d\n", resource);204 DEB_S("cannot get capture resource %d\n", resource);
359 if (vv->ov_suspend != NULL) {
360 saa7146_start_preview(vv->ov_suspend);
361 vv->ov_suspend = NULL;
362 }
363 return -EBUSY;205 return -EBUSY;
364 }206 }
365 207
@@ -369,37 +211,22 @@ static int video_begin(struct saa7146_fh *fh) · 3 unmodified lines
369 /* enable rps0 irqs */211 /* enable rps0 irqs */
370 SAA7146_IER_ENABLE(dev, MASK_27);212 SAA7146_IER_ENABLE(dev, MASK_27);
371 213
372 vv->video_fh = fh;
373 vv->video_status = STATUS_CAPTURE;
374
375 return 0;214 return 0;
376}215}
377 216
378static int video_end(struct saa7146_fh *fh, struct file *file)217static void video_end(struct saa7146_dev *dev)
379{218{
380 struct saa7146_dev *dev = fh->dev;
381 struct saa7146_vv *vv = dev->vv_data;219 struct saa7146_vv *vv = dev->vv_data;
382 struct saa7146_dmaqueue *q = &vv->video_dmaq;
383 struct saa7146_format *fmt = NULL;220 struct saa7146_format *fmt = NULL;
384 unsigned long flags;221 unsigned long flags;
385 unsigned int resource;222 unsigned int resource;
386 u32 dmas = 0;223 u32 dmas = 0;
387 DEB_EE("dev:%p, fh:%p\n", dev, fh);224 DEB_EE("dev:%p\n", dev);
388
389 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
390 DEB_S("not capturing\n");
391 return 0;
392 }
393
394 if (vv->video_fh != fh) {
395 DEB_S("capturing, but in another open\n");
396 return -EBUSY;
397 }
398 225
399 fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);226 fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
400 /* we need to have a valid format set here */227 /* we need to have a valid format set here */
401 if (!fmt)228 if (!fmt)
402 return -EINVAL;229 return;
403 230
404 if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {231 if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
405 resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;232 resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
@@ -419,88 +246,24 @@ static int video_end(struct saa7146_fh *fh, struct file *file) · 13 unmodified lines
419 /* shut down all used video dma transfers */246 /* shut down all used video dma transfers */
420 saa7146_write(dev, MC1, dmas);247 saa7146_write(dev, MC1, dmas);
421 248
422 if (q->curr)
423 saa7146_buffer_finish(dev, q, VIDEOBUF_DONE);
424
425 spin_unlock_irqrestore(&dev->slock, flags);249 spin_unlock_irqrestore(&dev->slock, flags);
426 250
427 vv->video_fh = NULL;251 saa7146_res_free(dev, resource);
428 vv->video_status = 0;
429
430 saa7146_res_free(fh, resource);
431
432 if (vv->ov_suspend != NULL) {
433 saa7146_start_preview(vv->ov_suspend);
434 vv->ov_suspend = NULL;
435 }
436
437 return 0;
438}252}
439 253
440static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)254static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
441{255{
442 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;256 struct saa7146_dev *dev = video_drvdata(file);
443 257
444 strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));258 strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
445 strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));259 strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
446 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |260 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
447 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |261 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
448 V4L2_CAP_DEVICE_CAPS;262 V4L2_CAP_DEVICE_CAPS;
449 cap->capabilities |= dev->ext_vv_data->capabilities;263 cap->capabilities |= dev->ext_vv_data->capabilities;
450 return 0;264 return 0;
451}265}
452 266
453static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
454{
455 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
456 struct saa7146_vv *vv = dev->vv_data;
457
458 *fb = vv->ov_fb;
459 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
460 fb->flags = V4L2_FBUF_FLAG_PRIMARY;
461 return 0;
462}
463
464static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
465{
466 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
467 struct saa7146_vv *vv = dev->vv_data;
468 struct saa7146_format *fmt;
469
470 DEB_EE("VIDIOC_S_FBUF\n");
471
472 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
473 return -EPERM;
474
475 /* check args */
476 fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);
477 if (NULL == fmt)
478 return -EINVAL;
479
480 /* planar formats are not allowed for overlay video, clipping and video dma would clash */
481 if (fmt->flags & FORMAT_IS_PLANAR)
482 DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
483 (char *)&fmt->pixelformat);
484
485 /* check if overlay is running */
486 if (IS_OVERLAY_ACTIVE(fh) != 0) {
487 if (vv->video_fh != fh) {
488 DEB_D("refusing to change framebuffer information while overlay is active in another open\n");
489 return -EBUSY;
490 }
491 }
492
493 /* ok, accept it */
494 vv->ov_fb = *fb;
495 vv->ov_fmt = fmt;
496
497 if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
498 vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
499 DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
500 }
501 return 0;
502}
503
504static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)267static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
505{268{
506 if (f->index >= ARRAY_SIZE(formats))269 if (f->index >= ARRAY_SIZE(formats))
@@ -543,13 +306,13 @@ int saa7146_s_ctrl(struct v4l2_ctrl *ctrl) · 36 unmodified lines
543 306
544 case V4L2_CID_HFLIP:307 case V4L2_CID_HFLIP:
545 /* fixme: we can support changing VFLIP and HFLIP here... */308 /* fixme: we can support changing VFLIP and HFLIP here... */
546 if ((vv->video_status & STATUS_CAPTURE))309 if (vb2_is_busy(&vv->video_dmaq.q))
547 return -EBUSY;310 return -EBUSY;
548 vv->hflip = ctrl->val;311 vv->hflip = ctrl->val;
549 break;312 break;
550 313
551 case V4L2_CID_VFLIP:314 case V4L2_CID_VFLIP:
552 if ((vv->video_status & STATUS_CAPTURE))315 if (vb2_is_busy(&vv->video_dmaq.q))
553 return -EBUSY;316 return -EBUSY;
554 vv->vflip = ctrl->val;317 vv->vflip = ctrl->val;
555 break;318 break;
@@ -557,20 +320,13 @@ int saa7146_s_ctrl(struct v4l2_ctrl *ctrl) · 1 unmodified line
557 default:320 default:
558 return -EINVAL;321 return -EINVAL;
559 }322 }
560
561 if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */
562 struct saa7146_fh *fh = vv->video_fh;
563
564 saa7146_stop_preview(fh);
565 saa7146_start_preview(fh);
566 }
567 return 0;323 return 0;
568}324}
569 325
570static int vidioc_g_parm(struct file *file, void *fh,326static int vidioc_g_parm(struct file *file, void *fh,
571 struct v4l2_streamparm *parm)327 struct v4l2_streamparm *parm)
572{328{
573 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;329 struct saa7146_dev *dev = video_drvdata(file);
574 struct saa7146_vv *vv = dev->vv_data;330 struct saa7146_vv *vv = dev->vv_data;
575 331
576 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)332 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -583,25 +339,16 @@ static int vidioc_g_parm(struct file *file, void *fh, · 6 unmodified lines
583 339
584static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)340static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
585{341{
586 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;342 struct saa7146_dev *dev = video_drvdata(file);
587 struct saa7146_vv *vv = dev->vv_data;343 struct saa7146_vv *vv = dev->vv_data;
588 344
589 f->fmt.pix = vv->video_fmt;345 f->fmt.pix = vv->video_fmt;
590 return 0;346 return 0;
591}347}
592 348
593static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
594{
595 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
596 struct saa7146_vv *vv = dev->vv_data;
597
598 f->fmt.win = vv->ov.win;
599 return 0;
600}
601
602static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)349static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
603{350{
604 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;351 struct saa7146_dev *dev = video_drvdata(file);
605 struct saa7146_vv *vv = dev->vv_data;352 struct saa7146_vv *vv = dev->vv_data;
606 353
607 f->fmt.vbi = vv->vbi_fmt;354 f->fmt.vbi = vv->vbi_fmt;
@@ -610,7 +357,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format · 2 unmodified lines
610 357
611static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)358static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
612{359{
613 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;360 struct saa7146_dev *dev = video_drvdata(file);
614 struct saa7146_vv *vv = dev->vv_data;361 struct saa7146_vv *vv = dev->vv_data;
615 struct saa7146_format *fmt;362 struct saa7146_format *fmt;
616 enum v4l2_field field;363 enum v4l2_field field;
@@ -634,24 +381,21 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma · 17 unmodified lines
634 }381 }
635 switch (field) {382 switch (field) {
636 case V4L2_FIELD_ALTERNATE:383 case V4L2_FIELD_ALTERNATE:
637 vv->last_field = V4L2_FIELD_TOP;
638 maxh = maxh / 2;
639 break;
640 case V4L2_FIELD_TOP:384 case V4L2_FIELD_TOP:
641 case V4L2_FIELD_BOTTOM:385 case V4L2_FIELD_BOTTOM:
642 vv->last_field = V4L2_FIELD_INTERLACED;
643 maxh = maxh / 2;386 maxh = maxh / 2;
644 break;387 break;
645 case V4L2_FIELD_INTERLACED:
646 vv->last_field = V4L2_FIELD_INTERLACED;
647 break;
648 default:388 default:
649 DEB_D("no known field mode '%d'\n", field);389 field = V4L2_FIELD_INTERLACED;
650 return -EINVAL;390 break;
651 }391 }
652 392
653 f->fmt.pix.field = field;393 f->fmt.pix.field = field;
654 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;394 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
395 if (f->fmt.pix.width < 48)
396 f->fmt.pix.width = 48;
397 if (f->fmt.pix.height < 32)
398 f->fmt.pix.height = 32;
655 if (f->fmt.pix.width > maxw)399 if (f->fmt.pix.width > maxw)
656 f->fmt.pix.width = maxw;400 f->fmt.pix.width = maxw;
657 if (f->fmt.pix.height > maxh)401 if (f->fmt.pix.height > maxh)
@@ -673,169 +417,65 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma · 15 unmodified lines
673 return 0;417 return 0;
674}418}
675 419
676 420static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
677static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
678{421{
679 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;422 struct saa7146_dev *dev = video_drvdata(file);
680 struct saa7146_vv *vv = dev->vv_data;
681 struct v4l2_window *win = &f->fmt.win;
682 enum v4l2_field field;
683 int maxw, maxh;
684
685 DEB_EE("dev:%p\n", dev);
686
687 if (NULL == vv->ov_fb.base) {
688 DEB_D("no fb base set\n");
689 return -EINVAL;
690 }
691 if (NULL == vv->ov_fmt) {
692 DEB_D("no fb fmt set\n");
693 return -EINVAL;
694 }
695 if (win->w.width < 48 || win->w.height < 32) {
696 DEB_D("min width/height. (%d,%d)\n",
697 win->w.width, win->w.height);
698 return -EINVAL;
699 }
700 if (win->clipcount > 16) {
701 DEB_D("clipcount too big\n");
702 return -EINVAL;
703 }
704
705 field = win->field;
706 maxw = vv->standard->h_max_out;
707 maxh = vv->standard->v_max_out;
708
709 if (V4L2_FIELD_ANY == field) {
710 field = (win->w.height > maxh / 2)
711 ? V4L2_FIELD_INTERLACED
712 : V4L2_FIELD_TOP;
713 }
714 switch (field) {
715 case V4L2_FIELD_TOP:
716 case V4L2_FIELD_BOTTOM:
717 case V4L2_FIELD_ALTERNATE:
718 maxh = maxh / 2;
719 break;
720 case V4L2_FIELD_INTERLACED:
721 break;
722 default:
723 DEB_D("no known field mode '%d'\n", field);
724 return -EINVAL;
725 }
726
727 win->field = field;
728 if (win->w.width > maxw)
729 win->w.width = maxw;
730 if (win->w.height > maxh)
731 win->w.height = maxh;
732
733 return 0;
734}
735
736static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f)
737{
738 struct saa7146_fh *fh = __fh;
739 struct saa7146_dev *dev = fh->dev;
740 struct saa7146_vv *vv = dev->vv_data;423 struct saa7146_vv *vv = dev->vv_data;
741 int err;424 int err;
742 425
743 DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);426 DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p\n", dev);
744 if (IS_CAPTURE_ACTIVE(fh) != 0) {427 if (vb2_is_busy(&vv->video_dmaq.q)) {
745 DEB_EE("streaming capture is active\n");428 DEB_EE("streaming capture is active\n");
746 return -EBUSY;429 return -EBUSY;
747 }430 }
748 err = vidioc_try_fmt_vid_cap(file, fh, f);431 err = vidioc_try_fmt_vid_cap(file, fh, f);
749 if (0 != err)432 if (0 != err)
750 return err;433 return err;
434 switch (f->fmt.pix.field) {
435 case V4L2_FIELD_ALTERNATE:
436 vv->last_field = V4L2_FIELD_TOP;
437 break;
438 default:
439 vv->last_field = V4L2_FIELD_INTERLACED;
440 break;
441 }
751 vv->video_fmt = f->fmt.pix;442 vv->video_fmt = f->fmt.pix;
752 DEB_EE("set to pixelformat '%4.4s'\n",443 DEB_EE("set to pixelformat '%4.4s'\n",
753 (char *)&vv->video_fmt.pixelformat);444 (char *)&vv->video_fmt.pixelformat);
754 return 0;445 return 0;
755}446}
756 447
757static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f)
758{
759 struct saa7146_fh *fh = __fh;
760 struct saa7146_dev *dev = fh->dev;
761 struct saa7146_vv *vv = dev->vv_data;
762 int err;
763
764 DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
765 err = vidioc_try_fmt_vid_overlay(file, fh, f);
766 if (0 != err)
767 return err;
768 vv->ov.win = f->fmt.win;
769 vv->ov.nclips = f->fmt.win.clipcount;
770 if (vv->ov.nclips > 16)
771 vv->ov.nclips = 16;
772 memcpy(vv->ov.clips, f->fmt.win.clips,
773 sizeof(struct v4l2_clip) * vv->ov.nclips);
774
775 /* vv->ov.fh is used to indicate that we have valid overlay information, too */
776 vv->ov.fh = fh;
777
778 /* check if our current overlay is active */
779 if (IS_OVERLAY_ACTIVE(fh) != 0) {
780 saa7146_stop_preview(fh);
781 saa7146_start_preview(fh);
782 }
783 return 0;
784}
785
786static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)448static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
787{449{
788 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;450 struct saa7146_dev *dev = video_drvdata(file);
789 struct saa7146_vv *vv = dev->vv_data;451 struct saa7146_vv *vv = dev->vv_data;
790 452
791 *norm = vv->standard->id;453 *norm = vv->standard->id;
792 return 0;454 return 0;
793}455}
794 456
795 /* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
796 PAL / NTSC / SECAM. if your hardware does not (or does more)
797 -- override this function in your extension */
798/*
799 case VIDIOC_ENUMSTD:
800 {
801 struct v4l2_standard *e = arg;
802 if (e->index < 0 )
803 return -EINVAL;
804 if( e->index < dev->ext_vv_data->num_stds ) {
805 DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
806 v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
807 return 0;
808 }
809 return -EINVAL;
810 }
811 */
812
813static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)457static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
814{458{
815 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;459 struct saa7146_dev *dev = video_drvdata(file);
816 struct saa7146_vv *vv = dev->vv_data;460 struct saa7146_vv *vv = dev->vv_data;
817 int found = 0;461 int found = 0;
818 int err, i;462 int i;
819 463
820 DEB_EE("VIDIOC_S_STD\n");464 DEB_EE("VIDIOC_S_STD\n");
821 465
822 if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {466 for (i = 0; i < dev->ext_vv_data->num_stds; i++)
467 if (id & dev->ext_vv_data->stds[i].id)
468 break;
469
470 if (i != dev->ext_vv_data->num_stds &&
471 vv->standard == &dev->ext_vv_data->stds[i])
472 return 0;
473
474 if (vb2_is_busy(&vv->video_dmaq.q) || vb2_is_busy(&vv->vbi_dmaq.q)) {
823 DEB_D("cannot change video standard while streaming capture is active\n");475 DEB_D("cannot change video standard while streaming capture is active\n");
824 return -EBUSY;476 return -EBUSY;
825 }477 }
826 478
827 if ((vv->video_status & STATUS_OVERLAY) != 0) {
828 vv->ov_suspend = vv->video_fh;
829 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
830 if (0 != err) {
831 DEB_D("suspending video failed. aborting\n");
832 return err;
833 }
834 }
835
836 for (i = 0; i < dev->ext_vv_data->num_stds; i++)
837 if (id & dev->ext_vv_data->stds[i].id)
838 break;
839 if (i != dev->ext_vv_data->num_stds) {479 if (i != dev->ext_vv_data->num_stds) {
840 vv->standard = &dev->ext_vv_data->stds[i];480 vv->standard = &dev->ext_vv_data->stds[i];
841 if (NULL != dev->ext_vv_data->std_callback)481 if (NULL != dev->ext_vv_data->std_callback)
@@ -843,11 +483,6 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id) · 1 unmodified line
843 found = 1;483 found = 1;
844 }484 }
845 485
846 if (vv->ov_suspend != NULL) {
847 saa7146_start_preview(vv->ov_suspend);
848 vv->ov_suspend = NULL;
849 }
850
851 if (!found) {486 if (!found) {
852 DEB_EE("VIDIOC_S_STD: standard not found\n");487 DEB_EE("VIDIOC_S_STD: standard not found\n");
853 return -EINVAL;488 return -EINVAL;
@@ -857,138 +492,22 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id) · 3 unmodified lines
857 return 0;492 return 0;
858}493}
859 494
860static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
861{
862 int err;
863
864 DEB_D("VIDIOC_OVERLAY on:%d\n", on);
865 if (on)
866 err = saa7146_start_preview(fh);
867 else
868 err = saa7146_stop_preview(fh);
869 return err;
870}
871
872static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b)
873{
874 struct saa7146_fh *fh = __fh;
875
876 if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
877 return videobuf_reqbufs(&fh->video_q, b);
878 if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE)
879 return videobuf_reqbufs(&fh->vbi_q, b);
880 return -EINVAL;
881}
882
883static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
884{
885 struct saa7146_fh *fh = __fh;
886
887 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
888 return videobuf_querybuf(&fh->video_q, buf);
889 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
890 return videobuf_querybuf(&fh->vbi_q, buf);
891 return -EINVAL;
892}
893
894static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
895{
896 struct saa7146_fh *fh = __fh;
897
898 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
899 return videobuf_qbuf(&fh->video_q, buf);
900 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
901 return videobuf_qbuf(&fh->vbi_q, buf);
902 return -EINVAL;
903}
904
905static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
906{
907 struct saa7146_fh *fh = __fh;
908
909 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
910 return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK);
911 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
912 return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK);
913 return -EINVAL;
914}
915
916static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
917{
918 struct saa7146_fh *fh = __fh;
919 int err;
920
921 DEB_D("VIDIOC_STREAMON, type:%d\n", type);
922
923 err = video_begin(fh);
924 if (err)
925 return err;
926 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
927 return videobuf_streamon(&fh->video_q);
928 if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
929 return videobuf_streamon(&fh->vbi_q);
930 return -EINVAL;
931}
932
933static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
934{
935 struct saa7146_fh *fh = __fh;
936 struct saa7146_dev *dev = fh->dev;
937 struct saa7146_vv *vv = dev->vv_data;
938 int err;
939
940 DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
941
942 /* ugly: we need to copy some checks from video_end(),
943 because videobuf_streamoff() relies on the capture running.
944 check and fix this */
945 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
946 DEB_S("not capturing\n");
947 return 0;
948 }
949
950 if (vv->video_fh != fh) {
951 DEB_S("capturing, but in another open\n");
952 return -EBUSY;
953 }
954
955 err = -EINVAL;
956 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
957 err = videobuf_streamoff(&fh->video_q);
958 else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
959 err = videobuf_streamoff(&fh->vbi_q);
960 if (0 != err) {
961 DEB_D("warning: videobuf_streamoff() failed\n");
962 video_end(fh, file);
963 } else {
964 err = video_end(fh, file);
965 }
966 return err;
967}
968
969const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {495const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
970 .vidioc_querycap = vidioc_querycap,496 .vidioc_querycap = vidioc_querycap,
971 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,497 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
972 .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap,
973 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,498 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
974 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,499 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
975 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,500 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
976 .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
977 .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
978 .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
979
980 .vidioc_overlay = vidioc_overlay,
981 .vidioc_g_fbuf = vidioc_g_fbuf,
982 .vidioc_s_fbuf = vidioc_s_fbuf,
983 .vidioc_reqbufs = vidioc_reqbufs,
984 .vidioc_querybuf = vidioc_querybuf,
985 .vidioc_qbuf = vidioc_qbuf,
986 .vidioc_dqbuf = vidioc_dqbuf,
987 .vidioc_g_std = vidioc_g_std,501 .vidioc_g_std = vidioc_g_std,
988 .vidioc_s_std = vidioc_s_std,502 .vidioc_s_std = vidioc_s_std,
989 .vidioc_streamon = vidioc_streamon,
990 .vidioc_streamoff = vidioc_streamoff,
991 .vidioc_g_parm = vidioc_g_parm,503 .vidioc_g_parm = vidioc_g_parm,
504 .vidioc_reqbufs = vb2_ioctl_reqbufs,
505 .vidioc_create_bufs = vb2_ioctl_create_bufs,
506 .vidioc_querybuf = vb2_ioctl_querybuf,
507 .vidioc_qbuf = vb2_ioctl_qbuf,
508 .vidioc_dqbuf = vb2_ioctl_dqbuf,
509 .vidioc_streamon = vb2_ioctl_streamon,
510 .vidioc_streamoff = vb2_ioctl_streamoff,
992 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,511 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
993 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,512 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
994};513};
@@ -996,16 +515,18 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { · 1 unmodified line
996const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {515const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
997 .vidioc_querycap = vidioc_querycap,516 .vidioc_querycap = vidioc_querycap,
998 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,517 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
999 518 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
1000 .vidioc_reqbufs = vidioc_reqbufs,519 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
1001 .vidioc_querybuf = vidioc_querybuf,
1002 .vidioc_qbuf = vidioc_qbuf,
1003 .vidioc_dqbuf = vidioc_dqbuf,
1004 .vidioc_g_std = vidioc_g_std,520 .vidioc_g_std = vidioc_g_std,
1005 .vidioc_s_std = vidioc_s_std,521 .vidioc_s_std = vidioc_s_std,
1006 .vidioc_streamon = vidioc_streamon,
1007 .vidioc_streamoff = vidioc_streamoff,
1008 .vidioc_g_parm = vidioc_g_parm,522 .vidioc_g_parm = vidioc_g_parm,
523 .vidioc_reqbufs = vb2_ioctl_reqbufs,
524 .vidioc_create_bufs = vb2_ioctl_create_bufs,
525 .vidioc_querybuf = vb2_ioctl_querybuf,
526 .vidioc_qbuf = vb2_ioctl_qbuf,
527 .vidioc_dqbuf = vb2_ioctl_dqbuf,
528 .vidioc_streamon = vb2_ioctl_streamon,
529 .vidioc_streamoff = vb2_ioctl_streamoff,
1009 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,530 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1010 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,531 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1011};532};
@@ -1019,7 +540,6 @@ static int buffer_activate (struct saa7146_dev *dev, · 7 unmodified lines
1019{540{
1020 struct saa7146_vv *vv = dev->vv_data;541 struct saa7146_vv *vv = dev->vv_data;
1021 542
1022 buf->vb.state = VIDEOBUF_ACTIVE;
1023 saa7146_set_capture(dev,buf,next);543 saa7146_set_capture(dev,buf,next);
1024 544
1025 mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);545 mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
@@ -1033,140 +553,136 @@ static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf * · 7 unmodified lines
1033 saa7146_pgtable_free(dev->pci, &buf->pt[2]);553 saa7146_pgtable_free(dev->pci, &buf->pt[2]);
1034}554}
1035 555
1036static int buffer_prepare(struct videobuf_queue *q,556static int queue_setup(struct vb2_queue *q,
1037 struct videobuf_buffer *vb, enum v4l2_field field)557 unsigned int *num_buffers, unsigned int *num_planes,
558 unsigned int sizes[], struct device *alloc_devs[])
1038{559{
1039 struct file *file = q->priv_data;560 struct saa7146_dev *dev = vb2_get_drv_priv(q);
1040 struct saa7146_fh *fh = file->private_data;561 unsigned int size = dev->vv_data->video_fmt.sizeimage;
1041 struct saa7146_dev *dev = fh->dev;
1042 struct saa7146_vv *vv = dev->vv_data;
1043 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1044 int size,err = 0;
1045
1046 DEB_CAP("vbuf:%p\n", vb);
1047
1048 /* sanity checks */
1049 if (vv->video_fmt.width < 48 ||
1050 vv->video_fmt.height < 32 ||
1051 vv->video_fmt.width > vv->standard->h_max_out ||
1052 vv->video_fmt.height > vv->standard->v_max_out) {
1053 DEB_D("w (%d) / h (%d) out of bounds\n",
1054 vv->video_fmt.width, vv->video_fmt.height);
1055 return -EINVAL;
1056 }
1057 562
1058 size = vv->video_fmt.sizeimage;563 if (*num_planes)
1059 if (0 != buf->vb.baddr && buf->vb.bsize < size) {564 return sizes[0] < size ? -EINVAL : 0;
1060 DEB_D("size mismatch\n");565 *num_planes = 1;
1061 return -EINVAL;566 sizes[0] = size;
1062 }
1063 567
1064 DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",568 return 0;
1065 vv->video_fmt.width, vv->video_fmt.height,569}
1066 size, v4l2_field_names[vv->video_fmt.field]);
1067 if (buf->vb.width != vv->video_fmt.width ||
1068 buf->vb.bytesperline != vv->video_fmt.bytesperline ||
1069 buf->vb.height != vv->video_fmt.height ||
1070 buf->vb.size != size ||
1071 buf->vb.field != field ||
1072 buf->vb.field != vv->video_fmt.field ||
1073 buf->fmt != &vv->video_fmt) {
1074 saa7146_dma_free(dev,q,buf);
1075 }
1076 570
1077 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {571static void buf_queue(struct vb2_buffer *vb)
1078 struct saa7146_format *sfmt;572{
573 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
574 struct vb2_queue *vq = vb->vb2_queue;
575 struct saa7146_dev *dev = vb2_get_drv_priv(vq);
576 struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
577 unsigned long flags;
1079 578
1080 buf->vb.bytesperline = vv->video_fmt.bytesperline;579 spin_lock_irqsave(&dev->slock, flags);
1081 buf->vb.width = vv->video_fmt.width;
1082 buf->vb.height = vv->video_fmt.height;
1083 buf->vb.size = size;
1084 buf->vb.field = field;
1085 buf->fmt = &vv->video_fmt;
1086 buf->vb.field = vv->video_fmt.field;
1087 580
1088 sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);581 saa7146_buffer_queue(dev, &dev->vv_data->video_dmaq, buf);
582 spin_unlock_irqrestore(&dev->slock, flags);
583}
1089 584
1090 release_all_pagetables(dev, buf);585static int buf_init(struct vb2_buffer *vb)
1091 if( 0 != IS_PLANAR(sfmt->trans)) {586{
1092 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);587 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1093 saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);588 struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
1094 saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);589 struct vb2_queue *vq = vb->vb2_queue;
1095 } else {590 struct saa7146_dev *dev = vb2_get_drv_priv(vq);
1096 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);591 struct saa7146_vv *vv = dev->vv_data;
1097 }592 struct saa7146_format *sfmt;
593 int ret;
1098 594
1099 err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
1100 if (err)
1101 goto oops;
1102 err = saa7146_pgtable_build(dev,buf);
1103 if (err)
1104 goto oops;
1105 }
1106 buf->vb.state = VIDEOBUF_PREPARED;
1107 buf->activate = buffer_activate;595 buf->activate = buffer_activate;
596 sfmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
1108 597
1109 return 0;598 if (IS_PLANAR(sfmt->trans)) {
1110 599 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
1111 oops:600 saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
1112 DEB_D("error out\n");601 saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
1113 saa7146_dma_free(dev,q,buf);602 } else {
603 saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
604 }
1114 605
1115 return err;606 ret = saa7146_pgtable_build(dev, buf);
607 if (ret)
608 release_all_pagetables(dev, buf);
609 return ret;
1116}610}
1117 611
1118static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)612static int buf_prepare(struct vb2_buffer *vb)
1119{613{
1120 struct file *file = q->priv_data;614 struct vb2_queue *vq = vb->vb2_queue;
1121 struct saa7146_fh *fh = file->private_data;615 struct saa7146_dev *dev = vb2_get_drv_priv(vq);
1122 struct saa7146_vv *vv = fh->dev->vv_data;616 struct saa7146_vv *vv = dev->vv_data;
1123 617 unsigned int size = vv->video_fmt.sizeimage;
1124 if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
1125 *count = MAX_SAA7146_CAPTURE_BUFFERS;
1126
1127 *size = vv->video_fmt.sizeimage;
1128 618
1129 /* check if we exceed the "max_memory" parameter */619 if (vb2_plane_size(vb, 0) < size)
1130 if( (*count * *size) > (max_memory*1048576) ) {620 return -EINVAL;
1131 *count = (max_memory*1048576) / *size;621 vb2_set_plane_payload(vb, 0, size);
1132 }622 return 0;
623}
1133 624
1134 DEB_CAP("%d buffers, %d bytes each\n", *count, *size);625static void buf_cleanup(struct vb2_buffer *vb)
626{
627 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
628 struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
629 struct vb2_queue *vq = vb->vb2_queue;
630 struct saa7146_dev *dev = vb2_get_drv_priv(vq);
1135 631
1136 return 0;632 release_all_pagetables(dev, buf);
1137}633}
1138 634
1139static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)635static void return_buffers(struct vb2_queue *q, int state)
1140{636{
1141 struct file *file = q->priv_data;637 struct saa7146_dev *dev = vb2_get_drv_priv(q);
1142 struct saa7146_fh *fh = file->private_data;638 struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq;
1143 struct saa7146_dev *dev = fh->dev;639 struct saa7146_buf *buf;
1144 struct saa7146_vv *vv = dev->vv_data;
1145 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1146 640
1147 DEB_CAP("vbuf:%p\n", vb);641 if (dq->curr) {
1148 saa7146_buffer_queue(fh->dev, &vv->video_dmaq, buf);642 buf = dq->curr;
643 dq->curr = NULL;
644 vb2_buffer_done(&buf->vb.vb2_buf, state);
645 }
646 while (!list_empty(&dq->queue)) {
647 buf = list_entry(dq->queue.next, struct saa7146_buf, list);
648 list_del(&buf->list);
649 vb2_buffer_done(&buf->vb.vb2_buf, state);
650 }
1149}651}
1150 652
1151static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)653static int start_streaming(struct vb2_queue *q, unsigned int count)
1152{654{
1153 struct file *file = q->priv_data;655 struct saa7146_dev *dev = vb2_get_drv_priv(q);
1154 struct saa7146_fh *fh = file->private_data;656 int ret;
1155 struct saa7146_dev *dev = fh->dev;
1156 struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1157 657
1158 DEB_CAP("vbuf:%p\n", vb);658 if (!vb2_is_streaming(&dev->vv_data->video_dmaq.q))
659 dev->vv_data->seqnr = 0;
660 ret = video_begin(dev);
661 if (ret)
662 return_buffers(q, VB2_BUF_STATE_QUEUED);
663 return ret;
664}
1159 665
1160 saa7146_dma_free(dev,q,buf);666static void stop_streaming(struct vb2_queue *q)
667{
668 struct saa7146_dev *dev = vb2_get_drv_priv(q);
669 struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq;
1161 670
1162 release_all_pagetables(dev, buf);671 del_timer(&dq->timeout);
672 video_end(dev);
673 return_buffers(q, VB2_BUF_STATE_ERROR);
1163}674}
1164 675
1165static const struct videobuf_queue_ops video_qops = {676const struct vb2_ops video_qops = {
1166 .buf_setup = buffer_setup,677 .queue_setup = queue_setup,
1167 .buf_prepare = buffer_prepare,678 .buf_queue = buf_queue,
1168 .buf_queue = buffer_queue,679 .buf_init = buf_init,
1169 .buf_release = buffer_release,680 .buf_prepare = buf_prepare,
681 .buf_cleanup = buf_cleanup,
682 .start_streaming = start_streaming,
683 .stop_streaming = stop_streaming,
684 .wait_prepare = vb2_ops_wait_prepare,
685 .wait_finish = vb2_ops_wait_finish,
1170};686};
1171 687
1172/********************************************************************************/688/********************************************************************************/
@@ -1187,38 +703,6 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv) · 14 unmodified lines
1187 vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;703 vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
1188}704}
1189 705
1190
1191static int video_open(struct saa7146_dev *dev, struct file *file)
1192{
1193 struct saa7146_fh *fh = file->private_data;
1194
1195 videobuf_queue_sg_init(&fh->video_q, &video_qops,
1196 &dev->pci->dev, &dev->slock,
1197 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1198 V4L2_FIELD_INTERLACED,
1199 sizeof(struct saa7146_buf),
1200 file, &dev->v4l2_lock);
1201
1202 return 0;
1203}
1204
1205
1206static void video_close(struct saa7146_dev *dev, struct file *file)
1207{
1208 struct saa7146_fh *fh = file->private_data;
1209 struct saa7146_vv *vv = dev->vv_data;
1210 struct videobuf_queue *q = &fh->video_q;
1211
1212 if (IS_CAPTURE_ACTIVE(fh) != 0)
1213 video_end(fh, file);
1214 else if (IS_OVERLAY_ACTIVE(fh) != 0)
1215 saa7146_stop_preview(fh);
1216
1217 videobuf_stop(q);
1218 /* hmm, why is this function declared void? */
1219}
1220
1221
1222static void video_irq_done(struct saa7146_dev *dev, unsigned long st)706static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
1223{707{
1224 struct saa7146_vv *vv = dev->vv_data;708 struct saa7146_vv *vv = dev->vv_data;
@@ -1228,59 +712,14 @@ static void video_irq_done(struct saa7146_dev *dev, unsigned long st) · 3 unmodified lines
1228 DEB_CAP("called\n");712 DEB_CAP("called\n");
1229 713
1230 /* only finish the buffer if we have one... */714 /* only finish the buffer if we have one... */
1231 if( NULL != q->curr ) {715 if (q->curr)
1232 saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);716 saa7146_buffer_finish(dev, q, VB2_BUF_STATE_DONE);
1233 }
1234 saa7146_buffer_next(dev,q,0);717 saa7146_buffer_next(dev,q,0);
1235 718
1236 spin_unlock(&dev->slock);719 spin_unlock(&dev->slock);
1237}720}
1238 721
1239static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1240{
1241 struct saa7146_fh *fh = file->private_data;
1242 struct saa7146_dev *dev = fh->dev;
1243 struct saa7146_vv *vv = dev->vv_data;
1244 ssize_t ret = 0;
1245
1246 DEB_EE("called\n");
1247
1248 if ((vv->video_status & STATUS_CAPTURE) != 0) {
1249 /* fixme: should we allow read() captures while streaming capture? */
1250 if (vv->video_fh == fh) {
1251 DEB_S("already capturing\n");
1252 return -EBUSY;
1253 }
1254 DEB_S("already capturing in another open\n");
1255 return -EBUSY;
1256 }
1257
1258 ret = video_begin(fh);
1259 if( 0 != ret) {
1260 goto out;
1261 }
1262
1263 ret = videobuf_read_one(&fh->video_q , data, count, ppos,
1264 file->f_flags & O_NONBLOCK);
1265 if (ret != 0) {
1266 video_end(fh, file);
1267 } else {
1268 ret = video_end(fh, file);
1269 }
1270out:
1271 /* restart overlay if it was active before */
1272 if (vv->ov_suspend != NULL) {
1273 saa7146_start_preview(vv->ov_suspend);
1274 vv->ov_suspend = NULL;
1275 }
1276
1277 return ret;
1278}
1279
1280const struct saa7146_use_ops saa7146_video_uops = {722const struct saa7146_use_ops saa7146_video_uops = {
1281 .init = video_init,723 .init = video_init,
1282 .open = video_open,
1283 .release = video_close,
1284 .irq_done = video_irq_done,724 .irq_done = video_irq_done,
1285 .read = video_read,
1286};725};
drivers/media/common/videobuf2/videobuf2-v4l2.c+3−2
@@ -1171,10 +1171,11 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf, · 1170 unmodified lines
1171 return -ERESTARTSYS;1171 return -ERESTARTSYS;
1172 if (vb2_queue_is_busy(vdev->queue, file))1172 if (vb2_queue_is_busy(vdev->queue, file))
1173 goto exit;1173 goto exit;
1174 vdev->queue->owner = file->private_data;
1174 err = vb2_read(vdev->queue, buf, count, ppos,1175 err = vb2_read(vdev->queue, buf, count, ppos,
1175 file->f_flags & O_NONBLOCK);1176 file->f_flags & O_NONBLOCK);
1176 if (vdev->queue->fileio)1177 if (!vdev->queue->fileio)
1177 vdev->queue->owner = file->private_data;1178 vdev->queue->owner = NULL;
1178exit:1179exit:
1179 if (lock)1180 if (lock)
1180 mutex_unlock(lock);1181 mutex_unlock(lock);
drivers/media/dvb-frontends/drx39xyj/drxj.c+1−1
@@ -11070,7 +11070,7 @@ ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode) · 11069 unmodified lines
11070 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;11070 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
11071 break;11071 break;
11072 default:11072 default:
11073 /* Unknow sleep mode */11073 /* Unknown sleep mode */
11074 return -EINVAL;11074 return -EINVAL;
11075 }11075 }
11076 11076
drivers/media/dvb-frontends/drxk_hard.c+1−1
@@ -1585,7 +1585,7 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) · 1584 unmodified lines
1585 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;1585 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
1586 break;1586 break;
1587 default:1587 default:
1588 /* Unknow sleep mode */1588 /* Unknown sleep mode */
1589 return -EINVAL;1589 return -EINVAL;
1590 }1590 }
1591 1591
drivers/media/dvb-frontends/rtl2832_sdr.c+2−4
@@ -1463,7 +1463,7 @@ err: · 1462 unmodified lines
1463 return ret;1463 return ret;
1464}1464}
1465 1465
1466static int rtl2832_sdr_remove(struct platform_device *pdev)1466static void rtl2832_sdr_remove(struct platform_device *pdev)
1467{1467{
1468 struct rtl2832_sdr_dev *dev = platform_get_drvdata(pdev);1468 struct rtl2832_sdr_dev *dev = platform_get_drvdata(pdev);
1469 1469
@@ -1479,8 +1479,6 @@ static int rtl2832_sdr_remove(struct platform_device *pdev) · 9 unmodified lines
1479 mutex_unlock(&dev->vb_queue_lock);1479 mutex_unlock(&dev->vb_queue_lock);
1480 v4l2_device_put(&dev->v4l2_dev);1480 v4l2_device_put(&dev->v4l2_dev);
1481 module_put(pdev->dev.parent->driver->owner);1481 module_put(pdev->dev.parent->driver->owner);
1482
1483 return 0;
1484}1482}
1485 1483
1486static struct platform_driver rtl2832_sdr_driver = {1484static struct platform_driver rtl2832_sdr_driver = {
@@ -1488,7 +1486,7 @@ static struct platform_driver rtl2832_sdr_driver = { · 1 unmodified line
1488 .name = "rtl2832_sdr",1486 .name = "rtl2832_sdr",
1489 },1487 },
1490 .probe = rtl2832_sdr_probe,1488 .probe = rtl2832_sdr_probe,
1491 .remove = rtl2832_sdr_remove,1489 .remove_new = rtl2832_sdr_remove,
1492};1490};
1493module_platform_driver(rtl2832_sdr_driver);1491module_platform_driver(rtl2832_sdr_driver);
1494 1492
drivers/media/dvb-frontends/zd1301_demod.c+2−4
@@ -515,7 +515,7 @@ err: · 514 unmodified lines
515 return ret;515 return ret;
516}516}
517 517
518static int zd1301_demod_remove(struct platform_device *pdev)518static void zd1301_demod_remove(struct platform_device *pdev)
519{519{
520 struct zd1301_demod_dev *dev = platform_get_drvdata(pdev);520 struct zd1301_demod_dev *dev = platform_get_drvdata(pdev);
521 521
@@ -523,8 +523,6 @@ static int zd1301_demod_remove(struct platform_device *pdev) · 1 unmodified line
523 523
524 i2c_del_adapter(&dev->adapter);524 i2c_del_adapter(&dev->adapter);
525 kfree(dev);525 kfree(dev);
526
527 return 0;
528}526}
529 527
530static struct platform_driver zd1301_demod_driver = {528static struct platform_driver zd1301_demod_driver = {
@@ -533,7 +531,7 @@ static struct platform_driver zd1301_demod_driver = { · 2 unmodified lines
533 .suppress_bind_attrs = true,531 .suppress_bind_attrs = true,
534 },532 },
535 .probe = zd1301_demod_probe,533 .probe = zd1301_demod_probe,
536 .remove = zd1301_demod_remove,534 .remove_new = zd1301_demod_remove,
537};535};
538module_platform_driver(zd1301_demod_driver);536module_platform_driver(zd1301_demod_driver);
539 537
drivers/media/i2c/Kconfig+1−67
@@ -267,16 +267,6 @@ config VIDEO_MT9M001 · 266 unmodified lines
267 This driver supports MT9M001 cameras from Micron, monochrome267 This driver supports MT9M001 cameras from Micron, monochrome
268 and colour models.268 and colour models.
269 269
270config VIDEO_MT9M032
271 tristate "MT9M032 camera sensor support"
272 depends on I2C && VIDEO_DEV
273 select MEDIA_CONTROLLER
274 select VIDEO_V4L2_SUBDEV_API
275 select VIDEO_APTINA_PLL
276 help
277 This driver supports MT9M032 camera sensors from Aptina, monochrome
278 models only.
279
280config VIDEO_MT9M111270config VIDEO_MT9M111
281 tristate "mt9m111, mt9m112 and mt9m131 support"271 tristate "mt9m111, mt9m112 and mt9m131 support"
282 depends on I2C && VIDEO_DEV272 depends on I2C && VIDEO_DEV
@@ -296,15 +286,6 @@ config VIDEO_MT9P031 · 13 unmodified lines
296 This is a Video4Linux2 sensor driver for the Aptina286 This is a Video4Linux2 sensor driver for the Aptina
297 (Micron) mt9p031 5 Mpixel camera.287 (Micron) mt9p031 5 Mpixel camera.
298 288
299config VIDEO_MT9T001
300 tristate "Aptina MT9T001 support"
301 depends on I2C && VIDEO_DEV
302 select MEDIA_CONTROLLER
303 select VIDEO_V4L2_SUBDEV_API
304 help
305 This is a Video4Linux2 sensor driver for the Aptina
306 (Micron) mt0t001 3 Mpixel camera.
307
308config VIDEO_MT9T112289config VIDEO_MT9T112
309 tristate "Aptina MT9T111/MT9T112 support"290 tristate "Aptina MT9T111/MT9T112 support"
310 depends on I2C && VIDEO_DEV291 depends on I2C && VIDEO_DEV
@@ -344,14 +325,6 @@ config VIDEO_MT9V111 · 33 unmodified lines
344 To compile this driver as a module, choose M here: the325 To compile this driver as a module, choose M here: the
345 module will be called mt9v111.326 module will be called mt9v111.
346 327
347config VIDEO_NOON010PC30
348 tristate "Siliconfile NOON010PC30 sensor support"
349 depends on I2C && VIDEO_DEV
350 select MEDIA_CONTROLLER
351 select VIDEO_V4L2_SUBDEV_API
352 help
353 This driver supports NOON010PC30 CIF camera from Siliconfile
354
355config VIDEO_OG01A1B328config VIDEO_OG01A1B
356 tristate "OmniVision OG01A1B sensor support"329 tristate "OmniVision OG01A1B sensor support"
357 depends on I2C && VIDEO_DEV330 depends on I2C && VIDEO_DEV
@@ -462,6 +435,7 @@ config VIDEO_OV2685 · 104 unmodified lines
462 tristate "OmniVision OV2685 sensor support"435 tristate "OmniVision OV2685 sensor support"
463 depends on VIDEO_DEV && I2C436 depends on VIDEO_DEV && I2C
464 select MEDIA_CONTROLLER437 select MEDIA_CONTROLLER
438 select VIDEO_V4L2_SUBDEV_API
465 select V4L2_FWNODE439 select V4L2_FWNODE
466 help440 help
467 This is a Video4Linux2 sensor driver for the OmniVision441 This is a Video4Linux2 sensor driver for the OmniVision
@@ -810,21 +784,6 @@ config VIDEO_S5K6A3 · 342 unmodified lines
810 This is a V4L2 sensor driver for Samsung S5K6A3 raw784 This is a V4L2 sensor driver for Samsung S5K6A3 raw
811 camera sensor.785 camera sensor.
812 786
813config VIDEO_S5K6AA
814 tristate "Samsung S5K6AAFX sensor support"
815 depends on I2C && VIDEO_DEV
816 select MEDIA_CONTROLLER
817 select VIDEO_V4L2_SUBDEV_API
818 help
819 This is a V4L2 sensor driver for Samsung S5K6AA(FX) 1.3M
820 camera sensor with an embedded SoC image signal processor.
821
822config VIDEO_SR030PC30
823 tristate "Siliconfile SR030PC30 sensor support"
824 depends on I2C && VIDEO_DEV
825 help
826 This driver supports SR030PC30 VGA camera from Siliconfile
827
828config VIDEO_ST_VGXY61787config VIDEO_ST_VGXY61
829 tristate "ST VGXY61 sensor support"788 tristate "ST VGXY61 sensor support"
830 depends on OF && GPIOLIB && VIDEO_DEV && I2C789 depends on OF && GPIOLIB && VIDEO_DEV && I2C
@@ -835,19 +794,8 @@ config VIDEO_ST_VGXY61 · 4 unmodified lines
835 This is a Video4Linux2 sensor driver for the ST VGXY61794 This is a Video4Linux2 sensor driver for the ST VGXY61
836 camera sensor.795 camera sensor.
837 796
838config VIDEO_VS6624
839 tristate "ST VS6624 sensor support"
840 depends on VIDEO_DEV && I2C
841 help
842 This is a Video4Linux2 sensor driver for the ST VS6624
843 camera.
844
845 To compile this driver as a module, choose M here: the
846 module will be called vs6624.
847
848source "drivers/media/i2c/ccs/Kconfig"797source "drivers/media/i2c/ccs/Kconfig"
849source "drivers/media/i2c/et8ek8/Kconfig"798source "drivers/media/i2c/et8ek8/Kconfig"
850source "drivers/media/i2c/m5mols/Kconfig"
851 799
852endmenu800endmenu
853 801
@@ -1453,20 +1401,6 @@ endmenu · 599 unmodified lines
1453menu "Video encoders"1401menu "Video encoders"
1454 visible if !MEDIA_HIDE_ANCILLARY_SUBDRV1402 visible if !MEDIA_HIDE_ANCILLARY_SUBDRV
1455 1403
1456config VIDEO_AD9389B
1457 tristate "Analog Devices AD9389B encoder"
1458 depends on VIDEO_DEV && I2C
1459 select MEDIA_CONTROLLER
1460 select VIDEO_V4L2_SUBDEV_API
1461
1462 help
1463 Support for the Analog Devices AD9389B video encoder.
1464
1465 This is a Analog Devices HDMI transmitter.
1466
1467 To compile this driver as a module, choose M here: the
1468 module will be called ad9389b.
1469
1470config VIDEO_ADV71701404config VIDEO_ADV7170
1471 tristate "Analog Devices ADV7170 video encoder"1405 tristate "Analog Devices ADV7170 video encoder"
1472 depends on VIDEO_DEV && I2C1406 depends on VIDEO_DEV && I2C
drivers/media/i2c/Makefile+0−8
@@ -4,7 +4,6 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o · 3 unmodified lines
4 4
5obj-$(CONFIG_SDR_MAX2175) += max2175.o5obj-$(CONFIG_SDR_MAX2175) += max2175.o
6obj-$(CONFIG_VIDEO_AD5820) += ad5820.o6obj-$(CONFIG_VIDEO_AD5820) += ad5820.o
7obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
8obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o7obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o
9obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o8obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
10obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o9obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
@@ -56,21 +55,17 @@ obj-$(CONFIG_VIDEO_KS0127) += ks0127.o · 45 unmodified lines
56obj-$(CONFIG_VIDEO_LM3560) += lm3560.o55obj-$(CONFIG_VIDEO_LM3560) += lm3560.o
57obj-$(CONFIG_VIDEO_LM3646) += lm3646.o56obj-$(CONFIG_VIDEO_LM3646) += lm3646.o
58obj-$(CONFIG_VIDEO_M52790) += m52790.o57obj-$(CONFIG_VIDEO_M52790) += m52790.o
59obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
60obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o58obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
61obj-$(CONFIG_VIDEO_MAX9286) += max9286.o59obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
62obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o60obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
63obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o61obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
64obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o62obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o
65obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
66obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o63obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o
67obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o64obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
68obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
69obj-$(CONFIG_VIDEO_MT9T112) += mt9t112.o65obj-$(CONFIG_VIDEO_MT9T112) += mt9t112.o
70obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o66obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
71obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o67obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
72obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o68obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o
73obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
74obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o69obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o
75obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o70obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o
76obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o71obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o
@@ -110,7 +105,6 @@ obj-$(CONFIG_VIDEO_RJ54N1) += rj54n1cb0c.o · 33 unmodified lines
110obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/105obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
111obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o106obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o
112obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o107obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o
113obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
114obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o108obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
115obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o109obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
116obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o110obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
@@ -119,7 +113,6 @@ obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o · 2 unmodified lines
119obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o113obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
120obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o114obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
121obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o115obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
122obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
123obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o116obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
124obj-$(CONFIG_VIDEO_ST_VGXY61) += st-vgxy61.o117obj-$(CONFIG_VIDEO_ST_VGXY61) += st-vgxy61.o
125obj-$(CONFIG_VIDEO_TC358743) += tc358743.o118obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
@@ -145,6 +138,5 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o · 19 unmodified lines
145obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o138obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
146obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o139obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
147obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o140obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
148obj-$(CONFIG_VIDEO_VS6624) += vs6624.o
149obj-$(CONFIG_VIDEO_WM8739) += wm8739.o141obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
150obj-$(CONFIG_VIDEO_WM8775) += wm8775.o142obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
drivers/media/i2c/ad9389b.c+0−1215
@@ -1,1215 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Analog Devices AD9389B/AD9889B video encoder driver
4 *
5 * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 */
7
8/*
9 * References (c = chapter, p = page):
10 * REF_01 - Analog Devices, Programming Guide, AD9889B/AD9389B,
11 * HDMI Transitter, Rev. A, October 2010
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/slab.h>
17#include <linux/i2c.h>
18#include <linux/delay.h>
19#include <linux/videodev2.h>
20#include <linux/workqueue.h>
21#include <linux/v4l2-dv-timings.h>
22#include <media/v4l2-device.h>
23#include <media/v4l2-common.h>
24#include <media/v4l2-dv-timings.h>
25#include <media/v4l2-ctrls.h>
26#include <media/i2c/ad9389b.h>
27
28static int debug;
29module_param(debug, int, 0644);
30MODULE_PARM_DESC(debug, "debug level (0-2)");
31
32MODULE_DESCRIPTION("Analog Devices AD9389B/AD9889B video encoder driver");
33MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
34MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>");
35MODULE_LICENSE("GPL");
36
37#define MASK_AD9389B_EDID_RDY_INT 0x04
38#define MASK_AD9389B_MSEN_INT 0x40
39#define MASK_AD9389B_HPD_INT 0x80
40
41#define MASK_AD9389B_HPD_DETECT 0x40
42#define MASK_AD9389B_MSEN_DETECT 0x20
43#define MASK_AD9389B_EDID_RDY 0x10
44
45#define EDID_MAX_RETRIES (8)
46#define EDID_DELAY 250
47#define EDID_MAX_SEGM 8
48
49/*
50**********************************************************************
51*
52* Arrays with configuration parameters for the AD9389B
53*
54**********************************************************************
55*/
56
57struct ad9389b_state_edid {
58 /* total number of blocks */
59 u32 blocks;
60 /* Number of segments read */
61 u32 segments;
62 u8 data[EDID_MAX_SEGM * 256];
63 /* Number of EDID read retries left */
64 unsigned read_retries;
65};
66
67struct ad9389b_state {
68 struct ad9389b_platform_data pdata;
69 struct v4l2_subdev sd;
70 struct media_pad pad;
71 struct v4l2_ctrl_handler hdl;
72 int chip_revision;
73 /* Is the ad9389b powered on? */
74 bool power_on;
75 /* Did we receive hotplug and rx-sense signals? */
76 bool have_monitor;
77 /* timings from s_dv_timings */
78 struct v4l2_dv_timings dv_timings;
79 /* controls */
80 struct v4l2_ctrl *hdmi_mode_ctrl;
81 struct v4l2_ctrl *hotplug_ctrl;
82 struct v4l2_ctrl *rx_sense_ctrl;
83 struct v4l2_ctrl *have_edid0_ctrl;
84 struct v4l2_ctrl *rgb_quantization_range_ctrl;
85 struct i2c_client *edid_i2c_client;
86 struct ad9389b_state_edid edid;
87 /* Running counter of the number of detected EDIDs (for debugging) */
88 unsigned edid_detect_counter;
89 struct delayed_work edid_handler; /* work entry */
90};
91
92static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd);
93static bool ad9389b_check_edid_status(struct v4l2_subdev *sd);
94static void ad9389b_setup(struct v4l2_subdev *sd);
95static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq);
96static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
97
98static inline struct ad9389b_state *get_ad9389b_state(struct v4l2_subdev *sd)
99{
100 return container_of(sd, struct ad9389b_state, sd);
101}
102
103static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
104{
105 return &container_of(ctrl->handler, struct ad9389b_state, hdl)->sd;
106}
107
108/* ------------------------ I2C ----------------------------------------------- */
109
110static int ad9389b_rd(struct v4l2_subdev *sd, u8 reg)
111{
112 struct i2c_client *client = v4l2_get_subdevdata(sd);
113
114 return i2c_smbus_read_byte_data(client, reg);
115}
116
117static int ad9389b_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
118{
119 struct i2c_client *client = v4l2_get_subdevdata(sd);
120 int ret;
121 int i;
122
123 for (i = 0; i < 3; i++) {
124 ret = i2c_smbus_write_byte_data(client, reg, val);
125 if (ret == 0)
126 return 0;
127 }
128 v4l2_err(sd, "%s: failed reg 0x%x, val 0x%x\n", __func__, reg, val);
129 return ret;
130}
131
132/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
133 and then the value-mask (to be OR-ed). */
134static inline void ad9389b_wr_and_or(struct v4l2_subdev *sd, u8 reg,
135 u8 clr_mask, u8 val_mask)
136{
137 ad9389b_wr(sd, reg, (ad9389b_rd(sd, reg) & clr_mask) | val_mask);
138}
139
140static void ad9389b_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf)
141{
142 struct ad9389b_state *state = get_ad9389b_state(sd);
143 int i;
144
145 v4l2_dbg(1, debug, sd, "%s:\n", __func__);
146
147 for (i = 0; i < len; i++)
148 buf[i] = i2c_smbus_read_byte_data(state->edid_i2c_client, i);
149}
150
151static inline bool ad9389b_have_hotplug(struct v4l2_subdev *sd)
152{
153 return ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT;
154}
155
156static inline bool ad9389b_have_rx_sense(struct v4l2_subdev *sd)
157{
158 return ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT;
159}
160
161static void ad9389b_csc_conversion_mode(struct v4l2_subdev *sd, u8 mode)
162{
163 ad9389b_wr_and_or(sd, 0x17, 0xe7, (mode & 0x3)<<3);
164 ad9389b_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5);
165}
166
167static void ad9389b_csc_coeff(struct v4l2_subdev *sd,
168 u16 A1, u16 A2, u16 A3, u16 A4,
169 u16 B1, u16 B2, u16 B3, u16 B4,
170 u16 C1, u16 C2, u16 C3, u16 C4)
171{
172 /* A */
173 ad9389b_wr_and_or(sd, 0x18, 0xe0, A1>>8);
174 ad9389b_wr(sd, 0x19, A1);
175 ad9389b_wr_and_or(sd, 0x1A, 0xe0, A2>>8);
176 ad9389b_wr(sd, 0x1B, A2);
177 ad9389b_wr_and_or(sd, 0x1c, 0xe0, A3>>8);
178 ad9389b_wr(sd, 0x1d, A3);
179 ad9389b_wr_and_or(sd, 0x1e, 0xe0, A4>>8);
180 ad9389b_wr(sd, 0x1f, A4);
181
182 /* B */
183 ad9389b_wr_and_or(sd, 0x20, 0xe0, B1>>8);
184 ad9389b_wr(sd, 0x21, B1);
185 ad9389b_wr_and_or(sd, 0x22, 0xe0, B2>>8);
186 ad9389b_wr(sd, 0x23, B2);
187 ad9389b_wr_and_or(sd, 0x24, 0xe0, B3>>8);
188 ad9389b_wr(sd, 0x25, B3);
189 ad9389b_wr_and_or(sd, 0x26, 0xe0, B4>>8);
190 ad9389b_wr(sd, 0x27, B4);
191
192 /* C */
193 ad9389b_wr_and_or(sd, 0x28, 0xe0, C1>>8);
194 ad9389b_wr(sd, 0x29, C1);
195 ad9389b_wr_and_or(sd, 0x2A, 0xe0, C2>>8);
196 ad9389b_wr(sd, 0x2B, C2);
197 ad9389b_wr_and_or(sd, 0x2C, 0xe0, C3>>8);
198 ad9389b_wr(sd, 0x2D, C3);
199 ad9389b_wr_and_or(sd, 0x2E, 0xe0, C4>>8);
200 ad9389b_wr(sd, 0x2F, C4);
201}
202
203static void ad9389b_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable)
204{
205 if (enable) {
206 u8 csc_mode = 0;
207
208 ad9389b_csc_conversion_mode(sd, csc_mode);
209 ad9389b_csc_coeff(sd,
210 4096-564, 0, 0, 256,
211 0, 4096-564, 0, 256,
212 0, 0, 4096-564, 256);
213 /* enable CSC */
214 ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x1);
215 /* AVI infoframe: Limited range RGB (16-235) */
216 ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x02);
217 } else {
218 /* disable CSC */
219 ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x0);
220 /* AVI infoframe: Full range RGB (0-255) */
221 ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x04);
222 }
223}
224
225static void ad9389b_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd)
226{
227 struct ad9389b_state *state = get_ad9389b_state(sd);
228
229 if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
230 /* CE format, not IT */
231 ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x00);
232 } else {
233 /* IT format */
234 ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x40);
235 }
236}
237
238static int ad9389b_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl)
239{
240 struct ad9389b_state *state = get_ad9389b_state(sd);
241
242 switch (ctrl->val) {
243 case V4L2_DV_RGB_RANGE_AUTO:
244 /* automatic */
245 if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
246 /* CE format, RGB limited range (16-235) */
247 ad9389b_csc_rgb_full2limit(sd, true);
248 } else {
249 /* not CE format, RGB full range (0-255) */
250 ad9389b_csc_rgb_full2limit(sd, false);
251 }
252 break;
253 case V4L2_DV_RGB_RANGE_LIMITED:
254 /* RGB limited range (16-235) */
255 ad9389b_csc_rgb_full2limit(sd, true);
256 break;
257 case V4L2_DV_RGB_RANGE_FULL:
258 /* RGB full range (0-255) */
259 ad9389b_csc_rgb_full2limit(sd, false);
260 break;
261 default:
262 return -EINVAL;
263 }
264 return 0;
265}
266
267static void ad9389b_set_manual_pll_gear(struct v4l2_subdev *sd, u32 pixelclock)
268{
269 u8 gear;
270
271 /* Workaround for TMDS PLL problem
272 * The TMDS PLL in AD9389b change gear when the chip is heated above a
273 * certain temperature. The output is disabled when the PLL change gear
274 * so the monitor has to lock on the signal again. A workaround for
275 * this is to use the manual PLL gears. This is a solution from Analog
276 * Devices that is not documented in the datasheets.
277 * 0x98 [7] = enable manual gearing. 0x98 [6:4] = gear
278 *
279 * The pixel frequency ranges are based on readout of the gear the
280 * automatic gearing selects for different pixel clocks
281 * (read from 0x9e [3:1]).
282 */
283
284 if (pixelclock > 140000000)
285 gear = 0xc0; /* 4th gear */
286 else if (pixelclock > 117000000)
287 gear = 0xb0; /* 3rd gear */
288 else if (pixelclock > 87000000)
289 gear = 0xa0; /* 2nd gear */
290 else if (pixelclock > 60000000)
291 gear = 0x90; /* 1st gear */
292 else
293 gear = 0x80; /* 0th gear */
294
295 ad9389b_wr_and_or(sd, 0x98, 0x0f, gear);
296}
297
298/* ------------------------------ CTRL OPS ------------------------------ */
299
300static int ad9389b_s_ctrl(struct v4l2_ctrl *ctrl)
301{
302 struct v4l2_subdev *sd = to_sd(ctrl);
303 struct ad9389b_state *state = get_ad9389b_state(sd);
304
305 v4l2_dbg(1, debug, sd,
306 "%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val);
307
308 if (state->hdmi_mode_ctrl == ctrl) {
309 /* Set HDMI or DVI-D */
310 ad9389b_wr_and_or(sd, 0xaf, 0xfd,
311 ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00);
312 return 0;
313 }
314 if (state->rgb_quantization_range_ctrl == ctrl)
315 return ad9389b_set_rgb_quantization_mode(sd, ctrl);
316 return -EINVAL;
317}
318
319static const struct v4l2_ctrl_ops ad9389b_ctrl_ops = {
320 .s_ctrl = ad9389b_s_ctrl,
321};
322
323/* ---------------------------- CORE OPS ------------------------------------------- */
324
325#ifdef CONFIG_VIDEO_ADV_DEBUG
326static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
327{
328 reg->val = ad9389b_rd(sd, reg->reg & 0xff);
329 reg->size = 1;
330 return 0;
331}
332
333static int ad9389b_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
334{
335 ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff);
336 return 0;
337}
338#endif
339
340static int ad9389b_log_status(struct v4l2_subdev *sd)
341{
342 struct ad9389b_state *state = get_ad9389b_state(sd);
343 struct ad9389b_state_edid *edid = &state->edid;
344
345 static const char * const states[] = {
346 "in reset",
347 "reading EDID",
348 "idle",
349 "initializing HDCP",
350 "HDCP enabled",
351 "initializing HDCP repeater",
352 "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
353 };
354 static const char * const errors[] = {
355 "no error",
356 "bad receiver BKSV",
357 "Ri mismatch",
358 "Pj mismatch",
359 "i2c error",
360 "timed out",
361 "max repeater cascade exceeded",
362 "hash check failed",
363 "too many devices",
364 "9", "A", "B", "C", "D", "E", "F"
365 };
366
367 u8 manual_gear;
368
369 v4l2_info(sd, "chip revision %d\n", state->chip_revision);
370 v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off");
371 v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n",
372 (ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT) ?
373 "detected" : "no",
374 (ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT) ?
375 "detected" : "no",
376 edid->segments ? "found" : "no", edid->blocks);
377 v4l2_info(sd, "%s output %s\n",
378 (ad9389b_rd(sd, 0xaf) & 0x02) ?
379 "HDMI" : "DVI-D",
380 (ad9389b_rd(sd, 0xa1) & 0x3c) ?
381 "disabled" : "enabled");
382 v4l2_info(sd, "ad9389b: %s\n", (ad9389b_rd(sd, 0xb8) & 0x40) ?
383 "encrypted" : "no encryption");
384 v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n",
385 states[ad9389b_rd(sd, 0xc8) & 0xf],
386 errors[ad9389b_rd(sd, 0xc8) >> 4],
387 state->edid_detect_counter,
388 ad9389b_rd(sd, 0x94), ad9389b_rd(sd, 0x96));
389 manual_gear = ad9389b_rd(sd, 0x98) & 0x80;
390 v4l2_info(sd, "ad9389b: RGB quantization: %s range\n",
391 ad9389b_rd(sd, 0x3b) & 0x01 ? "limited" : "full");
392 v4l2_info(sd, "ad9389b: %s gear %d\n",
393 manual_gear ? "manual" : "automatic",
394 manual_gear ? ((ad9389b_rd(sd, 0x98) & 0x70) >> 4) :
395 ((ad9389b_rd(sd, 0x9e) & 0x0e) >> 1));
396 if (ad9389b_rd(sd, 0xaf) & 0x02) {
397 /* HDMI only */
398 u8 manual_cts = ad9389b_rd(sd, 0x0a) & 0x80;
399 u32 N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 |
400 ad9389b_rd(sd, 0x02) << 8 |
401 ad9389b_rd(sd, 0x03);
402 u8 vic_detect = ad9389b_rd(sd, 0x3e) >> 2;
403 u8 vic_sent = ad9389b_rd(sd, 0x3d) & 0x3f;
404 u32 CTS;
405
406 if (manual_cts)
407 CTS = (ad9389b_rd(sd, 0x07) & 0xf) << 16 |
408 ad9389b_rd(sd, 0x08) << 8 |
409 ad9389b_rd(sd, 0x09);
410 else
411 CTS = (ad9389b_rd(sd, 0x04) & 0xf) << 16 |
412 ad9389b_rd(sd, 0x05) << 8 |
413 ad9389b_rd(sd, 0x06);
414 N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 |
415 ad9389b_rd(sd, 0x02) << 8 |
416 ad9389b_rd(sd, 0x03);
417
418 v4l2_info(sd, "ad9389b: CTS %s mode: N %d, CTS %d\n",
419 manual_cts ? "manual" : "automatic", N, CTS);
420
421 v4l2_info(sd, "ad9389b: VIC: detected %d, sent %d\n",
422 vic_detect, vic_sent);
423 }
424 if (state->dv_timings.type == V4L2_DV_BT_656_1120)
425 v4l2_print_dv_timings(sd->name, "timings: ",
426 &state->dv_timings, false);
427 else
428 v4l2_info(sd, "no timings set\n");
429 return 0;
430}
431
432/* Power up/down ad9389b */
433static int ad9389b_s_power(struct v4l2_subdev *sd, int on)
434{
435 struct ad9389b_state *state = get_ad9389b_state(sd);
436 struct ad9389b_platform_data *pdata = &state->pdata;
437 const int retries = 20;
438 int i;
439
440 v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off");
441
442 state->power_on = on;
443
444 if (!on) {
445 /* Power down */
446 ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40);
447 return true;
448 }
449
450 /* Power up */
451 /* The ad9389b does not always come up immediately.
452 Retry multiple times. */
453 for (i = 0; i < retries; i++) {
454 ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x0);
455 if ((ad9389b_rd(sd, 0x41) & 0x40) == 0)
456 break;
457 ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40);
458 msleep(10);
459 }
460 if (i == retries) {
461 v4l2_dbg(1, debug, sd, "failed to powerup the ad9389b\n");
462 ad9389b_s_power(sd, 0);
463 return false;
464 }
465 if (i > 1)
466 v4l2_dbg(1, debug, sd,
467 "needed %d retries to powerup the ad9389b\n", i);
468
469 /* Select chip: AD9389B */
470 ad9389b_wr_and_or(sd, 0xba, 0xef, 0x10);
471
472 /* Reserved registers that must be set according to REF_01 p. 11*/
473 ad9389b_wr_and_or(sd, 0x98, 0xf0, 0x07);
474 ad9389b_wr(sd, 0x9c, 0x38);
475 ad9389b_wr_and_or(sd, 0x9d, 0xfc, 0x01);
476
477 /* Differential output drive strength */
478 if (pdata->diff_data_drive_strength > 0)
479 ad9389b_wr(sd, 0xa2, pdata->diff_data_drive_strength);
480 else
481 ad9389b_wr(sd, 0xa2, 0x87);
482
483 if (pdata->diff_clk_drive_strength > 0)
484 ad9389b_wr(sd, 0xa3, pdata->diff_clk_drive_strength);
485 else
486 ad9389b_wr(sd, 0xa3, 0x87);
487
488 ad9389b_wr(sd, 0x0a, 0x01);
489 ad9389b_wr(sd, 0xbb, 0xff);
490
491 /* Set number of attempts to read the EDID */
492 ad9389b_wr(sd, 0xc9, 0xf);
493 return true;
494}
495
496/* Enable interrupts */
497static void ad9389b_set_isr(struct v4l2_subdev *sd, bool enable)
498{
499 u8 irqs = MASK_AD9389B_HPD_INT | MASK_AD9389B_MSEN_INT;
500 u8 irqs_rd;
501 int retries = 100;
502
503 /* The datasheet says that the EDID ready interrupt should be
504 disabled if there is no hotplug. */
505 if (!enable)
506 irqs = 0;
507 else if (ad9389b_have_hotplug(sd))
508 irqs |= MASK_AD9389B_EDID_RDY_INT;
509
510 /*
511 * This i2c write can fail (approx. 1 in 1000 writes). But it
512 * is essential that this register is correct, so retry it
513 * multiple times.
514 *
515 * Note that the i2c write does not report an error, but the readback
516 * clearly shows the wrong value.
517 */
518 do {
519 ad9389b_wr(sd, 0x94, irqs);
520 irqs_rd = ad9389b_rd(sd, 0x94);
521 } while (retries-- && irqs_rd != irqs);
522
523 if (irqs_rd != irqs)
524 v4l2_err(sd, "Could not set interrupts: hw failure?\n");
525}
526
527/* Interrupt handler */
528static int ad9389b_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
529{
530 u8 irq_status;
531
532 /* disable interrupts to prevent a race condition */
533 ad9389b_set_isr(sd, false);
534 irq_status = ad9389b_rd(sd, 0x96);
535 /* clear detected interrupts */
536 ad9389b_wr(sd, 0x96, irq_status);
537 /* enable interrupts */
538 ad9389b_set_isr(sd, true);
539
540 v4l2_dbg(1, debug, sd, "%s: irq_status 0x%x\n", __func__, irq_status);
541
542 if (irq_status & (MASK_AD9389B_HPD_INT))
543 ad9389b_check_monitor_present_status(sd);
544 if (irq_status & MASK_AD9389B_EDID_RDY_INT)
545 ad9389b_check_edid_status(sd);
546
547 *handled = true;
548 return 0;
549}
550
551static const struct v4l2_subdev_core_ops ad9389b_core_ops = {
552 .log_status = ad9389b_log_status,
553#ifdef CONFIG_VIDEO_ADV_DEBUG
554 .g_register = ad9389b_g_register,
555 .s_register = ad9389b_s_register,
556#endif
557 .s_power = ad9389b_s_power,
558 .interrupt_service_routine = ad9389b_isr,
559};
560
561/* ------------------------------ VIDEO OPS ------------------------------ */
562
563/* Enable/disable ad9389b output */
564static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable)
565{
566 v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
567
568 ad9389b_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c));
569 if (enable) {
570 ad9389b_check_monitor_present_status(sd);
571 } else {
572 ad9389b_s_power(sd, 0);
573 }
574 return 0;
575}
576
577static const struct v4l2_dv_timings_cap ad9389b_timings_cap = {
578 .type = V4L2_DV_BT_656_1120,
579 /* keep this initialization for compatibility with GCC < 4.4.6 */
580 .reserved = { 0 },
581 V4L2_INIT_BT_TIMINGS(640, 1920, 350, 1200, 25000000, 170000000,
582 V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
583 V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
584 V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
585 V4L2_DV_BT_CAP_CUSTOM)
586};
587
588static int ad9389b_s_dv_timings(struct v4l2_subdev *sd,
589 struct v4l2_dv_timings *timings)
590{
591 struct ad9389b_state *state = get_ad9389b_state(sd);
592
593 v4l2_dbg(1, debug, sd, "%s:\n", __func__);
594
595 /* quick sanity check */
596 if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap, NULL, NULL))
597 return -EINVAL;
598
599 /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
600 if the format is one of the CEA or DMT timings. */
601 v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0, NULL, NULL);
602
603 timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS;
604
605 /* save timings */
606 state->dv_timings = *timings;
607
608 /* update quantization range based on new dv_timings */
609 ad9389b_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl);
610
611 /* update PLL gear based on new dv_timings */
612 if (state->pdata.tmds_pll_gear == AD9389B_TMDS_PLL_GEAR_SEMI_AUTOMATIC)
613 ad9389b_set_manual_pll_gear(sd, (u32)timings->bt.pixelclock);
614
615 /* update AVI infoframe */
616 ad9389b_set_IT_content_AVI_InfoFrame(sd);
617
618 return 0;
619}
620
621static int ad9389b_g_dv_timings(struct v4l2_subdev *sd,
622 struct v4l2_dv_timings *timings)
623{
624 struct ad9389b_state *state = get_ad9389b_state(sd);
625
626 v4l2_dbg(1, debug, sd, "%s:\n", __func__);
627
628 if (!timings)
629 return -EINVAL;
630
631 *timings = state->dv_timings;
632
633 return 0;
634}
635
636static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd,
637 struct v4l2_enum_dv_timings *timings)
638{
639 if (timings->pad != 0)
640 return -EINVAL;
641
642 return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap,
643 NULL, NULL);
644}
645
646static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd,
647 struct v4l2_dv_timings_cap *cap)
648{
649 if (cap->pad != 0)
650 return -EINVAL;
651
652 *cap = ad9389b_timings_cap;
653 return 0;
654}
655
656static const struct v4l2_subdev_video_ops ad9389b_video_ops = {
657 .s_stream = ad9389b_s_stream,
658 .s_dv_timings = ad9389b_s_dv_timings,
659 .g_dv_timings = ad9389b_g_dv_timings,
660};
661
662/* ------------------------------ PAD OPS ------------------------------ */
663
664static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
665{
666 struct ad9389b_state *state = get_ad9389b_state(sd);
667
668 if (edid->pad != 0)
669 return -EINVAL;
670 if (edid->blocks == 0 || edid->blocks > 256)
671 return -EINVAL;
672 if (!state->edid.segments) {
673 v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
674 return -ENODATA;
675 }
676 if (edid->start_block >= state->edid.segments * 2)
677 return -E2BIG;
678 if (edid->blocks + edid->start_block >= state->edid.segments * 2)
679 edid->blocks = state->edid.segments * 2 - edid->start_block;
680 memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
681 128 * edid->blocks);
682 return 0;
683}
684
685static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = {
686 .get_edid = ad9389b_get_edid,
687 .enum_dv_timings = ad9389b_enum_dv_timings,
688 .dv_timings_cap = ad9389b_dv_timings_cap,
689};
690
691/* ------------------------------ AUDIO OPS ------------------------------ */
692
693static int ad9389b_s_audio_stream(struct v4l2_subdev *sd, int enable)
694{
695 v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
696
697 if (enable)
698 ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x80);
699 else
700 ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x40);
701
702 return 0;
703}
704
705static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
706{
707 u32 N;
708
709 switch (freq) {
710 case 32000: N = 4096; break;
711 case 44100: N = 6272; break;
712 case 48000: N = 6144; break;
713 case 88200: N = 12544; break;
714 case 96000: N = 12288; break;
715 case 176400: N = 25088; break;
716 case 192000: N = 24576; break;
717 default:
718 return -EINVAL;
719 }
720
721 /* Set N (used with CTS to regenerate the audio clock) */
722 ad9389b_wr(sd, 0x01, (N >> 16) & 0xf);
723 ad9389b_wr(sd, 0x02, (N >> 8) & 0xff);
724 ad9389b_wr(sd, 0x03, N & 0xff);
725
726 return 0;
727}
728
729static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
730{
731 u32 i2s_sf;
732
733 switch (freq) {
734 case 32000: i2s_sf = 0x30; break;
735 case 44100: i2s_sf = 0x00; break;
736 case 48000: i2s_sf = 0x20; break;
737 case 88200: i2s_sf = 0x80; break;
738 case 96000: i2s_sf = 0xa0; break;
739 case 176400: i2s_sf = 0xc0; break;
740 case 192000: i2s_sf = 0xe0; break;
741 default:
742 return -EINVAL;
743 }
744
745 /* Set sampling frequency for I2S audio to 48 kHz */
746 ad9389b_wr_and_or(sd, 0x15, 0xf, i2s_sf);
747
748 return 0;
749}
750
751static int ad9389b_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config)
752{
753 /* TODO based on input/output/config */
754 /* TODO See datasheet "Programmers guide" p. 39-40 */
755
756 /* Only 2 channels in use for application */
757 ad9389b_wr_and_or(sd, 0x50, 0x1f, 0x20);
758 /* Speaker mapping */
759 ad9389b_wr(sd, 0x51, 0x00);
760
761 /* TODO Where should this be placed? */
762 /* 16 bit audio word length */
763 ad9389b_wr_and_or(sd, 0x14, 0xf0, 0x02);
764
765 return 0;
766}
767
768static const struct v4l2_subdev_audio_ops ad9389b_audio_ops = {
769 .s_stream = ad9389b_s_audio_stream,
770 .s_clock_freq = ad9389b_s_clock_freq,
771 .s_i2s_clock_freq = ad9389b_s_i2s_clock_freq,
772 .s_routing = ad9389b_s_routing,
773};
774
775/* --------------------- SUBDEV OPS --------------------------------------- */
776
777static const struct v4l2_subdev_ops ad9389b_ops = {
778 .core = &ad9389b_core_ops,
779 .video = &ad9389b_video_ops,
780 .audio = &ad9389b_audio_ops,
781 .pad = &ad9389b_pad_ops,
782};
783
784/* ----------------------------------------------------------------------- */
785static void ad9389b_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd,
786 int segment, u8 *buf)
787{
788 int i, j;
789
790 if (debug < lvl)
791 return;
792
793 v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment);
794 for (i = 0; i < 256; i += 16) {
795 u8 b[128];
796 u8 *bp = b;
797
798 if (i == 128)
799 v4l2_dbg(lvl, debug, sd, "\n");
800 for (j = i; j < i + 16; j++) {
801 sprintf(bp, "0x%02x, ", buf[j]);
802 bp += 6;
803 }
804 bp[0] = '\0';
805 v4l2_dbg(lvl, debug, sd, "%s\n", b);
806 }
807}
808
809static void ad9389b_edid_handler(struct work_struct *work)
810{
811 struct delayed_work *dwork = to_delayed_work(work);
812 struct ad9389b_state *state =
813 container_of(dwork, struct ad9389b_state, edid_handler);
814 struct v4l2_subdev *sd = &state->sd;
815 struct ad9389b_edid_detect ed;
816
817 v4l2_dbg(1, debug, sd, "%s:\n", __func__);
818
819 if (ad9389b_check_edid_status(sd)) {
820 /* Return if we received the EDID. */
821 return;
822 }
823
824 if (ad9389b_have_hotplug(sd)) {
825 /* We must retry reading the EDID several times, it is possible
826 * that initially the EDID couldn't be read due to i2c errors
827 * (DVI connectors are particularly prone to this problem). */
828 if (state->edid.read_retries) {
829 state->edid.read_retries--;
830 v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__);
831 ad9389b_s_power(sd, false);
832 ad9389b_s_power(sd, true);
833 schedule_delayed_work(&state->edid_handler, EDID_DELAY);
834 return;
835 }
836 }
837
838 /* We failed to read the EDID, so send an event for this. */
839 ed.present = false;
840 ed.segment = ad9389b_rd(sd, 0xc4);
841 v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed);
842 v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__);
843}
844
845static void ad9389b_audio_setup(struct v4l2_subdev *sd)
846{
847 v4l2_dbg(1, debug, sd, "%s\n", __func__);
848
849 ad9389b_s_i2s_clock_freq(sd, 48000);
850 ad9389b_s_clock_freq(sd, 48000);
851 ad9389b_s_routing(sd, 0, 0, 0);
852}
853
854/* Initial setup of AD9389b */
855
856/* Configure hdmi transmitter. */
857static void ad9389b_setup(struct v4l2_subdev *sd)
858{
859 struct ad9389b_state *state = get_ad9389b_state(sd);
860
861 v4l2_dbg(1, debug, sd, "%s\n", __func__);
862
863 /* Input format: RGB 4:4:4 */
864 ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0);
865 /* Output format: RGB 4:4:4 */
866 ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0);
867 /* 1st order interpolation 4:2:2 -> 4:4:4 up conversion,
868 Aspect ratio: 16:9 */
869 ad9389b_wr_and_or(sd, 0x17, 0xf9, 0x06);
870 /* Output format: RGB 4:4:4, Active Format Information is valid. */
871 ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08);
872 /* Underscanned */
873 ad9389b_wr_and_or(sd, 0x46, 0x3f, 0x80);
874 /* Setup video format */
875 ad9389b_wr(sd, 0x3c, 0x0);
876 /* Active format aspect ratio: same as picure. */
877 ad9389b_wr(sd, 0x47, 0x80);
878 /* No encryption */
879 ad9389b_wr_and_or(sd, 0xaf, 0xef, 0x0);
880 /* Positive clk edge capture for input video clock */
881 ad9389b_wr_and_or(sd, 0xba, 0x1f, 0x60);
882
883 ad9389b_audio_setup(sd);
884
885 v4l2_ctrl_handler_setup(&state->hdl);
886
887 ad9389b_set_IT_content_AVI_InfoFrame(sd);
888}
889
890static void ad9389b_notify_monitor_detect(struct v4l2_subdev *sd)
891{
892 struct ad9389b_monitor_detect mdt;
893 struct ad9389b_state *state = get_ad9389b_state(sd);
894
895 mdt.present = state->have_monitor;
896 v4l2_subdev_notify(sd, AD9389B_MONITOR_DETECT, (void *)&mdt);
897}
898
899static void ad9389b_update_monitor_present_status(struct v4l2_subdev *sd)
900{
901 struct ad9389b_state *state = get_ad9389b_state(sd);
902 /* read hotplug and rx-sense state */
903 u8 status = ad9389b_rd(sd, 0x42);
904
905 v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n",
906 __func__,
907 status,
908 status & MASK_AD9389B_HPD_DETECT ? ", hotplug" : "",
909 status & MASK_AD9389B_MSEN_DETECT ? ", rx-sense" : "");
910
911 if (status & MASK_AD9389B_HPD_DETECT) {
912 v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__);
913 state->have_monitor = true;
914 if (!ad9389b_s_power(sd, true)) {
915 v4l2_dbg(1, debug, sd,
916 "%s: monitor detected, powerup failed\n", __func__);
917 return;
918 }
919 ad9389b_setup(sd);
920 ad9389b_notify_monitor_detect(sd);
921 state->edid.read_retries = EDID_MAX_RETRIES;
922 schedule_delayed_work(&state->edid_handler, EDID_DELAY);
923 } else if (!(status & MASK_AD9389B_HPD_DETECT)) {
924 v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__);
925 state->have_monitor = false;
926 ad9389b_notify_monitor_detect(sd);
927 ad9389b_s_power(sd, false);
928 memset(&state->edid, 0, sizeof(struct ad9389b_state_edid));
929 }
930
931 /* update read only ctrls */
932 v4l2_ctrl_s_ctrl(state->hotplug_ctrl, ad9389b_have_hotplug(sd) ? 0x1 : 0x0);
933 v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, ad9389b_have_rx_sense(sd) ? 0x1 : 0x0);
934 v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
935
936 /* update with setting from ctrls */
937 ad9389b_s_ctrl(state->rgb_quantization_range_ctrl);
938 ad9389b_s_ctrl(state->hdmi_mode_ctrl);
939}
940
941static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd)
942{
943 struct ad9389b_state *state = get_ad9389b_state(sd);
944 int retry = 0;
945
946 ad9389b_update_monitor_present_status(sd);
947
948 /*
949 * Rapid toggling of the hotplug may leave the chip powered off,
950 * even if we think it is on. In that case reset and power up again.
951 */
952 while (state->power_on && (ad9389b_rd(sd, 0x41) & 0x40)) {
953 if (++retry > 5) {
954 v4l2_err(sd, "retried %d times, give up\n", retry);
955 return;
956 }
957 v4l2_dbg(1, debug, sd, "%s: reset and re-check status (%d)\n", __func__, retry);
958 ad9389b_notify_monitor_detect(sd);
959 cancel_delayed_work_sync(&state->edid_handler);
960 memset(&state->edid, 0, sizeof(struct ad9389b_state_edid));
961 ad9389b_s_power(sd, false);
962 ad9389b_update_monitor_present_status(sd);
963 }
964}
965
966static bool edid_block_verify_crc(u8 *edid_block)
967{
968 u8 sum = 0;
969 int i;
970
971 for (i = 0; i < 128; i++)
972 sum += edid_block[i];
973 return sum == 0;
974}
975
976static bool edid_verify_crc(struct v4l2_subdev *sd, u32 segment)
977{
978 struct ad9389b_state *state = get_ad9389b_state(sd);
979 u32 blocks = state->edid.blocks;
980 u8 *data = state->edid.data;
981
982 if (edid_block_verify_crc(&data[segment * 256])) {
983 if ((segment + 1) * 2 <= blocks)
984 return edid_block_verify_crc(&data[segment * 256 + 128]);
985 return true;
986 }
987 return false;
988}
989
990static bool edid_verify_header(struct v4l2_subdev *sd, u32 segment)
991{
992 static const u8 hdmi_header[] = {
993 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
994 };
995 struct ad9389b_state *state = get_ad9389b_state(sd);
996 u8 *data = state->edid.data;
997 int i;
998
999 if (segment)
1000 return true;
1001
1002 for (i = 0; i < ARRAY_SIZE(hdmi_header); i++)
1003 if (data[i] != hdmi_header[i])
1004 return false;
1005
1006 return true;
1007}
1008
1009static bool ad9389b_check_edid_status(struct v4l2_subdev *sd)
1010{
1011 struct ad9389b_state *state = get_ad9389b_state(sd);
1012 struct ad9389b_edid_detect ed;
1013 int segment;
1014 u8 edidRdy = ad9389b_rd(sd, 0xc5);
1015
1016 v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n",
1017 __func__, EDID_MAX_RETRIES - state->edid.read_retries);
1018
1019 if (!(edidRdy & MASK_AD9389B_EDID_RDY))
1020 return false;
1021
1022 segment = ad9389b_rd(sd, 0xc4);
1023 if (segment >= EDID_MAX_SEGM) {
1024 v4l2_err(sd, "edid segment number too big\n");
1025 return false;
1026 }
1027 v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment);
1028 ad9389b_edid_rd(sd, 256, &state->edid.data[segment * 256]);
1029 ad9389b_dbg_dump_edid(2, debug, sd, segment,
1030 &state->edid.data[segment * 256]);
1031 if (segment == 0) {
1032 state->edid.blocks = state->edid.data[0x7e] + 1;
1033 v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n",
1034 __func__, state->edid.blocks);
1035 }
1036 if (!edid_verify_crc(sd, segment) ||
1037 !edid_verify_header(sd, segment)) {
1038 /* edid crc error, force reread of edid segment */
1039 v4l2_err(sd, "%s: edid crc or header error\n", __func__);
1040 ad9389b_s_power(sd, false);
1041 ad9389b_s_power(sd, true);
1042 return false;
1043 }
1044 /* one more segment read ok */
1045 state->edid.segments = segment + 1;
1046 if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) {
1047 /* Request next EDID segment */
1048 v4l2_dbg(1, debug, sd, "%s: request segment %d\n",
1049 __func__, state->edid.segments);
1050 ad9389b_wr(sd, 0xc9, 0xf);
1051 ad9389b_wr(sd, 0xc4, state->edid.segments);
1052 state->edid.read_retries = EDID_MAX_RETRIES;
1053 schedule_delayed_work(&state->edid_handler, EDID_DELAY);
1054 return false;
1055 }
1056
1057 /* report when we have all segments but report only for segment 0 */
1058 ed.present = true;
1059 ed.segment = 0;
1060 v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed);
1061 state->edid_detect_counter++;
1062 v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
1063 return ed.present;
1064}
1065
1066/* ----------------------------------------------------------------------- */
1067
1068static void ad9389b_init_setup(struct v4l2_subdev *sd)
1069{
1070 struct ad9389b_state *state = get_ad9389b_state(sd);
1071 struct ad9389b_state_edid *edid = &state->edid;
1072
1073 v4l2_dbg(1, debug, sd, "%s\n", __func__);
1074
1075 /* clear all interrupts */
1076 ad9389b_wr(sd, 0x96, 0xff);
1077
1078 memset(edid, 0, sizeof(struct ad9389b_state_edid));
1079 state->have_monitor = false;
1080 ad9389b_set_isr(sd, false);
1081}
1082
1083static int ad9389b_probe(struct i2c_client *client)
1084{
1085 const struct v4l2_dv_timings dv1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
1086 struct ad9389b_state *state;
1087 struct ad9389b_platform_data *pdata = client->dev.platform_data;
1088 struct v4l2_ctrl_handler *hdl;
1089 struct v4l2_subdev *sd;
1090 int err = -EIO;
1091
1092 /* Check if the adapter supports the needed features */
1093 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1094 return -EIO;
1095
1096 v4l_dbg(1, debug, client, "detecting ad9389b client on address 0x%x\n",
1097 client->addr << 1);
1098
1099 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
1100 if (!state)
1101 return -ENOMEM;
1102
1103 /* Platform data */
1104 if (pdata == NULL) {
1105 v4l_err(client, "No platform data!\n");
1106 return -ENODEV;
1107 }
1108 memcpy(&state->pdata, pdata, sizeof(state->pdata));
1109
1110 sd = &state->sd;
1111 v4l2_i2c_subdev_init(sd, client, &ad9389b_ops);
1112 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1113
1114 hdl = &state->hdl;
1115 v4l2_ctrl_handler_init(hdl, 5);
1116
1117 state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
1118 V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
1119 0, V4L2_DV_TX_MODE_DVI_D);
1120 state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL,
1121 V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0);
1122 state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL,
1123 V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0);
1124 state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL,
1125 V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0);
1126 state->rgb_quantization_range_ctrl =
1127 v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
1128 V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
1129 0, V4L2_DV_RGB_RANGE_AUTO);
1130 sd->ctrl_handler = hdl;
1131 if (hdl->error) {
1132 err = hdl->error;
1133
1134 goto err_hdl;
1135 }
1136 state->pad.flags = MEDIA_PAD_FL_SINK;
1137 sd->entity.function = MEDIA_ENT_F_DV_ENCODER;
1138 err = media_entity_pads_init(&sd->entity, 1, &state->pad);
1139 if (err)
1140 goto err_hdl;
1141
1142 state->chip_revision = ad9389b_rd(sd, 0x0);
1143 if (state->chip_revision != 2) {
1144 v4l2_err(sd, "chip_revision %d != 2\n", state->chip_revision);
1145 err = -EIO;
1146 goto err_entity;
1147 }
1148 v4l2_dbg(1, debug, sd, "reg 0x41 0x%x, chip version (reg 0x00) 0x%x\n",
1149 ad9389b_rd(sd, 0x41), state->chip_revision);
1150
1151 state->edid_i2c_client = i2c_new_dummy_device(client->adapter, (0x7e >> 1));
1152 if (IS_ERR(state->edid_i2c_client)) {
1153 v4l2_err(sd, "failed to register edid i2c client\n");
1154 err = PTR_ERR(state->edid_i2c_client);
1155 goto err_entity;
1156 }
1157
1158 INIT_DELAYED_WORK(&state->edid_handler, ad9389b_edid_handler);
1159 state->dv_timings = dv1080p60;
1160
1161 ad9389b_init_setup(sd);
1162 ad9389b_set_isr(sd, true);
1163
1164 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
1165 client->addr << 1, client->adapter->name);
1166 return 0;
1167
1168err_entity:
1169 media_entity_cleanup(&sd->entity);
1170err_hdl:
1171 v4l2_ctrl_handler_free(&state->hdl);
1172 return err;
1173}
1174
1175/* ----------------------------------------------------------------------- */
1176
1177static void ad9389b_remove(struct i2c_client *client)
1178{
1179 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1180 struct ad9389b_state *state = get_ad9389b_state(sd);
1181
1182 state->chip_revision = -1;
1183
1184 v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
1185 client->addr << 1, client->adapter->name);
1186
1187 ad9389b_s_stream(sd, false);
1188 ad9389b_s_audio_stream(sd, false);
1189 ad9389b_init_setup(sd);
1190 cancel_delayed_work_sync(&state->edid_handler);
1191 i2c_unregister_device(state->edid_i2c_client);
1192 v4l2_device_unregister_subdev(sd);
1193 media_entity_cleanup(&sd->entity);
1194 v4l2_ctrl_handler_free(sd->ctrl_handler);
1195}
1196
1197/* ----------------------------------------------------------------------- */
1198
1199static const struct i2c_device_id ad9389b_id[] = {
1200 { "ad9389b", 0 },
1201 { "ad9889b", 0 },
1202 { }
1203};
1204MODULE_DEVICE_TABLE(i2c, ad9389b_id);
1205
1206static struct i2c_driver ad9389b_driver = {
1207 .driver = {
1208 .name = "ad9389b",
1209 },
1210 .probe_new = ad9389b_probe,
1211 .remove = ad9389b_remove,
1212 .id_table = ad9389b_id,
1213};
1214
1215module_i2c_driver(ad9389b_driver);
drivers/media/i2c/adv748x/adv748x-hdmi.c+15−6
@@ -176,9 +176,9 @@ static int adv748x_hdmi_set_video_timings(struct adv748x_state *state, · 175 unmodified lines
176 unsigned int i;176 unsigned int i;
177 177
178 for (i = 0; i < ARRAY_SIZE(adv748x_hdmi_video_standards); i++) {178 for (i = 0; i < ARRAY_SIZE(adv748x_hdmi_video_standards); i++) {
179 if (!v4l2_match_dv_timings(timings, &stds[i].timings, 250000,179 if (v4l2_match_dv_timings(timings, &stds[i].timings, 250000,
180 false))180 false))
181 continue;181 break;
182 }182 }
183 183
184 if (i >= ARRAY_SIZE(adv748x_hdmi_video_standards))184 if (i >= ARRAY_SIZE(adv748x_hdmi_video_standards))
@@ -283,6 +283,16 @@ static int adv748x_hdmi_query_dv_timings(struct v4l2_subdev *sd, · 98 unmodified lines
283 283
284 memset(timings, 0, sizeof(struct v4l2_dv_timings));284 memset(timings, 0, sizeof(struct v4l2_dv_timings));
285 285
286 /*
287 * If the pattern generator is enabled the device shall not be queried
288 * for timings. Instead the timings programmed shall be reported as they
289 * are the ones being used to generate the pattern.
290 */
291 if (cp_read(state, ADV748X_CP_PAT_GEN) & ADV748X_CP_PAT_GEN_EN) {
292 *timings = hdmi->timings;
293 return 0;
294 }
295
286 if (!adv748x_hdmi_has_signal(state))296 if (!adv748x_hdmi_has_signal(state))
287 return -ENOLINK;297 return -ENOLINK;
288 298
@@ -721,11 +731,10 @@ static int adv748x_hdmi_init_controls(struct adv748x_hdmi *hdmi) · 432 unmodified lines
721int adv748x_hdmi_init(struct adv748x_hdmi *hdmi)731int adv748x_hdmi_init(struct adv748x_hdmi *hdmi)
722{732{
723 struct adv748x_state *state = adv748x_hdmi_to_state(hdmi);733 struct adv748x_state *state = adv748x_hdmi_to_state(hdmi);
724 static const struct v4l2_dv_timings cea1280x720 =734 struct v4l2_dv_timings cea1280x720 = V4L2_DV_BT_CEA_1280X720P30;
725 V4L2_DV_BT_CEA_1280X720P30;
726 int ret;735 int ret;
727 736
728 hdmi->timings = cea1280x720;737 adv748x_hdmi_s_dv_timings(&hdmi->sd, &cea1280x720);
729 738
730 /* Initialise a default 16:9 aspect ratio */739 /* Initialise a default 16:9 aspect ratio */
731 hdmi->aspect_ratio.numerator = 16;740 hdmi->aspect_ratio.numerator = 16;
drivers/media/i2c/adv7604.c+4−1
@@ -1805,6 +1805,9 @@ static void select_input(struct v4l2_subdev *sd) · 1804 unmodified lines
1805 v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",1805 v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
1806 __func__, state->selected_input);1806 __func__, state->selected_input);
1807 }1807 }
1808
1809 /* Enable video adjustment (contrast, saturation, brightness and hue) */
1810 cp_write_clr_set(sd, 0x3e, 0x80, 0x80);
1808}1811}
1809 1812
1810static int adv76xx_s_routing(struct v4l2_subdev *sd,1813static int adv76xx_s_routing(struct v4l2_subdev *sd,
@@ -3545,7 +3548,7 @@ static int adv76xx_probe(struct i2c_client *client) · 1734 unmodified lines
3545 v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,3548 v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
3546 V4L2_CID_SATURATION, 0, 255, 1, 128);3549 V4L2_CID_SATURATION, 0, 255, 1, 128);
3547 v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,3550 v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
3548 V4L2_CID_HUE, 0, 128, 1, 0);3551 V4L2_CID_HUE, 0, 255, 1, 0);
3549 ctrl = v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops,3552 ctrl = v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops,
3550 V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC,3553 V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_DV_IT_CONTENT_TYPE_NO_ITC,
3551 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC);3554 0, V4L2_DV_IT_CONTENT_TYPE_NO_ITC);
drivers/media/i2c/ccs/ccs-core.c+83−74
@@ -569,8 +569,6 @@ static u32 ccs_pixel_order(struct ccs_sensor *sensor) · 568 unmodified lines
569 flip |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP;569 flip |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP;
570 }570 }
571 571
572 flip ^= sensor->hvflip_inv_mask;
573
574 dev_dbg(&client->dev, "flip %u\n", flip);572 dev_dbg(&client->dev, "flip %u\n", flip);
575 return sensor->default_pixel_order ^ flip;573 return sensor->default_pixel_order ^ flip;
576}574}
@@ -632,8 +630,6 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl) · 55 unmodified lines
632 if (sensor->vflip->val)630 if (sensor->vflip->val)
633 orient |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP;631 orient |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP;
634 632
635 orient ^= sensor->hvflip_inv_mask;
636
637 ccs_update_mbus_formats(sensor);633 ccs_update_mbus_formats(sensor);
638 634
639 break;635 break;
@@ -800,14 +796,24 @@ static const struct v4l2_ctrl_ops ccs_ctrl_ops = { · 160 unmodified lines
800static int ccs_init_controls(struct ccs_sensor *sensor)796static int ccs_init_controls(struct ccs_sensor *sensor)
801{797{
802 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);798 struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
799 struct v4l2_fwnode_device_properties props;
803 int rval;800 int rval;
804 801
805 rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 17);802 rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 19);
806 if (rval)803 if (rval)
807 return rval;804 return rval;
808 805
809 sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;806 sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
810 807
808 rval = v4l2_fwnode_device_parse(&client->dev, &props);
809 if (rval)
810 return rval;
811
812 rval = v4l2_ctrl_new_fwnode_properties(&sensor->pixel_array->ctrl_handler,
813 &ccs_ctrl_ops, &props);
814 if (rval)
815 return rval;
816
811 switch (CCS_LIM(sensor, ANALOG_GAIN_CAPABILITY)) {817 switch (CCS_LIM(sensor, ANALOG_GAIN_CAPABILITY)) {
812 case CCS_ANALOG_GAIN_CAPABILITY_GLOBAL: {818 case CCS_ANALOG_GAIN_CAPABILITY_GLOBAL: {
813 struct {819 struct {
@@ -2828,6 +2834,10 @@ static int ccs_identify_module(struct ccs_sensor *sensor) · 2014 unmodified lines
2828 rval = ccs_read_addr_8only(sensor,2834 rval = ccs_read_addr_8only(sensor,
2829 CCS_R_SENSOR_REVISION_NUMBER,2835 CCS_R_SENSOR_REVISION_NUMBER,
2830 &minfo->sensor_revision_number);2836 &minfo->sensor_revision_number);
2837 if (!rval && !minfo->sensor_revision_number)
2838 rval = ccs_read_addr_8only(sensor,
2839 CCS_R_SENSOR_REVISION_NUMBER_16,
2840 &minfo->sensor_revision_number);
2831 if (!rval)2841 if (!rval)
2832 rval = ccs_read_addr_8only(sensor,2842 rval = ccs_read_addr_8only(sensor,
2833 CCS_R_SENSOR_FIRMWARE_VERSION,2843 CCS_R_SENSOR_FIRMWARE_VERSION,
@@ -2870,7 +2880,7 @@ static int ccs_identify_module(struct ccs_sensor *sensor) · 36 unmodified lines
2870 minfo->sensor_model_id);2880 minfo->sensor_model_id);
2871 2881
2872 dev_dbg(&client->dev,2882 dev_dbg(&client->dev,
2873 "sensor revision 0x%2.2x firmware version 0x%2.2x\n",2883 "sensor revision 0x%4.4x firmware version 0x%2.2x\n",
2874 minfo->sensor_revision_number, minfo->sensor_firmware_version);2884 minfo->sensor_revision_number, minfo->sensor_firmware_version);
2875 2885
2876 if (minfo->ccs_version) {2886 if (minfo->ccs_version) {
@@ -2884,19 +2894,18 @@ static int ccs_identify_module(struct ccs_sensor *sensor) · 7 unmodified lines
2884 "smia version %2.2d smiapp version %2.2d\n",2894 "smia version %2.2d smiapp version %2.2d\n",
2885 minfo->smia_version, minfo->smiapp_version);2895 minfo->smia_version, minfo->smiapp_version);
2886 minfo->name = SMIAPP_NAME;2896 minfo->name = SMIAPP_NAME;
2887 }2897 /*
2888 2898 * Some modules have bad data in the lvalues below. Hope the
2889 /*2899 * rvalues have better stuff. The lvalues are module
2890 * Some modules have bad data in the lvalues below. Hope the2900 * parameters whereas the rvalues are sensor parameters.
2891 * rvalues have better stuff. The lvalues are module2901 */
2892 * parameters whereas the rvalues are sensor parameters.2902 if (minfo->sensor_smia_manufacturer_id &&
2893 */2903 !minfo->smia_manufacturer_id && !minfo->model_id) {
2894 if (minfo->sensor_smia_manufacturer_id &&2904 minfo->smia_manufacturer_id =
2895 !minfo->smia_manufacturer_id && !minfo->model_id) {2905 minfo->sensor_smia_manufacturer_id;
2896 minfo->smia_manufacturer_id =2906 minfo->model_id = minfo->sensor_model_id;
2897 minfo->sensor_smia_manufacturer_id;2907 minfo->revision_number = minfo->sensor_revision_number;
2898 minfo->model_id = minfo->sensor_model_id;2908 }
2899 minfo->revision_number = minfo->sensor_revision_number;
2900 }2909 }
2901 2910
2902 for (i = 0; i < ARRAY_SIZE(ccs_module_idents); i++) {2911 for (i = 0; i < ARRAY_SIZE(ccs_module_idents); i++) {
@@ -3185,7 +3194,6 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev) · 282 unmodified lines
3185 struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_UNKNOWN };3194 struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_UNKNOWN };
3186 struct fwnode_handle *ep;3195 struct fwnode_handle *ep;
3187 struct fwnode_handle *fwnode = dev_fwnode(dev);3196 struct fwnode_handle *fwnode = dev_fwnode(dev);
3188 u32 rotation;
3189 unsigned int i;3197 unsigned int i;
3190 int rval;3198 int rval;
3191 3199
@@ -3224,22 +3232,6 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev) · 32 unmodified lines
3224 goto out_err;3232 goto out_err;
3225 }3233 }
3226 3234
3227 rval = fwnode_property_read_u32(fwnode, "rotation", &rotation);
3228 if (!rval) {
3229 switch (rotation) {
3230 case 180:
3231 hwcfg->module_board_orient =
3232 CCS_MODULE_BOARD_ORIENT_180;
3233 fallthrough;
3234 case 0:
3235 break;
3236 default:
3237 dev_err(dev, "invalid rotation %u\n", rotation);
3238 rval = -EINVAL;
3239 goto out_err;
3240 }
3241 }
3242
3243 rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",3235 rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
3244 &hwcfg->ext_clk);3236 &hwcfg->ext_clk);
3245 if (rval)3237 if (rval)
@@ -3279,8 +3271,47 @@ out_err: · 33 unmodified lines
3279 return rval;3271 return rval;
3280}3272}
3281 3273
3274static int ccs_firmware_name(struct i2c_client *client,
3275 struct ccs_sensor *sensor, char *filename,
3276 size_t filename_size, bool is_module)
3277{
3278 const struct ccs_device *ccsdev = device_get_match_data(&client->dev);
3279 bool is_ccs = !(ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA);
3280 bool is_smiapp = sensor->minfo.smiapp_version;
3281 u16 manufacturer_id;
3282 u16 model_id;
3283 u16 revision_number;
3284
3285 /*
3286 * Old SMIA is module-agnostic. Its sensor identification is based on
3287 * what now are those of the module.
3288 */
3289 if (is_module || (!is_ccs && !is_smiapp)) {
3290 manufacturer_id = is_ccs ?
3291 sensor->minfo.mipi_manufacturer_id :
3292 sensor->minfo.smia_manufacturer_id;
3293 model_id = sensor->minfo.model_id;
3294 revision_number = sensor->minfo.revision_number;
3295 } else {
3296 manufacturer_id = is_ccs ?
3297 sensor->minfo.sensor_mipi_manufacturer_id :
3298 sensor->minfo.sensor_smia_manufacturer_id;
3299 model_id = sensor->minfo.sensor_model_id;
3300 revision_number = sensor->minfo.sensor_revision_number;
3301 }
3302
3303 return snprintf(filename, filename_size,
3304 "ccs/%s-%s-%0*x-%4.4x-%0*x.fw",
3305 is_ccs ? "ccs" : is_smiapp ? "smiapp" : "smia",
3306 is_module || (!is_ccs && !is_smiapp) ?
3307 "module" : "sensor",
3308 is_ccs ? 4 : 2, manufacturer_id, model_id,
3309 !is_ccs && !is_module ? 2 : 4, revision_number);
3310}
3311
3282static int ccs_probe(struct i2c_client *client)3312static int ccs_probe(struct i2c_client *client)
3283{3313{
3314 const struct ccs_device *ccsdev = device_get_match_data(&client->dev);
3284 struct ccs_sensor *sensor;3315 struct ccs_sensor *sensor;
3285 const struct firmware *fw;3316 const struct firmware *fw;
3286 char filename[40];3317 char filename[40];
@@ -3389,11 +3420,8 @@ static int ccs_probe(struct i2c_client *client) · 102 unmodified lines
3389 goto out_power_off;3420 goto out_power_off;
3390 }3421 }
3391 3422
3392 rval = snprintf(filename, sizeof(filename),3423 rval = ccs_firmware_name(client, sensor, filename, sizeof(filename),
3393 "ccs/ccs-sensor-%4.4x-%4.4x-%4.4x.fw",3424 false);
3394 sensor->minfo.sensor_mipi_manufacturer_id,
3395 sensor->minfo.sensor_model_id,
3396 sensor->minfo.sensor_revision_number);
3397 if (rval >= sizeof(filename)) {3425 if (rval >= sizeof(filename)) {
3398 rval = -ENOMEM;3426 rval = -ENOMEM;
3399 goto out_power_off;3427 goto out_power_off;
@@ -3406,21 +3434,21 @@ static int ccs_probe(struct i2c_client *client) · 6 unmodified lines
3406 release_firmware(fw);3434 release_firmware(fw);
3407 }3435 }
3408 3436
3409 rval = snprintf(filename, sizeof(filename),3437 if (!(ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA) ||
3410 "ccs/ccs-module-%4.4x-%4.4x-%4.4x.fw",3438 sensor->minfo.smiapp_version) {
3411 sensor->minfo.mipi_manufacturer_id,3439 rval = ccs_firmware_name(client, sensor, filename,
3412 sensor->minfo.model_id,3440 sizeof(filename), true);
3413 sensor->minfo.revision_number);3441 if (rval >= sizeof(filename)) {
3414 if (rval >= sizeof(filename)) {3442 rval = -ENOMEM;
3415 rval = -ENOMEM;3443 goto out_release_sdata;
3416 goto out_release_sdata;3444 }
3417 }
3418 3445
3419 rval = request_firmware(&fw, filename, &client->dev);3446 rval = request_firmware(&fw, filename, &client->dev);
3420 if (!rval) {3447 if (!rval) {
3421 ccs_data_parse(&sensor->mdata, fw->data, fw->size, &client->dev,3448 ccs_data_parse(&sensor->mdata, fw->data, fw->size,
3422 true);3449 &client->dev, true);
3423 release_firmware(fw);3450 release_firmware(fw);
3451 }
3424 }3452 }
3425 3453
3426 rval = ccs_read_all_limits(sensor);3454 rval = ccs_read_all_limits(sensor);
@@ -3437,25 +3465,6 @@ static int ccs_probe(struct i2c_client *client) · 10 unmodified lines
3437 if (rval < 0)3465 if (rval < 0)
3438 goto out_free_ccs_limits;3466 goto out_free_ccs_limits;
3439 3467
3440 /*
3441 * Handle Sensor Module orientation on the board.
3442 *
3443 * The application of H-FLIP and V-FLIP on the sensor is modified by
3444 * the sensor orientation on the board.
3445 *
3446 * For CCS_BOARD_SENSOR_ORIENT_180 the default behaviour is to set
3447 * both H-FLIP and V-FLIP for normal operation which also implies
3448 * that a set/unset operation for user space HFLIP and VFLIP v4l2
3449 * controls will need to be internally inverted.
3450 *
3451 * Rotation also changes the bayer pattern.
3452 */
3453 if (sensor->hwcfg.module_board_orient ==
3454 CCS_MODULE_BOARD_ORIENT_180)
3455 sensor->hvflip_inv_mask =
3456 CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR |
3457 CCS_IMAGE_ORIENTATION_VERTICAL_FLIP;
3458
3459 rval = ccs_call_quirk(sensor, limits);3468 rval = ccs_call_quirk(sensor, limits);
3460 if (rval) {3469 if (rval) {
3461 dev_err(&client->dev, "limits quirks failed\n");3470 dev_err(&client->dev, "limits quirks failed\n");
drivers/media/i2c/ccs/ccs.h+0−14
@@ -57,17 +57,6 @@ · 56 unmodified lines
57#define CCS_LIM_AT(sensor, limit, offset) \57#define CCS_LIM_AT(sensor, limit, offset) \
58 ccs_get_limit(sensor, CCS_L_##limit, CCS_L_##limit##_OFFSET(offset))58 ccs_get_limit(sensor, CCS_L_##limit, CCS_L_##limit##_OFFSET(offset))
59 59
60/*
61 * Sometimes due to board layout considerations the camera module can be
62 * mounted rotated. The typical rotation used is 180 degrees which can be
63 * corrected by giving a default H-FLIP and V-FLIP in the sensor readout.
64 * FIXME: rotation also changes the bayer pattern.
65 */
66enum ccs_module_board_orient {
67 CCS_MODULE_BOARD_ORIENT_0 = 0,
68 CCS_MODULE_BOARD_ORIENT_180,
69};
70
71struct ccs_flash_strobe_parms {60struct ccs_flash_strobe_parms {
72 u8 mode;61 u8 mode;
73 u32 strobe_width_high_us;62 u32 strobe_width_high_us;
@@ -90,8 +79,6 @@ struct ccs_hwconfig { · 16 unmodified lines
90 u32 csi_signalling_mode; /* CCS_CSI_SIGNALLING_MODE_* */79 u32 csi_signalling_mode; /* CCS_CSI_SIGNALLING_MODE_* */
91 u64 *op_sys_clock;80 u64 *op_sys_clock;
92 81
93 enum ccs_module_board_orient module_board_orient;
94
95 struct ccs_flash_strobe_parms *strobe_setup;82 struct ccs_flash_strobe_parms *strobe_setup;
96};83};
97 84
@@ -243,7 +230,6 @@ struct ccs_sensor { · 145 unmodified lines
243 u8 scale_m;230 u8 scale_m;
244 u8 scaling_mode;231 u8 scaling_mode;
245 232
246 u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
247 u8 frame_skip;233 u8 frame_skip;
248 u16 embedded_start; /* embedded data start line */234 u16 embedded_start; /* embedded data start line */
249 u16 embedded_end;235 u16 embedded_end;
drivers/media/i2c/hi556.c+148−2
@@ -63,6 +63,14 @@ · 62 unmodified lines
63#define HI556_REG_ISP_TPG_EN 0x0163#define HI556_REG_ISP_TPG_EN 0x01
64#define HI556_REG_TEST_PATTERN 0x020164#define HI556_REG_TEST_PATTERN 0x0201
65 65
66/* HI556 native and active pixel array size. */
67#define HI556_NATIVE_WIDTH 2592U
68#define HI556_NATIVE_HEIGHT 1944U
69#define HI556_PIXEL_ARRAY_LEFT 0U
70#define HI556_PIXEL_ARRAY_TOP 0U
71#define HI556_PIXEL_ARRAY_WIDTH 2592U
72#define HI556_PIXEL_ARRAY_HEIGHT 1944U
73
66enum {74enum {
67 HI556_LINK_FREQ_437MHZ_INDEX,75 HI556_LINK_FREQ_437MHZ_INDEX,
68};76};
@@ -88,6 +96,9 @@ struct hi556_mode { · 19 unmodified lines
88 /* Frame height in pixels */96 /* Frame height in pixels */
89 u32 height;97 u32 height;
90 98
99 /* Analog crop rectangle. */
100 struct v4l2_rect crop;
101
91 /* Horizontal timining size */102 /* Horizontal timining size */
92 u32 llp;103 u32 llp;
93 104
@@ -378,6 +389,49 @@ static const struct hi556_reg mode_2592x1944_regs[] = { · 284 unmodified lines
378 {0x0958, 0xbb80},389 {0x0958, 0xbb80},
379};390};
380 391
392static const struct hi556_reg mode_2592x1444_regs[] = {
393 {0x0a00, 0x0000},
394 {0x0b0a, 0x8252},
395 {0x0f30, 0xe545},
396 {0x0f32, 0x7067},
397 {0x004a, 0x0100},
398 {0x004c, 0x0000},
399 {0x000c, 0x0022},
400 {0x0008, 0x0b00},
401 {0x005a, 0x0202},
402 {0x0012, 0x000e},
403 {0x0018, 0x0a33},
404 {0x0022, 0x0008},
405 {0x0028, 0x0017},
406 {0x0024, 0x0122},
407 {0x002a, 0x0127},
408 {0x0026, 0x012a},
409 {0x002c, 0x06cf},
410 {0x002e, 0x1111},
411 {0x0030, 0x1111},
412 {0x0032, 0x1111},
413 {0x0006, 0x0821},
414 {0x0a22, 0x0000},
415 {0x0a12, 0x0a20},
416 {0x0a14, 0x05a4},
417 {0x003e, 0x0000},
418 {0x0074, 0x081f},
419 {0x0070, 0x040f},
420 {0x0804, 0x0300},
421 {0x0806, 0x0100},
422 {0x0a04, 0x014a},
423 {0x090c, 0x0fdc},
424 {0x090e, 0x002d},
425 {0x0902, 0x4319},
426 {0x0914, 0xc10a},
427 {0x0916, 0x071f},
428 {0x0918, 0x0408},
429 {0x091a, 0x0c0d},
430 {0x091c, 0x0f09},
431 {0x091e, 0x0a00},
432 {0x0958, 0xbb80},
433};
434
381static const struct hi556_reg mode_1296x972_regs[] = {435static const struct hi556_reg mode_1296x972_regs[] = {
382 {0x0a00, 0x0000},436 {0x0a00, 0x0000},
383 {0x0b0a, 0x8259},437 {0x0b0a, 0x8259},
@@ -450,8 +504,14 @@ static const struct hi556_link_freq_config link_freq_configs[] = { · 66 unmodified lines
450 504
451static const struct hi556_mode supported_modes[] = {505static const struct hi556_mode supported_modes[] = {
452 {506 {
453 .width = 2592,507 .width = HI556_PIXEL_ARRAY_WIDTH,
454 .height = 1944,508 .height = HI556_PIXEL_ARRAY_HEIGHT,
509 .crop = {
510 .left = HI556_PIXEL_ARRAY_LEFT,
511 .top = HI556_PIXEL_ARRAY_TOP,
512 .width = HI556_PIXEL_ARRAY_WIDTH,
513 .height = HI556_PIXEL_ARRAY_HEIGHT
514 },
455 .fll_def = HI556_FLL_30FPS,515 .fll_def = HI556_FLL_30FPS,
456 .fll_min = HI556_FLL_30FPS_MIN,516 .fll_min = HI556_FLL_30FPS_MIN,
457 .llp = 0x0b00,517 .llp = 0x0b00,
@@ -461,9 +521,33 @@ static const struct hi556_mode supported_modes[] = { · 3 unmodified lines
461 },521 },
462 .link_freq_index = HI556_LINK_FREQ_437MHZ_INDEX,522 .link_freq_index = HI556_LINK_FREQ_437MHZ_INDEX,
463 },523 },
524 {
525 .width = HI556_PIXEL_ARRAY_WIDTH,
526 .height = 1444,
527 .crop = {
528 .left = HI556_PIXEL_ARRAY_LEFT,
529 .top = 250,
530 .width = HI556_PIXEL_ARRAY_WIDTH,
531 .height = 1444
532 },
533 .fll_def = 0x821,
534 .fll_min = 0x821,
535 .llp = 0x0b00,
536 .reg_list = {
537 .num_of_regs = ARRAY_SIZE(mode_2592x1444_regs),
538 .regs = mode_2592x1444_regs,
539 },
540 .link_freq_index = HI556_LINK_FREQ_437MHZ_INDEX,
541 },
464 {542 {
465 .width = 1296,543 .width = 1296,
466 .height = 972,544 .height = 972,
545 .crop = {
546 .left = HI556_PIXEL_ARRAY_LEFT,
547 .top = HI556_PIXEL_ARRAY_TOP,
548 .width = HI556_PIXEL_ARRAY_WIDTH,
549 .height = HI556_PIXEL_ARRAY_HEIGHT
550 },
467 .fll_def = HI556_FLL_30FPS,551 .fll_def = HI556_FLL_30FPS,
468 .fll_min = HI556_FLL_30FPS_MIN,552 .fll_min = HI556_FLL_30FPS_MIN,
469 .llp = 0x0b00,553 .llp = 0x0b00,
@@ -785,6 +869,58 @@ static int hi556_identify_module(struct hi556 *hi556) · 315 unmodified lines
785 return 0;869 return 0;
786}870}
787 871
872static const struct v4l2_rect *
873__hi556_get_pad_crop(struct hi556 *hi556,
874 struct v4l2_subdev_state *sd_state,
875 unsigned int pad, enum v4l2_subdev_format_whence which)
876{
877 switch (which) {
878 case V4L2_SUBDEV_FORMAT_TRY:
879 return v4l2_subdev_get_try_crop(&hi556->sd, sd_state, pad);
880 case V4L2_SUBDEV_FORMAT_ACTIVE:
881 return &hi556->cur_mode->crop;
882 }
883
884 return NULL;
885}
886
887static int hi556_get_selection(struct v4l2_subdev *sd,
888 struct v4l2_subdev_state *sd_state,
889 struct v4l2_subdev_selection *sel)
890{
891 switch (sel->target) {
892 case V4L2_SEL_TGT_CROP: {
893 struct hi556 *hi556 = to_hi556(sd);
894
895 mutex_lock(&hi556->mutex);
896 sel->r = *__hi556_get_pad_crop(hi556, sd_state, sel->pad,
897 sel->which);
898 mutex_unlock(&hi556->mutex);
899
900 return 0;
901 }
902
903 case V4L2_SEL_TGT_NATIVE_SIZE:
904 sel->r.top = 0;
905 sel->r.left = 0;
906 sel->r.width = HI556_NATIVE_WIDTH;
907 sel->r.height = HI556_NATIVE_HEIGHT;
908
909 return 0;
910
911 case V4L2_SEL_TGT_CROP_DEFAULT:
912 case V4L2_SEL_TGT_CROP_BOUNDS:
913 sel->r.top = HI556_PIXEL_ARRAY_TOP;
914 sel->r.left = HI556_PIXEL_ARRAY_LEFT;
915 sel->r.width = HI556_PIXEL_ARRAY_WIDTH;
916 sel->r.height = HI556_PIXEL_ARRAY_HEIGHT;
917
918 return 0;
919 }
920
921 return -EINVAL;
922}
923
788static int hi556_start_streaming(struct hi556 *hi556)924static int hi556_start_streaming(struct hi556 *hi556)
789{925{
790 struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd);926 struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd);
@@ -1000,10 +1136,19 @@ static int hi556_enum_frame_size(struct v4l2_subdev *sd, · 209 unmodified lines
1000static int hi556_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)1136static int hi556_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1001{1137{
1002 struct hi556 *hi556 = to_hi556(sd);1138 struct hi556 *hi556 = to_hi556(sd);
1139 struct v4l2_rect *try_crop;
1003 1140
1004 mutex_lock(&hi556->mutex);1141 mutex_lock(&hi556->mutex);
1005 hi556_assign_pad_format(&supported_modes[0],1142 hi556_assign_pad_format(&supported_modes[0],
1006 v4l2_subdev_get_try_format(sd, fh->state, 0));1143 v4l2_subdev_get_try_format(sd, fh->state, 0));
1144
1145 /* Initialize try_crop rectangle. */
1146 try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
1147 try_crop->top = HI556_PIXEL_ARRAY_TOP;
1148 try_crop->left = HI556_PIXEL_ARRAY_LEFT;
1149 try_crop->width = HI556_PIXEL_ARRAY_WIDTH;
1150 try_crop->height = HI556_PIXEL_ARRAY_HEIGHT;
1151
1007 mutex_unlock(&hi556->mutex);1152 mutex_unlock(&hi556->mutex);
1008 1153
1009 return 0;1154 return 0;
@@ -1016,6 +1161,7 @@ static const struct v4l2_subdev_video_ops hi556_video_ops = { · 6 unmodified lines
1016static const struct v4l2_subdev_pad_ops hi556_pad_ops = {1161static const struct v4l2_subdev_pad_ops hi556_pad_ops = {
1017 .set_fmt = hi556_set_format,1162 .set_fmt = hi556_set_format,
1018 .get_fmt = hi556_get_format,1163 .get_fmt = hi556_get_format,
1164 .get_selection = hi556_get_selection,
1019 .enum_mbus_code = hi556_enum_mbus_code,1165 .enum_mbus_code = hi556_enum_mbus_code,
1020 .enum_frame_size = hi556_enum_frame_size,1166 .enum_frame_size = hi556_enum_frame_size,
1021};1167};
drivers/media/i2c/hi846.c+8−3
@@ -1472,21 +1472,26 @@ static int hi846_init_controls(struct hi846 *hi846) · 1471 unmodified lines
1472 if (ctrl_hdlr->error) {1472 if (ctrl_hdlr->error) {
1473 dev_err(&client->dev, "v4l ctrl handler error: %d\n",1473 dev_err(&client->dev, "v4l ctrl handler error: %d\n",
1474 ctrl_hdlr->error);1474 ctrl_hdlr->error);
1475 return ctrl_hdlr->error;1475 ret = ctrl_hdlr->error;
1476 goto error;
1476 }1477 }
1477 1478
1478 ret = v4l2_fwnode_device_parse(&client->dev, &props);1479 ret = v4l2_fwnode_device_parse(&client->dev, &props);
1479 if (ret)1480 if (ret)
1480 return ret;1481 goto error;
1481 1482
1482 ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &hi846_ctrl_ops,1483 ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &hi846_ctrl_ops,
1483 &props);1484 &props);
1484 if (ret)1485 if (ret)
1485 return ret;1486 goto error;
1486 1487
1487 hi846->sd.ctrl_handler = ctrl_hdlr;1488 hi846->sd.ctrl_handler = ctrl_hdlr;
1488 1489
1489 return 0;1490 return 0;
1491
1492error:
1493 v4l2_ctrl_handler_free(ctrl_hdlr);
1494 return ret;
1490}1495}
1491 1496
1492static int hi846_set_video_mode(struct hi846 *hi846, int fps)1497static int hi846_set_video_mode(struct hi846 *hi846, int fps)
drivers/media/i2c/imx258.c+24−9
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/pm_runtime.h>9#include <linux/pm_runtime.h>
10#include <media/v4l2-ctrls.h>10#include <media/v4l2-ctrls.h>
11#include <media/v4l2-device.h>11#include <media/v4l2-device.h>
12#include <media/v4l2-fwnode.h>
12#include <asm/unaligned.h>13#include <asm/unaligned.h>
13 14
14#define IMX258_REG_VALUE_08BIT 115#define IMX258_REG_VALUE_08BIT 1
@@ -1148,7 +1149,9 @@ static const struct v4l2_subdev_internal_ops imx258_internal_ops = { · 1133 unmodified lines
1148static int imx258_init_controls(struct imx258 *imx258)1149static int imx258_init_controls(struct imx258 *imx258)
1149{1150{
1150 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);1151 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
1152 struct v4l2_fwnode_device_properties props;
1151 struct v4l2_ctrl_handler *ctrl_hdlr;1153 struct v4l2_ctrl_handler *ctrl_hdlr;
1154 struct v4l2_ctrl *vflip, *hflip;
1152 s64 vblank_def;1155 s64 vblank_def;
1153 s64 vblank_min;1156 s64 vblank_min;
1154 s64 pixel_rate_min;1157 s64 pixel_rate_min;
@@ -1156,7 +1159,7 @@ static int imx258_init_controls(struct imx258 *imx258) · 1 unmodified line
1156 int ret;1159 int ret;
1157 1160
1158 ctrl_hdlr = &imx258->ctrl_handler;1161 ctrl_hdlr = &imx258->ctrl_handler;
1159 ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);1162 ret = v4l2_ctrl_handler_init(ctrl_hdlr, 13);
1160 if (ret)1163 if (ret)
1161 return ret;1164 return ret;
1162 1165
@@ -1172,6 +1175,17 @@ static int imx258_init_controls(struct imx258 *imx258) · 9 unmodified lines
1172 if (imx258->link_freq)1175 if (imx258->link_freq)
1173 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;1176 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1174 1177
1178 /* The driver only supports one bayer order and flips by default. */
1179 hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
1180 V4L2_CID_HFLIP, 1, 1, 1, 1);
1181 if (hflip)
1182 hflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1183
1184 vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
1185 V4L2_CID_VFLIP, 1, 1, 1, 1);
1186 if (vflip)
1187 vflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1188
1175 pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);1189 pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
1176 pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]);1190 pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]);
1177 /* By default, PIXEL_RATE is read only */1191 /* By default, PIXEL_RATE is read only */
@@ -1232,6 +1246,15 @@ static int imx258_init_controls(struct imx258 *imx258) · 54 unmodified lines
1232 goto error;1246 goto error;
1233 }1247 }
1234 1248
1249 ret = v4l2_fwnode_device_parse(&client->dev, &props);
1250 if (ret)
1251 goto error;
1252
1253 ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx258_ctrl_ops,
1254 &props);
1255 if (ret)
1256 goto error;
1257
1235 imx258->sd.ctrl_handler = ctrl_hdlr;1258 imx258->sd.ctrl_handler = ctrl_hdlr;
1236 1259
1237 return 0;1260 return 0;
@@ -1276,14 +1299,6 @@ static int imx258_probe(struct i2c_client *client) · 38 unmodified lines
1276 return -EINVAL;1299 return -EINVAL;
1277 }1300 }
1278 1301
1279 /*
1280 * Check that the device is mounted upside down. The driver only
1281 * supports a single pixel order right now.
1282 */
1283 ret = device_property_read_u32(&client->dev, "rotation", &val);
1284 if (ret || val != 180)
1285 return -EINVAL;
1286
1287 /* Initialize subdev */1302 /* Initialize subdev */
1288 v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);1303 v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);
1289 1304
drivers/media/i2c/imx290.c+477−119
@@ -13,12 +13,17 @@ · 12 unmodified lines
13#include <linux/gpio/consumer.h>13#include <linux/gpio/consumer.h>
14#include <linux/i2c.h>14#include <linux/i2c.h>
15#include <linux/module.h>15#include <linux/module.h>
16#include <linux/of_device.h>
16#include <linux/pm_runtime.h>17#include <linux/pm_runtime.h>
17#include <linux/regmap.h>18#include <linux/regmap.h>
18#include <linux/regulator/consumer.h>19#include <linux/regulator/consumer.h>
20
21#include <asm/unaligned.h>
22
19#include <media/media-entity.h>23#include <media/media-entity.h>
20#include <media/v4l2-ctrls.h>24#include <media/v4l2-ctrls.h>
21#include <media/v4l2-device.h>25#include <media/v4l2-device.h>
26#include <media/v4l2-event.h>
22#include <media/v4l2-fwnode.h>27#include <media/v4l2-fwnode.h>
23#include <media/v4l2-subdev.h>28#include <media/v4l2-subdev.h>
24 29
@@ -44,7 +49,9 @@ · 19 unmodified lines
44#define IMX290_BLKLEVEL IMX290_REG_16BIT(0x300a)49#define IMX290_BLKLEVEL IMX290_REG_16BIT(0x300a)
45#define IMX290_GAIN IMX290_REG_8BIT(0x3014)50#define IMX290_GAIN IMX290_REG_8BIT(0x3014)
46#define IMX290_VMAX IMX290_REG_24BIT(0x3018)51#define IMX290_VMAX IMX290_REG_24BIT(0x3018)
52#define IMX290_VMAX_MAX 0x3ffff
47#define IMX290_HMAX IMX290_REG_16BIT(0x301c)53#define IMX290_HMAX IMX290_REG_16BIT(0x301c)
54#define IMX290_HMAX_MAX 0xffff
48#define IMX290_SHS1 IMX290_REG_24BIT(0x3020)55#define IMX290_SHS1 IMX290_REG_24BIT(0x3020)
49#define IMX290_WINWV_OB IMX290_REG_8BIT(0x303a)56#define IMX290_WINWV_OB IMX290_REG_8BIT(0x303a)
50#define IMX290_WINPV IMX290_REG_16BIT(0x303c)57#define IMX290_WINPV IMX290_REG_16BIT(0x303c)
@@ -98,13 +105,16 @@ · 47 unmodified lines
98#define IMX290_TCLKPREPARE IMX290_REG_16BIT(0x3452)105#define IMX290_TCLKPREPARE IMX290_REG_16BIT(0x3452)
99#define IMX290_TLPX IMX290_REG_16BIT(0x3454)106#define IMX290_TLPX IMX290_REG_16BIT(0x3454)
100#define IMX290_X_OUT_SIZE IMX290_REG_16BIT(0x3472)107#define IMX290_X_OUT_SIZE IMX290_REG_16BIT(0x3472)
108#define IMX290_INCKSEL7 IMX290_REG_8BIT(0x3480)
101 109
102#define IMX290_PGCTRL_REGEN BIT(0)110#define IMX290_PGCTRL_REGEN BIT(0)
103#define IMX290_PGCTRL_THRU BIT(1)111#define IMX290_PGCTRL_THRU BIT(1)
104#define IMX290_PGCTRL_MODE(n) ((n) << 4)112#define IMX290_PGCTRL_MODE(n) ((n) << 4)
105 113
106#define IMX290_VMAX_DEFAULT 1125114/* Number of lines by which exposure must be less than VMAX */
115#define IMX290_EXPOSURE_OFFSET 2
107 116
117#define IMX290_PIXEL_RATE 148500000
108 118
109/*119/*
110 * The IMX290 pixel array is organized as follows:120 * The IMX290 pixel array is organized as follows:
@@ -157,26 +167,81 @@ · 46 unmodified lines
157 167
158#define IMX290_NUM_SUPPLIES 3168#define IMX290_NUM_SUPPLIES 3
159 169
170enum imx290_colour_variant {
171 IMX290_VARIANT_COLOUR,
172 IMX290_VARIANT_MONO,
173 IMX290_VARIANT_MAX
174};
175
176enum imx290_model {
177 IMX290_MODEL_IMX290LQR,
178 IMX290_MODEL_IMX290LLR,
179 IMX290_MODEL_IMX327LQR,
180};
181
182struct imx290_model_info {
183 enum imx290_colour_variant colour_variant;
184 const struct imx290_regval *init_regs;
185 size_t init_regs_num;
186 const char *name;
187};
188
189enum imx290_clk_freq {
190 IMX290_CLK_37_125,
191 IMX290_CLK_74_25,
192 IMX290_NUM_CLK
193};
194
160struct imx290_regval {195struct imx290_regval {
161 u32 reg;196 u32 reg;
162 u32 val;197 u32 val;
163};198};
164 199
200/*
201 * Clock configuration for registers INCKSEL1 to INCKSEL6.
202 */
203struct imx290_clk_cfg {
204 u8 incksel1;
205 u8 incksel2;
206 u8 incksel3;
207 u8 incksel4;
208 u8 incksel5;
209 u8 incksel6;
210};
211
165struct imx290_mode {212struct imx290_mode {
166 u32 width;213 u32 width;
167 u32 height;214 u32 height;
168 u32 hmax;215 u32 hmax_min;
216 u32 vmax_min;
169 u8 link_freq_index;217 u8 link_freq_index;
218 u8 ctrl_07;
170 219
171 const struct imx290_regval *data;220 const struct imx290_regval *data;
172 u32 data_size;221 u32 data_size;
222
223 const struct imx290_clk_cfg *clk_cfg;
224};
225
226struct imx290_csi_cfg {
227 u16 repetition;
228 u16 tclkpost;
229 u16 thszero;
230 u16 thsprepare;
231 u16 tclktrail;
232 u16 thstrail;
233 u16 tclkzero;
234 u16 tclkprepare;
235 u16 tlpx;
173};236};
174 237
175struct imx290 {238struct imx290 {
176 struct device *dev;239 struct device *dev;
177 struct clk *xclk;240 struct clk *xclk;
178 struct regmap *regmap;241 struct regmap *regmap;
242 enum imx290_clk_freq xclk_idx;
179 u8 nlanes;243 u8 nlanes;
244 const struct imx290_model_info *model;
180 245
181 struct v4l2_subdev sd;246 struct v4l2_subdev sd;
182 struct media_pad pad;247 struct media_pad pad;
@@ -188,9 +253,13 @@ struct imx290 { · 5 unmodified lines
188 253
189 struct v4l2_ctrl_handler ctrls;254 struct v4l2_ctrl_handler ctrls;
190 struct v4l2_ctrl *link_freq;255 struct v4l2_ctrl *link_freq;
191 struct v4l2_ctrl *pixel_rate;
192 struct v4l2_ctrl *hblank;256 struct v4l2_ctrl *hblank;
193 struct v4l2_ctrl *vblank;257 struct v4l2_ctrl *vblank;
258 struct v4l2_ctrl *exposure;
259 struct {
260 struct v4l2_ctrl *hflip;
261 struct v4l2_ctrl *vflip;
262 };
194};263};
195 264
196static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)265static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
@@ -203,9 +272,6 @@ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd) · 6 unmodified lines
203 */272 */
204 273
205static const struct imx290_regval imx290_global_init_settings[] = {274static const struct imx290_regval imx290_global_init_settings[] = {
206 { IMX290_CTRL_07, IMX290_WINMODE_1080P },
207 { IMX290_VMAX, IMX290_VMAX_DEFAULT },
208 { IMX290_EXTCK_FREQ, 0x2520 },
209 { IMX290_WINWV_OB, 12 },275 { IMX290_WINWV_OB, 12 },
210 { IMX290_WINPH, 0 },276 { IMX290_WINPH, 0 },
211 { IMX290_WINPV, 0 },277 { IMX290_WINPV, 0 },
@@ -213,10 +279,14 @@ static const struct imx290_regval imx290_global_init_settings[] = { · 1 unmodified line
213 { IMX290_WINWV, 1097 },279 { IMX290_WINWV, 1097 },
214 { IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |280 { IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
215 IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },281 IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
216 { IMX290_REG_8BIT(0x300f), 0x00 },282 { IMX290_REG_8BIT(0x3011), 0x02 },
217 { IMX290_REG_8BIT(0x3010), 0x21 },
218 { IMX290_REG_8BIT(0x3012), 0x64 },283 { IMX290_REG_8BIT(0x3012), 0x64 },
219 { IMX290_REG_8BIT(0x3013), 0x00 },284 { IMX290_REG_8BIT(0x3013), 0x00 },
285};
286
287static const struct imx290_regval imx290_global_init_settings_290[] = {
288 { IMX290_REG_8BIT(0x300f), 0x00 },
289 { IMX290_REG_8BIT(0x3010), 0x21 },
220 { IMX290_REG_8BIT(0x3016), 0x09 },290 { IMX290_REG_8BIT(0x3016), 0x09 },
221 { IMX290_REG_8BIT(0x3070), 0x02 },291 { IMX290_REG_8BIT(0x3070), 0x02 },
222 { IMX290_REG_8BIT(0x3071), 0x11 },292 { IMX290_REG_8BIT(0x3071), 0x11 },
@@ -255,57 +325,40 @@ static const struct imx290_regval imx290_global_init_settings[] = { · 32 unmodified lines
255 { IMX290_REG_8BIT(0x33b0), 0x50 },325 { IMX290_REG_8BIT(0x33b0), 0x50 },
256 { IMX290_REG_8BIT(0x33b2), 0x1a },326 { IMX290_REG_8BIT(0x33b2), 0x1a },
257 { IMX290_REG_8BIT(0x33b3), 0x04 },327 { IMX290_REG_8BIT(0x33b3), 0x04 },
258 { IMX290_REG_8BIT(0x3480), 0x49 },328};
329
330#define IMX290_NUM_CLK_REGS 2
331static const struct imx290_regval xclk_regs[][IMX290_NUM_CLK_REGS] = {
332 [IMX290_CLK_37_125] = {
333 { IMX290_EXTCK_FREQ, (37125 * 256) / 1000 },
334 { IMX290_INCKSEL7, 0x49 },
335 },
336 [IMX290_CLK_74_25] = {
337 { IMX290_EXTCK_FREQ, (74250 * 256) / 1000 },
338 { IMX290_INCKSEL7, 0x92 },
339 },
340};
341
342static const struct imx290_regval imx290_global_init_settings_327[] = {
343 { IMX290_REG_8BIT(0x309e), 0x4A },
344 { IMX290_REG_8BIT(0x309f), 0x4A },
345 { IMX290_REG_8BIT(0x313b), 0x61 },
259};346};
260 347
261static const struct imx290_regval imx290_1080p_settings[] = {348static const struct imx290_regval imx290_1080p_settings[] = {
262 /* mode settings */349 /* mode settings */
263 { IMX290_CTRL_07, IMX290_WINMODE_1080P },
264 { IMX290_WINWV_OB, 12 },350 { IMX290_WINWV_OB, 12 },
265 { IMX290_OPB_SIZE_V, 10 },351 { IMX290_OPB_SIZE_V, 10 },
266 { IMX290_X_OUT_SIZE, 1920 },352 { IMX290_X_OUT_SIZE, 1920 },
267 { IMX290_Y_OUT_SIZE, 1080 },353 { IMX290_Y_OUT_SIZE, 1080 },
268 { IMX290_INCKSEL1, 0x18 },
269 { IMX290_INCKSEL2, 0x03 },
270 { IMX290_INCKSEL3, 0x20 },
271 { IMX290_INCKSEL4, 0x01 },
272 { IMX290_INCKSEL5, 0x1a },
273 { IMX290_INCKSEL6, 0x1a },
274 /* data rate settings */
275 { IMX290_REPETITION, 0x10 },
276 { IMX290_TCLKPOST, 87 },
277 { IMX290_THSZERO, 55 },
278 { IMX290_THSPREPARE, 31 },
279 { IMX290_TCLKTRAIL, 31 },
280 { IMX290_THSTRAIL, 31 },
281 { IMX290_TCLKZERO, 119 },
282 { IMX290_TCLKPREPARE, 31 },
283 { IMX290_TLPX, 23 },
284};354};
285 355
286static const struct imx290_regval imx290_720p_settings[] = {356static const struct imx290_regval imx290_720p_settings[] = {
287 /* mode settings */357 /* mode settings */
288 { IMX290_CTRL_07, IMX290_WINMODE_720P },
289 { IMX290_WINWV_OB, 6 },358 { IMX290_WINWV_OB, 6 },
290 { IMX290_OPB_SIZE_V, 4 },359 { IMX290_OPB_SIZE_V, 4 },
291 { IMX290_X_OUT_SIZE, 1280 },360 { IMX290_X_OUT_SIZE, 1280 },
292 { IMX290_Y_OUT_SIZE, 720 },361 { IMX290_Y_OUT_SIZE, 720 },
293 { IMX290_INCKSEL1, 0x20 },
294 { IMX290_INCKSEL2, 0x00 },
295 { IMX290_INCKSEL3, 0x20 },
296 { IMX290_INCKSEL4, 0x01 },
297 { IMX290_INCKSEL5, 0x1a },
298 { IMX290_INCKSEL6, 0x1a },
299 /* data rate settings */
300 { IMX290_REPETITION, 0x10 },
301 { IMX290_TCLKPOST, 79 },
302 { IMX290_THSZERO, 47 },
303 { IMX290_THSPREPARE, 23 },
304 { IMX290_TCLKTRAIL, 23 },
305 { IMX290_THSTRAIL, 23 },
306 { IMX290_TCLKZERO, 87 },
307 { IMX290_TCLKPREPARE, 23 },
308 { IMX290_TLPX, 23 },
309};362};
310 363
311static const struct imx290_regval imx290_10bit_settings[] = {364static const struct imx290_regval imx290_10bit_settings[] = {
@@ -326,6 +379,58 @@ static const struct imx290_regval imx290_12bit_settings[] = { · 14 unmodified lines
326 { IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW12 },379 { IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW12 },
327};380};
328 381
382static const struct imx290_csi_cfg imx290_csi_222_75mhz = {
383 /* 222.75MHz or 445.5Mbit/s per lane */
384 .repetition = 0x10,
385 .tclkpost = 87,
386 .thszero = 55,
387 .thsprepare = 31,
388 .tclktrail = 31,
389 .thstrail = 31,
390 .tclkzero = 119,
391 .tclkprepare = 31,
392 .tlpx = 23,
393};
394
395static const struct imx290_csi_cfg imx290_csi_445_5mhz = {
396 /* 445.5MHz or 891Mbit/s per lane */
397 .repetition = 0x00,
398 .tclkpost = 119,
399 .thszero = 103,
400 .thsprepare = 71,
401 .tclktrail = 55,
402 .thstrail = 63,
403 .tclkzero = 255,
404 .tclkprepare = 63,
405 .tlpx = 55,
406};
407
408static const struct imx290_csi_cfg imx290_csi_148_5mhz = {
409 /* 148.5MHz or 297Mbit/s per lane */
410 .repetition = 0x10,
411 .tclkpost = 79,
412 .thszero = 47,
413 .thsprepare = 23,
414 .tclktrail = 23,
415 .thstrail = 23,
416 .tclkzero = 87,
417 .tclkprepare = 23,
418 .tlpx = 23,
419};
420
421static const struct imx290_csi_cfg imx290_csi_297mhz = {
422 /* 297MHz or 594Mbit/s per lane */
423 .repetition = 0x00,
424 .tclkpost = 103,
425 .thszero = 87,
426 .thsprepare = 47,
427 .tclktrail = 39,
428 .thstrail = 47,
429 .tclkzero = 191,
430 .tclkprepare = 47,
431 .tlpx = 39,
432};
433
329/* supported link frequencies */434/* supported link frequencies */
330#define FREQ_INDEX_1080P 0435#define FREQ_INDEX_1080P 0
331#define FREQ_INDEX_720P 1436#define FREQ_INDEX_720P 1
@@ -333,6 +438,7 @@ static const s64 imx290_link_freq_2lanes[] = { · 1 unmodified line
333 [FREQ_INDEX_1080P] = 445500000,438 [FREQ_INDEX_1080P] = 445500000,
334 [FREQ_INDEX_720P] = 297000000,439 [FREQ_INDEX_720P] = 297000000,
335};440};
441
336static const s64 imx290_link_freq_4lanes[] = {442static const s64 imx290_link_freq_4lanes[] = {
337 [FREQ_INDEX_1080P] = 222750000,443 [FREQ_INDEX_1080P] = 222750000,
338 [FREQ_INDEX_720P] = 148500000,444 [FREQ_INDEX_720P] = 148500000,
@@ -358,23 +464,71 @@ static inline int imx290_link_freqs_num(const struct imx290 *imx290) · 19 unmodified lines
358 return ARRAY_SIZE(imx290_link_freq_4lanes);464 return ARRAY_SIZE(imx290_link_freq_4lanes);
359}465}
360 466
467static const struct imx290_clk_cfg imx290_1080p_clock_config[] = {
468 [IMX290_CLK_37_125] = {
469 /* 37.125MHz clock config */
470 .incksel1 = 0x18,
471 .incksel2 = 0x03,
472 .incksel3 = 0x20,
473 .incksel4 = 0x01,
474 .incksel5 = 0x1a,
475 .incksel6 = 0x1a,
476 },
477 [IMX290_CLK_74_25] = {
478 /* 74.25MHz clock config */
479 .incksel1 = 0x0c,
480 .incksel2 = 0x03,
481 .incksel3 = 0x10,
482 .incksel4 = 0x01,
483 .incksel5 = 0x1b,
484 .incksel6 = 0x1b,
485 },
486};
487
488static const struct imx290_clk_cfg imx290_720p_clock_config[] = {
489 [IMX290_CLK_37_125] = {
490 /* 37.125MHz clock config */
491 .incksel1 = 0x20,
492 .incksel2 = 0x00,
493 .incksel3 = 0x20,
494 .incksel4 = 0x01,
495 .incksel5 = 0x1a,
496 .incksel6 = 0x1a,
497 },
498 [IMX290_CLK_74_25] = {
499 /* 74.25MHz clock config */
500 .incksel1 = 0x10,
501 .incksel2 = 0x00,
502 .incksel3 = 0x10,
503 .incksel4 = 0x01,
504 .incksel5 = 0x1b,
505 .incksel6 = 0x1b,
506 },
507};
508
361/* Mode configs */509/* Mode configs */
362static const struct imx290_mode imx290_modes_2lanes[] = {510static const struct imx290_mode imx290_modes_2lanes[] = {
363 {511 {
364 .width = 1920,512 .width = 1920,
365 .height = 1080,513 .height = 1080,
366 .hmax = 4400,514 .hmax_min = 2200,
515 .vmax_min = 1125,
367 .link_freq_index = FREQ_INDEX_1080P,516 .link_freq_index = FREQ_INDEX_1080P,
517 .ctrl_07 = IMX290_WINMODE_1080P,
368 .data = imx290_1080p_settings,518 .data = imx290_1080p_settings,
369 .data_size = ARRAY_SIZE(imx290_1080p_settings),519 .data_size = ARRAY_SIZE(imx290_1080p_settings),
520 .clk_cfg = imx290_1080p_clock_config,
370 },521 },
371 {522 {
372 .width = 1280,523 .width = 1280,
373 .height = 720,524 .height = 720,
374 .hmax = 6600,525 .hmax_min = 3300,
526 .vmax_min = 750,
375 .link_freq_index = FREQ_INDEX_720P,527 .link_freq_index = FREQ_INDEX_720P,
528 .ctrl_07 = IMX290_WINMODE_720P,
376 .data = imx290_720p_settings,529 .data = imx290_720p_settings,
377 .data_size = ARRAY_SIZE(imx290_720p_settings),530 .data_size = ARRAY_SIZE(imx290_720p_settings),
531 .clk_cfg = imx290_720p_clock_config,
378 },532 },
379};533};
380 534
@@ -382,18 +536,24 @@ static const struct imx290_mode imx290_modes_4lanes[] = { · 1 unmodified line
382 {536 {
383 .width = 1920,537 .width = 1920,
384 .height = 1080,538 .height = 1080,
385 .hmax = 2200,539 .hmax_min = 2200,
540 .vmax_min = 1125,
386 .link_freq_index = FREQ_INDEX_1080P,541 .link_freq_index = FREQ_INDEX_1080P,
542 .ctrl_07 = IMX290_WINMODE_1080P,
387 .data = imx290_1080p_settings,543 .data = imx290_1080p_settings,
388 .data_size = ARRAY_SIZE(imx290_1080p_settings),544 .data_size = ARRAY_SIZE(imx290_1080p_settings),
545 .clk_cfg = imx290_1080p_clock_config,
389 },546 },
390 {547 {
391 .width = 1280,548 .width = 1280,
392 .height = 720,549 .height = 720,
393 .hmax = 3300,550 .hmax_min = 3300,
551 .vmax_min = 750,
394 .link_freq_index = FREQ_INDEX_720P,552 .link_freq_index = FREQ_INDEX_720P,
553 .ctrl_07 = IMX290_WINMODE_720P,
395 .data = imx290_720p_settings,554 .data = imx290_720p_settings,
396 .data_size = ARRAY_SIZE(imx290_720p_settings),555 .data_size = ARRAY_SIZE(imx290_720p_settings),
556 .clk_cfg = imx290_720p_clock_config,
397 },557 },
398};558};
399 559
@@ -414,7 +574,7 @@ static inline int imx290_modes_num(const struct imx290 *imx290) · 14 unmodified lines
414}574}
415 575
416struct imx290_format_info {576struct imx290_format_info {
417 u32 code;577 u32 code[IMX290_VARIANT_MAX];
418 u8 bpp;578 u8 bpp;
419 const struct imx290_regval *regs;579 const struct imx290_regval *regs;
420 unsigned int num_regs;580 unsigned int num_regs;
@@ -422,26 +582,33 @@ struct imx290_format_info { · 1 unmodified line
422 582
423static const struct imx290_format_info imx290_formats[] = {583static const struct imx290_format_info imx290_formats[] = {
424 {584 {
425 .code = MEDIA_BUS_FMT_SRGGB10_1X10,585 .code = {
586 [IMX290_VARIANT_COLOUR] = MEDIA_BUS_FMT_SRGGB10_1X10,
587 [IMX290_VARIANT_MONO] = MEDIA_BUS_FMT_Y10_1X10
588 },
426 .bpp = 10,589 .bpp = 10,
427 .regs = imx290_10bit_settings,590 .regs = imx290_10bit_settings,
428 .num_regs = ARRAY_SIZE(imx290_10bit_settings),591 .num_regs = ARRAY_SIZE(imx290_10bit_settings),
429 }, {592 }, {
430 .code = MEDIA_BUS_FMT_SRGGB12_1X12,593 .code = {
594 [IMX290_VARIANT_COLOUR] = MEDIA_BUS_FMT_SRGGB12_1X12,
595 [IMX290_VARIANT_MONO] = MEDIA_BUS_FMT_Y12_1X12
596 },
431 .bpp = 12,597 .bpp = 12,
432 .regs = imx290_12bit_settings,598 .regs = imx290_12bit_settings,
433 .num_regs = ARRAY_SIZE(imx290_12bit_settings),599 .num_regs = ARRAY_SIZE(imx290_12bit_settings),
434 }600 }
435};601};
436 602
437static const struct imx290_format_info *imx290_format_info(u32 code)603static const struct imx290_format_info *
604imx290_format_info(const struct imx290 *imx290, u32 code)
438{605{
439 unsigned int i;606 unsigned int i;
440 607
441 for (i = 0; i < ARRAY_SIZE(imx290_formats); ++i) {608 for (i = 0; i < ARRAY_SIZE(imx290_formats); ++i) {
442 const struct imx290_format_info *info = &imx290_formats[i];609 const struct imx290_format_info *info = &imx290_formats[i];
443 610
444 if (info->code == code)611 if (info->code[imx290->model->colour_variant] == code)
445 return info;612 return info;
446 }613 }
447 614
@@ -461,28 +628,30 @@ static int __always_unused imx290_read(struct imx290 *imx290, u32 addr, u32 *val · 13 unmodified lines
461 data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);628 data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
462 if (ret < 0) {629 if (ret < 0) {
463 dev_err(imx290->dev, "%u-bit read from 0x%04x failed: %d\n",630 dev_err(imx290->dev, "%u-bit read from 0x%04x failed: %d\n",
464 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,631 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
465 addr & IMX290_REG_ADDR_MASK, ret);632 addr & IMX290_REG_ADDR_MASK, ret);
466 return ret;633 return ret;
467 }634 }
468 635
469 *value = (data[2] << 16) | (data[1] << 8) | data[0];636 *value = get_unaligned_le24(data);
470 return 0;637 return 0;
471}638}
472 639
473static int imx290_write(struct imx290 *imx290, u32 addr, u32 value, int *err)640static int imx290_write(struct imx290 *imx290, u32 addr, u32 value, int *err)
474{641{
475 u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };642 u8 data[3];
476 int ret;643 int ret;
477 644
478 if (err && *err)645 if (err && *err)
479 return *err;646 return *err;
480 647
648 put_unaligned_le24(value, data);
649
481 ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,650 ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
482 data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);651 data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
483 if (ret < 0) {652 if (ret < 0) {
484 dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",653 dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
485 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,654 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
486 addr & IMX290_REG_ADDR_MASK, ret);655 addr & IMX290_REG_ADDR_MASK, ret);
487 if (err)656 if (err)
488 *err = ret;657 *err = ret;
@@ -510,24 +679,33 @@ static int imx290_set_register_array(struct imx290 *imx290, · 21 unmodified lines
510 return 0;679 return 0;
511}680}
512 681
682static int imx290_set_clock(struct imx290 *imx290)
683{
684 const struct imx290_mode *mode = imx290->current_mode;
685 enum imx290_clk_freq clk_idx = imx290->xclk_idx;
686 const struct imx290_clk_cfg *clk_cfg = &mode->clk_cfg[clk_idx];
687 int ret;
688
689 ret = imx290_set_register_array(imx290, xclk_regs[clk_idx],
690 IMX290_NUM_CLK_REGS);
691
692 imx290_write(imx290, IMX290_INCKSEL1, clk_cfg->incksel1, &ret);
693 imx290_write(imx290, IMX290_INCKSEL2, clk_cfg->incksel2, &ret);
694 imx290_write(imx290, IMX290_INCKSEL3, clk_cfg->incksel3, &ret);
695 imx290_write(imx290, IMX290_INCKSEL4, clk_cfg->incksel4, &ret);
696 imx290_write(imx290, IMX290_INCKSEL5, clk_cfg->incksel5, &ret);
697 imx290_write(imx290, IMX290_INCKSEL6, clk_cfg->incksel6, &ret);
698
699 return ret;
700}
701
513static int imx290_set_data_lanes(struct imx290 *imx290)702static int imx290_set_data_lanes(struct imx290 *imx290)
514{703{
515 int ret = 0;704 int ret = 0;
516 u32 frsel;
517
518 switch (imx290->nlanes) {
519 case 2:
520 default:
521 frsel = 0x02;
522 break;
523 case 4:
524 frsel = 0x01;
525 break;
526 }
527 705
528 imx290_write(imx290, IMX290_PHY_LANE_NUM, imx290->nlanes - 1, &ret);706 imx290_write(imx290, IMX290_PHY_LANE_NUM, imx290->nlanes - 1, &ret);
529 imx290_write(imx290, IMX290_CSI_LANE_MODE, imx290->nlanes - 1, &ret);707 imx290_write(imx290, IMX290_CSI_LANE_MODE, imx290->nlanes - 1, &ret);
530 imx290_write(imx290, IMX290_FR_FDG_SEL, frsel, &ret);708 imx290_write(imx290, IMX290_FR_FDG_SEL, 0x01, &ret);
531 709
532 return ret;710 return ret;
533}711}
@@ -536,19 +714,55 @@ static int imx290_set_black_level(struct imx290 *imx290, · 2 unmodified lines
536 const struct v4l2_mbus_framefmt *format,714 const struct v4l2_mbus_framefmt *format,
537 unsigned int black_level, int *err)715 unsigned int black_level, int *err)
538{716{
539 unsigned int bpp = imx290_format_info(format->code)->bpp;717 unsigned int bpp = imx290_format_info(imx290, format->code)->bpp;
540 718
541 return imx290_write(imx290, IMX290_BLKLEVEL,719 return imx290_write(imx290, IMX290_BLKLEVEL,
542 black_level >> (16 - bpp), err);720 black_level >> (16 - bpp), err);
543}721}
544 722
723static int imx290_set_csi_config(struct imx290 *imx290)
724{
725 const s64 *link_freqs = imx290_link_freqs_ptr(imx290);
726 const struct imx290_csi_cfg *csi_cfg;
727 int ret = 0;
728
729 switch (link_freqs[imx290->current_mode->link_freq_index]) {
730 case 445500000:
731 csi_cfg = &imx290_csi_445_5mhz;
732 break;
733 case 297000000:
734 csi_cfg = &imx290_csi_297mhz;
735 break;
736 case 222750000:
737 csi_cfg = &imx290_csi_222_75mhz;
738 break;
739 case 148500000:
740 csi_cfg = &imx290_csi_148_5mhz;
741 break;
742 default:
743 return -EINVAL;
744 }
745
746 imx290_write(imx290, IMX290_REPETITION, csi_cfg->repetition, &ret);
747 imx290_write(imx290, IMX290_TCLKPOST, csi_cfg->tclkpost, &ret);
748 imx290_write(imx290, IMX290_THSZERO, csi_cfg->thszero, &ret);
749 imx290_write(imx290, IMX290_THSPREPARE, csi_cfg->thsprepare, &ret);
750 imx290_write(imx290, IMX290_TCLKTRAIL, csi_cfg->tclktrail, &ret);
751 imx290_write(imx290, IMX290_THSTRAIL, csi_cfg->thstrail, &ret);
752 imx290_write(imx290, IMX290_TCLKZERO, csi_cfg->tclkzero, &ret);
753 imx290_write(imx290, IMX290_TCLKPREPARE, csi_cfg->tclkprepare, &ret);
754 imx290_write(imx290, IMX290_TLPX, csi_cfg->tlpx, &ret);
755
756 return ret;
757}
758
545static int imx290_setup_format(struct imx290 *imx290,759static int imx290_setup_format(struct imx290 *imx290,
546 const struct v4l2_mbus_framefmt *format)760 const struct v4l2_mbus_framefmt *format)
547{761{
548 const struct imx290_format_info *info;762 const struct imx290_format_info *info;
549 int ret;763 int ret;
550 764
551 info = imx290_format_info(format->code);765 info = imx290_format_info(imx290, format->code);
552 766
553 ret = imx290_set_register_array(imx290, info->regs, info->num_regs);767 ret = imx290_set_register_array(imx290, info->regs, info->num_regs);
554 if (ret < 0) {768 if (ret < 0) {
@@ -563,6 +777,16 @@ static int imx290_setup_format(struct imx290 *imx290, · 8 unmodified lines
563/* ----------------------------------------------------------------------------777/* ----------------------------------------------------------------------------
564 * Controls778 * Controls
565 */779 */
780static void imx290_exposure_update(struct imx290 *imx290,
781 const struct imx290_mode *mode)
782{
783 unsigned int exposure_max;
784
785 exposure_max = imx290->vblank->val + mode->height -
786 IMX290_EXPOSURE_OFFSET;
787 __v4l2_ctrl_modify_range(imx290->exposure, 1, exposure_max, 1,
788 exposure_max);
789}
566 790
567static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)791static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
568{792{
@@ -570,7 +794,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl) · 1 unmodified line
570 struct imx290, ctrls);794 struct imx290, ctrls);
571 const struct v4l2_mbus_framefmt *format;795 const struct v4l2_mbus_framefmt *format;
572 struct v4l2_subdev_state *state;796 struct v4l2_subdev_state *state;
573 int ret = 0;797 int ret = 0, vmax;
574 798
575 /*799 /*
576 * Return immediately for controls that don't need to be applied to the800 * Return immediately for controls that don't need to be applied to the
@@ -579,6 +803,11 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl) · 2 unmodified lines
579 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)803 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
580 return 0;804 return 0;
581 805
806 if (ctrl->id == V4L2_CID_VBLANK) {
807 /* Changing vblank changes the allowed range for exposure. */
808 imx290_exposure_update(imx290, imx290->current_mode);
809 }
810
582 /* V4L2 controls values will be applied only when power is already up */811 /* V4L2 controls values will be applied only when power is already up */
583 if (!pm_runtime_get_if_in_use(imx290->dev))812 if (!pm_runtime_get_if_in_use(imx290->dev))
584 return 0;813 return 0;
@@ -591,9 +820,23 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl) · 6 unmodified lines
591 ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);820 ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
592 break;821 break;
593 822
823 case V4L2_CID_VBLANK:
824 ret = imx290_write(imx290, IMX290_VMAX,
825 ctrl->val + imx290->current_mode->height,
826 NULL);
827 /*
828 * Due to the way that exposure is programmed in this sensor in
829 * relation to VMAX, we have to reprogramme it whenever VMAX is
830 * changed.
831 * Update ctrl so that the V4L2_CID_EXPOSURE case can refer to
832 * it.
833 */
834 ctrl = imx290->exposure;
835 fallthrough;
594 case V4L2_CID_EXPOSURE:836 case V4L2_CID_EXPOSURE:
837 vmax = imx290->vblank->val + imx290->current_mode->height;
595 ret = imx290_write(imx290, IMX290_SHS1,838 ret = imx290_write(imx290, IMX290_SHS1,
596 IMX290_VMAX_DEFAULT - ctrl->val - 1, NULL);839 vmax - ctrl->val - 1, NULL);
597 break;840 break;
598 841
599 case V4L2_CID_TEST_PATTERN:842 case V4L2_CID_TEST_PATTERN:
@@ -612,6 +855,26 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl) · 12 unmodified lines
612 }855 }
613 break;856 break;
614 857
858 case V4L2_CID_HBLANK:
859 ret = imx290_write(imx290, IMX290_HMAX,
860 ctrl->val + imx290->current_mode->width,
861 NULL);
862 break;
863
864 case V4L2_CID_HFLIP:
865 case V4L2_CID_VFLIP:
866 {
867 u32 reg;
868
869 reg = imx290->current_mode->ctrl_07;
870 if (imx290->hflip->val)
871 reg |= IMX290_HREVERSE;
872 if (imx290->vflip->val)
873 reg |= IMX290_VREVERSE;
874 ret = imx290_write(imx290, IMX290_CTRL_07, reg, NULL);
875 break;
876 }
877
615 default:878 default:
616 ret = -EINVAL;879 ret = -EINVAL;
617 break;880 break;
@@ -642,20 +905,17 @@ static void imx290_ctrl_update(struct imx290 *imx290, · 24 unmodified lines
642 const struct v4l2_mbus_framefmt *format,905 const struct v4l2_mbus_framefmt *format,
643 const struct imx290_mode *mode)906 const struct imx290_mode *mode)
644{907{
645 unsigned int hblank = mode->hmax - mode->width;908 unsigned int hblank_min = mode->hmax_min - mode->width;
646 unsigned int vblank = IMX290_VMAX_DEFAULT - mode->height;909 unsigned int hblank_max = IMX290_HMAX_MAX - mode->width;
647 s64 link_freq = imx290_link_freqs_ptr(imx290)[mode->link_freq_index];910 unsigned int vblank_min = mode->vmax_min - mode->height;
648 u64 pixel_rate;911 unsigned int vblank_max = IMX290_VMAX_MAX - mode->height;
649
650 /* pixel rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
651 pixel_rate = link_freq * 2 * imx290->nlanes;
652 do_div(pixel_rate, imx290_format_info(format->code)->bpp);
653 912
654 __v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);913 __v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);
655 __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate, pixel_rate);
656 914
657 __v4l2_ctrl_modify_range(imx290->hblank, hblank, hblank, 1, hblank);915 __v4l2_ctrl_modify_range(imx290->hblank, hblank_min, hblank_max, 1,
658 __v4l2_ctrl_modify_range(imx290->vblank, vblank, vblank, 1, vblank);916 hblank_min);
917 __v4l2_ctrl_modify_range(imx290->vblank, vblank_min, vblank_max, 1,
918 vblank_min);
659}919}
660 920
661static int imx290_ctrl_init(struct imx290 *imx290)921static int imx290_ctrl_init(struct imx290 *imx290)
@@ -667,7 +927,7 @@ static int imx290_ctrl_init(struct imx290 *imx290) · 5 unmodified lines
667 if (ret < 0)927 if (ret < 0)
668 return ret;928 return ret;
669 929
670 v4l2_ctrl_handler_init(&imx290->ctrls, 9);930 v4l2_ctrl_handler_init(&imx290->ctrls, 11);
671 931
672 /*932 /*
673 * The sensor has an analog gain and a digital gain, both controlled933 * The sensor has an analog gain and a digital gain, both controlled
@@ -685,9 +945,13 @@ static int imx290_ctrl_init(struct imx290 *imx290) · 11 unmodified lines
685 v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,945 v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
686 V4L2_CID_ANALOGUE_GAIN, 0, 100, 1, 0);946 V4L2_CID_ANALOGUE_GAIN, 0, 100, 1, 0);
687 947
688 v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,948 /*
689 V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,949 * Correct range will be determined through imx290_ctrl_update setting
690 IMX290_VMAX_DEFAULT - 2);950 * V4L2_CID_VBLANK.
951 */
952 imx290->exposure = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
953 V4L2_CID_EXPOSURE, 1, 65535, 1,
954 65535);
691 955
692 /*956 /*
693 * Set the link frequency, pixel rate, horizontal blanking and vertical957 * Set the link frequency, pixel rate, horizontal blanking and vertical
@@ -702,24 +966,29 @@ static int imx290_ctrl_init(struct imx290 *imx290) · 8 unmodified lines
702 if (imx290->link_freq)966 if (imx290->link_freq)
703 imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;967 imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
704 968
705 imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,969 v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops, V4L2_CID_PIXEL_RATE,
706 V4L2_CID_PIXEL_RATE,970 IMX290_PIXEL_RATE, IMX290_PIXEL_RATE, 1,
707 1, INT_MAX, 1, 1);971 IMX290_PIXEL_RATE);
708 972
709 v4l2_ctrl_new_std_menu_items(&imx290->ctrls, &imx290_ctrl_ops,973 v4l2_ctrl_new_std_menu_items(&imx290->ctrls, &imx290_ctrl_ops,
710 V4L2_CID_TEST_PATTERN,974 V4L2_CID_TEST_PATTERN,
711 ARRAY_SIZE(imx290_test_pattern_menu) - 1,975 ARRAY_SIZE(imx290_test_pattern_menu) - 1,
712 0, 0, imx290_test_pattern_menu);976 0, 0, imx290_test_pattern_menu);
713 977
978 /*
979 * Actual range will be set from imx290_ctrl_update later in the probe.
980 */
714 imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,981 imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
715 V4L2_CID_HBLANK, 1, 1, 1, 1);982 V4L2_CID_HBLANK, 1, 1, 1, 1);
716 if (imx290->hblank)
717 imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
718 983
719 imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,984 imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
720 V4L2_CID_VBLANK, 1, 1, 1, 1);985 V4L2_CID_VBLANK, 1, 1, 1, 1);
721 if (imx290->vblank)986
722 imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;987 imx290->hflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
988 V4L2_CID_HFLIP, 0, 1, 1, 0);
989 imx290->vflip = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
990 V4L2_CID_VFLIP, 0, 1, 1, 0);
991 v4l2_ctrl_cluster(2, &imx290->hflip);
723 992
724 v4l2_ctrl_new_fwnode_properties(&imx290->ctrls, &imx290_ctrl_ops,993 v4l2_ctrl_new_fwnode_properties(&imx290->ctrls, &imx290_ctrl_ops,
725 &props);994 &props);
@@ -748,17 +1017,37 @@ static int imx290_start_streaming(struct imx290 *imx290, · 22 unmodified lines
748 1017
749 /* Set init register settings */1018 /* Set init register settings */
750 ret = imx290_set_register_array(imx290, imx290_global_init_settings,1019 ret = imx290_set_register_array(imx290, imx290_global_init_settings,
751 ARRAY_SIZE(1020 ARRAY_SIZE(imx290_global_init_settings));
752 imx290_global_init_settings));
753 if (ret < 0) {1021 if (ret < 0) {
754 dev_err(imx290->dev, "Could not set init registers\n");1022 dev_err(imx290->dev, "Could not set init registers\n");
755 return ret;1023 return ret;
756 }1024 }
757 1025
1026 /* Set mdel specific init register settings */
1027 ret = imx290_set_register_array(imx290, imx290->model->init_regs,
1028 imx290->model->init_regs_num);
1029 if (ret < 0) {
1030 dev_err(imx290->dev, "Could not set model specific init registers\n");
1031 return ret;
1032 }
1033
1034 /* Set clock parameters based on mode and xclk */
1035 ret = imx290_set_clock(imx290);
1036 if (ret < 0) {
1037 dev_err(imx290->dev, "Could not set clocks - %d\n", ret);
1038 return ret;
1039 }
1040
758 /* Set data lane count */1041 /* Set data lane count */
759 ret = imx290_set_data_lanes(imx290);1042 ret = imx290_set_data_lanes(imx290);
760 if (ret < 0) {1043 if (ret < 0) {
761 dev_err(imx290->dev, "Could not set data lanes\n");1044 dev_err(imx290->dev, "Could not set data lanes - %d\n", ret);
1045 return ret;
1046 }
1047
1048 ret = imx290_set_csi_config(imx290);
1049 if (ret < 0) {
1050 dev_err(imx290->dev, "Could not set csi cfg - %d\n", ret);
762 return ret;1051 return ret;
763 }1052 }
764 1053
@@ -766,7 +1055,7 @@ static int imx290_start_streaming(struct imx290 *imx290, · 1 unmodified line
766 format = v4l2_subdev_get_pad_format(&imx290->sd, state, 0);1055 format = v4l2_subdev_get_pad_format(&imx290->sd, state, 0);
767 ret = imx290_setup_format(imx290, format);1056 ret = imx290_setup_format(imx290, format);
768 if (ret < 0) {1057 if (ret < 0) {
769 dev_err(imx290->dev, "Could not set frame format\n");1058 dev_err(imx290->dev, "Could not set frame format - %d\n", ret);
770 return ret;1059 return ret;
771 }1060 }
772 1061
@@ -774,19 +1063,14 @@ static int imx290_start_streaming(struct imx290 *imx290, · 1 unmodified line
774 ret = imx290_set_register_array(imx290, imx290->current_mode->data,1063 ret = imx290_set_register_array(imx290, imx290->current_mode->data,
775 imx290->current_mode->data_size);1064 imx290->current_mode->data_size);
776 if (ret < 0) {1065 if (ret < 0) {
777 dev_err(imx290->dev, "Could not set current mode\n");1066 dev_err(imx290->dev, "Could not set current mode - %d\n", ret);
778 return ret;1067 return ret;
779 }1068 }
780 1069
781 ret = imx290_write(imx290, IMX290_HMAX, imx290->current_mode->hmax,
782 NULL);
783 if (ret)
784 return ret;
785
786 /* Apply customized values from user */1070 /* Apply customized values from user */
787 ret = __v4l2_ctrl_handler_setup(imx290->sd.ctrl_handler);1071 ret = __v4l2_ctrl_handler_setup(imx290->sd.ctrl_handler);
788 if (ret) {1072 if (ret) {
789 dev_err(imx290->dev, "Could not sync v4l2 controls\n");1073 dev_err(imx290->dev, "Could not sync v4l2 controls - %d\n", ret);
790 return ret;1074 return ret;
791 }1075 }
792 1076
@@ -835,6 +1119,13 @@ static int imx290_set_stream(struct v4l2_subdev *sd, int enable) · 42 unmodified lines
835 pm_runtime_put_autosuspend(imx290->dev);1119 pm_runtime_put_autosuspend(imx290->dev);
836 }1120 }
837 1121
1122 /*
1123 * vflip and hflip should not be changed during streaming as the sensor
1124 * will produce an invalid frame.
1125 */
1126 __v4l2_ctrl_grab(imx290->vflip, enable);
1127 __v4l2_ctrl_grab(imx290->hflip, enable);
1128
838unlock:1129unlock:
839 v4l2_subdev_unlock_state(state);1130 v4l2_subdev_unlock_state(state);
840 return ret;1131 return ret;
@@ -844,10 +1135,12 @@ static int imx290_enum_mbus_code(struct v4l2_subdev *sd, · 3 unmodified lines
844 struct v4l2_subdev_state *sd_state,1135 struct v4l2_subdev_state *sd_state,
845 struct v4l2_subdev_mbus_code_enum *code)1136 struct v4l2_subdev_mbus_code_enum *code)
846{1137{
1138 const struct imx290 *imx290 = to_imx290(sd);
1139
847 if (code->index >= ARRAY_SIZE(imx290_formats))1140 if (code->index >= ARRAY_SIZE(imx290_formats))
848 return -EINVAL;1141 return -EINVAL;
849 1142
850 code->code = imx290_formats[code->index].code;1143 code->code = imx290_formats[code->index].code[imx290->model->colour_variant];
851 1144
852 return 0;1145 return 0;
853}1146}
@@ -859,7 +1152,7 @@ static int imx290_enum_frame_size(struct v4l2_subdev *sd, · 5 unmodified lines
859 const struct imx290 *imx290 = to_imx290(sd);1152 const struct imx290 *imx290 = to_imx290(sd);
860 const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);1153 const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);
861 1154
862 if (!imx290_format_info(fse->code))1155 if (!imx290_format_info(imx290, fse->code))
863 return -EINVAL;1156 return -EINVAL;
864 1157
865 if (fse->index >= imx290_modes_num(imx290))1158 if (fse->index >= imx290_modes_num(imx290))
@@ -888,10 +1181,14 @@ static int imx290_set_fmt(struct v4l2_subdev *sd, · 22 unmodified lines
888 fmt->format.width = mode->width;1181 fmt->format.width = mode->width;
889 fmt->format.height = mode->height;1182 fmt->format.height = mode->height;
890 1183
891 if (!imx290_format_info(fmt->format.code))1184 if (!imx290_format_info(imx290, fmt->format.code))
892 fmt->format.code = imx290_formats[0].code;1185 fmt->format.code = imx290_formats[0].code[imx290->model->colour_variant];
893 1186
894 fmt->format.field = V4L2_FIELD_NONE;1187 fmt->format.field = V4L2_FIELD_NONE;
1188 fmt->format.colorspace = V4L2_COLORSPACE_RAW;
1189 fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_601;
1190 fmt->format.quantization = V4L2_QUANTIZATION_FULL_RANGE;
1191 fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
895 1192
896 format = v4l2_subdev_get_pad_format(sd, sd_state, 0);1193 format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
897 1194
@@ -899,6 +1196,7 @@ static int imx290_set_fmt(struct v4l2_subdev *sd, · 1 unmodified line
899 imx290->current_mode = mode;1196 imx290->current_mode = mode;
900 1197
901 imx290_ctrl_update(imx290, &fmt->format, mode);1198 imx290_ctrl_update(imx290, &fmt->format, mode);
1199 imx290_exposure_update(imx290, mode);
902 }1200 }
903 1201
904 *format = fmt->format;1202 *format = fmt->format;
@@ -910,16 +1208,23 @@ static int imx290_get_selection(struct v4l2_subdev *sd, · 5 unmodified lines
910 struct v4l2_subdev_state *sd_state,1208 struct v4l2_subdev_state *sd_state,
911 struct v4l2_subdev_selection *sel)1209 struct v4l2_subdev_selection *sel)
912{1210{
1211 struct imx290 *imx290 = to_imx290(sd);
913 struct v4l2_mbus_framefmt *format;1212 struct v4l2_mbus_framefmt *format;
914 1213
915 switch (sel->target) {1214 switch (sel->target) {
916 case V4L2_SEL_TGT_CROP: {1215 case V4L2_SEL_TGT_CROP: {
917 format = v4l2_subdev_get_pad_format(sd, sd_state, 0);1216 format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
918 1217
1218 /*
1219 * The sensor moves the readout by 1 pixel based on flips to
1220 * keep the Bayer order the same.
1221 */
919 sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP1222 sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP
920 + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2;1223 + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2
1224 + imx290->vflip->val;
921 sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT1225 sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT
922 + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2;1226 + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2
1227 + imx290->hflip->val;
923 sel->r.width = format->width;1228 sel->r.width = format->width;
924 sel->r.height = format->height;1229 sel->r.height = format->height;
925 1230
@@ -964,6 +1269,11 @@ static int imx290_entity_init_cfg(struct v4l2_subdev *subdev, · 38 unmodified lines
964 return 0;1269 return 0;
965}1270}
966 1271
1272static const struct v4l2_subdev_core_ops imx290_core_ops = {
1273 .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
1274 .unsubscribe_event = v4l2_event_subdev_unsubscribe,
1275};
1276
967static const struct v4l2_subdev_video_ops imx290_video_ops = {1277static const struct v4l2_subdev_video_ops imx290_video_ops = {
968 .s_stream = imx290_set_stream,1278 .s_stream = imx290_set_stream,
969};1279};
@@ -978,6 +1288,7 @@ static const struct v4l2_subdev_pad_ops imx290_pad_ops = { · 8 unmodified lines
978};1288};
979 1289
980static const struct v4l2_subdev_ops imx290_subdev_ops = {1290static const struct v4l2_subdev_ops imx290_subdev_ops = {
1291 .core = &imx290_core_ops,
981 .video = &imx290_video_ops,1292 .video = &imx290_video_ops,
982 .pad = &imx290_pad_ops,1293 .pad = &imx290_pad_ops,
983};1294};
@@ -996,7 +1307,8 @@ static int imx290_subdev_init(struct imx290 *imx290) · 12 unmodified lines
996 imx290->current_mode = &imx290_modes_ptr(imx290)[0];1307 imx290->current_mode = &imx290_modes_ptr(imx290)[0];
997 1308
998 v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);1309 v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
999 imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1310 imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
1311 V4L2_SUBDEV_FL_HAS_EVENTS;
1000 imx290->sd.dev = imx290->dev;1312 imx290->sd.dev = imx290->dev;
1001 imx290->sd.entity.ops = &imx290_subdev_entity_ops;1313 imx290->sd.entity.ops = &imx290_subdev_entity_ops;
1002 imx290->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;1314 imx290->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
@@ -1132,15 +1444,22 @@ static int imx290_init_clk(struct imx290 *imx290) · 129 unmodified lines
1132 u32 xclk_freq;1444 u32 xclk_freq;
1133 int ret;1445 int ret;
1134 1446
1135 ret = fwnode_property_read_u32(dev_fwnode(imx290->dev),1447 ret = device_property_read_u32(imx290->dev, "clock-frequency",
1136 "clock-frequency", &xclk_freq);1448 &xclk_freq);
1137 if (ret) {1449 if (ret) {
1138 dev_err(imx290->dev, "Could not get xclk frequency\n");1450 dev_err(imx290->dev, "Could not get xclk frequency\n");
1139 return ret;1451 return ret;
1140 }1452 }
1141 1453
1142 /* external clock must be 37.125 MHz */1454 /* external clock must be 37.125 MHz or 74.25MHz */
1143 if (xclk_freq != 37125000) {1455 switch (xclk_freq) {
1456 case 37125000:
1457 imx290->xclk_idx = IMX290_CLK_37_125;
1458 break;
1459 case 74250000:
1460 imx290->xclk_idx = IMX290_CLK_74_25;
1461 break;
1462 default:
1144 dev_err(imx290->dev, "External clock frequency %u is not supported\n",1463 dev_err(imx290->dev, "External clock frequency %u is not supported\n",
1145 xclk_freq);1464 xclk_freq);
1146 return -EINVAL;1465 return -EINVAL;
@@ -1177,6 +1496,27 @@ static s64 imx290_check_link_freqs(const struct imx290 *imx290, · 30 unmodified lines
1177 return 0;1496 return 0;
1178}1497}
1179 1498
1499static const struct imx290_model_info imx290_models[] = {
1500 [IMX290_MODEL_IMX290LQR] = {
1501 .colour_variant = IMX290_VARIANT_COLOUR,
1502 .init_regs = imx290_global_init_settings_290,
1503 .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_290),
1504 .name = "imx290",
1505 },
1506 [IMX290_MODEL_IMX290LLR] = {
1507 .colour_variant = IMX290_VARIANT_MONO,
1508 .init_regs = imx290_global_init_settings_290,
1509 .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_290),
1510 .name = "imx290",
1511 },
1512 [IMX290_MODEL_IMX327LQR] = {
1513 .colour_variant = IMX290_VARIANT_COLOUR,
1514 .init_regs = imx290_global_init_settings_327,
1515 .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_327),
1516 .name = "imx327",
1517 },
1518};
1519
1180static int imx290_parse_dt(struct imx290 *imx290)1520static int imx290_parse_dt(struct imx290 *imx290)
1181{1521{
1182 /* Only CSI2 is supported for now: */1522 /* Only CSI2 is supported for now: */
@@ -1187,6 +1527,8 @@ static int imx290_parse_dt(struct imx290 *imx290) · 4 unmodified lines
1187 int ret;1527 int ret;
1188 s64 fq;1528 s64 fq;
1189 1529
1530 imx290->model = of_device_get_match_data(imx290->dev);
1531
1190 endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(imx290->dev), NULL);1532 endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(imx290->dev), NULL);
1191 if (!endpoint) {1533 if (!endpoint) {
1192 dev_err(imx290->dev, "Endpoint node not found\n");1534 dev_err(imx290->dev, "Endpoint node not found\n");
@@ -1260,7 +1602,7 @@ static int imx290_probe(struct i2c_client *client) · 67 unmodified lines
1260 imx290->xclk = devm_clk_get(dev, "xclk");1602 imx290->xclk = devm_clk_get(dev, "xclk");
1261 if (IS_ERR(imx290->xclk))1603 if (IS_ERR(imx290->xclk))
1262 return dev_err_probe(dev, PTR_ERR(imx290->xclk),1604 return dev_err_probe(dev, PTR_ERR(imx290->xclk),
1263 "Could not get xclk");1605 "Could not get xclk\n");
1264 1606
1265 ret = imx290_get_regulators(dev, imx290);1607 ret = imx290_get_regulators(dev, imx290);
1266 if (ret < 0)1608 if (ret < 0)
@@ -1304,6 +1646,9 @@ static int imx290_probe(struct i2c_client *client) · 37 unmodified lines
1304 if (ret)1646 if (ret)
1305 goto err_pm;1647 goto err_pm;
1306 1648
1649 v4l2_i2c_subdev_set_name(&imx290->sd, client,
1650 imx290->model->name, NULL);
1651
1307 /*1652 /*
1308 * Finally, register the V4L2 subdev. This must be done after1653 * Finally, register the V4L2 subdev. This must be done after
1309 * initializing everything as the subdev can be used immediately after1654 * initializing everything as the subdev can be used immediately after
@@ -1352,8 +1697,21 @@ static void imx290_remove(struct i2c_client *client) · 42 unmodified lines
1352}1697}
1353 1698
1354static const struct of_device_id imx290_of_match[] = {1699static const struct of_device_id imx290_of_match[] = {
1355 { .compatible = "sony,imx290" },1700 {
1356 { /* sentinel */ }1701 /* Deprecated - synonym for "sony,imx290lqr" */
1702 .compatible = "sony,imx290",
1703 .data = &imx290_models[IMX290_MODEL_IMX290LQR],
1704 }, {
1705 .compatible = "sony,imx290lqr",
1706 .data = &imx290_models[IMX290_MODEL_IMX290LQR],
1707 }, {
1708 .compatible = "sony,imx290llr",
1709 .data = &imx290_models[IMX290_MODEL_IMX290LLR],
1710 }, {
1711 .compatible = "sony,imx327lqr",
1712 .data = &imx290_models[IMX290_MODEL_IMX327LQR],
1713 },
1714 { /* sentinel */ },
1357};1715};
1358MODULE_DEVICE_TABLE(of, imx290_of_match);1716MODULE_DEVICE_TABLE(of, imx290_of_match);
1359 1717
drivers/media/i2c/imx296.c+1−10
@@ -685,15 +685,6 @@ static int imx296_enum_frame_size(struct v4l2_subdev *sd, · 684 unmodified lines
685 return 0;685 return 0;
686}686}
687 687
688static int imx296_get_format(struct v4l2_subdev *sd,
689 struct v4l2_subdev_state *state,
690 struct v4l2_subdev_format *fmt)
691{
692 fmt->format = *v4l2_subdev_get_pad_format(sd, state, fmt->pad);
693
694 return 0;
695}
696
697static int imx296_set_format(struct v4l2_subdev *sd,688static int imx296_set_format(struct v4l2_subdev *sd,
698 struct v4l2_subdev_state *state,689 struct v4l2_subdev_state *state,
699 struct v4l2_subdev_format *fmt)690 struct v4l2_subdev_format *fmt)
@@ -845,7 +836,7 @@ static const struct v4l2_subdev_video_ops imx296_subdev_video_ops = { · 145 unmodified lines
845static const struct v4l2_subdev_pad_ops imx296_subdev_pad_ops = {836static const struct v4l2_subdev_pad_ops imx296_subdev_pad_ops = {
846 .enum_mbus_code = imx296_enum_mbus_code,837 .enum_mbus_code = imx296_enum_mbus_code,
847 .enum_frame_size = imx296_enum_frame_size,838 .enum_frame_size = imx296_enum_frame_size,
848 .get_fmt = imx296_get_format,839 .get_fmt = v4l2_subdev_get_fmt,
849 .set_fmt = imx296_set_format,840 .set_fmt = imx296_set_format,
850 .get_selection = imx296_get_selection,841 .get_selection = imx296_get_selection,
851 .set_selection = imx296_set_selection,842 .set_selection = imx296_set_selection,
drivers/media/i2c/imx334.c+294−28
@@ -79,7 +79,6 @@ struct imx334_reg_list { · 78 unmodified lines
79 * struct imx334_mode - imx334 sensor mode structure79 * struct imx334_mode - imx334 sensor mode structure
80 * @width: Frame width80 * @width: Frame width
81 * @height: Frame height81 * @height: Frame height
82 * @code: Format code
83 * @hblank: Horizontal blanking in lines82 * @hblank: Horizontal blanking in lines
84 * @vblank: Vertical blanking in lines83 * @vblank: Vertical blanking in lines
85 * @vblank_min: Minimal vertical blanking in lines84 * @vblank_min: Minimal vertical blanking in lines
@@ -91,7 +90,6 @@ struct imx334_reg_list { · 5 unmodified lines
91struct imx334_mode {90struct imx334_mode {
92 u32 width;91 u32 width;
93 u32 height;92 u32 height;
94 u32 code;
95 u32 hblank;93 u32 hblank;
96 u32 vblank;94 u32 vblank;
97 u32 vblank_min;95 u32 vblank_min;
@@ -119,6 +117,7 @@ struct imx334_mode { · 21 unmodified lines
119 * @vblank: Vertical blanking in lines117 * @vblank: Vertical blanking in lines
120 * @cur_mode: Pointer to current selected sensor mode118 * @cur_mode: Pointer to current selected sensor mode
121 * @mutex: Mutex for serializing sensor controls119 * @mutex: Mutex for serializing sensor controls
120 * @cur_code: current selected format code
122 * @streaming: Flag indicating streaming state121 * @streaming: Flag indicating streaming state
123 */122 */
124struct imx334 {123struct imx334 {
@@ -140,6 +139,7 @@ struct imx334 { · 15 unmodified lines
140 u32 vblank;139 u32 vblank;
141 const struct imx334_mode *cur_mode;140 const struct imx334_mode *cur_mode;
142 struct mutex mutex;141 struct mutex mutex;
142 u32 cur_code;
143 bool streaming;143 bool streaming;
144};144};
145 145
@@ -147,7 +147,170 @@ static const s64 link_freq[] = { · 1 unmodified line
147 IMX334_LINK_FREQ,147 IMX334_LINK_FREQ,
148};148};
149 149
150/* Sensor mode registers */150/* Sensor mode registers for 1920x1080@30fps */
151static const struct imx334_reg mode_1920x1080_regs[] = {
152 {0x3000, 0x01},
153 {0x3018, 0x04},
154 {0x3030, 0xca},
155 {0x3031, 0x08},
156 {0x3032, 0x00},
157 {0x3034, 0x4c},
158 {0x3035, 0x04},
159 {0x302c, 0xf0},
160 {0x302d, 0x03},
161 {0x302e, 0x80},
162 {0x302f, 0x07},
163 {0x3074, 0xcc},
164 {0x3075, 0x02},
165 {0x308e, 0xcd},
166 {0x308f, 0x02},
167 {0x3076, 0x38},
168 {0x3077, 0x04},
169 {0x3090, 0x38},
170 {0x3091, 0x04},
171 {0x3308, 0x38},
172 {0x3309, 0x04},
173 {0x30C6, 0x00},
174 {0x30c7, 0x00},
175 {0x30ce, 0x00},
176 {0x30cf, 0x00},
177 {0x30d8, 0x18},
178 {0x30d9, 0x0a},
179 {0x304c, 0x00},
180 {0x304e, 0x00},
181 {0x304f, 0x00},
182 {0x3050, 0x00},
183 {0x30b6, 0x00},
184 {0x30b7, 0x00},
185 {0x3116, 0x08},
186 {0x3117, 0x00},
187 {0x31a0, 0x20},
188 {0x31a1, 0x0f},
189 {0x300c, 0x3b},
190 {0x300d, 0x29},
191 {0x314c, 0x29},
192 {0x314d, 0x01},
193 {0x315a, 0x06},
194 {0x3168, 0xa0},
195 {0x316a, 0x7e},
196 {0x319e, 0x02},
197 {0x3199, 0x00},
198 {0x319d, 0x00},
199 {0x31dd, 0x03},
200 {0x3300, 0x00},
201 {0x341c, 0xff},
202 {0x341d, 0x01},
203 {0x3a01, 0x03},
204 {0x3a18, 0x7f},
205 {0x3a19, 0x00},
206 {0x3a1a, 0x37},
207 {0x3a1b, 0x00},
208 {0x3a1c, 0x37},
209 {0x3a1d, 0x00},
210 {0x3a1e, 0xf7},
211 {0x3a1f, 0x00},
212 {0x3a20, 0x3f},
213 {0x3a21, 0x00},
214 {0x3a20, 0x6f},
215 {0x3a21, 0x00},
216 {0x3a20, 0x3f},
217 {0x3a21, 0x00},
218 {0x3a20, 0x5f},
219 {0x3a21, 0x00},
220 {0x3a20, 0x2f},
221 {0x3a21, 0x00},
222 {0x3078, 0x02},
223 {0x3079, 0x00},
224 {0x307a, 0x00},
225 {0x307b, 0x00},
226 {0x3080, 0x02},
227 {0x3081, 0x00},
228 {0x3082, 0x00},
229 {0x3083, 0x00},
230 {0x3088, 0x02},
231 {0x3094, 0x00},
232 {0x3095, 0x00},
233 {0x3096, 0x00},
234 {0x309b, 0x02},
235 {0x309c, 0x00},
236 {0x309d, 0x00},
237 {0x309e, 0x00},
238 {0x30a4, 0x00},
239 {0x30a5, 0x00},
240 {0x3288, 0x21},
241 {0x328a, 0x02},
242 {0x3414, 0x05},
243 {0x3416, 0x18},
244 {0x35Ac, 0x0e},
245 {0x3648, 0x01},
246 {0x364a, 0x04},
247 {0x364c, 0x04},
248 {0x3678, 0x01},
249 {0x367c, 0x31},
250 {0x367e, 0x31},
251 {0x3708, 0x02},
252 {0x3714, 0x01},
253 {0x3715, 0x02},
254 {0x3716, 0x02},
255 {0x3717, 0x02},
256 {0x371c, 0x3d},
257 {0x371d, 0x3f},
258 {0x372c, 0x00},
259 {0x372d, 0x00},
260 {0x372e, 0x46},
261 {0x372f, 0x00},
262 {0x3730, 0x89},
263 {0x3731, 0x00},
264 {0x3732, 0x08},
265 {0x3733, 0x01},
266 {0x3734, 0xfe},
267 {0x3735, 0x05},
268 {0x375d, 0x00},
269 {0x375e, 0x00},
270 {0x375f, 0x61},
271 {0x3760, 0x06},
272 {0x3768, 0x1b},
273 {0x3769, 0x1b},
274 {0x376a, 0x1a},
275 {0x376b, 0x19},
276 {0x376c, 0x18},
277 {0x376d, 0x14},
278 {0x376e, 0x0f},
279 {0x3776, 0x00},
280 {0x3777, 0x00},
281 {0x3778, 0x46},
282 {0x3779, 0x00},
283 {0x377a, 0x08},
284 {0x377b, 0x01},
285 {0x377c, 0x45},
286 {0x377d, 0x01},
287 {0x377e, 0x23},
288 {0x377f, 0x02},
289 {0x3780, 0xd9},
290 {0x3781, 0x03},
291 {0x3782, 0xf5},
292 {0x3783, 0x06},
293 {0x3784, 0xa5},
294 {0x3788, 0x0f},
295 {0x378a, 0xd9},
296 {0x378b, 0x03},
297 {0x378c, 0xeb},
298 {0x378d, 0x05},
299 {0x378e, 0x87},
300 {0x378f, 0x06},
301 {0x3790, 0xf5},
302 {0x3792, 0x43},
303 {0x3794, 0x7a},
304 {0x3796, 0xa1},
305 {0x37b0, 0x37},
306 {0x3e04, 0x0e},
307 {0x30e8, 0x50},
308 {0x30e9, 0x00},
309 {0x3e04, 0x0e},
310 {0x3002, 0x00},
311};
312
313/* Sensor mode registers for 3840x2160@30fps */
151static const struct imx334_reg mode_3840x2160_regs[] = {314static const struct imx334_reg mode_3840x2160_regs[] = {
152 {0x3000, 0x01},315 {0x3000, 0x01},
153 {0x3002, 0x00},316 {0x3002, 0x00},
@@ -166,6 +329,7 @@ static const struct imx334_reg mode_3840x2160_regs[] = { · 12 unmodified lines
166 {0x3288, 0x21},329 {0x3288, 0x21},
167 {0x328a, 0x02},330 {0x328a, 0x02},
168 {0x302c, 0x3c},331 {0x302c, 0x3c},
332 {0x302d, 0x00},
169 {0x302e, 0x00},333 {0x302e, 0x00},
170 {0x302f, 0x0f},334 {0x302f, 0x0f},
171 {0x3076, 0x70},335 {0x3076, 0x70},
@@ -240,23 +404,75 @@ static const struct imx334_reg mode_3840x2160_regs[] = { · 68 unmodified lines
240 {0x3794, 0x7a},404 {0x3794, 0x7a},
241 {0x3796, 0xa1},405 {0x3796, 0xa1},
242 {0x3e04, 0x0e},406 {0x3e04, 0x0e},
407 {0x319e, 0x00},
243 {0x3a00, 0x01},408 {0x3a00, 0x01},
409 {0x3a18, 0xbf},
410 {0x3a19, 0x00},
411 {0x3a1a, 0x67},
412 {0x3a1b, 0x00},
413 {0x3a1c, 0x6f},
414 {0x3a1d, 0x00},
415 {0x3a1e, 0xd7},
416 {0x3a1f, 0x01},
417 {0x3a20, 0x6f},
418 {0x3a21, 0x00},
419 {0x3a22, 0xcf},
420 {0x3a23, 0x00},
421 {0x3a24, 0x6f},
422 {0x3a25, 0x00},
423 {0x3a26, 0xb7},
424 {0x3a27, 0x00},
425 {0x3a28, 0x5f},
426 {0x3a29, 0x00},
427};
428
429static const struct imx334_reg raw10_framefmt_regs[] = {
430 {0x3050, 0x00},
431 {0x319d, 0x00},
432 {0x341c, 0xff},
433 {0x341d, 0x01},
434};
435
436static const struct imx334_reg raw12_framefmt_regs[] = {
437 {0x3050, 0x01},
438 {0x319d, 0x01},
439 {0x341c, 0x47},
440 {0x341d, 0x00},
441};
442
443static const u32 imx334_mbus_codes[] = {
444 MEDIA_BUS_FMT_SRGGB12_1X12,
445 MEDIA_BUS_FMT_SRGGB10_1X10,
244};446};
245 447
246/* Supported sensor mode configurations */448/* Supported sensor mode configurations */
247static const struct imx334_mode supported_mode = {449static const struct imx334_mode supported_modes[] = {
248 .width = 3840,450 {
249 .height = 2160,451 .width = 3840,
250 .hblank = 560,452 .height = 2160,
251 .vblank = 2340,453 .hblank = 560,
252 .vblank_min = 90,454 .vblank = 2340,
253 .vblank_max = 132840,455 .vblank_min = 90,
254 .pclk = 594000000,456 .vblank_max = 132840,
255 .link_freq_idx = 0,457 .pclk = 594000000,
256 .code = MEDIA_BUS_FMT_SRGGB12_1X12,458 .link_freq_idx = 0,
257 .reg_list = {459 .reg_list = {
258 .num_of_regs = ARRAY_SIZE(mode_3840x2160_regs),460 .num_of_regs = ARRAY_SIZE(mode_3840x2160_regs),
259 .regs = mode_3840x2160_regs,461 .regs = mode_3840x2160_regs,
462 },
463 }, {
464 .width = 1920,
465 .height = 1080,
466 .hblank = 2480,
467 .vblank = 1170,
468 .vblank_min = 45,
469 .vblank_max = 132840,
470 .pclk = 297000000,
471 .link_freq_idx = 0,
472 .reg_list = {
473 .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
474 .regs = mode_1920x1080_regs,
475 },
260 },476 },
261};477};
262 478
@@ -382,7 +598,8 @@ static int imx334_update_controls(struct imx334 *imx334, · 119 unmodified lines
382 if (ret)598 if (ret)
383 return ret;599 return ret;
384 600
385 ret = __v4l2_ctrl_s_ctrl(imx334->hblank_ctrl, mode->hblank);601 ret = __v4l2_ctrl_modify_range(imx334->hblank_ctrl, mode->hblank,
602 mode->hblank, 1, mode->hblank);
386 if (ret)603 if (ret)
387 return ret;604 return ret;
388 605
@@ -480,6 +697,9 @@ static int imx334_set_ctrl(struct v4l2_ctrl *ctrl) · 91 unmodified lines
480 697
481 pm_runtime_put(imx334->dev);698 pm_runtime_put(imx334->dev);
482 699
700 break;
701 case V4L2_CID_HBLANK:
702 ret = 0;
483 break;703 break;
484 default:704 default:
485 dev_err(imx334->dev, "Invalid control %d", ctrl->id);705 dev_err(imx334->dev, "Invalid control %d", ctrl->id);
@@ -494,6 +714,18 @@ static const struct v4l2_ctrl_ops imx334_ctrl_ops = { · 8 unmodified lines
494 .s_ctrl = imx334_set_ctrl,714 .s_ctrl = imx334_set_ctrl,
495};715};
496 716
717static int imx334_get_format_code(struct imx334 *imx334, u32 code)
718{
719 unsigned int i;
720
721 for (i = 0; i < ARRAY_SIZE(imx334_mbus_codes); i++) {
722 if (imx334_mbus_codes[i] == code)
723 return imx334_mbus_codes[i];
724 }
725
726 return imx334_mbus_codes[0];
727}
728
497/**729/**
498 * imx334_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes730 * imx334_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
499 * @sd: pointer to imx334 V4L2 sub-device structure731 * @sd: pointer to imx334 V4L2 sub-device structure
@@ -506,10 +738,10 @@ static int imx334_enum_mbus_code(struct v4l2_subdev *sd, · 6 unmodified lines
506 struct v4l2_subdev_state *sd_state,738 struct v4l2_subdev_state *sd_state,
507 struct v4l2_subdev_mbus_code_enum *code)739 struct v4l2_subdev_mbus_code_enum *code)
508{740{
509 if (code->index > 0)741 if (code->index >= ARRAY_SIZE(imx334_mbus_codes))
510 return -EINVAL;742 return -EINVAL;
511 743
512 code->code = supported_mode.code;744 code->code = imx334_mbus_codes[code->index];
513 745
514 return 0;746 return 0;
515}747}
@@ -526,15 +758,20 @@ static int imx334_enum_frame_size(struct v4l2_subdev *sd, · 10 unmodified lines
526 struct v4l2_subdev_state *sd_state,758 struct v4l2_subdev_state *sd_state,
527 struct v4l2_subdev_frame_size_enum *fsize)759 struct v4l2_subdev_frame_size_enum *fsize)
528{760{
529 if (fsize->index > 0)761 struct imx334 *imx334 = to_imx334(sd);
762 u32 code;
763
764 if (fsize->index >= ARRAY_SIZE(supported_modes))
530 return -EINVAL;765 return -EINVAL;
531 766
532 if (fsize->code != supported_mode.code)767 code = imx334_get_format_code(imx334, fsize->code);
768
769 if (fsize->code != code)
533 return -EINVAL;770 return -EINVAL;
534 771
535 fsize->min_width = supported_mode.width;772 fsize->min_width = supported_modes[fsize->index].width;
536 fsize->max_width = fsize->min_width;773 fsize->max_width = fsize->min_width;
537 fsize->min_height = supported_mode.height;774 fsize->min_height = supported_modes[fsize->index].height;
538 fsize->max_height = fsize->min_height;775 fsize->max_height = fsize->min_height;
539 776
540 return 0;777 return 0;
@@ -553,7 +790,6 @@ static void imx334_fill_pad_format(struct imx334 *imx334, · 12 unmodified lines
553{790{
554 fmt->format.width = mode->width;791 fmt->format.width = mode->width;
555 fmt->format.height = mode->height;792 fmt->format.height = mode->height;
556 fmt->format.code = mode->code;
557 fmt->format.field = V4L2_FIELD_NONE;793 fmt->format.field = V4L2_FIELD_NONE;
558 fmt->format.colorspace = V4L2_COLORSPACE_RAW;794 fmt->format.colorspace = V4L2_COLORSPACE_RAW;
559 fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;795 fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
@@ -583,6 +819,7 @@ static int imx334_get_pad_format(struct v4l2_subdev *sd, · 23 unmodified lines
583 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);819 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
584 fmt->format = *framefmt;820 fmt->format = *framefmt;
585 } else {821 } else {
822 fmt->format.code = imx334->cur_code;
586 imx334_fill_pad_format(imx334, imx334->cur_mode, fmt);823 imx334_fill_pad_format(imx334, imx334->cur_mode, fmt);
587 }824 }
588 825
@@ -609,15 +846,21 @@ static int imx334_set_pad_format(struct v4l2_subdev *sd, · 20 unmodified lines
609 846
610 mutex_lock(&imx334->mutex);847 mutex_lock(&imx334->mutex);
611 848
612 mode = &supported_mode;849 mode = v4l2_find_nearest_size(supported_modes,
850 ARRAY_SIZE(supported_modes),
851 width, height,
852 fmt->format.width, fmt->format.height);
853
613 imx334_fill_pad_format(imx334, mode, fmt);854 imx334_fill_pad_format(imx334, mode, fmt);
855 fmt->format.code = imx334_get_format_code(imx334, fmt->format.code);
614 856
615 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {857 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
616 struct v4l2_mbus_framefmt *framefmt;858 struct v4l2_mbus_framefmt *framefmt;
617 859
618 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);860 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
619 *framefmt = fmt->format;861 *framefmt = fmt->format;
620 } else {862 } else if (imx334->cur_mode != mode || imx334->cur_code != fmt->format.code) {
863 imx334->cur_code = fmt->format.code;
621 ret = imx334_update_controls(imx334, mode);864 ret = imx334_update_controls(imx334, mode);
622 if (!ret)865 if (!ret)
623 imx334->cur_mode = mode;866 imx334->cur_mode = mode;
@@ -642,11 +885,26 @@ static int imx334_init_pad_cfg(struct v4l2_subdev *sd, · 18 unmodified lines
642 struct v4l2_subdev_format fmt = { 0 };885 struct v4l2_subdev_format fmt = { 0 };
643 886
644 fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;887 fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
645 imx334_fill_pad_format(imx334, &supported_mode, &fmt);888 imx334_fill_pad_format(imx334, &supported_modes[0], &fmt);
646 889
647 return imx334_set_pad_format(sd, sd_state, &fmt);890 return imx334_set_pad_format(sd, sd_state, &fmt);
648}891}
649 892
893static int imx334_set_framefmt(struct imx334 *imx334)
894{
895 switch (imx334->cur_code) {
896 case MEDIA_BUS_FMT_SRGGB10_1X10:
897 return imx334_write_regs(imx334, raw10_framefmt_regs,
898 ARRAY_SIZE(raw10_framefmt_regs));
899
900 case MEDIA_BUS_FMT_SRGGB12_1X12:
901 return imx334_write_regs(imx334, raw12_framefmt_regs,
902 ARRAY_SIZE(raw12_framefmt_regs));
903 }
904
905 return -EINVAL;
906}
907
650/**908/**
651 * imx334_start_streaming() - Start sensor stream909 * imx334_start_streaming() - Start sensor stream
652 * @imx334: pointer to imx334 device910 * @imx334: pointer to imx334 device
@@ -667,6 +925,13 @@ static int imx334_start_streaming(struct imx334 *imx334) · 14 unmodified lines
667 return ret;925 return ret;
668 }926 }
669 927
928 ret = imx334_set_framefmt(imx334);
929 if (ret) {
930 dev_err(imx334->dev, "%s failed to set frame format: %d\n",
931 __func__, ret);
932 return ret;
933 }
934
670 /* Setup handler will write actual exposure and gain */935 /* Setup handler will write actual exposure and gain */
671 ret = __v4l2_ctrl_handler_setup(imx334->sd.ctrl_handler);936 ret = __v4l2_ctrl_handler_setup(imx334->sd.ctrl_handler);
672 if (ret) {937 if (ret) {
@@ -1037,7 +1302,8 @@ static int imx334_probe(struct i2c_client *client) · 364 unmodified lines
1037 }1302 }
1038 1303
1039 /* Set default mode to max resolution */1304 /* Set default mode to max resolution */
1040 imx334->cur_mode = &supported_mode;1305 imx334->cur_mode = &supported_modes[0];
1306 imx334->cur_code = imx334_mbus_codes[0];
1041 imx334->vblank = imx334->cur_mode->vblank;1307 imx334->vblank = imx334->cur_mode->vblank;
1042 1308
1043 ret = imx334_init_controls(imx334);1309 ret = imx334_init_controls(imx334);
drivers/media/i2c/m5mols/Kconfig+0−8
@@ -1,8 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0-only
2config VIDEO_M5MOLS
3 tristate "Fujitsu M-5MOLS 8MP sensor support"
4 depends on I2C && VIDEO_DEV
5 select MEDIA_CONTROLLER
6 select VIDEO_V4L2_SUBDEV_API
7 help
8 This driver supports Fujitsu M-5MOLS camera sensor with ISP
drivers/media/i2c/m5mols/Makefile+0−4
@@ -1,4 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0-only
2m5mols-objs := m5mols_core.o m5mols_controls.o m5mols_capture.o
3
4obj-$(CONFIG_VIDEO_M5MOLS) += m5mols.o
drivers/media/i2c/m5mols/m5mols.h+0−349
@@ -1,349 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Header for M-5MOLS 8M Pixel camera sensor with ISP
4 *
5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
6 * Author: HeungJun Kim <riverful.kim@samsung.com>
7 *
8 * Copyright (C) 2009 Samsung Electronics Co., Ltd.
9 * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
10 */
11
12#ifndef M5MOLS_H
13#define M5MOLS_H
14
15#include <linux/sizes.h>
16#include <linux/gpio/consumer.h>
17#include <media/v4l2-subdev.h>
18#include "m5mols_reg.h"
19
20
21/* An amount of data transmitted in addition to the value
22 * determined by CAPP_JPEG_SIZE_MAX register.
23 */
24#define M5MOLS_JPEG_TAGS_SIZE 0x20000
25#define M5MOLS_MAIN_JPEG_SIZE_MAX (5 * SZ_1M)
26
27extern int m5mols_debug;
28
29enum m5mols_restype {
30 M5MOLS_RESTYPE_MONITOR,
31 M5MOLS_RESTYPE_CAPTURE,
32 M5MOLS_RESTYPE_MAX,
33};
34
35/**
36 * struct m5mols_resolution - structure for the resolution
37 * @type: resolution type according to the pixel code
38 * @width: width of the resolution
39 * @height: height of the resolution
40 * @reg: resolution preset register value
41 */
42struct m5mols_resolution {
43 u8 reg;
44 enum m5mols_restype type;
45 u16 width;
46 u16 height;
47};
48
49/**
50 * struct m5mols_exif - structure for the EXIF information of M-5MOLS
51 * @exposure_time: exposure time register value
52 * @shutter_speed: speed of the shutter register value
53 * @aperture: aperture register value
54 * @brightness: brightness register value
55 * @exposure_bias: it calls also EV bias
56 * @iso_speed: ISO register value
57 * @flash: status register value of the flash
58 * @sdr: status register value of the Subject Distance Range
59 * @qval: not written exact meaning in document
60 */
61struct m5mols_exif {
62 u32 exposure_time;
63 u32 shutter_speed;
64 u32 aperture;
65 u32 brightness;
66 u32 exposure_bias;
67 u16 iso_speed;
68 u16 flash;
69 u16 sdr;
70 u16 qval;
71};
72
73/**
74 * struct m5mols_capture - Structure for the capture capability
75 * @exif: EXIF information
76 * @buf_size: internal JPEG frame buffer size, in bytes
77 * @main: size in bytes of the main image
78 * @thumb: size in bytes of the thumb image, if it was accompanied
79 * @total: total size in bytes of the produced image
80 */
81struct m5mols_capture {
82 struct m5mols_exif exif;
83 unsigned int buf_size;
84 u32 main;
85 u32 thumb;
86 u32 total;
87};
88
89/**
90 * struct m5mols_scenemode - structure for the scenemode capability
91 * @metering: metering light register value
92 * @ev_bias: EV bias register value
93 * @wb_mode: mode which means the WhiteBalance is Auto or Manual
94 * @wb_preset: whitebalance preset register value in the Manual mode
95 * @chroma_en: register value whether the Chroma capability is enabled or not
96 * @chroma_lvl: chroma's level register value
97 * @edge_en: register value Whether the Edge capability is enabled or not
98 * @edge_lvl: edge's level register value
99 * @af_range: Auto Focus's range
100 * @fd_mode: Face Detection mode
101 * @mcc: Multi-axis Color Conversion which means emotion color
102 * @light: status of the Light
103 * @flash: status of the Flash
104 * @tone: Tone color which means Contrast
105 * @iso: ISO register value
106 * @capt_mode: Mode of the Image Stabilization while the camera capturing
107 * @wdr: Wide Dynamic Range register value
108 *
109 * The each value according to each scenemode is recommended in the documents.
110 */
111struct m5mols_scenemode {
112 u8 metering;
113 u8 ev_bias;
114 u8 wb_mode;
115 u8 wb_preset;
116 u8 chroma_en;
117 u8 chroma_lvl;
118 u8 edge_en;
119 u8 edge_lvl;
120 u8 af_range;
121 u8 fd_mode;
122 u8 mcc;
123 u8 light;
124 u8 flash;
125 u8 tone;
126 u8 iso;
127 u8 capt_mode;
128 u8 wdr;
129};
130
131#define VERSION_STRING_SIZE 22
132
133/**
134 * struct m5mols_version - firmware version information
135 * @customer: customer information
136 * @project: version of project information according to customer
137 * @fw: firmware revision
138 * @hw: hardware revision
139 * @param: version of the parameter
140 * @awb: Auto WhiteBalance algorithm version
141 * @str: information about manufacturer and packaging vendor
142 * @af: Auto Focus version
143 *
144 * The register offset starts the customer version at 0x0, and it ends
145 * the awb version at 0x09. The customer, project information occupies 1 bytes
146 * each. And also the fw, hw, param, awb each requires 2 bytes. The str is
147 * unique string associated with firmware's version. It includes information
148 * about manufacturer and the vendor of the sensor's packaging. The least
149 * significant 2 bytes of the string indicate packaging manufacturer.
150 */
151struct m5mols_version {
152 u8 customer;
153 u8 project;
154 u16 fw;
155 u16 hw;
156 u16 param;
157 u16 awb;
158 u8 str[VERSION_STRING_SIZE];
159 u8 af;
160};
161
162/**
163 * struct m5mols_info - M-5MOLS driver data structure
164 * @pdata: platform data
165 * @sd: v4l-subdev instance
166 * @pad: media pad
167 * @irq_waitq: waitqueue for the capture
168 * @irq_done: set to 1 in the interrupt handler
169 * @handle: control handler
170 * @auto_exposure: auto/manual exposure control
171 * @exposure_bias: exposure compensation control
172 * @exposure: manual exposure control
173 * @metering: exposure metering control
174 * @auto_iso: auto/manual ISO sensitivity control
175 * @iso: manual ISO sensitivity control
176 * @auto_wb: auto white balance control
177 * @lock_3a: 3A lock control
178 * @colorfx: color effect control
179 * @saturation: saturation control
180 * @zoom: zoom control
181 * @wdr: wide dynamic range control
182 * @stabilization: image stabilization control
183 * @jpeg_quality: JPEG compression quality control
184 * @set_power: optional power callback to the board code
185 * @reset: GPIO driving the reset pin of M-5MOLS
186 * @lock: mutex protecting the structure fields below
187 * @ffmt: current fmt according to resolution type
188 * @res_type: current resolution type
189 * @ver: information of the version
190 * @cap: the capture mode attributes
191 * @isp_ready: 1 when the ISP controller has completed booting
192 * @power: current sensor's power status
193 * @ctrl_sync: 1 when the control handler state is restored in H/W
194 * @resolution: register value for current resolution
195 * @mode: register value for current operation mode
196 */
197struct m5mols_info {
198 const struct m5mols_platform_data *pdata;
199 struct v4l2_subdev sd;
200 struct media_pad pad;
201
202 wait_queue_head_t irq_waitq;
203 atomic_t irq_done;
204
205 struct v4l2_ctrl_handler handle;
206 struct {
207 /* exposure/exposure bias/auto exposure cluster */
208 struct v4l2_ctrl *auto_exposure;
209 struct v4l2_ctrl *exposure_bias;
210 struct v4l2_ctrl *exposure;
211 struct v4l2_ctrl *metering;
212 };
213 struct {
214 /* iso/auto iso cluster */
215 struct v4l2_ctrl *auto_iso;
216 struct v4l2_ctrl *iso;
217 };
218 struct v4l2_ctrl *auto_wb;
219
220 struct v4l2_ctrl *lock_3a;
221 struct v4l2_ctrl *colorfx;
222 struct v4l2_ctrl *saturation;
223 struct v4l2_ctrl *zoom;
224 struct v4l2_ctrl *wdr;
225 struct v4l2_ctrl *stabilization;
226 struct v4l2_ctrl *jpeg_quality;
227
228 int (*set_power)(struct device *dev, int on);
229 struct gpio_desc *reset;
230
231 struct mutex lock;
232
233 struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
234 int res_type;
235
236 struct m5mols_version ver;
237 struct m5mols_capture cap;
238
239 unsigned int isp_ready:1;
240 unsigned int power:1;
241 unsigned int ctrl_sync:1;
242
243 u8 resolution;
244 u8 mode;
245};
246
247#define is_available_af(__info) (__info->ver.af)
248#define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code)
249#define is_manufacturer(__info, __manufacturer) \
250 (__info->ver.str[0] == __manufacturer[0] && \
251 __info->ver.str[1] == __manufacturer[1])
252/*
253 * I2C operation of the M-5MOLS
254 *
255 * The I2C read operation of the M-5MOLS requires 2 messages. The first
256 * message sends the information about the command, command category, and total
257 * message size. The second message is used to retrieve the data specified in
258 * the first message
259 *
260 * 1st message 2nd message
261 * +-------+---+----------+-----+-------+ +------+------+------+------+
262 * | size1 | R | category | cmd | size2 | | d[0] | d[1] | d[2] | d[3] |
263 * +-------+---+----------+-----+-------+ +------+------+------+------+
264 * - size1: message data size(5 in this case)
265 * - size2: desired buffer size of the 2nd message
266 * - d[0..3]: according to size2
267 *
268 * The I2C write operation needs just one message. The message includes
269 * category, command, total size, and desired data.
270 *
271 * 1st message
272 * +-------+---+----------+-----+------+------+------+------+
273 * | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] |
274 * +-------+---+----------+-----+------+------+------+------+
275 * - d[0..3]: according to size1
276 */
277int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
278int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
279int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
280int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
281
282int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
283 int timeout);
284
285/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */
286#define M5MOLS_I2C_RDY_WAIT_FL (1 << 16)
287/* ISP state transition timeout, in ms */
288#define M5MOLS_MODE_CHANGE_TIMEOUT 200
289#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT 250
290
291/*
292 * Mode operation of the M-5MOLS
293 *
294 * Changing the mode of the M-5MOLS is needed right executing order.
295 * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed
296 * by user. There are various categories associated with each mode.
297 *
298 * +============================================================+
299 * | mode | category |
300 * +============================================================+
301 * | FLASH | FLASH(only after Stand-by or Power-on) |
302 * | SYSTEM | SYSTEM(only after sensor arm-booting) |
303 * | PARAMETER | PARAMETER |
304 * | MONITOR | MONITOR(preview), Auto Focus, Face Detection |
305 * | CAPTURE | Single CAPTURE, Preview(recording) |
306 * +============================================================+
307 *
308 * The available executing order between each modes are as follows:
309 * PARAMETER <---> MONITOR <---> CAPTURE
310 */
311int m5mols_set_mode(struct m5mols_info *info, u8 mode);
312
313int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
314int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout);
315int m5mols_restore_controls(struct m5mols_info *info);
316int m5mols_start_capture(struct m5mols_info *info);
317int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
318int m5mols_lock_3a(struct m5mols_info *info, bool lock);
319int m5mols_set_ctrl(struct v4l2_ctrl *ctrl);
320int m5mols_init_controls(struct v4l2_subdev *sd);
321
322/* The firmware function */
323int m5mols_update_fw(struct v4l2_subdev *sd,
324 int (*set_power)(struct m5mols_info *, bool));
325
326static inline struct m5mols_info *to_m5mols(struct v4l2_subdev *subdev)
327{
328 return container_of(subdev, struct m5mols_info, sd);
329}
330
331static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
332{
333 struct m5mols_info *info = container_of(ctrl->handler,
334 struct m5mols_info, handle);
335 return &info->sd;
336}
337
338static inline void m5mols_set_ctrl_mode(struct v4l2_ctrl *ctrl,
339 unsigned int mode)
340{
341 ctrl->priv = (void *)(uintptr_t)mode;
342}
343
344static inline unsigned int m5mols_get_ctrl_mode(struct v4l2_ctrl *ctrl)
345{
346 return (unsigned int)(uintptr_t)ctrl->priv;
347}
348
349#endif /* M5MOLS_H */
drivers/media/i2c/m5mols/m5mols_capture.c+0−158
@@ -1,158 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3/*
4 * The Capture code for Fujitsu M-5MOLS ISP
5 *
6 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
7 * Author: HeungJun Kim <riverful.kim@samsung.com>
8 *
9 * Copyright (C) 2009 Samsung Electronics Co., Ltd.
10 * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
11 */
12
13#include <linux/i2c.h>
14#include <linux/slab.h>
15#include <linux/irq.h>
16#include <linux/interrupt.h>
17#include <linux/delay.h>
18#include <linux/regulator/consumer.h>
19#include <linux/videodev2.h>
20#include <media/v4l2-ctrls.h>
21#include <media/v4l2-device.h>
22#include <media/v4l2-subdev.h>
23#include <media/i2c/m5mols.h>
24#include <media/drv-intf/exynos-fimc.h>
25
26#include "m5mols.h"
27#include "m5mols_reg.h"
28
29/**
30 * m5mols_read_rational - I2C read of a rational number
31 * @sd: sub-device, as pointed by struct v4l2_subdev
32 * @addr_num: numerator register
33 * @addr_den: denominator register
34 * @val: place to store the division result
35 *
36 * Read numerator and denominator from registers @addr_num and @addr_den
37 * respectively and return the division result in @val.
38 */
39static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num,
40 u32 addr_den, u32 *val)
41{
42 u32 num, den;
43
44 int ret = m5mols_read_u32(sd, addr_num, &num);
45 if (!ret)
46 ret = m5mols_read_u32(sd, addr_den, &den);
47 if (ret)
48 return ret;
49 *val = den == 0 ? 0 : num / den;
50 return ret;
51}
52
53/**
54 * m5mols_capture_info - Gather captured image information
55 * @info: M-5MOLS driver data structure
56 *
57 * For now it gathers only EXIF information and file size.
58 */
59static int m5mols_capture_info(struct m5mols_info *info)
60{
61 struct m5mols_exif *exif = &info->cap.exif;
62 struct v4l2_subdev *sd = &info->sd;
63 int ret;
64
65 ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU,
66 EXIF_INFO_EXPTIME_DE, &exif->exposure_time);
67 if (ret)
68 return ret;
69 ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE,
70 &exif->shutter_speed);
71 if (ret)
72 return ret;
73 ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE,
74 &exif->aperture);
75 if (ret)
76 return ret;
77 ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE,
78 &exif->brightness);
79 if (ret)
80 return ret;
81 ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE,
82 &exif->exposure_bias);
83 if (ret)
84 return ret;
85
86 ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed);
87 if (!ret)
88 ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash);
89 if (!ret)
90 ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr);
91 if (!ret)
92 ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval);
93 if (ret)
94 return ret;
95
96 if (!ret)
97 ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main);
98 if (!ret)
99 ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb);
100 if (!ret)
101 info->cap.total = info->cap.main + info->cap.thumb;
102
103 return ret;
104}
105
106int m5mols_start_capture(struct m5mols_info *info)
107{
108 unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE;
109 struct v4l2_subdev *sd = &info->sd;
110 int ret;
111
112 /*
113 * Synchronize the controls, set the capture frame resolution and color
114 * format. The frame capture is initiated during switching from Monitor
115 * to Capture mode.
116 */
117 ret = m5mols_set_mode(info, REG_MONITOR);
118 if (!ret)
119 ret = m5mols_restore_controls(info);
120 if (!ret)
121 ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
122 if (!ret)
123 ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution);
124 if (!ret)
125 ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize);
126 if (!ret)
127 ret = m5mols_set_mode(info, REG_CAPTURE);
128 if (!ret)
129 /* Wait until a frame is captured to ISP internal memory */
130 ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
131 if (ret)
132 return ret;
133
134 /*
135 * Initiate the captured data transfer to a MIPI-CSI receiver.
136 */
137 ret = m5mols_write(sd, CAPC_SEL_FRAME, 1);
138 if (!ret)
139 ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);
140 if (!ret) {
141 bool captured = false;
142 unsigned int size;
143
144 /* Wait for the capture completion interrupt */
145 ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
146 if (!ret) {
147 captured = true;
148 ret = m5mols_capture_info(info);
149 }
150 size = captured ? info->cap.main : 0;
151 v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n",
152 __func__, size, info->cap.thumb);
153
154 v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size);
155 }
156
157 return ret;
158}
drivers/media/i2c/m5mols/m5mols_controls.c+0−625
@@ -1,625 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Controls for M-5MOLS 8M Pixel camera sensor with ISP
4 *
5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
6 * Author: HeungJun Kim <riverful.kim@samsung.com>
7 *
8 * Copyright (C) 2009 Samsung Electronics Co., Ltd.
9 * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
10 */
11
12#include <linux/i2c.h>
13#include <linux/delay.h>
14#include <linux/videodev2.h>
15#include <media/v4l2-ctrls.h>
16
17#include "m5mols.h"
18#include "m5mols_reg.h"
19
20static struct m5mols_scenemode m5mols_default_scenemode[] = {
21 [REG_SCENE_NORMAL] = {
22 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
23 REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
24 REG_AF_NORMAL, REG_FD_OFF,
25 REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF,
26 5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
27 },
28 [REG_SCENE_PORTRAIT] = {
29 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
30 REG_CHROMA_ON, 3, REG_EDGE_ON, 4,
31 REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME,
32 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
33 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
34 },
35 [REG_SCENE_LANDSCAPE] = {
36 REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
37 REG_CHROMA_ON, 4, REG_EDGE_ON, 6,
38 REG_AF_NORMAL, REG_FD_OFF,
39 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
40 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
41 },
42 [REG_SCENE_SPORTS] = {
43 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
44 REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
45 REG_AF_NORMAL, REG_FD_OFF,
46 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
47 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
48 },
49 [REG_SCENE_PARTY_INDOOR] = {
50 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
51 REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
52 REG_AF_NORMAL, REG_FD_OFF,
53 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
54 6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF,
55 },
56 [REG_SCENE_BEACH_SNOW] = {
57 REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0,
58 REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
59 REG_AF_NORMAL, REG_FD_OFF,
60 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
61 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
62 },
63 [REG_SCENE_SUNSET] = {
64 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
65 REG_AWB_DAYLIGHT,
66 REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
67 REG_AF_NORMAL, REG_FD_OFF,
68 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
69 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
70 },
71 [REG_SCENE_DAWN_DUSK] = {
72 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
73 REG_AWB_FLUORESCENT_1,
74 REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
75 REG_AF_NORMAL, REG_FD_OFF,
76 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
77 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
78 },
79 [REG_SCENE_FALL] = {
80 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
81 REG_CHROMA_ON, 5, REG_EDGE_ON, 5,
82 REG_AF_NORMAL, REG_FD_OFF,
83 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
84 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
85 },
86 [REG_SCENE_NIGHT] = {
87 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
88 REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
89 REG_AF_NORMAL, REG_FD_OFF,
90 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
91 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
92 },
93 [REG_SCENE_AGAINST_LIGHT] = {
94 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
95 REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
96 REG_AF_NORMAL, REG_FD_OFF,
97 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
98 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
99 },
100 [REG_SCENE_FIRE] = {
101 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
102 REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
103 REG_AF_NORMAL, REG_FD_OFF,
104 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
105 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
106 },
107 [REG_SCENE_TEXT] = {
108 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
109 REG_CHROMA_ON, 3, REG_EDGE_ON, 7,
110 REG_AF_MACRO, REG_FD_OFF,
111 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
112 6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON,
113 },
114 [REG_SCENE_CANDLE] = {
115 REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
116 REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
117 REG_AF_NORMAL, REG_FD_OFF,
118 REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
119 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
120 },
121};
122
123/**
124 * m5mols_do_scenemode() - Change current scenemode
125 * @info: M-5MOLS driver data structure
126 * @mode: Desired mode of the scenemode
127 *
128 * WARNING: The execution order is important. Do not change the order.
129 */
130int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
131{
132 struct v4l2_subdev *sd = &info->sd;
133 struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];
134 int ret;
135
136 if (mode > REG_SCENE_CANDLE)
137 return -EINVAL;
138
139 ret = v4l2_ctrl_s_ctrl(info->lock_3a, 0);
140 if (!ret)
141 ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);
142 if (!ret)
143 ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode);
144 if (!ret)
145 ret = m5mols_write(sd, AE_MODE, scenemode.metering);
146 if (!ret)
147 ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias);
148 if (!ret)
149 ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode);
150 if (!ret)
151 ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset);
152 if (!ret)
153 ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en);
154 if (!ret)
155 ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl);
156 if (!ret)
157 ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en);
158 if (!ret)
159 ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl);
160 if (!ret && is_available_af(info))
161 ret = m5mols_write(sd, AF_MODE, scenemode.af_range);
162 if (!ret && is_available_af(info))
163 ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode);
164 if (!ret)
165 ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone);
166 if (!ret)
167 ret = m5mols_write(sd, AE_ISO, scenemode.iso);
168 if (!ret)
169 ret = m5mols_set_mode(info, REG_CAPTURE);
170 if (!ret)
171 ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr);
172 if (!ret)
173 ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc);
174 if (!ret)
175 ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light);
176 if (!ret)
177 ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash);
178 if (!ret)
179 ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode);
180 if (!ret)
181 ret = m5mols_set_mode(info, REG_MONITOR);
182
183 return ret;
184}
185
186static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
187{
188 bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
189 int ret = 0;
190
191 if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
192 bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
193
194 ret = m5mols_write(&info->sd, AE_LOCK, ae_lock ?
195 REG_AE_LOCK : REG_AE_UNLOCK);
196 if (ret)
197 return ret;
198 }
199
200 if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
201 && info->auto_wb->val) {
202 bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;
203
204 ret = m5mols_write(&info->sd, AWB_LOCK, awb_lock ?
205 REG_AWB_LOCK : REG_AWB_UNLOCK);
206 if (ret)
207 return ret;
208 }
209
210 if (!info->ver.af || !af_lock)
211 return ret;
212
213 if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
214 ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
215
216 return ret;
217}
218
219static int m5mols_set_metering_mode(struct m5mols_info *info, int mode)
220{
221 unsigned int metering;
222
223 switch (mode) {
224 case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
225 metering = REG_AE_CENTER;
226 break;
227 case V4L2_EXPOSURE_METERING_SPOT:
228 metering = REG_AE_SPOT;
229 break;
230 default:
231 metering = REG_AE_ALL;
232 break;
233 }
234
235 return m5mols_write(&info->sd, AE_MODE, metering);
236}
237
238static int m5mols_set_exposure(struct m5mols_info *info, int exposure)
239{
240 struct v4l2_subdev *sd = &info->sd;
241 int ret = 0;
242
243 if (exposure == V4L2_EXPOSURE_AUTO) {
244 /* Unlock auto exposure */
245 info->lock_3a->val &= ~V4L2_LOCK_EXPOSURE;
246 m5mols_3a_lock(info, info->lock_3a);
247
248 ret = m5mols_set_metering_mode(info, info->metering->val);
249 if (ret < 0)
250 return ret;
251
252 v4l2_dbg(1, m5mols_debug, sd,
253 "%s: exposure bias: %#x, metering: %#x\n",
254 __func__, info->exposure_bias->val,
255 info->metering->val);
256
257 return m5mols_write(sd, AE_INDEX, info->exposure_bias->val);
258 }
259
260 if (exposure == V4L2_EXPOSURE_MANUAL) {
261 ret = m5mols_write(sd, AE_MODE, REG_AE_OFF);
262 if (ret == 0)
263 ret = m5mols_write(sd, AE_MAN_GAIN_MON,
264 info->exposure->val);
265 if (ret == 0)
266 ret = m5mols_write(sd, AE_MAN_GAIN_CAP,
267 info->exposure->val);
268
269 v4l2_dbg(1, m5mols_debug, sd, "%s: exposure: %#x\n",
270 __func__, info->exposure->val);
271 }
272
273 return ret;
274}
275
276static int m5mols_set_white_balance(struct m5mols_info *info, int val)
277{
278 static const unsigned short wb[][2] = {
279 { V4L2_WHITE_BALANCE_INCANDESCENT, REG_AWB_INCANDESCENT },
280 { V4L2_WHITE_BALANCE_FLUORESCENT, REG_AWB_FLUORESCENT_1 },
281 { V4L2_WHITE_BALANCE_FLUORESCENT_H, REG_AWB_FLUORESCENT_2 },
282 { V4L2_WHITE_BALANCE_HORIZON, REG_AWB_HORIZON },
283 { V4L2_WHITE_BALANCE_DAYLIGHT, REG_AWB_DAYLIGHT },
284 { V4L2_WHITE_BALANCE_FLASH, REG_AWB_LEDLIGHT },
285 { V4L2_WHITE_BALANCE_CLOUDY, REG_AWB_CLOUDY },
286 { V4L2_WHITE_BALANCE_SHADE, REG_AWB_SHADE },
287 { V4L2_WHITE_BALANCE_AUTO, REG_AWB_AUTO },
288 };
289 int i;
290 struct v4l2_subdev *sd = &info->sd;
291 int ret = -EINVAL;
292
293 for (i = 0; i < ARRAY_SIZE(wb); i++) {
294 int awb;
295 if (wb[i][0] != val)
296 continue;
297
298 v4l2_dbg(1, m5mols_debug, sd,
299 "Setting white balance to: %#x\n", wb[i][0]);
300
301 awb = wb[i][0] == V4L2_WHITE_BALANCE_AUTO;
302 ret = m5mols_write(sd, AWB_MODE, awb ? REG_AWB_AUTO :
303 REG_AWB_PRESET);
304 if (ret < 0)
305 return ret;
306
307 if (!awb)
308 ret = m5mols_write(sd, AWB_MANUAL, wb[i][1]);
309 }
310
311 return ret;
312}
313
314static int m5mols_set_saturation(struct m5mols_info *info, int val)
315{
316 int ret = m5mols_write(&info->sd, MON_CHROMA_LVL, val);
317 if (ret < 0)
318 return ret;
319
320 return m5mols_write(&info->sd, MON_CHROMA_EN, REG_CHROMA_ON);
321}
322
323static int m5mols_set_color_effect(struct m5mols_info *info, int val)
324{
325 unsigned int m_effect = REG_COLOR_EFFECT_OFF;
326 unsigned int p_effect = REG_EFFECT_OFF;
327 unsigned int cfix_r = 0, cfix_b = 0;
328 struct v4l2_subdev *sd = &info->sd;
329 int ret = 0;
330
331 switch (val) {
332 case V4L2_COLORFX_BW:
333 m_effect = REG_COLOR_EFFECT_ON;
334 break;
335 case V4L2_COLORFX_NEGATIVE:
336 p_effect = REG_EFFECT_NEGA;
337 break;
338 case V4L2_COLORFX_EMBOSS:
339 p_effect = REG_EFFECT_EMBOSS;
340 break;
341 case V4L2_COLORFX_SEPIA:
342 m_effect = REG_COLOR_EFFECT_ON;
343 cfix_r = REG_CFIXR_SEPIA;
344 cfix_b = REG_CFIXB_SEPIA;
345 break;
346 }
347
348 ret = m5mols_write(sd, PARM_EFFECT, p_effect);
349 if (!ret)
350 ret = m5mols_write(sd, MON_EFFECT, m_effect);
351
352 if (ret == 0 && m_effect == REG_COLOR_EFFECT_ON) {
353 ret = m5mols_write(sd, MON_CFIXR, cfix_r);
354 if (!ret)
355 ret = m5mols_write(sd, MON_CFIXB, cfix_b);
356 }
357
358 v4l2_dbg(1, m5mols_debug, sd,
359 "p_effect: %#x, m_effect: %#x, r: %#x, b: %#x (%d)\n",
360 p_effect, m_effect, cfix_r, cfix_b, ret);
361
362 return ret;
363}
364
365static int m5mols_set_iso(struct m5mols_info *info, int auto_iso)
366{
367 u32 iso = auto_iso ? 0 : info->iso->val + 1;
368
369 return m5mols_write(&info->sd, AE_ISO, iso);
370}
371
372static int m5mols_set_wdr(struct m5mols_info *info, int wdr)
373{
374 int ret;
375
376 ret = m5mols_write(&info->sd, MON_TONE_CTL, wdr ? 9 : 5);
377 if (ret < 0)
378 return ret;
379
380 ret = m5mols_set_mode(info, REG_CAPTURE);
381 if (ret < 0)
382 return ret;
383
384 return m5mols_write(&info->sd, CAPP_WDR_EN, wdr);
385}
386
387static int m5mols_set_stabilization(struct m5mols_info *info, int val)
388{
389 struct v4l2_subdev *sd = &info->sd;
390 unsigned int evp = val ? 0xe : 0x0;
391 int ret;
392
393 ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, evp);
394 if (ret < 0)
395 return ret;
396
397 return m5mols_write(sd, AE_EV_PRESET_CAPTURE, evp);
398}
399
400static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
401{
402 struct v4l2_subdev *sd = to_sd(ctrl);
403 struct m5mols_info *info = to_m5mols(sd);
404 int ret = 0;
405 u8 status = REG_ISO_AUTO;
406
407 v4l2_dbg(1, m5mols_debug, sd, "%s: ctrl: %s (%d)\n",
408 __func__, ctrl->name, info->isp_ready);
409
410 if (!info->isp_ready)
411 return -EBUSY;
412
413 switch (ctrl->id) {
414 case V4L2_CID_ISO_SENSITIVITY_AUTO:
415 ret = m5mols_read_u8(sd, AE_ISO, &status);
416 if (ret == 0)
417 ctrl->val = !status;
418 if (status != REG_ISO_AUTO)
419 info->iso->val = status - 1;
420 break;
421
422 case V4L2_CID_3A_LOCK:
423 ctrl->val &= ~0x7;
424
425 ret = m5mols_read_u8(sd, AE_LOCK, &status);
426 if (ret)
427 return ret;
428 if (status)
429 info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
430
431 ret = m5mols_read_u8(sd, AWB_LOCK, &status);
432 if (ret)
433 return ret;
434 if (status)
435 info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
436
437 ret = m5mols_read_u8(sd, AF_EXECUTE, &status);
438 if (!status)
439 info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
440 break;
441 }
442
443 return ret;
444}
445
446static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
447{
448 unsigned int ctrl_mode = m5mols_get_ctrl_mode(ctrl);
449 struct v4l2_subdev *sd = to_sd(ctrl);
450 struct m5mols_info *info = to_m5mols(sd);
451 int last_mode = info->mode;
452 int ret = 0;
453
454 /*
455 * If needed, defer restoring the controls until
456 * the device is fully initialized.
457 */
458 if (!info->isp_ready) {
459 info->ctrl_sync = 0;
460 return 0;
461 }
462
463 v4l2_dbg(1, m5mols_debug, sd, "%s: %s, val: %d, priv: %p\n",
464 __func__, ctrl->name, ctrl->val, ctrl->priv);
465
466 if (ctrl_mode && ctrl_mode != info->mode) {
467 ret = m5mols_set_mode(info, ctrl_mode);
468 if (ret < 0)
469 return ret;
470 }
471
472 switch (ctrl->id) {
473 case V4L2_CID_3A_LOCK:
474 ret = m5mols_3a_lock(info, ctrl);
475 break;
476
477 case V4L2_CID_ZOOM_ABSOLUTE:
478 ret = m5mols_write(sd, MON_ZOOM, ctrl->val);
479 break;
480
481 case V4L2_CID_EXPOSURE_AUTO:
482 ret = m5mols_set_exposure(info, ctrl->val);
483 break;
484
485 case V4L2_CID_ISO_SENSITIVITY:
486 ret = m5mols_set_iso(info, ctrl->val);
487 break;
488
489 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
490 ret = m5mols_set_white_balance(info, ctrl->val);
491 break;
492
493 case V4L2_CID_SATURATION:
494 ret = m5mols_set_saturation(info, ctrl->val);
495 break;
496
497 case V4L2_CID_COLORFX:
498 ret = m5mols_set_color_effect(info, ctrl->val);
499 break;
500
501 case V4L2_CID_WIDE_DYNAMIC_RANGE:
502 ret = m5mols_set_wdr(info, ctrl->val);
503 break;
504
505 case V4L2_CID_IMAGE_STABILIZATION:
506 ret = m5mols_set_stabilization(info, ctrl->val);
507 break;
508
509 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
510 ret = m5mols_write(sd, CAPP_JPEG_RATIO, ctrl->val);
511 break;
512 }
513
514 if (ret == 0 && info->mode != last_mode)
515 ret = m5mols_set_mode(info, last_mode);
516
517 return ret;
518}
519
520static const struct v4l2_ctrl_ops m5mols_ctrl_ops = {
521 .g_volatile_ctrl = m5mols_g_volatile_ctrl,
522 .s_ctrl = m5mols_s_ctrl,
523};
524
525/* Supported manual ISO values */
526static const s64 iso_qmenu[] = {
527 /* AE_ISO: 0x01...0x07 (ISO: 50...3200) */
528 50000, 100000, 200000, 400000, 800000, 1600000, 3200000
529};
530
531/* Supported Exposure Bias values, -2.0EV...+2.0EV */
532static const s64 ev_bias_qmenu[] = {
533 /* AE_INDEX: 0x00...0x08 */
534 -2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
535};
536
537int m5mols_init_controls(struct v4l2_subdev *sd)
538{
539 struct m5mols_info *info = to_m5mols(sd);
540 u16 exposure_max;
541 u16 zoom_step;
542 int ret;
543
544 /* Determine the firmware dependent control range and step values */
545 ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max);
546 if (ret < 0)
547 return ret;
548
549 zoom_step = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1;
550 v4l2_ctrl_handler_init(&info->handle, 20);
551
552 info->auto_wb = v4l2_ctrl_new_std_menu(&info->handle,
553 &m5mols_ctrl_ops, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
554 9, ~0x3fe, V4L2_WHITE_BALANCE_AUTO);
555
556 /* Exposure control cluster */
557 info->auto_exposure = v4l2_ctrl_new_std_menu(&info->handle,
558 &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
559 1, ~0x03, V4L2_EXPOSURE_AUTO);
560
561 info->exposure = v4l2_ctrl_new_std(&info->handle,
562 &m5mols_ctrl_ops, V4L2_CID_EXPOSURE,
563 0, exposure_max, 1, exposure_max / 2);
564
565 info->exposure_bias = v4l2_ctrl_new_int_menu(&info->handle,
566 &m5mols_ctrl_ops, V4L2_CID_AUTO_EXPOSURE_BIAS,
567 ARRAY_SIZE(ev_bias_qmenu) - 1,
568 ARRAY_SIZE(ev_bias_qmenu)/2 - 1,
569 ev_bias_qmenu);
570
571 info->metering = v4l2_ctrl_new_std_menu(&info->handle,
572 &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_METERING,
573 2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE);
574
575 /* ISO control cluster */
576 info->auto_iso = v4l2_ctrl_new_std_menu(&info->handle, &m5mols_ctrl_ops,
577 V4L2_CID_ISO_SENSITIVITY_AUTO, 1, ~0x03, 1);
578
579 info->iso = v4l2_ctrl_new_int_menu(&info->handle, &m5mols_ctrl_ops,
580 V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1,
581 ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu);
582
583 info->saturation = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
584 V4L2_CID_SATURATION, 1, 5, 1, 3);
585
586 info->zoom = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
587 V4L2_CID_ZOOM_ABSOLUTE, 1, 70, zoom_step, 1);
588
589 info->colorfx = v4l2_ctrl_new_std_menu(&info->handle, &m5mols_ctrl_ops,
590 V4L2_CID_COLORFX, 4, 0, V4L2_COLORFX_NONE);
591
592 info->wdr = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
593 V4L2_CID_WIDE_DYNAMIC_RANGE, 0, 1, 1, 0);
594
595 info->stabilization = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
596 V4L2_CID_IMAGE_STABILIZATION, 0, 1, 1, 0);
597
598 info->jpeg_quality = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
599 V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 80);
600
601 info->lock_3a = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
602 V4L2_CID_3A_LOCK, 0, 0x7, 0, 0);
603
604 if (info->handle.error) {
605 int ret = info->handle.error;
606 v4l2_err(sd, "Failed to initialize controls: %d\n", ret);
607 v4l2_ctrl_handler_free(&info->handle);
608 return ret;
609 }
610
611 v4l2_ctrl_auto_cluster(4, &info->auto_exposure, 1, false);
612 info->auto_iso->flags |= V4L2_CTRL_FLAG_VOLATILE |
613 V4L2_CTRL_FLAG_UPDATE;
614 v4l2_ctrl_auto_cluster(2, &info->auto_iso, 0, false);
615
616 info->lock_3a->flags |= V4L2_CTRL_FLAG_VOLATILE;
617
618 m5mols_set_ctrl_mode(info->auto_exposure, REG_PARAMETER);
619 m5mols_set_ctrl_mode(info->auto_wb, REG_PARAMETER);
620 m5mols_set_ctrl_mode(info->colorfx, REG_MONITOR);
621
622 sd->ctrl_handler = &info->handle;
623
624 return 0;
625}
drivers/media/i2c/m5mols/m5mols_core.c+0−1051
@@ -1,1051 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Driver for M-5MOLS 8M Pixel camera sensor with ISP
4 *
5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
6 * Author: HeungJun Kim <riverful.kim@samsung.com>
7 *
8 * Copyright (C) 2009 Samsung Electronics Co., Ltd.
9 * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
10 */
11
12#include <linux/i2c.h>
13#include <linux/slab.h>
14#include <linux/irq.h>
15#include <linux/interrupt.h>
16#include <linux/delay.h>
17#include <linux/gpio/consumer.h>
18#include <linux/regulator/consumer.h>
19#include <linux/videodev2.h>
20#include <linux/module.h>
21#include <media/v4l2-ctrls.h>
22#include <media/v4l2-device.h>
23#include <media/v4l2-subdev.h>
24#include <media/i2c/m5mols.h>
25
26#include "m5mols.h"
27#include "m5mols_reg.h"
28
29int m5mols_debug;
30module_param(m5mols_debug, int, 0644);
31
32#define MODULE_NAME "M5MOLS"
33#define M5MOLS_I2C_CHECK_RETRY 500
34
35/* The regulator consumer names for external voltage regulators */
36static struct regulator_bulk_data supplies[] = {
37 {
38 .supply = "core", /* ARM core power, 1.2V */
39 }, {
40 .supply = "dig_18", /* digital power 1, 1.8V */
41 }, {
42 .supply = "d_sensor", /* sensor power 1, 1.8V */
43 }, {
44 .supply = "dig_28", /* digital power 2, 2.8V */
45 }, {
46 .supply = "a_sensor", /* analog power */
47 }, {
48 .supply = "dig_12", /* digital power 3, 1.2V */
49 },
50};
51
52static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = {
53 [M5MOLS_RESTYPE_MONITOR] = {
54 .width = 1920,
55 .height = 1080,
56 .code = MEDIA_BUS_FMT_VYUY8_2X8,
57 .field = V4L2_FIELD_NONE,
58 .colorspace = V4L2_COLORSPACE_JPEG,
59 },
60 [M5MOLS_RESTYPE_CAPTURE] = {
61 .width = 1920,
62 .height = 1080,
63 .code = MEDIA_BUS_FMT_JPEG_1X8,
64 .field = V4L2_FIELD_NONE,
65 .colorspace = V4L2_COLORSPACE_JPEG,
66 },
67};
68#define SIZE_DEFAULT_FFMT ARRAY_SIZE(m5mols_default_ffmt)
69
70static const struct m5mols_resolution m5mols_reg_res[] = {
71 { 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 }, /* SUB-QCIF */
72 { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 }, /* QQVGA */
73 { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 }, /* QCIF */
74 { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 },
75 { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 }, /* QVGA */
76 { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 }, /* QVGA */
77 { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 }, /* WQVGA */
78 { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 }, /* WQVGA */
79 { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 }, /* CIF */
80 { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 },
81 { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 }, /* qHD */
82 { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 }, /* VGA */
83 { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 },
84 { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 }, /* WVGA */
85 { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 }, /* SVGA */
86 { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 }, /* HD */
87 { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 }, /* 1080p */
88 { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 }, /* 2.63fps 8M */
89 { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 }, /* AHS_MON debug */
90
91 { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 }, /* QVGA */
92 { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 }, /* WQVGA */
93 { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 },
94 { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 }, /* qHD */
95 { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 }, /* VGA */
96 { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 }, /* WVGA */
97 { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 }, /* HD */
98 { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 }, /* 1M */
99 { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 }, /* 2M */
100 { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 }, /* Full-HD */
101 { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 }, /* 3Mega */
102 { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 },
103 { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 }, /* 4Mega */
104 { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 },
105 { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 }, /* 5Mega */
106 { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 }, /* 6Mega */
107 { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 },
108 { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 }, /* 8Mega */
109};
110
111/**
112 * m5mols_swap_byte - an byte array to integer conversion function
113 * @data: byte array
114 * @length: size in bytes of I2C packet defined in the M-5MOLS datasheet
115 *
116 * Convert I2C data byte array with performing any required byte
117 * reordering to assure proper values for each data type, regardless
118 * of the architecture endianness.
119 */
120static u32 m5mols_swap_byte(u8 *data, u8 length)
121{
122 if (length == 1)
123 return *data;
124 else if (length == 2)
125 return be16_to_cpu(*((__be16 *)data));
126 else
127 return be32_to_cpu(*((__be32 *)data));
128}
129
130/**
131 * m5mols_read - I2C read function
132 * @sd: sub-device, as pointed by struct v4l2_subdev
133 * @size: desired size of I2C packet
134 * @reg: combination of size, category and command for the I2C packet
135 * @val: read value
136 *
137 * Returns 0 on success, or else negative errno.
138 */
139static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
140{
141 struct i2c_client *client = v4l2_get_subdevdata(sd);
142 struct m5mols_info *info = to_m5mols(sd);
143 u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
144 u8 category = I2C_CATEGORY(reg);
145 u8 cmd = I2C_COMMAND(reg);
146 struct i2c_msg msg[2];
147 u8 wbuf[5];
148 int ret;
149
150 if (!client->adapter)
151 return -ENODEV;
152
153 msg[0].addr = client->addr;
154 msg[0].flags = 0;
155 msg[0].len = 5;
156 msg[0].buf = wbuf;
157 wbuf[0] = 5;
158 wbuf[1] = M5MOLS_BYTE_READ;
159 wbuf[2] = category;
160 wbuf[3] = cmd;
161 wbuf[4] = size;
162
163 msg[1].addr = client->addr;
164 msg[1].flags = I2C_M_RD;
165 msg[1].len = size + 1;
166 msg[1].buf = rbuf;
167
168 /* minimum stabilization time */
169 usleep_range(200, 300);
170
171 ret = i2c_transfer(client->adapter, msg, 2);
172
173 if (ret == 2) {
174 *val = m5mols_swap_byte(&rbuf[1], size);
175 return 0;
176 }
177
178 if (info->isp_ready)
179 v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
180 size, category, cmd, ret);
181
182 return ret < 0 ? ret : -EIO;
183}
184
185int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
186{
187 u32 val_32;
188 int ret;
189
190 if (I2C_SIZE(reg) != 1) {
191 v4l2_err(sd, "Wrong data size\n");
192 return -EINVAL;
193 }
194
195 ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
196 if (ret)
197 return ret;
198
199 *val = (u8)val_32;
200 return ret;
201}
202
203int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val)
204{
205 u32 val_32;
206 int ret;
207
208 if (I2C_SIZE(reg) != 2) {
209 v4l2_err(sd, "Wrong data size\n");
210 return -EINVAL;
211 }
212
213 ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
214 if (ret)
215 return ret;
216
217 *val = (u16)val_32;
218 return ret;
219}
220
221int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
222{
223 if (I2C_SIZE(reg) != 4) {
224 v4l2_err(sd, "Wrong data size\n");
225 return -EINVAL;
226 }
227
228 return m5mols_read(sd, I2C_SIZE(reg), reg, val);
229}
230
231/**
232 * m5mols_write - I2C command write function
233 * @sd: sub-device, as pointed by struct v4l2_subdev
234 * @reg: combination of size, category and command for the I2C packet
235 * @val: value to write
236 *
237 * Returns 0 on success, or else negative errno.
238 */
239int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
240{
241 struct i2c_client *client = v4l2_get_subdevdata(sd);
242 struct m5mols_info *info = to_m5mols(sd);
243 u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
244 u8 category = I2C_CATEGORY(reg);
245 u8 cmd = I2C_COMMAND(reg);
246 u8 size = I2C_SIZE(reg);
247 u32 *buf = (u32 *)&wbuf[4];
248 struct i2c_msg msg[1];
249 int ret;
250
251 if (!client->adapter)
252 return -ENODEV;
253
254 if (size != 1 && size != 2 && size != 4) {
255 v4l2_err(sd, "Wrong data size\n");
256 return -EINVAL;
257 }
258
259 msg->addr = client->addr;
260 msg->flags = 0;
261 msg->len = (u16)size + 4;
262 msg->buf = wbuf;
263 wbuf[0] = size + 4;
264 wbuf[1] = M5MOLS_BYTE_WRITE;
265 wbuf[2] = category;
266 wbuf[3] = cmd;
267
268 *buf = m5mols_swap_byte((u8 *)&val, size);
269
270 /* minimum stabilization time */
271 usleep_range(200, 300);
272
273 ret = i2c_transfer(client->adapter, msg, 1);
274 if (ret == 1)
275 return 0;
276
277 if (info->isp_ready)
278 v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n",
279 category, cmd, ret);
280
281 return ret < 0 ? ret : -EIO;
282}
283
284/**
285 * m5mols_busy_wait - Busy waiting with I2C register polling
286 * @sd: sub-device, as pointed by struct v4l2_subdev
287 * @reg: the I2C_REG() address of an 8-bit status register to check
288 * @value: expected status register value
289 * @mask: bit mask for the read status register value
290 * @timeout: timeout in milliseconds, or -1 for default timeout
291 *
292 * The @reg register value is ORed with @mask before comparing with @value.
293 *
294 * Return: 0 if the requested condition became true within less than
295 * @timeout ms, or else negative errno.
296 */
297int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
298 int timeout)
299{
300 int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
301 unsigned long end = jiffies + msecs_to_jiffies(ms);
302 u8 status;
303
304 do {
305 int ret = m5mols_read_u8(sd, reg, &status);
306
307 if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
308 return ret;
309 if (!ret && (status & mask & 0xff) == (value & 0xff))
310 return 0;
311 usleep_range(100, 250);
312 } while (ms > 0 && time_is_after_jiffies(end));
313
314 return -EBUSY;
315}
316
317/**
318 * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts
319 * @sd: sub-device, as pointed by struct v4l2_subdev
320 * @reg: combination of size, category and command for the I2C packet
321 *
322 * Before writing desired interrupt value the INT_FACTOR register should
323 * be read to clear pending interrupts.
324 */
325int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
326{
327 struct m5mols_info *info = to_m5mols(sd);
328 u8 mask = is_available_af(info) ? REG_INT_AF : 0;
329 u8 dummy;
330 int ret;
331
332 ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
333 if (!ret)
334 ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
335 return ret;
336}
337
338int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout)
339{
340 struct m5mols_info *info = to_m5mols(sd);
341
342 int ret = wait_event_interruptible_timeout(info->irq_waitq,
343 atomic_add_unless(&info->irq_done, -1, 0),
344 msecs_to_jiffies(timeout));
345 if (ret <= 0)
346 return ret ? ret : -ETIMEDOUT;
347
348 return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask,
349 M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1);
350}
351
352/**
353 * m5mols_reg_mode - Write the mode and check busy status
354 * @sd: sub-device, as pointed by struct v4l2_subdev
355 * @mode: the required operation mode
356 *
357 * It always accompanies a little delay changing the M-5MOLS mode, so it is
358 * needed checking current busy status to guarantee right mode.
359 */
360static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
361{
362 int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
363 if (ret < 0)
364 return ret;
365 return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
366 M5MOLS_MODE_CHANGE_TIMEOUT);
367}
368
369/**
370 * m5mols_set_mode - set the M-5MOLS controller mode
371 * @info: M-5MOLS driver data structure
372 * @mode: the required operation mode
373 *
374 * The commands of M-5MOLS are grouped into specific modes. Each functionality
375 * can be guaranteed only when the sensor is operating in mode which a command
376 * belongs to.
377 */
378int m5mols_set_mode(struct m5mols_info *info, u8 mode)
379{
380 struct v4l2_subdev *sd = &info->sd;
381 int ret = -EINVAL;
382 u8 reg;
383
384 if (mode < REG_PARAMETER || mode > REG_CAPTURE)
385 return ret;
386
387 ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
388 if (ret || reg == mode)
389 return ret;
390
391 switch (reg) {
392 case REG_PARAMETER:
393 ret = m5mols_reg_mode(sd, REG_MONITOR);
394 if (mode == REG_MONITOR)
395 break;
396 if (!ret)
397 ret = m5mols_reg_mode(sd, REG_CAPTURE);
398 break;
399
400 case REG_MONITOR:
401 if (mode == REG_PARAMETER) {
402 ret = m5mols_reg_mode(sd, REG_PARAMETER);
403 break;
404 }
405
406 ret = m5mols_reg_mode(sd, REG_CAPTURE);
407 break;
408
409 case REG_CAPTURE:
410 ret = m5mols_reg_mode(sd, REG_MONITOR);
411 if (mode == REG_MONITOR)
412 break;
413 if (!ret)
414 ret = m5mols_reg_mode(sd, REG_PARAMETER);
415 break;
416
417 default:
418 v4l2_warn(sd, "Wrong mode: %d\n", mode);
419 }
420
421 if (!ret)
422 info->mode = mode;
423
424 return ret;
425}
426
427/**
428 * m5mols_get_version - retrieve full revisions information of M-5MOLS
429 * @sd: sub-device, as pointed by struct v4l2_subdev
430 *
431 * The version information includes revisions of hardware and firmware,
432 * AutoFocus alghorithm version and the version string.
433 */
434static int m5mols_get_version(struct v4l2_subdev *sd)
435{
436 struct m5mols_info *info = to_m5mols(sd);
437 struct m5mols_version *ver = &info->ver;
438 u8 *str = ver->str;
439 int i;
440 int ret;
441
442 ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer);
443 if (!ret)
444 ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project);
445 if (!ret)
446 ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw);
447 if (!ret)
448 ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw);
449 if (!ret)
450 ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param);
451 if (!ret)
452 ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb);
453 if (!ret)
454 ret = m5mols_read_u8(sd, AF_VERSION, &ver->af);
455 if (ret)
456 return ret;
457
458 for (i = 0; i < VERSION_STRING_SIZE; i++) {
459 ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]);
460 if (ret)
461 return ret;
462 }
463
464 v4l2_info(sd, "Manufacturer\t[%s]\n",
465 is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
466 "Samsung Electro-Mechanics" :
467 is_manufacturer(info, REG_SAMSUNG_OPTICS) ?
468 "Samsung Fiber-Optics" :
469 is_manufacturer(info, REG_SAMSUNG_TECHWIN) ?
470 "Samsung Techwin" : "None");
471 v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n",
472 info->ver.customer, info->ver.project);
473
474 if (!is_available_af(info))
475 v4l2_info(sd, "No support Auto Focus on this firmware\n");
476
477 return ret;
478}
479
480/**
481 * __find_restype - Lookup M-5MOLS resolution type according to pixel code
482 * @code: pixel code
483 */
484static enum m5mols_restype __find_restype(u32 code)
485{
486 enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
487
488 do {
489 if (code == m5mols_default_ffmt[type].code)
490 return type;
491 } while (++type != SIZE_DEFAULT_FFMT);
492
493 return 0;
494}
495
496/**
497 * __find_resolution - Lookup preset and type of M-5MOLS's resolution
498 * @sd: sub-device, as pointed by struct v4l2_subdev
499 * @mf: pixel format to find/negotiate the resolution preset for
500 * @type: M-5MOLS resolution type
501 * @resolution: M-5MOLS resolution preset register value
502 *
503 * Find nearest resolution matching resolution preset and adjust mf
504 * to supported values.
505 */
506static int __find_resolution(struct v4l2_subdev *sd,
507 struct v4l2_mbus_framefmt *mf,
508 enum m5mols_restype *type,
509 u32 *resolution)
510{
511 const struct m5mols_resolution *fsize = &m5mols_reg_res[0];
512 const struct m5mols_resolution *match = NULL;
513 enum m5mols_restype stype = __find_restype(mf->code);
514 int i = ARRAY_SIZE(m5mols_reg_res);
515 unsigned int min_err = ~0;
516
517 while (i--) {
518 int err;
519 if (stype == fsize->type) {
520 err = abs(fsize->width - mf->width)
521 + abs(fsize->height - mf->height);
522
523 if (err < min_err) {
524 min_err = err;
525 match = fsize;
526 }
527 }
528 fsize++;
529 }
530 if (match) {
531 mf->width = match->width;
532 mf->height = match->height;
533 *resolution = match->reg;
534 *type = stype;
535 return 0;
536 }
537
538 return -EINVAL;
539}
540
541static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info,
542 struct v4l2_subdev_state *sd_state,
543 enum v4l2_subdev_format_whence which,
544 enum m5mols_restype type)
545{
546 if (which == V4L2_SUBDEV_FORMAT_TRY)
547 return sd_state ? v4l2_subdev_get_try_format(&info->sd,
548 sd_state, 0) : NULL;
549
550 return &info->ffmt[type];
551}
552
553static int m5mols_get_fmt(struct v4l2_subdev *sd,
554 struct v4l2_subdev_state *sd_state,
555 struct v4l2_subdev_format *fmt)
556{
557 struct m5mols_info *info = to_m5mols(sd);
558 struct v4l2_mbus_framefmt *format;
559 int ret = 0;
560
561 mutex_lock(&info->lock);
562
563 format = __find_format(info, sd_state, fmt->which, info->res_type);
564 if (format)
565 fmt->format = *format;
566 else
567 ret = -EINVAL;
568
569 mutex_unlock(&info->lock);
570 return ret;
571}
572
573static int m5mols_set_fmt(struct v4l2_subdev *sd,
574 struct v4l2_subdev_state *sd_state,
575 struct v4l2_subdev_format *fmt)
576{
577 struct m5mols_info *info = to_m5mols(sd);
578 struct v4l2_mbus_framefmt *format = &fmt->format;
579 struct v4l2_mbus_framefmt *sfmt;
580 enum m5mols_restype type;
581 u32 resolution = 0;
582 int ret;
583
584 ret = __find_resolution(sd, format, &type, &resolution);
585 if (ret < 0)
586 return ret;
587
588 sfmt = __find_format(info, sd_state, fmt->which, type);
589 if (!sfmt)
590 return 0;
591
592 mutex_lock(&info->lock);
593
594 format->code = m5mols_default_ffmt[type].code;
595 format->colorspace = V4L2_COLORSPACE_JPEG;
596 format->field = V4L2_FIELD_NONE;
597
598 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
599 *sfmt = *format;
600 info->resolution = resolution;
601 info->res_type = type;
602 }
603
604 mutex_unlock(&info->lock);
605 return ret;
606}
607
608static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
609 struct v4l2_mbus_frame_desc *fd)
610{
611 struct m5mols_info *info = to_m5mols(sd);
612
613 if (pad != 0 || fd == NULL)
614 return -EINVAL;
615
616 mutex_lock(&info->lock);
617 /*
618 * .get_frame_desc is only used for compressed formats,
619 * thus we always return the capture frame parameters here.
620 */
621 fd->entry[0].length = info->cap.buf_size;
622 fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code;
623 mutex_unlock(&info->lock);
624
625 fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
626 fd->num_entries = 1;
627
628 return 0;
629}
630
631static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
632 struct v4l2_mbus_frame_desc *fd)
633{
634 struct m5mols_info *info = to_m5mols(sd);
635 struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE];
636
637 if (pad != 0 || fd == NULL)
638 return -EINVAL;
639
640 fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
641 fd->num_entries = 1;
642 fd->entry[0].length = clamp_t(u32, fd->entry[0].length,
643 mf->width * mf->height,
644 M5MOLS_MAIN_JPEG_SIZE_MAX);
645 mutex_lock(&info->lock);
646 info->cap.buf_size = fd->entry[0].length;
647 mutex_unlock(&info->lock);
648
649 return 0;
650}
651
652
653static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
654 struct v4l2_subdev_state *sd_state,
655 struct v4l2_subdev_mbus_code_enum *code)
656{
657 if (!code || code->index >= SIZE_DEFAULT_FFMT)
658 return -EINVAL;
659
660 code->code = m5mols_default_ffmt[code->index].code;
661
662 return 0;
663}
664
665static const struct v4l2_subdev_pad_ops m5mols_pad_ops = {
666 .enum_mbus_code = m5mols_enum_mbus_code,
667 .get_fmt = m5mols_get_fmt,
668 .set_fmt = m5mols_set_fmt,
669 .get_frame_desc = m5mols_get_frame_desc,
670 .set_frame_desc = m5mols_set_frame_desc,
671};
672
673/**
674 * m5mols_restore_controls - Apply current control values to the registers
675 * @info: M-5MOLS driver data structure
676 *
677 * m5mols_do_scenemode() handles all parameters for which there is yet no
678 * individual control. It should be replaced at some point by setting each
679 * control individually, in required register set up order.
680 */
681int m5mols_restore_controls(struct m5mols_info *info)
682{
683 int ret;
684
685 if (info->ctrl_sync)
686 return 0;
687
688 ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
689 if (ret)
690 return ret;
691
692 ret = v4l2_ctrl_handler_setup(&info->handle);
693 info->ctrl_sync = !ret;
694
695 return ret;
696}
697
698/**
699 * m5mols_start_monitor - Start the monitor mode
700 * @info: M-5MOLS driver data structure
701 *
702 * Before applying the controls setup the resolution and frame rate
703 * in PARAMETER mode, and then switch over to MONITOR mode.
704 */
705static int m5mols_start_monitor(struct m5mols_info *info)
706{
707 struct v4l2_subdev *sd = &info->sd;
708 int ret;
709
710 ret = m5mols_set_mode(info, REG_PARAMETER);
711 if (!ret)
712 ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution);
713 if (!ret)
714 ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30);
715 if (!ret)
716 ret = m5mols_set_mode(info, REG_MONITOR);
717 if (!ret)
718 ret = m5mols_restore_controls(info);
719
720 return ret;
721}
722
723static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
724{
725 struct m5mols_info *info = to_m5mols(sd);
726 u32 code;
727 int ret;
728
729 mutex_lock(&info->lock);
730 code = info->ffmt[info->res_type].code;
731
732 if (enable) {
733 if (is_code(code, M5MOLS_RESTYPE_MONITOR))
734 ret = m5mols_start_monitor(info);
735 else if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
736 ret = m5mols_start_capture(info);
737 else
738 ret = -EINVAL;
739 } else {
740 ret = m5mols_set_mode(info, REG_PARAMETER);
741 }
742
743 mutex_unlock(&info->lock);
744 return ret;
745}
746
747static const struct v4l2_subdev_video_ops m5mols_video_ops = {
748 .s_stream = m5mols_s_stream,
749};
750
751static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
752{
753 struct v4l2_subdev *sd = &info->sd;
754 struct i2c_client *client = v4l2_get_subdevdata(sd);
755 int ret;
756
757 if (info->power == enable)
758 return 0;
759
760 if (enable) {
761 if (info->set_power) {
762 ret = info->set_power(&client->dev, 1);
763 if (ret)
764 return ret;
765 }
766
767 ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
768 if (ret) {
769 if (info->set_power)
770 info->set_power(&client->dev, 0);
771 return ret;
772 }
773
774 gpiod_set_value(info->reset, 0);
775 info->power = 1;
776
777 return ret;
778 }
779
780 ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
781 if (ret)
782 return ret;
783
784 if (info->set_power)
785 info->set_power(&client->dev, 0);
786
787 gpiod_set_value(info->reset, 1);
788
789 info->isp_ready = 0;
790 info->power = 0;
791
792 return ret;
793}
794
795/* m5mols_update_fw - optional firmware update routine */
796int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd,
797 int (*set_power)(struct m5mols_info *, bool))
798{
799 return 0;
800}
801
802/**
803 * m5mols_fw_start - M-5MOLS internal ARM controller initialization
804 * @sd: sub-device, as pointed by struct v4l2_subdev
805 *
806 * Execute the M-5MOLS internal ARM controller initialization sequence.
807 * This function should be called after the supply voltage has been
808 * applied and before any requests to the device are made.
809 */
810static int m5mols_fw_start(struct v4l2_subdev *sd)
811{
812 struct m5mols_info *info = to_m5mols(sd);
813 int ret;
814
815 atomic_set(&info->irq_done, 0);
816 /* Wait until I2C slave is initialized in Flash Writer mode */
817 ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
818 M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
819 if (!ret)
820 ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
821 if (!ret)
822 ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
823 if (ret < 0)
824 return ret;
825
826 info->isp_ready = 1;
827
828 ret = m5mols_get_version(sd);
829 if (!ret)
830 ret = m5mols_update_fw(sd, m5mols_sensor_power);
831 if (ret)
832 return ret;
833
834 v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n");
835
836 ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
837 if (!ret)
838 ret = m5mols_enable_interrupt(sd,
839 REG_INT_AF | REG_INT_CAPTURE);
840
841 return ret;
842}
843
844/* Execute the lens soft-landing algorithm */
845static int m5mols_auto_focus_stop(struct m5mols_info *info)
846{
847 int ret;
848
849 ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
850 if (!ret)
851 ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF);
852 if (!ret)
853 ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE,
854 0xff, -1);
855 return ret;
856}
857
858/**
859 * m5mols_s_power - Main sensor power control function
860 * @sd: sub-device, as pointed by struct v4l2_subdev
861 * @on: if true, powers on the device; powers off otherwise.
862 *
863 * To prevent breaking the lens when the sensor is powered off the Soft-Landing
864 * algorithm is called where available. The Soft-Landing algorithm availability
865 * dependends on the firmware provider.
866 */
867static int m5mols_s_power(struct v4l2_subdev *sd, int on)
868{
869 struct m5mols_info *info = to_m5mols(sd);
870 int ret;
871
872 mutex_lock(&info->lock);
873
874 if (on) {
875 ret = m5mols_sensor_power(info, true);
876 if (!ret)
877 ret = m5mols_fw_start(sd);
878 } else {
879 if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
880 ret = m5mols_set_mode(info, REG_MONITOR);
881 if (!ret)
882 ret = m5mols_auto_focus_stop(info);
883 if (ret < 0)
884 v4l2_warn(sd, "Soft landing lens failed\n");
885 }
886 ret = m5mols_sensor_power(info, false);
887
888 info->ctrl_sync = 0;
889 }
890
891 mutex_unlock(&info->lock);
892 return ret;
893}
894
895static int m5mols_log_status(struct v4l2_subdev *sd)
896{
897 struct m5mols_info *info = to_m5mols(sd);
898
899 v4l2_ctrl_handler_log_status(&info->handle, sd->name);
900
901 return 0;
902}
903
904static const struct v4l2_subdev_core_ops m5mols_core_ops = {
905 .s_power = m5mols_s_power,
906 .log_status = m5mols_log_status,
907};
908
909/*
910 * V4L2 subdev internal operations
911 */
912static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
913{
914 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
915 fh->state,
916 0);
917
918 *format = m5mols_default_ffmt[0];
919 return 0;
920}
921
922static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = {
923 .open = m5mols_open,
924};
925
926static const struct v4l2_subdev_ops m5mols_ops = {
927 .core = &m5mols_core_ops,
928 .pad = &m5mols_pad_ops,
929 .video = &m5mols_video_ops,
930};
931
932static irqreturn_t m5mols_irq_handler(int irq, void *data)
933{
934 struct m5mols_info *info = to_m5mols(data);
935
936 atomic_set(&info->irq_done, 1);
937 wake_up_interruptible(&info->irq_waitq);
938
939 return IRQ_HANDLED;
940}
941
942static int m5mols_probe(struct i2c_client *client)
943{
944 const struct m5mols_platform_data *pdata = client->dev.platform_data;
945 struct m5mols_info *info;
946 struct v4l2_subdev *sd;
947 int ret;
948
949 if (pdata == NULL) {
950 dev_err(&client->dev, "No platform data\n");
951 return -EINVAL;
952 }
953
954 if (!client->irq) {
955 dev_err(&client->dev, "Interrupt not assigned\n");
956 return -EINVAL;
957 }
958
959 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
960 if (!info)
961 return -ENOMEM;
962
963 /* This asserts reset, descriptor shall have polarity specified */
964 info->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
965 if (IS_ERR(info->reset))
966 return PTR_ERR(info->reset);
967 /* Notice: the "N" in M5MOLS_NRST implies active low */
968 gpiod_set_consumer_name(info->reset, "M5MOLS_NRST");
969
970 info->pdata = pdata;
971 info->set_power = pdata->set_power;
972
973 ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies),
974 supplies);
975 if (ret) {
976 dev_err(&client->dev, "Failed to get regulators: %d\n", ret);
977 return ret;
978 }
979
980 sd = &info->sd;
981 v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
982 /* Static name; NEVER use in new drivers! */
983 strscpy(sd->name, MODULE_NAME, sizeof(sd->name));
984 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
985
986 sd->internal_ops = &m5mols_subdev_internal_ops;
987 info->pad.flags = MEDIA_PAD_FL_SOURCE;
988 ret = media_entity_pads_init(&sd->entity, 1, &info->pad);
989 if (ret < 0)
990 return ret;
991 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
992
993 init_waitqueue_head(&info->irq_waitq);
994 mutex_init(&info->lock);
995
996 ret = devm_request_irq(&client->dev, client->irq, m5mols_irq_handler,
997 IRQF_TRIGGER_RISING, MODULE_NAME, sd);
998 if (ret) {
999 dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
1000 goto error;
1001 }
1002 info->res_type = M5MOLS_RESTYPE_MONITOR;
1003 info->ffmt[0] = m5mols_default_ffmt[0];
1004 info->ffmt[1] = m5mols_default_ffmt[1];
1005
1006 ret = m5mols_sensor_power(info, true);
1007 if (ret)
1008 goto error;
1009
1010 ret = m5mols_fw_start(sd);
1011 if (!ret)
1012 ret = m5mols_init_controls(sd);
1013
1014 ret = m5mols_sensor_power(info, false);
1015 if (!ret)
1016 return 0;
1017error:
1018 media_entity_cleanup(&sd->entity);
1019 return ret;
1020}
1021
1022static void m5mols_remove(struct i2c_client *client)
1023{
1024 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1025
1026 v4l2_device_unregister_subdev(sd);
1027 v4l2_ctrl_handler_free(sd->ctrl_handler);
1028 media_entity_cleanup(&sd->entity);
1029}
1030
1031static const struct i2c_device_id m5mols_id[] = {
1032 { MODULE_NAME, 0 },
1033 { },
1034};
1035MODULE_DEVICE_TABLE(i2c, m5mols_id);
1036
1037static struct i2c_driver m5mols_i2c_driver = {
1038 .driver = {
1039 .name = MODULE_NAME,
1040 },
1041 .probe_new = m5mols_probe,
1042 .remove = m5mols_remove,
1043 .id_table = m5mols_id,
1044};
1045
1046module_i2c_driver(m5mols_i2c_driver);
1047
1048MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
1049MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>");
1050MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver");
1051MODULE_LICENSE("GPL");
drivers/media/i2c/m5mols/m5mols_reg.h+0−359
@@ -1,359 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Register map for M-5MOLS 8M Pixel camera sensor with ISP
4 *
5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
6 * Author: HeungJun Kim <riverful.kim@samsung.com>
7 *
8 * Copyright (C) 2009 Samsung Electronics Co., Ltd.
9 * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
10 */
11
12#ifndef M5MOLS_REG_H
13#define M5MOLS_REG_H
14
15#define M5MOLS_I2C_MAX_SIZE 4
16#define M5MOLS_BYTE_READ 0x01
17#define M5MOLS_BYTE_WRITE 0x02
18
19#define I2C_CATEGORY(__cat) ((__cat >> 16) & 0xff)
20#define I2C_COMMAND(__comm) ((__comm >> 8) & 0xff)
21#define I2C_SIZE(__reg_s) ((__reg_s) & 0xff)
22#define I2C_REG(__cat, __cmd, __reg_s) ((__cat << 16) | (__cmd << 8) | __reg_s)
23
24/*
25 * Category section register
26 *
27 * The category means set including relevant command of M-5MOLS.
28 */
29#define CAT_SYSTEM 0x00
30#define CAT_PARAM 0x01
31#define CAT_MONITOR 0x02
32#define CAT_AE 0x03
33#define CAT_WB 0x06
34#define CAT_EXIF 0x07
35#define CAT_FD 0x09
36#define CAT_LENS 0x0a
37#define CAT_CAPT_PARM 0x0b
38#define CAT_CAPT_CTRL 0x0c
39#define CAT_FLASH 0x0f /* related to FW, revisions, booting */
40
41/*
42 * Category 0 - SYSTEM mode
43 *
44 * The SYSTEM mode in the M-5MOLS means area available to handle with the whole
45 * & all-round system of sensor. It deals with version/interrupt/setting mode &
46 * even sensor's status. Especially, the M-5MOLS sensor with ISP varies by
47 * packaging & manufacturer, even the customer and project code. And the
48 * function details may vary among them. The version information helps to
49 * determine what methods shall be used in the driver.
50 *
51 * There is many registers between customer version address and awb one. For
52 * more specific contents, see definition if file m5mols.h.
53 */
54#define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, 0x00, 1)
55#define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, 0x01, 1)
56#define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, 0x02, 2)
57#define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, 0x04, 2)
58#define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, 0x06, 2)
59#define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, 0x08, 2)
60
61#define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, 0x0b, 1)
62#define REG_SYSINIT 0x00 /* SYSTEM mode */
63#define REG_PARAMETER 0x01 /* PARAMETER mode */
64#define REG_MONITOR 0x02 /* MONITOR mode */
65#define REG_CAPTURE 0x03 /* CAPTURE mode */
66
67#define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1)
68#define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, 0x0a, 1)
69#define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */
70#define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */
71#define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */
72/* SYSTEM mode status */
73#define SYSTEM_STATUS I2C_REG(CAT_SYSTEM, 0x0c, 1)
74
75/* Interrupt pending register */
76#define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, 0x10, 1)
77/* interrupt enable register */
78#define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, 0x11, 1)
79#define REG_INT_MODE (1 << 0)
80#define REG_INT_AF (1 << 1)
81#define REG_INT_ZOOM (1 << 2)
82#define REG_INT_CAPTURE (1 << 3)
83#define REG_INT_FRAMESYNC (1 << 4)
84#define REG_INT_FD (1 << 5)
85#define REG_INT_LENS_INIT (1 << 6)
86#define REG_INT_SOUND (1 << 7)
87#define REG_INT_MASK 0x0f
88
89/*
90 * category 1 - PARAMETER mode
91 *
92 * This category supports function of camera features of M-5MOLS. It means we
93 * can handle with preview(MONITOR) resolution size/frame per second/interface
94 * between the sensor and the Application Processor/even the image effect.
95 */
96
97/* Resolution in the MONITOR mode */
98#define PARM_MON_SIZE I2C_REG(CAT_PARAM, 0x01, 1)
99
100/* Frame rate */
101#define PARM_MON_FPS I2C_REG(CAT_PARAM, 0x02, 1)
102#define REG_FPS_30 0x02
103
104/* Video bus between the sensor and a host processor */
105#define PARM_INTERFACE I2C_REG(CAT_PARAM, 0x00, 1)
106#define REG_INTERFACE_MIPI 0x02
107
108/* Image effects */
109#define PARM_EFFECT I2C_REG(CAT_PARAM, 0x0b, 1)
110#define REG_EFFECT_OFF 0x00
111#define REG_EFFECT_NEGA 0x01
112#define REG_EFFECT_EMBOSS 0x06
113#define REG_EFFECT_OUTLINE 0x07
114#define REG_EFFECT_WATERCOLOR 0x08
115
116/*
117 * Category 2 - MONITOR mode
118 *
119 * The MONITOR mode is same as preview mode as we said. The M-5MOLS has another
120 * mode named "Preview", but this preview mode is used at the case specific
121 * vider-recording mode. This mmode supports only YUYV format. On the other
122 * hand, the JPEG & RAW formats is supports by CAPTURE mode. And, there are
123 * another options like zoom/color effect(different with effect in PARAMETER
124 * mode)/anti hand shaking algorithm.
125 */
126
127/* Target digital zoom position */
128#define MON_ZOOM I2C_REG(CAT_MONITOR, 0x01, 1)
129
130/* CR value for color effect */
131#define MON_CFIXR I2C_REG(CAT_MONITOR, 0x0a, 1)
132/* CB value for color effect */
133#define MON_CFIXB I2C_REG(CAT_MONITOR, 0x09, 1)
134#define REG_CFIXB_SEPIA 0xd8
135#define REG_CFIXR_SEPIA 0x18
136
137#define MON_EFFECT I2C_REG(CAT_MONITOR, 0x0b, 1)
138#define REG_COLOR_EFFECT_OFF 0x00
139#define REG_COLOR_EFFECT_ON 0x01
140
141/* Chroma enable */
142#define MON_CHROMA_EN I2C_REG(CAT_MONITOR, 0x10, 1)
143/* Chroma level */
144#define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, 0x0f, 1)
145#define REG_CHROMA_OFF 0x00
146#define REG_CHROMA_ON 0x01
147
148/* Sharpness on/off */
149#define MON_EDGE_EN I2C_REG(CAT_MONITOR, 0x12, 1)
150/* Sharpness level */
151#define MON_EDGE_LVL I2C_REG(CAT_MONITOR, 0x11, 1)
152#define REG_EDGE_OFF 0x00
153#define REG_EDGE_ON 0x01
154
155/* Set color tone (contrast) */
156#define MON_TONE_CTL I2C_REG(CAT_MONITOR, 0x25, 1)
157
158/*
159 * Category 3 - Auto Exposure
160 *
161 * The M-5MOLS exposure capbility is detailed as which is similar to digital
162 * camera. This category supports AE locking/various AE mode(range of exposure)
163 * /ISO/flickering/EV bias/shutter/meteoring, and anything else. And the
164 * maximum/minimum exposure gain value depending on M-5MOLS firmware, may be
165 * different. So, this category also provide getting the max/min values. And,
166 * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values.
167 */
168
169/* Auto Exposure locking */
170#define AE_LOCK I2C_REG(CAT_AE, 0x00, 1)
171#define REG_AE_UNLOCK 0x00
172#define REG_AE_LOCK 0x01
173
174/* Auto Exposure algorithm mode */
175#define AE_MODE I2C_REG(CAT_AE, 0x01, 1)
176#define REG_AE_OFF 0x00 /* AE off */
177#define REG_AE_ALL 0x01 /* calc AE in all block integral */
178#define REG_AE_CENTER 0x03 /* calc AE in center weighted */
179#define REG_AE_SPOT 0x06 /* calc AE in specific spot */
180
181#define AE_ISO I2C_REG(CAT_AE, 0x05, 1)
182#define REG_ISO_AUTO 0x00
183#define REG_ISO_50 0x01
184#define REG_ISO_100 0x02
185#define REG_ISO_200 0x03
186#define REG_ISO_400 0x04
187#define REG_ISO_800 0x05
188
189/* EV (scenemode) preset for MONITOR */
190#define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, 0x0a, 1)
191/* EV (scenemode) preset for CAPTURE */
192#define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, 0x0b, 1)
193#define REG_SCENE_NORMAL 0x00
194#define REG_SCENE_PORTRAIT 0x01
195#define REG_SCENE_LANDSCAPE 0x02
196#define REG_SCENE_SPORTS 0x03
197#define REG_SCENE_PARTY_INDOOR 0x04
198#define REG_SCENE_BEACH_SNOW 0x05
199#define REG_SCENE_SUNSET 0x06
200#define REG_SCENE_DAWN_DUSK 0x07
201#define REG_SCENE_FALL 0x08
202#define REG_SCENE_NIGHT 0x09
203#define REG_SCENE_AGAINST_LIGHT 0x0a
204#define REG_SCENE_FIRE 0x0b
205#define REG_SCENE_TEXT 0x0c
206#define REG_SCENE_CANDLE 0x0d
207
208/* Manual gain in MONITOR mode */
209#define AE_MAN_GAIN_MON I2C_REG(CAT_AE, 0x12, 2)
210/* Maximum gain in MONITOR mode */
211#define AE_MAX_GAIN_MON I2C_REG(CAT_AE, 0x1a, 2)
212/* Manual gain in CAPTURE mode */
213#define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, 0x26, 2)
214
215#define AE_INDEX I2C_REG(CAT_AE, 0x38, 1)
216#define REG_AE_INDEX_20_NEG 0x00
217#define REG_AE_INDEX_15_NEG 0x01
218#define REG_AE_INDEX_10_NEG 0x02
219#define REG_AE_INDEX_05_NEG 0x03
220#define REG_AE_INDEX_00 0x04
221#define REG_AE_INDEX_05_POS 0x05
222#define REG_AE_INDEX_10_POS 0x06
223#define REG_AE_INDEX_15_POS 0x07
224#define REG_AE_INDEX_20_POS 0x08
225
226/*
227 * Category 6 - White Balance
228 */
229
230/* Auto Whitebalance locking */
231#define AWB_LOCK I2C_REG(CAT_WB, 0x00, 1)
232#define REG_AWB_UNLOCK 0x00
233#define REG_AWB_LOCK 0x01
234
235#define AWB_MODE I2C_REG(CAT_WB, 0x02, 1)
236#define REG_AWB_AUTO 0x01 /* AWB off */
237#define REG_AWB_PRESET 0x02 /* AWB preset */
238
239/* Manual WB (preset) */
240#define AWB_MANUAL I2C_REG(CAT_WB, 0x03, 1)
241#define REG_AWB_INCANDESCENT 0x01
242#define REG_AWB_FLUORESCENT_1 0x02
243#define REG_AWB_FLUORESCENT_2 0x03
244#define REG_AWB_DAYLIGHT 0x04
245#define REG_AWB_CLOUDY 0x05
246#define REG_AWB_SHADE 0x06
247#define REG_AWB_HORIZON 0x07
248#define REG_AWB_LEDLIGHT 0x09
249
250/*
251 * Category 7 - EXIF information
252 */
253#define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, 0x00, 4)
254#define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, 0x04, 4)
255#define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, 0x08, 4)
256#define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, 0x0c, 4)
257#define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, 0x10, 4)
258#define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, 0x14, 4)
259#define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, 0x18, 4)
260#define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, 0x1c, 4)
261#define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, 0x20, 4)
262#define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, 0x24, 4)
263#define EXIF_INFO_ISO I2C_REG(CAT_EXIF, 0x28, 2)
264#define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, 0x2a, 2)
265#define EXIF_INFO_SDR I2C_REG(CAT_EXIF, 0x2c, 2)
266#define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, 0x2e, 2)
267
268/*
269 * Category 9 - Face Detection
270 */
271#define FD_CTL I2C_REG(CAT_FD, 0x00, 1)
272#define BIT_FD_EN 0
273#define BIT_FD_DRAW_FACE_FRAME 4
274#define BIT_FD_DRAW_SMILE_LVL 6
275#define REG_FD(shift) (1 << shift)
276#define REG_FD_OFF 0x0
277
278/*
279 * Category A - Lens Parameter
280 */
281#define AF_MODE I2C_REG(CAT_LENS, 0x01, 1)
282#define REG_AF_NORMAL 0x00 /* Normal AF, one time */
283#define REG_AF_MACRO 0x01 /* Macro AF, one time */
284#define REG_AF_POWEROFF 0x07
285
286#define AF_EXECUTE I2C_REG(CAT_LENS, 0x02, 1)
287#define REG_AF_STOP 0x00
288#define REG_AF_EXE_AUTO 0x01
289#define REG_AF_EXE_CAF 0x02
290
291#define AF_STATUS I2C_REG(CAT_LENS, 0x03, 1)
292#define REG_AF_FAIL 0x00
293#define REG_AF_SUCCESS 0x02
294#define REG_AF_IDLE 0x04
295#define REG_AF_BUSY 0x05
296
297#define AF_VERSION I2C_REG(CAT_LENS, 0x0a, 1)
298
299/*
300 * Category B - CAPTURE Parameter
301 */
302#define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, 0x00, 1)
303#define REG_YUV422 0x00
304#define REG_BAYER10 0x05
305#define REG_BAYER8 0x06
306#define REG_JPEG 0x10
307
308#define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, 0x01, 1)
309#define CAPP_JPEG_SIZE_MAX I2C_REG(CAT_CAPT_PARM, 0x0f, 4)
310#define CAPP_JPEG_RATIO I2C_REG(CAT_CAPT_PARM, 0x17, 1)
311
312#define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
313#define REG_MCC_OFF 0x00
314#define REG_MCC_NORMAL 0x01
315
316#define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, 0x2c, 1)
317#define REG_WDR_OFF 0x00
318#define REG_WDR_ON 0x01
319#define REG_WDR_AUTO 0x02
320
321#define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, 0x40, 1)
322#define REG_LIGHT_OFF 0x00
323#define REG_LIGHT_ON 0x01
324#define REG_LIGHT_AUTO 0x02
325
326#define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, 0x41, 1)
327#define REG_FLASH_OFF 0x00
328#define REG_FLASH_ON 0x01
329#define REG_FLASH_AUTO 0x02
330
331/*
332 * Category C - CAPTURE Control
333 */
334#define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, 0x00, 1)
335#define REG_CAP_NONE 0x00
336#define REG_CAP_ANTI_SHAKE 0x02
337
338/* Select single- or multi-shot capture */
339#define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, 0x06, 1)
340
341#define CAPC_START I2C_REG(CAT_CAPT_CTRL, 0x09, 1)
342#define REG_CAP_START_MAIN 0x01
343#define REG_CAP_START_THUMB 0x03
344
345#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, 0x0d, 4)
346#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, 0x11, 4)
347
348/*
349 * Category F - Flash
350 *
351 * This mode provides functions about internal flash stuff and system startup.
352 */
353
354/* Starts internal ARM core booting after power-up */
355#define FLASH_CAM_START I2C_REG(CAT_FLASH, 0x12, 1)
356#define REG_START_ARM_BOOT 0x01 /* write value */
357#define REG_IN_FLASH_MODE 0x00 /* read value */
358
359#endif /* M5MOLS_REG_H */
drivers/media/i2c/max9286.c+1−0
@@ -1122,6 +1122,7 @@ err_async: · 1121 unmodified lines
1122static void max9286_v4l2_unregister(struct max9286_priv *priv)1122static void max9286_v4l2_unregister(struct max9286_priv *priv)
1123{1123{
1124 fwnode_handle_put(priv->sd.fwnode);1124 fwnode_handle_put(priv->sd.fwnode);
1125 v4l2_ctrl_handler_free(&priv->ctrls);
1125 v4l2_async_unregister_subdev(&priv->sd);1126 v4l2_async_unregister_subdev(&priv->sd);
1126 max9286_v4l2_notifier_unregister(priv);1127 max9286_v4l2_notifier_unregister(priv);
1127}1128}
drivers/media/i2c/mt9m032.c+0−891
@@ -1,891 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for MT9M032 CMOS Image Sensor from Micron
4 *
5 * Copyright (C) 2010-2011 Lund Engineering
6 * Contact: Gil Lund <gwlund@lundeng.com>
7 * Author: Martin Hostettler <martin@neutronstar.dyndns.org>
8 */
9
10#include <linux/delay.h>
11#include <linux/i2c.h>
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/math64.h>
15#include <linux/module.h>
16#include <linux/mutex.h>
17#include <linux/slab.h>
18#include <linux/v4l2-mediabus.h>
19
20#include <media/media-entity.h>
21#include <media/i2c/mt9m032.h>
22#include <media/v4l2-ctrls.h>
23#include <media/v4l2-device.h>
24#include <media/v4l2-subdev.h>
25
26#include "aptina-pll.h"
27
28/*
29 * width and height include active boundary and black parts
30 *
31 * column 0- 15 active boundary
32 * column 16-1455 image
33 * column 1456-1471 active boundary
34 * column 1472-1599 black
35 *
36 * row 0- 51 black
37 * row 53- 59 active boundary
38 * row 60-1139 image
39 * row 1140-1147 active boundary
40 * row 1148-1151 black
41 */
42
43#define MT9M032_PIXEL_ARRAY_WIDTH 1600
44#define MT9M032_PIXEL_ARRAY_HEIGHT 1152
45
46#define MT9M032_CHIP_VERSION 0x00
47#define MT9M032_CHIP_VERSION_VALUE 0x1402
48#define MT9M032_ROW_START 0x01
49#define MT9M032_ROW_START_MIN 0
50#define MT9M032_ROW_START_MAX 1152
51#define MT9M032_ROW_START_DEF 60
52#define MT9M032_COLUMN_START 0x02
53#define MT9M032_COLUMN_START_MIN 0
54#define MT9M032_COLUMN_START_MAX 1600
55#define MT9M032_COLUMN_START_DEF 16
56#define MT9M032_ROW_SIZE 0x03
57#define MT9M032_ROW_SIZE_MIN 32
58#define MT9M032_ROW_SIZE_MAX 1152
59#define MT9M032_ROW_SIZE_DEF 1080
60#define MT9M032_COLUMN_SIZE 0x04
61#define MT9M032_COLUMN_SIZE_MIN 32
62#define MT9M032_COLUMN_SIZE_MAX 1600
63#define MT9M032_COLUMN_SIZE_DEF 1440
64#define MT9M032_HBLANK 0x05
65#define MT9M032_VBLANK 0x06
66#define MT9M032_VBLANK_MAX 0x7ff
67#define MT9M032_SHUTTER_WIDTH_HIGH 0x08
68#define MT9M032_SHUTTER_WIDTH_LOW 0x09
69#define MT9M032_SHUTTER_WIDTH_MIN 1
70#define MT9M032_SHUTTER_WIDTH_MAX 1048575
71#define MT9M032_SHUTTER_WIDTH_DEF 1943
72#define MT9M032_PIX_CLK_CTRL 0x0a
73#define MT9M032_PIX_CLK_CTRL_INV_PIXCLK 0x8000
74#define MT9M032_RESTART 0x0b
75#define MT9M032_RESET 0x0d
76#define MT9M032_PLL_CONFIG1 0x11
77#define MT9M032_PLL_CONFIG1_PREDIV_MASK 0x3f
78#define MT9M032_PLL_CONFIG1_MUL_SHIFT 8
79#define MT9M032_READ_MODE1 0x1e
80#define MT9M032_READ_MODE1_OUTPUT_BAD_FRAMES (1 << 13)
81#define MT9M032_READ_MODE1_MAINTAIN_FRAME_RATE (1 << 12)
82#define MT9M032_READ_MODE1_XOR_LINE_VALID (1 << 11)
83#define MT9M032_READ_MODE1_CONT_LINE_VALID (1 << 10)
84#define MT9M032_READ_MODE1_INVERT_TRIGGER (1 << 9)
85#define MT9M032_READ_MODE1_SNAPSHOT (1 << 8)
86#define MT9M032_READ_MODE1_GLOBAL_RESET (1 << 7)
87#define MT9M032_READ_MODE1_BULB_EXPOSURE (1 << 6)
88#define MT9M032_READ_MODE1_INVERT_STROBE (1 << 5)
89#define MT9M032_READ_MODE1_STROBE_ENABLE (1 << 4)
90#define MT9M032_READ_MODE1_STROBE_START_TRIG1 (0 << 2)
91#define MT9M032_READ_MODE1_STROBE_START_EXP (1 << 2)
92#define MT9M032_READ_MODE1_STROBE_START_SHUTTER (2 << 2)
93#define MT9M032_READ_MODE1_STROBE_START_TRIG2 (3 << 2)
94#define MT9M032_READ_MODE1_STROBE_END_TRIG1 (0 << 0)
95#define MT9M032_READ_MODE1_STROBE_END_EXP (1 << 0)
96#define MT9M032_READ_MODE1_STROBE_END_SHUTTER (2 << 0)
97#define MT9M032_READ_MODE1_STROBE_END_TRIG2 (3 << 0)
98#define MT9M032_READ_MODE2 0x20
99#define MT9M032_READ_MODE2_VFLIP_SHIFT 15
100#define MT9M032_READ_MODE2_HFLIP_SHIFT 14
101#define MT9M032_READ_MODE2_ROW_BLC 0x40
102#define MT9M032_GAIN_GREEN1 0x2b
103#define MT9M032_GAIN_BLUE 0x2c
104#define MT9M032_GAIN_RED 0x2d
105#define MT9M032_GAIN_GREEN2 0x2e
106
107/* write only */
108#define MT9M032_GAIN_ALL 0x35
109#define MT9M032_GAIN_DIGITAL_MASK 0x7f
110#define MT9M032_GAIN_DIGITAL_SHIFT 8
111#define MT9M032_GAIN_AMUL_SHIFT 6
112#define MT9M032_GAIN_ANALOG_MASK 0x3f
113#define MT9M032_FORMATTER1 0x9e
114#define MT9M032_FORMATTER1_PLL_P1_6 (1 << 8)
115#define MT9M032_FORMATTER1_PARALLEL (1 << 12)
116#define MT9M032_FORMATTER2 0x9f
117#define MT9M032_FORMATTER2_DOUT_EN 0x1000
118#define MT9M032_FORMATTER2_PIXCLK_EN 0x2000
119
120/*
121 * The available MT9M032 datasheet is missing documentation for register 0x10
122 * MT9P031 seems to be close enough, so use constants from that datasheet for
123 * now.
124 * But keep the name MT9P031 to remind us, that this isn't really confirmed
125 * for this sensor.
126 */
127#define MT9P031_PLL_CONTROL 0x10
128#define MT9P031_PLL_CONTROL_PWROFF 0x0050
129#define MT9P031_PLL_CONTROL_PWRON 0x0051
130#define MT9P031_PLL_CONTROL_USEPLL 0x0052
131
132struct mt9m032 {
133 struct v4l2_subdev subdev;
134 struct media_pad pad;
135 struct mt9m032_platform_data *pdata;
136
137 unsigned int pix_clock;
138
139 struct v4l2_ctrl_handler ctrls;
140 struct {
141 struct v4l2_ctrl *hflip;
142 struct v4l2_ctrl *vflip;
143 };
144
145 struct mutex lock; /* Protects streaming, format, interval and crop */
146
147 bool streaming;
148
149 struct v4l2_mbus_framefmt format;
150 struct v4l2_rect crop;
151 struct v4l2_fract frame_interval;
152};
153
154#define to_mt9m032(sd) container_of(sd, struct mt9m032, subdev)
155#define to_dev(sensor) \
156 (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev)
157
158static int mt9m032_read(struct i2c_client *client, u8 reg)
159{
160 return i2c_smbus_read_word_swapped(client, reg);
161}
162
163static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data)
164{
165 return i2c_smbus_write_word_swapped(client, reg, data);
166}
167
168static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width)
169{
170 unsigned int effective_width;
171 u32 ns;
172
173 effective_width = width + 716; /* empirical value */
174 ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock);
175 dev_dbg(to_dev(sensor), "MT9M032 line time: %u ns\n", ns);
176 return ns;
177}
178
179static int mt9m032_update_timing(struct mt9m032 *sensor,
180 struct v4l2_fract *interval)
181{
182 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
183 struct v4l2_rect *crop = &sensor->crop;
184 unsigned int min_vblank;
185 unsigned int vblank;
186 u32 row_time;
187
188 if (!interval)
189 interval = &sensor->frame_interval;
190
191 row_time = mt9m032_row_time(sensor, crop->width);
192
193 vblank = div_u64(1000000000ULL * interval->numerator,
194 (u64)row_time * interval->denominator)
195 - crop->height;
196
197 if (vblank > MT9M032_VBLANK_MAX) {
198 /* hardware limits to 11 bit values */
199 interval->denominator = 1000;
200 interval->numerator =
201 div_u64((crop->height + MT9M032_VBLANK_MAX) *
202 (u64)row_time * interval->denominator,
203 1000000000ULL);
204 vblank = div_u64(1000000000ULL * interval->numerator,
205 (u64)row_time * interval->denominator)
206 - crop->height;
207 }
208 /* enforce minimal 1.6ms blanking time. */
209 min_vblank = 1600000 / row_time;
210 vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX);
211
212 return mt9m032_write(client, MT9M032_VBLANK, vblank);
213}
214
215static int mt9m032_update_geom_timing(struct mt9m032 *sensor)
216{
217 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
218 int ret;
219
220 ret = mt9m032_write(client, MT9M032_COLUMN_SIZE,
221 sensor->crop.width - 1);
222 if (!ret)
223 ret = mt9m032_write(client, MT9M032_ROW_SIZE,
224 sensor->crop.height - 1);
225 if (!ret)
226 ret = mt9m032_write(client, MT9M032_COLUMN_START,
227 sensor->crop.left);
228 if (!ret)
229 ret = mt9m032_write(client, MT9M032_ROW_START,
230 sensor->crop.top);
231 if (!ret)
232 ret = mt9m032_update_timing(sensor, NULL);
233 return ret;
234}
235
236static int update_formatter2(struct mt9m032 *sensor, bool streaming)
237{
238 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
239 u16 reg_val = MT9M032_FORMATTER2_DOUT_EN
240 | 0x0070; /* parts reserved! */
241 /* possibly for changing to 14-bit mode */
242
243 if (streaming)
244 reg_val |= MT9M032_FORMATTER2_PIXCLK_EN; /* pixclock enable */
245
246 return mt9m032_write(client, MT9M032_FORMATTER2, reg_val);
247}
248
249static int mt9m032_setup_pll(struct mt9m032 *sensor)
250{
251 static const struct aptina_pll_limits limits = {
252 .ext_clock_min = 8000000,
253 .ext_clock_max = 16500000,
254 .int_clock_min = 2000000,
255 .int_clock_max = 24000000,
256 .out_clock_min = 322000000,
257 .out_clock_max = 693000000,
258 .pix_clock_max = 99000000,
259 .n_min = 1,
260 .n_max = 64,
261 .m_min = 16,
262 .m_max = 255,
263 .p1_min = 6,
264 .p1_max = 7,
265 };
266
267 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
268 struct mt9m032_platform_data *pdata = sensor->pdata;
269 struct aptina_pll pll;
270 u16 reg_val;
271 int ret;
272
273 pll.ext_clock = pdata->ext_clock;
274 pll.pix_clock = pdata->pix_clock;
275
276 ret = aptina_pll_calculate(&client->dev, &limits, &pll);
277 if (ret < 0)
278 return ret;
279
280 sensor->pix_clock = pdata->pix_clock;
281
282 ret = mt9m032_write(client, MT9M032_PLL_CONFIG1,
283 (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) |
284 ((pll.n - 1) & MT9M032_PLL_CONFIG1_PREDIV_MASK));
285 if (!ret)
286 ret = mt9m032_write(client, MT9P031_PLL_CONTROL,
287 MT9P031_PLL_CONTROL_PWRON |
288 MT9P031_PLL_CONTROL_USEPLL);
289 if (!ret) /* more reserved, Continuous, Master Mode */
290 ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8000 |
291 MT9M032_READ_MODE1_STROBE_START_EXP |
292 MT9M032_READ_MODE1_STROBE_END_SHUTTER);
293 if (!ret) {
294 reg_val = (pll.p1 == 6 ? MT9M032_FORMATTER1_PLL_P1_6 : 0)
295 | MT9M032_FORMATTER1_PARALLEL | 0x001e; /* 14-bit */
296 ret = mt9m032_write(client, MT9M032_FORMATTER1, reg_val);
297 }
298
299 return ret;
300}
301
302/* -----------------------------------------------------------------------------
303 * Subdev pad operations
304 */
305
306static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev,
307 struct v4l2_subdev_state *sd_state,
308 struct v4l2_subdev_mbus_code_enum *code)
309{
310 if (code->index != 0)
311 return -EINVAL;
312
313 code->code = MEDIA_BUS_FMT_Y8_1X8;
314 return 0;
315}
316
317static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev,
318 struct v4l2_subdev_state *sd_state,
319 struct v4l2_subdev_frame_size_enum *fse)
320{
321 if (fse->index != 0 || fse->code != MEDIA_BUS_FMT_Y8_1X8)
322 return -EINVAL;
323
324 fse->min_width = MT9M032_COLUMN_SIZE_DEF;
325 fse->max_width = MT9M032_COLUMN_SIZE_DEF;
326 fse->min_height = MT9M032_ROW_SIZE_DEF;
327 fse->max_height = MT9M032_ROW_SIZE_DEF;
328
329 return 0;
330}
331
332/**
333 * __mt9m032_get_pad_crop() - get crop rect
334 * @sensor: pointer to the sensor struct
335 * @sd_state: v4l2_subdev_state for getting the try crop rect from
336 * @which: select try or active crop rect
337 *
338 * Returns a pointer the current active or fh relative try crop rect
339 */
340static struct v4l2_rect *
341__mt9m032_get_pad_crop(struct mt9m032 *sensor,
342 struct v4l2_subdev_state *sd_state,
343 enum v4l2_subdev_format_whence which)
344{
345 switch (which) {
346 case V4L2_SUBDEV_FORMAT_TRY:
347 return v4l2_subdev_get_try_crop(&sensor->subdev, sd_state, 0);
348 case V4L2_SUBDEV_FORMAT_ACTIVE:
349 return &sensor->crop;
350 default:
351 return NULL;
352 }
353}
354
355/**
356 * __mt9m032_get_pad_format() - get format
357 * @sensor: pointer to the sensor struct
358 * @sd_state: v4l2_subdev_state for getting the try format from
359 * @which: select try or active format
360 *
361 * Returns a pointer the current active or fh relative try format
362 */
363static struct v4l2_mbus_framefmt *
364__mt9m032_get_pad_format(struct mt9m032 *sensor,
365 struct v4l2_subdev_state *sd_state,
366 enum v4l2_subdev_format_whence which)
367{
368 switch (which) {
369 case V4L2_SUBDEV_FORMAT_TRY:
370 return v4l2_subdev_get_try_format(&sensor->subdev, sd_state,
371 0);
372 case V4L2_SUBDEV_FORMAT_ACTIVE:
373 return &sensor->format;
374 default:
375 return NULL;
376 }
377}
378
379static int mt9m032_get_pad_format(struct v4l2_subdev *subdev,
380 struct v4l2_subdev_state *sd_state,
381 struct v4l2_subdev_format *fmt)
382{
383 struct mt9m032 *sensor = to_mt9m032(subdev);
384
385 mutex_lock(&sensor->lock);
386 fmt->format = *__mt9m032_get_pad_format(sensor, sd_state, fmt->which);
387 mutex_unlock(&sensor->lock);
388
389 return 0;
390}
391
392static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
393 struct v4l2_subdev_state *sd_state,
394 struct v4l2_subdev_format *fmt)
395{
396 struct mt9m032 *sensor = to_mt9m032(subdev);
397 int ret;
398
399 mutex_lock(&sensor->lock);
400
401 if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
402 ret = -EBUSY;
403 goto done;
404 }
405
406 /* Scaling is not supported, the format is thus fixed. */
407 fmt->format = *__mt9m032_get_pad_format(sensor, sd_state, fmt->which);
408 ret = 0;
409
410done:
411 mutex_unlock(&sensor->lock);
412 return ret;
413}
414
415static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev,
416 struct v4l2_subdev_state *sd_state,
417 struct v4l2_subdev_selection *sel)
418{
419 struct mt9m032 *sensor = to_mt9m032(subdev);
420
421 if (sel->target != V4L2_SEL_TGT_CROP)
422 return -EINVAL;
423
424 mutex_lock(&sensor->lock);
425 sel->r = *__mt9m032_get_pad_crop(sensor, sd_state, sel->which);
426 mutex_unlock(&sensor->lock);
427
428 return 0;
429}
430
431static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev,
432 struct v4l2_subdev_state *sd_state,
433 struct v4l2_subdev_selection *sel)
434{
435 struct mt9m032 *sensor = to_mt9m032(subdev);
436 struct v4l2_mbus_framefmt *format;
437 struct v4l2_rect *__crop;
438 struct v4l2_rect rect;
439 int ret = 0;
440
441 if (sel->target != V4L2_SEL_TGT_CROP)
442 return -EINVAL;
443
444 mutex_lock(&sensor->lock);
445
446 if (sensor->streaming && sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
447 ret = -EBUSY;
448 goto done;
449 }
450
451 /* Clamp the crop rectangle boundaries and align them to a multiple of 2
452 * pixels to ensure a GRBG Bayer pattern.
453 */
454 rect.left = clamp(ALIGN(sel->r.left, 2), MT9M032_COLUMN_START_MIN,
455 MT9M032_COLUMN_START_MAX);
456 rect.top = clamp(ALIGN(sel->r.top, 2), MT9M032_ROW_START_MIN,
457 MT9M032_ROW_START_MAX);
458 rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
459 MT9M032_COLUMN_SIZE_MIN, MT9M032_COLUMN_SIZE_MAX);
460 rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
461 MT9M032_ROW_SIZE_MIN, MT9M032_ROW_SIZE_MAX);
462
463 rect.width = min_t(unsigned int, rect.width,
464 MT9M032_PIXEL_ARRAY_WIDTH - rect.left);
465 rect.height = min_t(unsigned int, rect.height,
466 MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);
467
468 __crop = __mt9m032_get_pad_crop(sensor, sd_state, sel->which);
469
470 if (rect.width != __crop->width || rect.height != __crop->height) {
471 /* Reset the output image size if the crop rectangle size has
472 * been modified.
473 */
474 format = __mt9m032_get_pad_format(sensor, sd_state,
475 sel->which);
476 format->width = rect.width;
477 format->height = rect.height;
478 }
479
480 *__crop = rect;
481 sel->r = rect;
482
483 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
484 ret = mt9m032_update_geom_timing(sensor);
485
486done:
487 mutex_unlock(&sensor->lock);
488 return ret;
489}
490
491static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev,
492 struct v4l2_subdev_frame_interval *fi)
493{
494 struct mt9m032 *sensor = to_mt9m032(subdev);
495
496 mutex_lock(&sensor->lock);
497 memset(fi, 0, sizeof(*fi));
498 fi->interval = sensor->frame_interval;
499 mutex_unlock(&sensor->lock);
500
501 return 0;
502}
503
504static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev,
505 struct v4l2_subdev_frame_interval *fi)
506{
507 struct mt9m032 *sensor = to_mt9m032(subdev);
508 int ret;
509
510 mutex_lock(&sensor->lock);
511
512 if (sensor->streaming) {
513 ret = -EBUSY;
514 goto done;
515 }
516
517 /* Avoid divisions by 0. */
518 if (fi->interval.denominator == 0)
519 fi->interval.denominator = 1;
520
521 ret = mt9m032_update_timing(sensor, &fi->interval);
522 if (!ret)
523 sensor->frame_interval = fi->interval;
524
525done:
526 mutex_unlock(&sensor->lock);
527 return ret;
528}
529
530static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming)
531{
532 struct mt9m032 *sensor = to_mt9m032(subdev);
533 int ret;
534
535 mutex_lock(&sensor->lock);
536 ret = update_formatter2(sensor, streaming);
537 if (!ret)
538 sensor->streaming = streaming;
539 mutex_unlock(&sensor->lock);
540
541 return ret;
542}
543
544/* -----------------------------------------------------------------------------
545 * V4L2 subdev core operations
546 */
547
548#ifdef CONFIG_VIDEO_ADV_DEBUG
549static int mt9m032_g_register(struct v4l2_subdev *sd,
550 struct v4l2_dbg_register *reg)
551{
552 struct mt9m032 *sensor = to_mt9m032(sd);
553 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
554 int val;
555
556 if (reg->reg > 0xff)
557 return -EINVAL;
558
559 val = mt9m032_read(client, reg->reg);
560 if (val < 0)
561 return -EIO;
562
563 reg->size = 2;
564 reg->val = val;
565
566 return 0;
567}
568
569static int mt9m032_s_register(struct v4l2_subdev *sd,
570 const struct v4l2_dbg_register *reg)
571{
572 struct mt9m032 *sensor = to_mt9m032(sd);
573 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
574
575 if (reg->reg > 0xff)
576 return -EINVAL;
577
578 return mt9m032_write(client, reg->reg, reg->val);
579}
580#endif
581
582/* -----------------------------------------------------------------------------
583 * V4L2 subdev control operations
584 */
585
586static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip)
587{
588 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
589 int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT)
590 | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT)
591 | MT9M032_READ_MODE2_ROW_BLC
592 | 0x0007;
593
594 return mt9m032_write(client, MT9M032_READ_MODE2, reg_val);
595}
596
597static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val)
598{
599 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
600 int digital_gain_val; /* in 1/8th (0..127) */
601 int analog_mul; /* 0 or 1 */
602 int analog_gain_val; /* in 1/16th. (0..63) */
603 u16 reg_val;
604
605 digital_gain_val = 51; /* from setup example */
606
607 if (val < 63) {
608 analog_mul = 0;
609 analog_gain_val = val;
610 } else {
611 analog_mul = 1;
612 analog_gain_val = val / 2;
613 }
614
615 /* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */
616 /* overall_gain = a_gain * (1 + digital_gain_val / 8) */
617
618 reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK)
619 << MT9M032_GAIN_DIGITAL_SHIFT)
620 | ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT)
621 | (analog_gain_val & MT9M032_GAIN_ANALOG_MASK);
622
623 return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val);
624}
625
626static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl)
627{
628 if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) {
629 /* round because of multiplier used for values >= 63 */
630 ctrl->val &= ~1;
631 }
632
633 return 0;
634}
635
636static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl)
637{
638 struct mt9m032 *sensor =
639 container_of(ctrl->handler, struct mt9m032, ctrls);
640 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
641 int ret;
642
643 switch (ctrl->id) {
644 case V4L2_CID_GAIN:
645 return mt9m032_set_gain(sensor, ctrl->val);
646
647 case V4L2_CID_HFLIP:
648 /* case V4L2_CID_VFLIP: -- In the same cluster */
649 return update_read_mode2(sensor, sensor->vflip->val,
650 sensor->hflip->val);
651
652 case V4L2_CID_EXPOSURE:
653 ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH,
654 (ctrl->val >> 16) & 0xffff);
655 if (ret < 0)
656 return ret;
657
658 return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW,
659 ctrl->val & 0xffff);
660 }
661
662 return 0;
663}
664
665static const struct v4l2_ctrl_ops mt9m032_ctrl_ops = {
666 .s_ctrl = mt9m032_set_ctrl,
667 .try_ctrl = mt9m032_try_ctrl,
668};
669
670/* -------------------------------------------------------------------------- */
671
672static const struct v4l2_subdev_core_ops mt9m032_core_ops = {
673#ifdef CONFIG_VIDEO_ADV_DEBUG
674 .g_register = mt9m032_g_register,
675 .s_register = mt9m032_s_register,
676#endif
677};
678
679static const struct v4l2_subdev_video_ops mt9m032_video_ops = {
680 .s_stream = mt9m032_s_stream,
681 .g_frame_interval = mt9m032_get_frame_interval,
682 .s_frame_interval = mt9m032_set_frame_interval,
683};
684
685static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = {
686 .enum_mbus_code = mt9m032_enum_mbus_code,
687 .enum_frame_size = mt9m032_enum_frame_size,
688 .get_fmt = mt9m032_get_pad_format,
689 .set_fmt = mt9m032_set_pad_format,
690 .set_selection = mt9m032_set_pad_selection,
691 .get_selection = mt9m032_get_pad_selection,
692};
693
694static const struct v4l2_subdev_ops mt9m032_ops = {
695 .core = &mt9m032_core_ops,
696 .video = &mt9m032_video_ops,
697 .pad = &mt9m032_pad_ops,
698};
699
700/* -----------------------------------------------------------------------------
701 * Driver initialization and probing
702 */
703
704static int mt9m032_probe(struct i2c_client *client)
705{
706 struct mt9m032_platform_data *pdata = client->dev.platform_data;
707 struct i2c_adapter *adapter = client->adapter;
708 struct mt9m032 *sensor;
709 int chip_version;
710 int ret;
711
712 if (pdata == NULL) {
713 dev_err(&client->dev, "No platform data\n");
714 return -EINVAL;
715 }
716
717 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
718 dev_warn(&client->dev,
719 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
720 return -EIO;
721 }
722
723 if (!client->dev.platform_data)
724 return -ENODEV;
725
726 sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
727 if (sensor == NULL)
728 return -ENOMEM;
729
730 mutex_init(&sensor->lock);
731
732 sensor->pdata = pdata;
733
734 v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
735 sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
736
737 chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION);
738 if (chip_version != MT9M032_CHIP_VERSION_VALUE) {
739 dev_err(&client->dev, "MT9M032 not detected, wrong version "
740 "0x%04x\n", chip_version);
741 ret = -ENODEV;
742 goto error_sensor;
743 }
744
745 dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n",
746 client->addr);
747
748 sensor->frame_interval.numerator = 1;
749 sensor->frame_interval.denominator = 30;
750
751 sensor->crop.left = MT9M032_COLUMN_START_DEF;
752 sensor->crop.top = MT9M032_ROW_START_DEF;
753 sensor->crop.width = MT9M032_COLUMN_SIZE_DEF;
754 sensor->crop.height = MT9M032_ROW_SIZE_DEF;
755
756 sensor->format.width = sensor->crop.width;
757 sensor->format.height = sensor->crop.height;
758 sensor->format.code = MEDIA_BUS_FMT_Y8_1X8;
759 sensor->format.field = V4L2_FIELD_NONE;
760 sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
761
762 v4l2_ctrl_handler_init(&sensor->ctrls, 5);
763
764 v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
765 V4L2_CID_GAIN, 0, 127, 1, 64);
766
767 sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls,
768 &mt9m032_ctrl_ops,
769 V4L2_CID_HFLIP, 0, 1, 1, 0);
770 sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls,
771 &mt9m032_ctrl_ops,
772 V4L2_CID_VFLIP, 0, 1, 1, 0);
773
774 v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
775 V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN,
776 MT9M032_SHUTTER_WIDTH_MAX, 1,
777 MT9M032_SHUTTER_WIDTH_DEF);
778 v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
779 V4L2_CID_PIXEL_RATE, pdata->pix_clock,
780 pdata->pix_clock, 1, pdata->pix_clock);
781
782 if (sensor->ctrls.error) {
783 ret = sensor->ctrls.error;
784 dev_err(&client->dev, "control initialization error %d\n", ret);
785 goto error_ctrl;
786 }
787
788 v4l2_ctrl_cluster(2, &sensor->hflip);
789
790 sensor->subdev.ctrl_handler = &sensor->ctrls;
791 sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
792 sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
793 ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad);
794 if (ret < 0)
795 goto error_ctrl;
796
797 ret = mt9m032_write(client, MT9M032_RESET, 1); /* reset on */
798 if (ret < 0)
799 goto error_entity;
800 ret = mt9m032_write(client, MT9M032_RESET, 0); /* reset off */
801 if (ret < 0)
802 goto error_entity;
803
804 ret = mt9m032_setup_pll(sensor);
805 if (ret < 0)
806 goto error_entity;
807 usleep_range(10000, 11000);
808
809 ret = v4l2_ctrl_handler_setup(&sensor->ctrls);
810 if (ret < 0)
811 goto error_entity;
812
813 /* SIZE */
814 ret = mt9m032_update_geom_timing(sensor);
815 if (ret < 0)
816 goto error_entity;
817
818 ret = mt9m032_write(client, 0x41, 0x0000); /* reserved !!! */
819 if (ret < 0)
820 goto error_entity;
821 ret = mt9m032_write(client, 0x42, 0x0003); /* reserved !!! */
822 if (ret < 0)
823 goto error_entity;
824 ret = mt9m032_write(client, 0x43, 0x0003); /* reserved !!! */
825 if (ret < 0)
826 goto error_entity;
827 ret = mt9m032_write(client, 0x7f, 0x0000); /* reserved !!! */
828 if (ret < 0)
829 goto error_entity;
830 if (sensor->pdata->invert_pixclock) {
831 ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL,
832 MT9M032_PIX_CLK_CTRL_INV_PIXCLK);
833 if (ret < 0)
834 goto error_entity;
835 }
836
837 ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */
838 if (ret < 0)
839 goto error_entity;
840 msleep(100);
841 ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */
842 if (ret < 0)
843 goto error_entity;
844 msleep(100);
845 ret = update_formatter2(sensor, false);
846 if (ret < 0)
847 goto error_entity;
848
849 return ret;
850
851error_entity:
852 media_entity_cleanup(&sensor->subdev.entity);
853error_ctrl:
854 v4l2_ctrl_handler_free(&sensor->ctrls);
855error_sensor:
856 mutex_destroy(&sensor->lock);
857 return ret;
858}
859
860static void mt9m032_remove(struct i2c_client *client)
861{
862 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
863 struct mt9m032 *sensor = to_mt9m032(subdev);
864
865 v4l2_device_unregister_subdev(subdev);
866 v4l2_ctrl_handler_free(&sensor->ctrls);
867 media_entity_cleanup(&subdev->entity);
868 mutex_destroy(&sensor->lock);
869}
870
871static const struct i2c_device_id mt9m032_id_table[] = {
872 { MT9M032_NAME, 0 },
873 { }
874};
875
876MODULE_DEVICE_TABLE(i2c, mt9m032_id_table);
877
878static struct i2c_driver mt9m032_i2c_driver = {
879 .driver = {
880 .name = MT9M032_NAME,
881 },
882 .probe_new = mt9m032_probe,
883 .remove = mt9m032_remove,
884 .id_table = mt9m032_id_table,
885};
886
887module_i2c_driver(mt9m032_i2c_driver);
888
889MODULE_AUTHOR("Martin Hostettler <martin@neutronstar.dyndns.org>");
890MODULE_DESCRIPTION("MT9M032 camera sensor driver");
891MODULE_LICENSE("GPL v2");
drivers/media/i2c/mt9t001.c+0−992
@@ -1,992 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Driver for MT9T001 CMOS Image Sensor from Aptina (Micron)
4 *
5 * Copyright (C) 2010-2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
6 *
7 * Based on the MT9M001 driver,
8 *
9 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
10 */
11
12#include <linux/clk.h>
13#include <linux/i2c.h>
14#include <linux/log2.h>
15#include <linux/module.h>
16#include <linux/regulator/consumer.h>
17#include <linux/slab.h>
18#include <linux/videodev2.h>
19#include <linux/v4l2-mediabus.h>
20
21#include <media/i2c/mt9t001.h>
22#include <media/v4l2-ctrls.h>
23#include <media/v4l2-device.h>
24#include <media/v4l2-subdev.h>
25
26#define MT9T001_PIXEL_ARRAY_HEIGHT 1568
27#define MT9T001_PIXEL_ARRAY_WIDTH 2112
28
29#define MT9T001_CHIP_VERSION 0x00
30#define MT9T001_CHIP_ID 0x1621
31#define MT9T001_ROW_START 0x01
32#define MT9T001_ROW_START_MIN 0
33#define MT9T001_ROW_START_DEF 20
34#define MT9T001_ROW_START_MAX 1534
35#define MT9T001_COLUMN_START 0x02
36#define MT9T001_COLUMN_START_MIN 0
37#define MT9T001_COLUMN_START_DEF 32
38#define MT9T001_COLUMN_START_MAX 2046
39#define MT9T001_WINDOW_HEIGHT 0x03
40#define MT9T001_WINDOW_HEIGHT_MIN 1
41#define MT9T001_WINDOW_HEIGHT_DEF 1535
42#define MT9T001_WINDOW_HEIGHT_MAX 1567
43#define MT9T001_WINDOW_WIDTH 0x04
44#define MT9T001_WINDOW_WIDTH_MIN 1
45#define MT9T001_WINDOW_WIDTH_DEF 2047
46#define MT9T001_WINDOW_WIDTH_MAX 2111
47#define MT9T001_HORIZONTAL_BLANKING 0x05
48#define MT9T001_HORIZONTAL_BLANKING_MIN 21
49#define MT9T001_HORIZONTAL_BLANKING_MAX 1023
50#define MT9T001_VERTICAL_BLANKING 0x06
51#define MT9T001_VERTICAL_BLANKING_MIN 3
52#define MT9T001_VERTICAL_BLANKING_MAX 1023
53#define MT9T001_OUTPUT_CONTROL 0x07
54#define MT9T001_OUTPUT_CONTROL_SYNC (1 << 0)
55#define MT9T001_OUTPUT_CONTROL_CHIP_ENABLE (1 << 1)
56#define MT9T001_OUTPUT_CONTROL_TEST_DATA (1 << 6)
57#define MT9T001_OUTPUT_CONTROL_DEF 0x0002
58#define MT9T001_SHUTTER_WIDTH_HIGH 0x08
59#define MT9T001_SHUTTER_WIDTH_LOW 0x09
60#define MT9T001_SHUTTER_WIDTH_MIN 1
61#define MT9T001_SHUTTER_WIDTH_DEF 1561
62#define MT9T001_SHUTTER_WIDTH_MAX (1024 * 1024)
63#define MT9T001_PIXEL_CLOCK 0x0a
64#define MT9T001_PIXEL_CLOCK_INVERT (1 << 15)
65#define MT9T001_PIXEL_CLOCK_SHIFT_MASK (7 << 8)
66#define MT9T001_PIXEL_CLOCK_SHIFT_SHIFT 8
67#define MT9T001_PIXEL_CLOCK_DIVIDE_MASK (0x7f << 0)
68#define MT9T001_FRAME_RESTART 0x0b
69#define MT9T001_SHUTTER_DELAY 0x0c
70#define MT9T001_SHUTTER_DELAY_MAX 2047
71#define MT9T001_RESET 0x0d
72#define MT9T001_READ_MODE1 0x1e
73#define MT9T001_READ_MODE_SNAPSHOT (1 << 8)
74#define MT9T001_READ_MODE_STROBE_ENABLE (1 << 9)
75#define MT9T001_READ_MODE_STROBE_WIDTH (1 << 10)
76#define MT9T001_READ_MODE_STROBE_OVERRIDE (1 << 11)
77#define MT9T001_READ_MODE2 0x20
78#define MT9T001_READ_MODE_BAD_FRAMES (1 << 0)
79#define MT9T001_READ_MODE_LINE_VALID_CONTINUOUS (1 << 9)
80#define MT9T001_READ_MODE_LINE_VALID_FRAME (1 << 10)
81#define MT9T001_READ_MODE3 0x21
82#define MT9T001_READ_MODE_GLOBAL_RESET (1 << 0)
83#define MT9T001_READ_MODE_GHST_CTL (1 << 1)
84#define MT9T001_ROW_ADDRESS_MODE 0x22
85#define MT9T001_ROW_SKIP_MASK (7 << 0)
86#define MT9T001_ROW_BIN_MASK (3 << 3)
87#define MT9T001_ROW_BIN_SHIFT 3
88#define MT9T001_COLUMN_ADDRESS_MODE 0x23
89#define MT9T001_COLUMN_SKIP_MASK (7 << 0)
90#define MT9T001_COLUMN_BIN_MASK (3 << 3)
91#define MT9T001_COLUMN_BIN_SHIFT 3
92#define MT9T001_GREEN1_GAIN 0x2b
93#define MT9T001_BLUE_GAIN 0x2c
94#define MT9T001_RED_GAIN 0x2d
95#define MT9T001_GREEN2_GAIN 0x2e
96#define MT9T001_TEST_DATA 0x32
97#define MT9T001_GLOBAL_GAIN 0x35
98#define MT9T001_GLOBAL_GAIN_MIN 8
99#define MT9T001_GLOBAL_GAIN_MAX 1024
100#define MT9T001_BLACK_LEVEL 0x49
101#define MT9T001_ROW_BLACK_DEFAULT_OFFSET 0x4b
102#define MT9T001_BLC_DELTA_THRESHOLDS 0x5d
103#define MT9T001_CAL_THRESHOLDS 0x5f
104#define MT9T001_GREEN1_OFFSET 0x60
105#define MT9T001_GREEN2_OFFSET 0x61
106#define MT9T001_BLACK_LEVEL_CALIBRATION 0x62
107#define MT9T001_BLACK_LEVEL_OVERRIDE (1 << 0)
108#define MT9T001_BLACK_LEVEL_DISABLE_OFFSET (1 << 1)
109#define MT9T001_BLACK_LEVEL_RECALCULATE (1 << 12)
110#define MT9T001_BLACK_LEVEL_LOCK_RED_BLUE (1 << 13)
111#define MT9T001_BLACK_LEVEL_LOCK_GREEN (1 << 14)
112#define MT9T001_RED_OFFSET 0x63
113#define MT9T001_BLUE_OFFSET 0x64
114
115struct mt9t001 {
116 struct v4l2_subdev subdev;
117 struct media_pad pad;
118
119 struct clk *clk;
120 struct regulator_bulk_data regulators[2];
121
122 struct mutex power_lock; /* lock to protect power_count */
123 int power_count;
124
125 struct v4l2_mbus_framefmt format;
126 struct v4l2_rect crop;
127
128 struct v4l2_ctrl_handler ctrls;
129 struct v4l2_ctrl *gains[4];
130
131 u16 output_control;
132 u16 black_level;
133};
134
135static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
136{
137 return container_of(sd, struct mt9t001, subdev);
138}
139
140static int mt9t001_read(struct i2c_client *client, u8 reg)
141{
142 return i2c_smbus_read_word_swapped(client, reg);
143}
144
145static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
146{
147 return i2c_smbus_write_word_swapped(client, reg, data);
148}
149
150static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
151 u16 set)
152{
153 struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
154 u16 value = (mt9t001->output_control & ~clear) | set;
155 int ret;
156
157 if (value == mt9t001->output_control)
158 return 0;
159
160 ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, value);
161 if (ret < 0)
162 return ret;
163
164 mt9t001->output_control = value;
165 return 0;
166}
167
168static int mt9t001_reset(struct mt9t001 *mt9t001)
169{
170 struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
171 int ret;
172
173 /* Reset the chip and stop data read out */
174 ret = mt9t001_write(client, MT9T001_RESET, 1);
175 if (ret < 0)
176 return ret;
177
178 ret = mt9t001_write(client, MT9T001_RESET, 0);
179 if (ret < 0)
180 return ret;
181
182 mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
183
184 return mt9t001_set_output_control(mt9t001,
185 MT9T001_OUTPUT_CONTROL_CHIP_ENABLE,
186 0);
187}
188
189static int mt9t001_power_on(struct mt9t001 *mt9t001)
190{
191 int ret;
192
193 /* Bring up the supplies */
194 ret = regulator_bulk_enable(ARRAY_SIZE(mt9t001->regulators),
195 mt9t001->regulators);
196 if (ret < 0)
197 return ret;
198
199 /* Enable clock */
200 ret = clk_prepare_enable(mt9t001->clk);
201 if (ret < 0)
202 regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
203 mt9t001->regulators);
204
205 return ret;
206}
207
208static void mt9t001_power_off(struct mt9t001 *mt9t001)
209{
210 regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
211 mt9t001->regulators);
212
213 clk_disable_unprepare(mt9t001->clk);
214}
215
216static int __mt9t001_set_power(struct mt9t001 *mt9t001, bool on)
217{
218 struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
219 int ret;
220
221 if (!on) {
222 mt9t001_power_off(mt9t001);
223 return 0;
224 }
225
226 ret = mt9t001_power_on(mt9t001);
227 if (ret < 0)
228 return ret;
229
230 ret = mt9t001_reset(mt9t001);
231 if (ret < 0) {
232 dev_err(&client->dev, "Failed to reset the camera\n");
233 goto e_power;
234 }
235
236 ret = v4l2_ctrl_handler_setup(&mt9t001->ctrls);
237 if (ret < 0) {
238 dev_err(&client->dev, "Failed to set up control handlers\n");
239 goto e_power;
240 }
241
242 return 0;
243
244e_power:
245 mt9t001_power_off(mt9t001);
246
247 return ret;
248}
249
250/* -----------------------------------------------------------------------------
251 * V4L2 subdev video operations
252 */
253
254static struct v4l2_mbus_framefmt *
255__mt9t001_get_pad_format(struct mt9t001 *mt9t001,
256 struct v4l2_subdev_state *sd_state,
257 unsigned int pad, enum v4l2_subdev_format_whence which)
258{
259 switch (which) {
260 case V4L2_SUBDEV_FORMAT_TRY:
261 return v4l2_subdev_get_try_format(&mt9t001->subdev, sd_state,
262 pad);
263 case V4L2_SUBDEV_FORMAT_ACTIVE:
264 return &mt9t001->format;
265 default:
266 return NULL;
267 }
268}
269
270static struct v4l2_rect *
271__mt9t001_get_pad_crop(struct mt9t001 *mt9t001,
272 struct v4l2_subdev_state *sd_state,
273 unsigned int pad, enum v4l2_subdev_format_whence which)
274{
275 switch (which) {
276 case V4L2_SUBDEV_FORMAT_TRY:
277 return v4l2_subdev_get_try_crop(&mt9t001->subdev, sd_state,
278 pad);
279 case V4L2_SUBDEV_FORMAT_ACTIVE:
280 return &mt9t001->crop;
281 default:
282 return NULL;
283 }
284}
285
286static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
287{
288 const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
289 struct i2c_client *client = v4l2_get_subdevdata(subdev);
290 struct mt9t001_platform_data *pdata = client->dev.platform_data;
291 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
292 struct v4l2_mbus_framefmt *format = &mt9t001->format;
293 struct v4l2_rect *crop = &mt9t001->crop;
294 unsigned int hratio;
295 unsigned int vratio;
296 int ret;
297
298 if (!enable)
299 return mt9t001_set_output_control(mt9t001, mode, 0);
300
301 /* Configure the pixel clock polarity */
302 if (pdata->clk_pol) {
303 ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
304 MT9T001_PIXEL_CLOCK_INVERT);
305 if (ret < 0)
306 return ret;
307 }
308
309 /* Configure the window size and row/column bin */
310 hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
311 vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
312
313 ret = mt9t001_write(client, MT9T001_ROW_ADDRESS_MODE, hratio - 1);
314 if (ret < 0)
315 return ret;
316
317 ret = mt9t001_write(client, MT9T001_COLUMN_ADDRESS_MODE, vratio - 1);
318 if (ret < 0)
319 return ret;
320
321 ret = mt9t001_write(client, MT9T001_COLUMN_START, crop->left);
322 if (ret < 0)
323 return ret;
324
325 ret = mt9t001_write(client, MT9T001_ROW_START, crop->top);
326 if (ret < 0)
327 return ret;
328
329 ret = mt9t001_write(client, MT9T001_WINDOW_WIDTH, crop->width - 1);
330 if (ret < 0)
331 return ret;
332
333 ret = mt9t001_write(client, MT9T001_WINDOW_HEIGHT, crop->height - 1);
334 if (ret < 0)
335 return ret;
336
337 /* Switch to master "normal" mode */
338 return mt9t001_set_output_control(mt9t001, 0, mode);
339}
340
341static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
342 struct v4l2_subdev_state *sd_state,
343 struct v4l2_subdev_mbus_code_enum *code)
344{
345 if (code->index > 0)
346 return -EINVAL;
347
348 code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
349 return 0;
350}
351
352static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
353 struct v4l2_subdev_state *sd_state,
354 struct v4l2_subdev_frame_size_enum *fse)
355{
356 if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
357 return -EINVAL;
358
359 fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
360 fse->max_width = fse->min_width;
361 fse->min_height = (MT9T001_WINDOW_HEIGHT_DEF + 1) / fse->index;
362 fse->max_height = fse->min_height;
363
364 return 0;
365}
366
367static int mt9t001_get_format(struct v4l2_subdev *subdev,
368 struct v4l2_subdev_state *sd_state,
369 struct v4l2_subdev_format *format)
370{
371 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
372
373 format->format = *__mt9t001_get_pad_format(mt9t001, sd_state,
374 format->pad,
375 format->which);
376 return 0;
377}
378
379static int mt9t001_set_format(struct v4l2_subdev *subdev,
380 struct v4l2_subdev_state *sd_state,
381 struct v4l2_subdev_format *format)
382{
383 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
384 struct v4l2_mbus_framefmt *__format;
385 struct v4l2_rect *__crop;
386 unsigned int width;
387 unsigned int height;
388 unsigned int hratio;
389 unsigned int vratio;
390
391 __crop = __mt9t001_get_pad_crop(mt9t001, sd_state, format->pad,
392 format->which);
393
394 /* Clamp the width and height to avoid dividing by zero. */
395 width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
396 max_t(unsigned int, __crop->width / 8,
397 MT9T001_WINDOW_HEIGHT_MIN + 1),
398 __crop->width);
399 height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
400 max_t(unsigned int, __crop->height / 8,
401 MT9T001_WINDOW_HEIGHT_MIN + 1),
402 __crop->height);
403
404 hratio = DIV_ROUND_CLOSEST(__crop->width, width);
405 vratio = DIV_ROUND_CLOSEST(__crop->height, height);
406
407 __format = __mt9t001_get_pad_format(mt9t001, sd_state, format->pad,
408 format->which);
409 __format->width = __crop->width / hratio;
410 __format->height = __crop->height / vratio;
411
412 format->format = *__format;
413
414 return 0;
415}
416
417static int mt9t001_get_selection(struct v4l2_subdev *subdev,
418 struct v4l2_subdev_state *sd_state,
419 struct v4l2_subdev_selection *sel)
420{
421 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
422
423 if (sel->target != V4L2_SEL_TGT_CROP)
424 return -EINVAL;
425
426 sel->r = *__mt9t001_get_pad_crop(mt9t001, sd_state, sel->pad,
427 sel->which);
428 return 0;
429}
430
431static int mt9t001_set_selection(struct v4l2_subdev *subdev,
432 struct v4l2_subdev_state *sd_state,
433 struct v4l2_subdev_selection *sel)
434{
435 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
436 struct v4l2_mbus_framefmt *__format;
437 struct v4l2_rect *__crop;
438 struct v4l2_rect rect;
439
440 if (sel->target != V4L2_SEL_TGT_CROP)
441 return -EINVAL;
442
443 /* Clamp the crop rectangle boundaries and align them to a multiple of 2
444 * pixels.
445 */
446 rect.left = clamp(ALIGN(sel->r.left, 2),
447 MT9T001_COLUMN_START_MIN,
448 MT9T001_COLUMN_START_MAX);
449 rect.top = clamp(ALIGN(sel->r.top, 2),
450 MT9T001_ROW_START_MIN,
451 MT9T001_ROW_START_MAX);
452 rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
453 MT9T001_WINDOW_WIDTH_MIN + 1,
454 MT9T001_WINDOW_WIDTH_MAX + 1);
455 rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
456 MT9T001_WINDOW_HEIGHT_MIN + 1,
457 MT9T001_WINDOW_HEIGHT_MAX + 1);
458
459 rect.width = min_t(unsigned int, rect.width,
460 MT9T001_PIXEL_ARRAY_WIDTH - rect.left);
461 rect.height = min_t(unsigned int, rect.height,
462 MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
463
464 __crop = __mt9t001_get_pad_crop(mt9t001, sd_state, sel->pad,
465 sel->which);
466
467 if (rect.width != __crop->width || rect.height != __crop->height) {
468 /* Reset the output image size if the crop rectangle size has
469 * been modified.
470 */
471 __format = __mt9t001_get_pad_format(mt9t001, sd_state,
472 sel->pad,
473 sel->which);
474 __format->width = rect.width;
475 __format->height = rect.height;
476 }
477
478 *__crop = rect;
479 sel->r = rect;
480
481 return 0;
482}
483
484/* -----------------------------------------------------------------------------
485 * V4L2 subdev control operations
486 */
487
488#define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_BASE | 0x1001)
489#define V4L2_CID_BLACK_LEVEL_AUTO (V4L2_CID_USER_BASE | 0x1002)
490#define V4L2_CID_BLACK_LEVEL_OFFSET (V4L2_CID_USER_BASE | 0x1003)
491#define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004)
492
493#define V4L2_CID_GAIN_RED (V4L2_CTRL_CLASS_CAMERA | 0x1001)
494#define V4L2_CID_GAIN_GREEN_RED (V4L2_CTRL_CLASS_CAMERA | 0x1002)
495#define V4L2_CID_GAIN_GREEN_BLUE (V4L2_CTRL_CLASS_CAMERA | 0x1003)
496#define V4L2_CID_GAIN_BLUE (V4L2_CTRL_CLASS_CAMERA | 0x1004)
497
498static u16 mt9t001_gain_value(s32 *gain)
499{
500 /* Gain is controlled by 2 analog stages and a digital stage. Valid
501 * values for the 3 stages are
502 *
503 * Stage Min Max Step
504 * ------------------------------------------
505 * First analog stage x1 x2 1
506 * Second analog stage x1 x4 0.125
507 * Digital stage x1 x16 0.125
508 *
509 * To minimize noise, the gain stages should be used in the second
510 * analog stage, first analog stage, digital stage order. Gain from a
511 * previous stage should be pushed to its maximum value before the next
512 * stage is used.
513 */
514 if (*gain <= 32)
515 return *gain;
516
517 if (*gain <= 64) {
518 *gain &= ~1;
519 return (1 << 6) | (*gain >> 1);
520 }
521
522 *gain &= ~7;
523 return ((*gain - 64) << 5) | (1 << 6) | 32;
524}
525
526static int mt9t001_ctrl_freeze(struct mt9t001 *mt9t001, bool freeze)
527{
528 return mt9t001_set_output_control(mt9t001,
529 freeze ? 0 : MT9T001_OUTPUT_CONTROL_SYNC,
530 freeze ? MT9T001_OUTPUT_CONTROL_SYNC : 0);
531}
532
533static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
534{
535 static const u8 gains[4] = {
536 MT9T001_RED_GAIN, MT9T001_GREEN1_GAIN,
537 MT9T001_GREEN2_GAIN, MT9T001_BLUE_GAIN
538 };
539
540 struct mt9t001 *mt9t001 =
541 container_of(ctrl->handler, struct mt9t001, ctrls);
542 struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
543 unsigned int count;
544 unsigned int i;
545 u16 value;
546 int ret;
547
548 switch (ctrl->id) {
549 case V4L2_CID_GAIN_RED:
550 case V4L2_CID_GAIN_GREEN_RED:
551 case V4L2_CID_GAIN_GREEN_BLUE:
552 case V4L2_CID_GAIN_BLUE:
553
554 /* Disable control updates if more than one control has changed
555 * in the cluster.
556 */
557 for (i = 0, count = 0; i < 4; ++i) {
558 struct v4l2_ctrl *gain = mt9t001->gains[i];
559
560 if (gain->val != gain->cur.val)
561 count++;
562 }
563
564 if (count > 1) {
565 ret = mt9t001_ctrl_freeze(mt9t001, true);
566 if (ret < 0)
567 return ret;
568 }
569
570 /* Update the gain controls. */
571 for (i = 0; i < 4; ++i) {
572 struct v4l2_ctrl *gain = mt9t001->gains[i];
573
574 if (gain->val == gain->cur.val)
575 continue;
576
577 value = mt9t001_gain_value(&gain->val);
578 ret = mt9t001_write(client, gains[i], value);
579 if (ret < 0) {
580 mt9t001_ctrl_freeze(mt9t001, false);
581 return ret;
582 }
583 }
584
585 /* Enable control updates. */
586 if (count > 1) {
587 ret = mt9t001_ctrl_freeze(mt9t001, false);
588 if (ret < 0)
589 return ret;
590 }
591
592 break;
593
594 case V4L2_CID_EXPOSURE:
595 ret = mt9t001_write(client, MT9T001_SHUTTER_WIDTH_LOW,
596 ctrl->val & 0xffff);
597 if (ret < 0)
598 return ret;
599
600 return mt9t001_write(client, MT9T001_SHUTTER_WIDTH_HIGH,
601 ctrl->val >> 16);
602
603 case V4L2_CID_TEST_PATTERN:
604 return mt9t001_set_output_control(mt9t001,
605 ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
606 ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
607
608 case V4L2_CID_TEST_PATTERN_COLOR:
609 return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
610
611 case V4L2_CID_BLACK_LEVEL_AUTO:
612 value = ctrl->val ? 0 : MT9T001_BLACK_LEVEL_OVERRIDE;
613 ret = mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
614 value);
615 if (ret < 0)
616 return ret;
617
618 mt9t001->black_level = value;
619 break;
620
621 case V4L2_CID_BLACK_LEVEL_OFFSET:
622 ret = mt9t001_write(client, MT9T001_GREEN1_OFFSET, ctrl->val);
623 if (ret < 0)
624 return ret;
625
626 ret = mt9t001_write(client, MT9T001_GREEN2_OFFSET, ctrl->val);
627 if (ret < 0)
628 return ret;
629
630 ret = mt9t001_write(client, MT9T001_RED_OFFSET, ctrl->val);
631 if (ret < 0)
632 return ret;
633
634 return mt9t001_write(client, MT9T001_BLUE_OFFSET, ctrl->val);
635
636 case V4L2_CID_BLACK_LEVEL_CALIBRATE:
637 return mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
638 MT9T001_BLACK_LEVEL_RECALCULATE |
639 mt9t001->black_level);
640 }
641
642 return 0;
643}
644
645static const struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
646 .s_ctrl = mt9t001_s_ctrl,
647};
648
649static const char * const mt9t001_test_pattern_menu[] = {
650 "Disabled",
651 "Enabled",
652};
653
654static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
655 {
656 .ops = &mt9t001_ctrl_ops,
657 .id = V4L2_CID_TEST_PATTERN_COLOR,
658 .type = V4L2_CTRL_TYPE_INTEGER,
659 .name = "Test Pattern Color",
660 .min = 0,
661 .max = 1023,
662 .step = 1,
663 .def = 0,
664 .flags = 0,
665 }, {
666 .ops = &mt9t001_ctrl_ops,
667 .id = V4L2_CID_BLACK_LEVEL_AUTO,
668 .type = V4L2_CTRL_TYPE_BOOLEAN,
669 .name = "Black Level, Auto",
670 .min = 0,
671 .max = 1,
672 .step = 1,
673 .def = 1,
674 .flags = 0,
675 }, {
676 .ops = &mt9t001_ctrl_ops,
677 .id = V4L2_CID_BLACK_LEVEL_OFFSET,
678 .type = V4L2_CTRL_TYPE_INTEGER,
679 .name = "Black Level, Offset",
680 .min = -256,
681 .max = 255,
682 .step = 1,
683 .def = 32,
684 .flags = 0,
685 }, {
686 .ops = &mt9t001_ctrl_ops,
687 .id = V4L2_CID_BLACK_LEVEL_CALIBRATE,
688 .type = V4L2_CTRL_TYPE_BUTTON,
689 .name = "Black Level, Calibrate",
690 .min = 0,
691 .max = 0,
692 .step = 0,
693 .def = 0,
694 .flags = V4L2_CTRL_FLAG_WRITE_ONLY,
695 },
696};
697
698static const struct v4l2_ctrl_config mt9t001_gains[] = {
699 {
700 .ops = &mt9t001_ctrl_ops,
701 .id = V4L2_CID_GAIN_RED,
702 .type = V4L2_CTRL_TYPE_INTEGER,
703 .name = "Gain, Red",
704 .min = MT9T001_GLOBAL_GAIN_MIN,
705 .max = MT9T001_GLOBAL_GAIN_MAX,
706 .step = 1,
707 .def = MT9T001_GLOBAL_GAIN_MIN,
708 .flags = 0,
709 }, {
710 .ops = &mt9t001_ctrl_ops,
711 .id = V4L2_CID_GAIN_GREEN_RED,
712 .type = V4L2_CTRL_TYPE_INTEGER,
713 .name = "Gain, Green (R)",
714 .min = MT9T001_GLOBAL_GAIN_MIN,
715 .max = MT9T001_GLOBAL_GAIN_MAX,
716 .step = 1,
717 .def = MT9T001_GLOBAL_GAIN_MIN,
718 .flags = 0,
719 }, {
720 .ops = &mt9t001_ctrl_ops,
721 .id = V4L2_CID_GAIN_GREEN_BLUE,
722 .type = V4L2_CTRL_TYPE_INTEGER,
723 .name = "Gain, Green (B)",
724 .min = MT9T001_GLOBAL_GAIN_MIN,
725 .max = MT9T001_GLOBAL_GAIN_MAX,
726 .step = 1,
727 .def = MT9T001_GLOBAL_GAIN_MIN,
728 .flags = 0,
729 }, {
730 .ops = &mt9t001_ctrl_ops,
731 .id = V4L2_CID_GAIN_BLUE,
732 .type = V4L2_CTRL_TYPE_INTEGER,
733 .name = "Gain, Blue",
734 .min = MT9T001_GLOBAL_GAIN_MIN,
735 .max = MT9T001_GLOBAL_GAIN_MAX,
736 .step = 1,
737 .def = MT9T001_GLOBAL_GAIN_MIN,
738 .flags = 0,
739 },
740};
741
742/* -----------------------------------------------------------------------------
743 * V4L2 subdev core operations
744 */
745
746static int mt9t001_set_power(struct v4l2_subdev *subdev, int on)
747{
748 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
749 int ret = 0;
750
751 mutex_lock(&mt9t001->power_lock);
752
753 /* If the power count is modified from 0 to != 0 or from != 0 to 0,
754 * update the power state.
755 */
756 if (mt9t001->power_count == !on) {
757 ret = __mt9t001_set_power(mt9t001, !!on);
758 if (ret < 0)
759 goto out;
760 }
761
762 /* Update the power count. */
763 mt9t001->power_count += on ? 1 : -1;
764 WARN_ON(mt9t001->power_count < 0);
765
766out:
767 mutex_unlock(&mt9t001->power_lock);
768 return ret;
769}
770
771/* -----------------------------------------------------------------------------
772 * V4L2 subdev internal operations
773 */
774
775static int mt9t001_registered(struct v4l2_subdev *subdev)
776{
777 struct i2c_client *client = v4l2_get_subdevdata(subdev);
778 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
779 s32 data;
780 int ret;
781
782 ret = mt9t001_power_on(mt9t001);
783 if (ret < 0) {
784 dev_err(&client->dev, "MT9T001 power up failed\n");
785 return ret;
786 }
787
788 /* Read out the chip version register */
789 data = mt9t001_read(client, MT9T001_CHIP_VERSION);
790 mt9t001_power_off(mt9t001);
791
792 if (data != MT9T001_CHIP_ID) {
793 dev_err(&client->dev,
794 "MT9T001 not detected, wrong version 0x%04x\n", data);
795 return -ENODEV;
796 }
797
798 dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
799 client->addr);
800
801 return 0;
802}
803
804static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
805{
806 struct v4l2_mbus_framefmt *format;
807 struct v4l2_rect *crop;
808
809 crop = v4l2_subdev_get_try_crop(subdev, fh->state, 0);
810 crop->left = MT9T001_COLUMN_START_DEF;
811 crop->top = MT9T001_ROW_START_DEF;
812 crop->width = MT9T001_WINDOW_WIDTH_DEF + 1;
813 crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
814
815 format = v4l2_subdev_get_try_format(subdev, fh->state, 0);
816 format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
817 format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
818 format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
819 format->field = V4L2_FIELD_NONE;
820 format->colorspace = V4L2_COLORSPACE_SRGB;
821
822 return mt9t001_set_power(subdev, 1);
823}
824
825static int mt9t001_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
826{
827 return mt9t001_set_power(subdev, 0);
828}
829
830static const struct v4l2_subdev_core_ops mt9t001_subdev_core_ops = {
831 .s_power = mt9t001_set_power,
832};
833
834static const struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = {
835 .s_stream = mt9t001_s_stream,
836};
837
838static const struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
839 .enum_mbus_code = mt9t001_enum_mbus_code,
840 .enum_frame_size = mt9t001_enum_frame_size,
841 .get_fmt = mt9t001_get_format,
842 .set_fmt = mt9t001_set_format,
843 .get_selection = mt9t001_get_selection,
844 .set_selection = mt9t001_set_selection,
845};
846
847static const struct v4l2_subdev_ops mt9t001_subdev_ops = {
848 .core = &mt9t001_subdev_core_ops,
849 .video = &mt9t001_subdev_video_ops,
850 .pad = &mt9t001_subdev_pad_ops,
851};
852
853static const struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = {
854 .registered = mt9t001_registered,
855 .open = mt9t001_open,
856 .close = mt9t001_close,
857};
858
859static int mt9t001_probe(struct i2c_client *client)
860{
861 struct mt9t001_platform_data *pdata = client->dev.platform_data;
862 struct mt9t001 *mt9t001;
863 unsigned int i;
864 int ret;
865
866 if (pdata == NULL) {
867 dev_err(&client->dev, "No platform data\n");
868 return -EINVAL;
869 }
870
871 if (!i2c_check_functionality(client->adapter,
872 I2C_FUNC_SMBUS_WORD_DATA)) {
873 dev_warn(&client->adapter->dev,
874 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
875 return -EIO;
876 }
877
878 mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL);
879 if (!mt9t001)
880 return -ENOMEM;
881
882 mutex_init(&mt9t001->power_lock);
883 mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
884
885 mt9t001->regulators[0].supply = "vdd";
886 mt9t001->regulators[1].supply = "vaa";
887
888 ret = devm_regulator_bulk_get(&client->dev, 2, mt9t001->regulators);
889 if (ret < 0) {
890 dev_err(&client->dev, "Unable to get regulators\n");
891 return ret;
892 }
893
894 mt9t001->clk = devm_clk_get(&client->dev, NULL);
895 if (IS_ERR(mt9t001->clk)) {
896 dev_err(&client->dev, "Unable to get clock\n");
897 return PTR_ERR(mt9t001->clk);
898 }
899
900 v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
901 ARRAY_SIZE(mt9t001_gains) + 4);
902
903 v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
904 V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
905 MT9T001_SHUTTER_WIDTH_MAX, 1,
906 MT9T001_SHUTTER_WIDTH_DEF);
907 v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
908 V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
909 v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
910 V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
911 1, pdata->ext_clk);
912 v4l2_ctrl_new_std_menu_items(&mt9t001->ctrls, &mt9t001_ctrl_ops,
913 V4L2_CID_TEST_PATTERN,
914 ARRAY_SIZE(mt9t001_test_pattern_menu) - 1, 0,
915 0, mt9t001_test_pattern_menu);
916
917 for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
918 v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
919
920 for (i = 0; i < ARRAY_SIZE(mt9t001_gains); ++i)
921 mt9t001->gains[i] = v4l2_ctrl_new_custom(&mt9t001->ctrls,
922 &mt9t001_gains[i], NULL);
923
924 v4l2_ctrl_cluster(ARRAY_SIZE(mt9t001_gains), mt9t001->gains);
925
926 mt9t001->subdev.ctrl_handler = &mt9t001->ctrls;
927
928 if (mt9t001->ctrls.error) {
929 printk(KERN_INFO "%s: control initialization error %d\n",
930 __func__, mt9t001->ctrls.error);
931 ret = -EINVAL;
932 goto done;
933 }
934
935 mt9t001->crop.left = MT9T001_COLUMN_START_DEF;
936 mt9t001->crop.top = MT9T001_ROW_START_DEF;
937 mt9t001->crop.width = MT9T001_WINDOW_WIDTH_DEF + 1;
938 mt9t001->crop.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
939
940 mt9t001->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
941 mt9t001->format.width = MT9T001_WINDOW_WIDTH_DEF + 1;
942 mt9t001->format.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
943 mt9t001->format.field = V4L2_FIELD_NONE;
944 mt9t001->format.colorspace = V4L2_COLORSPACE_SRGB;
945
946 v4l2_i2c_subdev_init(&mt9t001->subdev, client, &mt9t001_subdev_ops);
947 mt9t001->subdev.internal_ops = &mt9t001_subdev_internal_ops;
948 mt9t001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
949
950 mt9t001->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
951 mt9t001->pad.flags = MEDIA_PAD_FL_SOURCE;
952 ret = media_entity_pads_init(&mt9t001->subdev.entity, 1, &mt9t001->pad);
953
954done:
955 if (ret < 0) {
956 v4l2_ctrl_handler_free(&mt9t001->ctrls);
957 media_entity_cleanup(&mt9t001->subdev.entity);
958 }
959
960 return ret;
961}
962
963static void mt9t001_remove(struct i2c_client *client)
964{
965 struct v4l2_subdev *subdev = i2c_get_clientdata(client);
966 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
967
968 v4l2_ctrl_handler_free(&mt9t001->ctrls);
969 v4l2_device_unregister_subdev(subdev);
970 media_entity_cleanup(&subdev->entity);
971}
972
973static const struct i2c_device_id mt9t001_id[] = {
974 { "mt9t001", 0 },
975 { }
976};
977MODULE_DEVICE_TABLE(i2c, mt9t001_id);
978
979static struct i2c_driver mt9t001_driver = {
980 .driver = {
981 .name = "mt9t001",
982 },
983 .probe_new = mt9t001_probe,
984 .remove = mt9t001_remove,
985 .id_table = mt9t001_id,
986};
987
988module_i2c_driver(mt9t001_driver);
989
990MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver");
991MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
992MODULE_LICENSE("GPL");
drivers/media/i2c/noon010pc30.c+0−821
@@ -1,821 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Driver for SiliconFile NOON010PC30 CIF (1/11") Image Sensor with ISP
4 *
5 * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
6 * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
7 *
8 * Initial register configuration based on a driver authored by
9 * HeungJun Kim <riverful.kim@samsung.com>.
10 */
11
12#include <linux/delay.h>
13#include <linux/gpio/consumer.h>
14#include <linux/i2c.h>
15#include <linux/slab.h>
16#include <linux/regulator/consumer.h>
17#include <media/i2c/noon010pc30.h>
18#include <linux/videodev2.h>
19#include <linux/module.h>
20#include <media/v4l2-ctrls.h>
21#include <media/v4l2-device.h>
22#include <media/v4l2-mediabus.h>
23#include <media/v4l2-subdev.h>
24
25static int debug;
26module_param(debug, int, 0644);
27MODULE_PARM_DESC(debug, "Enable module debug trace. Set to 1 to enable.");
28
29#define MODULE_NAME "NOON010PC30"
30
31/*
32 * Register offsets within a page
33 * b15..b8 - page id, b7..b0 - register address
34 */
35#define POWER_CTRL_REG 0x0001
36#define PAGEMODE_REG 0x03
37#define DEVICE_ID_REG 0x0004
38#define NOON010PC30_ID 0x86
39#define VDO_CTL_REG(n) (0x0010 + (n))
40#define SYNC_CTL_REG 0x0012
41/* Window size and position */
42#define WIN_ROWH_REG 0x0013
43#define WIN_ROWL_REG 0x0014
44#define WIN_COLH_REG 0x0015
45#define WIN_COLL_REG 0x0016
46#define WIN_HEIGHTH_REG 0x0017
47#define WIN_HEIGHTL_REG 0x0018
48#define WIN_WIDTHH_REG 0x0019
49#define WIN_WIDTHL_REG 0x001A
50#define HBLANKH_REG 0x001B
51#define HBLANKL_REG 0x001C
52#define VSYNCH_REG 0x001D
53#define VSYNCL_REG 0x001E
54/* VSYNC control */
55#define VS_CTL_REG(n) (0x00A1 + (n))
56/* page 1 */
57#define ISP_CTL_REG(n) (0x0110 + (n))
58#define YOFS_REG 0x0119
59#define DARK_YOFS_REG 0x011A
60#define SAT_CTL_REG 0x0120
61#define BSAT_REG 0x0121
62#define RSAT_REG 0x0122
63/* Color correction */
64#define CMC_CTL_REG 0x0130
65#define CMC_OFSGH_REG 0x0133
66#define CMC_OFSGL_REG 0x0135
67#define CMC_SIGN_REG 0x0136
68#define CMC_GOFS_REG 0x0137
69#define CMC_COEF_REG(n) (0x0138 + (n))
70#define CMC_OFS_REG(n) (0x0141 + (n))
71/* Gamma correction */
72#define GMA_CTL_REG 0x0160
73#define GMA_COEF_REG(n) (0x0161 + (n))
74/* Lens Shading */
75#define LENS_CTRL_REG 0x01D0
76#define LENS_XCEN_REG 0x01D1
77#define LENS_YCEN_REG 0x01D2
78#define LENS_RC_REG 0x01D3
79#define LENS_GC_REG 0x01D4
80#define LENS_BC_REG 0x01D5
81#define L_AGON_REG 0x01D6
82#define L_AGOFF_REG 0x01D7
83/* Page 3 - Auto Exposure */
84#define AE_CTL_REG(n) (0x0310 + (n))
85#define AE_CTL9_REG 0x032C
86#define AE_CTL10_REG 0x032D
87#define AE_YLVL_REG 0x031C
88#define AE_YTH_REG(n) (0x031D + (n))
89#define AE_WGT_REG 0x0326
90#define EXP_TIMEH_REG 0x0333
91#define EXP_TIMEM_REG 0x0334
92#define EXP_TIMEL_REG 0x0335
93#define EXP_MMINH_REG 0x0336
94#define EXP_MMINL_REG 0x0337
95#define EXP_MMAXH_REG 0x0338
96#define EXP_MMAXM_REG 0x0339
97#define EXP_MMAXL_REG 0x033A
98/* Page 4 - Auto White Balance */
99#define AWB_CTL_REG(n) (0x0410 + (n))
100#define AWB_ENABE 0x80
101#define AWB_WGHT_REG 0x0419
102#define BGAIN_PAR_REG(n) (0x044F + (n))
103/* Manual white balance, when AWB_CTL2[0]=1 */
104#define MWB_RGAIN_REG 0x0466
105#define MWB_BGAIN_REG 0x0467
106
107/* The token to mark an array end */
108#define REG_TERM 0xFFFF
109
110struct noon010_format {
111 u32 code;
112 enum v4l2_colorspace colorspace;
113 u16 ispctl1_reg;
114};
115
116struct noon010_frmsize {
117 u16 width;
118 u16 height;
119 int vid_ctl1;
120};
121
122static const char * const noon010_supply_name[] = {
123 "vdd_core", "vddio", "vdda"
124};
125
126#define NOON010_NUM_SUPPLIES ARRAY_SIZE(noon010_supply_name)
127
128struct noon010_info {
129 struct v4l2_subdev sd;
130 struct media_pad pad;
131 struct v4l2_ctrl_handler hdl;
132 struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
133 struct gpio_desc *reset;
134 struct gpio_desc *stby;
135
136 /* Protects the struct members below */
137 struct mutex lock;
138
139 const struct noon010_format *curr_fmt;
140 const struct noon010_frmsize *curr_win;
141 unsigned int apply_new_cfg:1;
142 unsigned int streaming:1;
143 unsigned int hflip:1;
144 unsigned int vflip:1;
145 unsigned int power:1;
146 u8 i2c_reg_page;
147};
148
149struct i2c_regval {
150 u16 addr;
151 u16 val;
152};
153
154/* Supported resolutions. */
155static const struct noon010_frmsize noon010_sizes[] = {
156 {
157 .width = 352,
158 .height = 288,
159 .vid_ctl1 = 0,
160 }, {
161 .width = 176,
162 .height = 144,
163 .vid_ctl1 = 0x10,
164 }, {
165 .width = 88,
166 .height = 72,
167 .vid_ctl1 = 0x20,
168 },
169};
170
171/* Supported pixel formats. */
172static const struct noon010_format noon010_formats[] = {
173 {
174 .code = MEDIA_BUS_FMT_YUYV8_2X8,
175 .colorspace = V4L2_COLORSPACE_JPEG,
176 .ispctl1_reg = 0x03,
177 }, {
178 .code = MEDIA_BUS_FMT_YVYU8_2X8,
179 .colorspace = V4L2_COLORSPACE_JPEG,
180 .ispctl1_reg = 0x02,
181 }, {
182 .code = MEDIA_BUS_FMT_VYUY8_2X8,
183 .colorspace = V4L2_COLORSPACE_JPEG,
184 .ispctl1_reg = 0,
185 }, {
186 .code = MEDIA_BUS_FMT_UYVY8_2X8,
187 .colorspace = V4L2_COLORSPACE_JPEG,
188 .ispctl1_reg = 0x01,
189 }, {
190 .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
191 .colorspace = V4L2_COLORSPACE_JPEG,
192 .ispctl1_reg = 0x40,
193 },
194};
195
196static const struct i2c_regval noon010_base_regs[] = {
197 { WIN_COLL_REG, 0x06 }, { HBLANKL_REG, 0x7C },
198 /* Color corection and saturation */
199 { ISP_CTL_REG(0), 0x30 }, { ISP_CTL_REG(2), 0x30 },
200 { YOFS_REG, 0x80 }, { DARK_YOFS_REG, 0x04 },
201 { SAT_CTL_REG, 0x1F }, { BSAT_REG, 0x90 },
202 { CMC_CTL_REG, 0x0F }, { CMC_OFSGH_REG, 0x3C },
203 { CMC_OFSGL_REG, 0x2C }, { CMC_SIGN_REG, 0x3F },
204 { CMC_COEF_REG(0), 0x79 }, { CMC_OFS_REG(0), 0x00 },
205 { CMC_COEF_REG(1), 0x39 }, { CMC_OFS_REG(1), 0x00 },
206 { CMC_COEF_REG(2), 0x00 }, { CMC_OFS_REG(2), 0x00 },
207 { CMC_COEF_REG(3), 0x11 }, { CMC_OFS_REG(3), 0x8B },
208 { CMC_COEF_REG(4), 0x65 }, { CMC_OFS_REG(4), 0x07 },
209 { CMC_COEF_REG(5), 0x14 }, { CMC_OFS_REG(5), 0x04 },
210 { CMC_COEF_REG(6), 0x01 }, { CMC_OFS_REG(6), 0x9C },
211 { CMC_COEF_REG(7), 0x33 }, { CMC_OFS_REG(7), 0x89 },
212 { CMC_COEF_REG(8), 0x74 }, { CMC_OFS_REG(8), 0x25 },
213 /* Automatic white balance */
214 { AWB_CTL_REG(0), 0x78 }, { AWB_CTL_REG(1), 0x2E },
215 { AWB_CTL_REG(2), 0x20 }, { AWB_CTL_REG(3), 0x85 },
216 /* Auto exposure */
217 { AE_CTL_REG(0), 0xDC }, { AE_CTL_REG(1), 0x81 },
218 { AE_CTL_REG(2), 0x30 }, { AE_CTL_REG(3), 0xA5 },
219 { AE_CTL_REG(4), 0x40 }, { AE_CTL_REG(5), 0x51 },
220 { AE_CTL_REG(6), 0x33 }, { AE_CTL_REG(7), 0x7E },
221 { AE_CTL9_REG, 0x00 }, { AE_CTL10_REG, 0x02 },
222 { AE_YLVL_REG, 0x44 }, { AE_YTH_REG(0), 0x34 },
223 { AE_YTH_REG(1), 0x30 }, { AE_WGT_REG, 0xD5 },
224 /* Lens shading compensation */
225 { LENS_CTRL_REG, 0x01 }, { LENS_XCEN_REG, 0x80 },
226 { LENS_YCEN_REG, 0x70 }, { LENS_RC_REG, 0x53 },
227 { LENS_GC_REG, 0x40 }, { LENS_BC_REG, 0x3E },
228 { REG_TERM, 0 },
229};
230
231static inline struct noon010_info *to_noon010(struct v4l2_subdev *sd)
232{
233 return container_of(sd, struct noon010_info, sd);
234}
235
236static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
237{
238 return &container_of(ctrl->handler, struct noon010_info, hdl)->sd;
239}
240
241static inline int set_i2c_page(struct noon010_info *info,
242 struct i2c_client *client, unsigned int reg)
243{
244 u32 page = reg >> 8 & 0xFF;
245 int ret = 0;
246
247 if (info->i2c_reg_page != page && (reg & 0xFF) != 0x03) {
248 ret = i2c_smbus_write_byte_data(client, PAGEMODE_REG, page);
249 if (!ret)
250 info->i2c_reg_page = page;
251 }
252 return ret;
253}
254
255static int cam_i2c_read(struct v4l2_subdev *sd, u32 reg_addr)
256{
257 struct i2c_client *client = v4l2_get_subdevdata(sd);
258 struct noon010_info *info = to_noon010(sd);
259 int ret = set_i2c_page(info, client, reg_addr);
260
261 if (ret)
262 return ret;
263 return i2c_smbus_read_byte_data(client, reg_addr & 0xFF);
264}
265
266static int cam_i2c_write(struct v4l2_subdev *sd, u32 reg_addr, u32 val)
267{
268 struct i2c_client *client = v4l2_get_subdevdata(sd);
269 struct noon010_info *info = to_noon010(sd);
270 int ret = set_i2c_page(info, client, reg_addr);
271
272 if (ret)
273 return ret;
274 return i2c_smbus_write_byte_data(client, reg_addr & 0xFF, val);
275}
276
277static inline int noon010_bulk_write_reg(struct v4l2_subdev *sd,
278 const struct i2c_regval *msg)
279{
280 while (msg->addr != REG_TERM) {
281 int ret = cam_i2c_write(sd, msg->addr, msg->val);
282
283 if (ret)
284 return ret;
285 msg++;
286 }
287 return 0;
288}
289
290/* Device reset and sleep mode control */
291static int noon010_power_ctrl(struct v4l2_subdev *sd, bool reset, bool sleep)
292{
293 struct noon010_info *info = to_noon010(sd);
294 u8 reg = sleep ? 0xF1 : 0xF0;
295 int ret = 0;
296
297 if (reset) {
298 ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
299 udelay(20);
300 }
301 if (!ret) {
302 ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
303 if (reset && !ret)
304 info->i2c_reg_page = -1;
305 }
306 return ret;
307}
308
309/* Automatic white balance control */
310static int noon010_enable_autowhitebalance(struct v4l2_subdev *sd, int on)
311{
312 int ret;
313
314 ret = cam_i2c_write(sd, AWB_CTL_REG(1), on ? 0x2E : 0x2F);
315 if (!ret)
316 ret = cam_i2c_write(sd, AWB_CTL_REG(0), on ? 0xFB : 0x7B);
317 return ret;
318}
319
320/* Called with struct noon010_info.lock mutex held */
321static int noon010_set_flip(struct v4l2_subdev *sd, int hflip, int vflip)
322{
323 struct noon010_info *info = to_noon010(sd);
324 int reg, ret;
325
326 reg = cam_i2c_read(sd, VDO_CTL_REG(1));
327 if (reg < 0)
328 return reg;
329
330 reg &= 0x7C;
331 if (hflip)
332 reg |= 0x01;
333 if (vflip)
334 reg |= 0x02;
335
336 ret = cam_i2c_write(sd, VDO_CTL_REG(1), reg | 0x80);
337 if (!ret) {
338 info->hflip = hflip;
339 info->vflip = vflip;
340 }
341 return ret;
342}
343
344/* Configure resolution and color format */
345static int noon010_set_params(struct v4l2_subdev *sd)
346{
347 struct noon010_info *info = to_noon010(sd);
348
349 int ret = cam_i2c_write(sd, VDO_CTL_REG(0),
350 info->curr_win->vid_ctl1);
351 if (ret)
352 return ret;
353 return cam_i2c_write(sd, ISP_CTL_REG(0),
354 info->curr_fmt->ispctl1_reg);
355}
356
357/* Find nearest matching image pixel size. */
358static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf,
359 const struct noon010_frmsize **size)
360{
361 unsigned int min_err = ~0;
362 int i = ARRAY_SIZE(noon010_sizes);
363 const struct noon010_frmsize *fsize = &noon010_sizes[0],
364 *match = NULL;
365
366 while (i--) {
367 int err = abs(fsize->width - mf->width)
368 + abs(fsize->height - mf->height);
369
370 if (err < min_err) {
371 min_err = err;
372 match = fsize;
373 }
374 fsize++;
375 }
376 if (match) {
377 mf->width = match->width;
378 mf->height = match->height;
379 if (size)
380 *size = match;
381 return 0;
382 }
383 return -EINVAL;
384}
385
386/* Called with info.lock mutex held */
387static int power_enable(struct noon010_info *info)
388{
389 int ret;
390
391 if (info->power) {
392 v4l2_info(&info->sd, "%s: sensor is already on\n", __func__);
393 return 0;
394 }
395
396 /* Assert standby: line should be flagged active low in descriptor */
397 if (info->stby)
398 gpiod_set_value(info->stby, 1);
399
400 /* Assert reset: line should be flagged active low in descriptor */
401 if (info->reset)
402 gpiod_set_value(info->reset, 1);
403
404 ret = regulator_bulk_enable(NOON010_NUM_SUPPLIES, info->supply);
405 if (ret)
406 return ret;
407
408 /* De-assert reset and standby */
409 if (info->reset) {
410 msleep(50);
411 gpiod_set_value(info->reset, 0);
412 }
413 if (info->stby) {
414 udelay(1000);
415 gpiod_set_value(info->stby, 0);
416 }
417 /* Cycle reset: assert and deassert */
418 if (info->reset) {
419 udelay(1000);
420 gpiod_set_value(info->reset, 1);
421 msleep(100);
422 gpiod_set_value(info->reset, 0);
423 msleep(20);
424 }
425 info->power = 1;
426
427 v4l2_dbg(1, debug, &info->sd, "%s: sensor is on\n", __func__);
428 return 0;
429}
430
431/* Called with info.lock mutex held */
432static int power_disable(struct noon010_info *info)
433{
434 int ret;
435
436 if (!info->power) {
437 v4l2_info(&info->sd, "%s: sensor is already off\n", __func__);
438 return 0;
439 }
440
441 ret = regulator_bulk_disable(NOON010_NUM_SUPPLIES, info->supply);
442 if (ret)
443 return ret;
444
445 /* Assert standby and reset */
446 if (info->stby)
447 gpiod_set_value(info->stby, 1);
448
449 if (info->reset)
450 gpiod_set_value(info->reset, 1);
451
452 info->power = 0;
453
454 v4l2_dbg(1, debug, &info->sd, "%s: sensor is off\n", __func__);
455
456 return 0;
457}
458
459static int noon010_s_ctrl(struct v4l2_ctrl *ctrl)
460{
461 struct v4l2_subdev *sd = to_sd(ctrl);
462 struct noon010_info *info = to_noon010(sd);
463 int ret = 0;
464
465 v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
466 __func__, ctrl->id, ctrl->val);
467
468 mutex_lock(&info->lock);
469 /*
470 * If the device is not powered up by the host driver do
471 * not apply any controls to H/W at this time. Instead
472 * the controls will be restored right after power-up.
473 */
474 if (!info->power)
475 goto unlock;
476
477 switch (ctrl->id) {
478 case V4L2_CID_AUTO_WHITE_BALANCE:
479 ret = noon010_enable_autowhitebalance(sd, ctrl->val);
480 break;
481 case V4L2_CID_BLUE_BALANCE:
482 ret = cam_i2c_write(sd, MWB_BGAIN_REG, ctrl->val);
483 break;
484 case V4L2_CID_RED_BALANCE:
485 ret = cam_i2c_write(sd, MWB_RGAIN_REG, ctrl->val);
486 break;
487 default:
488 ret = -EINVAL;
489 }
490unlock:
491 mutex_unlock(&info->lock);
492 return ret;
493}
494
495static int noon010_enum_mbus_code(struct v4l2_subdev *sd,
496 struct v4l2_subdev_state *sd_state,
497 struct v4l2_subdev_mbus_code_enum *code)
498{
499 if (code->index >= ARRAY_SIZE(noon010_formats))
500 return -EINVAL;
501
502 code->code = noon010_formats[code->index].code;
503 return 0;
504}
505
506static int noon010_get_fmt(struct v4l2_subdev *sd,
507 struct v4l2_subdev_state *sd_state,
508 struct v4l2_subdev_format *fmt)
509{
510 struct noon010_info *info = to_noon010(sd);
511 struct v4l2_mbus_framefmt *mf;
512
513 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
514 if (sd_state) {
515 mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
516 fmt->format = *mf;
517 }
518 return 0;
519 }
520 mf = &fmt->format;
521
522 mutex_lock(&info->lock);
523 mf->width = info->curr_win->width;
524 mf->height = info->curr_win->height;
525 mf->code = info->curr_fmt->code;
526 mf->colorspace = info->curr_fmt->colorspace;
527 mf->field = V4L2_FIELD_NONE;
528
529 mutex_unlock(&info->lock);
530 return 0;
531}
532
533/* Return nearest media bus frame format. */
534static const struct noon010_format *noon010_try_fmt(struct v4l2_subdev *sd,
535 struct v4l2_mbus_framefmt *mf)
536{
537 int i = ARRAY_SIZE(noon010_formats);
538
539 while (--i)
540 if (mf->code == noon010_formats[i].code)
541 break;
542 mf->code = noon010_formats[i].code;
543
544 return &noon010_formats[i];
545}
546
547static int noon010_set_fmt(struct v4l2_subdev *sd,
548 struct v4l2_subdev_state *sd_state,
549 struct v4l2_subdev_format *fmt)
550{
551 struct noon010_info *info = to_noon010(sd);
552 const struct noon010_frmsize *size = NULL;
553 const struct noon010_format *nf;
554 struct v4l2_mbus_framefmt *mf;
555 int ret = 0;
556
557 nf = noon010_try_fmt(sd, &fmt->format);
558 noon010_try_frame_size(&fmt->format, &size);
559 fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
560 fmt->format.field = V4L2_FIELD_NONE;
561
562 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
563 if (sd_state) {
564 mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
565 *mf = fmt->format;
566 }
567 return 0;
568 }
569 mutex_lock(&info->lock);
570 if (!info->streaming) {
571 info->apply_new_cfg = 1;
572 info->curr_fmt = nf;
573 info->curr_win = size;
574 } else {
575 ret = -EBUSY;
576 }
577 mutex_unlock(&info->lock);
578 return ret;
579}
580
581/* Called with struct noon010_info.lock mutex held */
582static int noon010_base_config(struct v4l2_subdev *sd)
583{
584 int ret = noon010_bulk_write_reg(sd, noon010_base_regs);
585 if (!ret)
586 ret = noon010_set_params(sd);
587 if (!ret)
588 ret = noon010_set_flip(sd, 1, 0);
589
590 return ret;
591}
592
593static int noon010_s_power(struct v4l2_subdev *sd, int on)
594{
595 struct noon010_info *info = to_noon010(sd);
596 int ret;
597
598 mutex_lock(&info->lock);
599 if (on) {
600 ret = power_enable(info);
601 if (!ret)
602 ret = noon010_base_config(sd);
603 } else {
604 noon010_power_ctrl(sd, false, true);
605 ret = power_disable(info);
606 }
607 mutex_unlock(&info->lock);
608
609 /* Restore the controls state */
610 if (!ret && on)
611 ret = v4l2_ctrl_handler_setup(&info->hdl);
612
613 return ret;
614}
615
616static int noon010_s_stream(struct v4l2_subdev *sd, int on)
617{
618 struct noon010_info *info = to_noon010(sd);
619 int ret = 0;
620
621 mutex_lock(&info->lock);
622 if (!info->streaming != !on) {
623 ret = noon010_power_ctrl(sd, false, !on);
624 if (!ret)
625 info->streaming = on;
626 }
627 if (!ret && on && info->apply_new_cfg) {
628 ret = noon010_set_params(sd);
629 if (!ret)
630 info->apply_new_cfg = 0;
631 }
632 mutex_unlock(&info->lock);
633 return ret;
634}
635
636static int noon010_log_status(struct v4l2_subdev *sd)
637{
638 struct noon010_info *info = to_noon010(sd);
639
640 v4l2_ctrl_handler_log_status(&info->hdl, sd->name);
641 return 0;
642}
643
644static int noon010_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
645{
646 struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(sd,
647 fh->state,
648 0);
649
650 mf->width = noon010_sizes[0].width;
651 mf->height = noon010_sizes[0].height;
652 mf->code = noon010_formats[0].code;
653 mf->colorspace = V4L2_COLORSPACE_JPEG;
654 mf->field = V4L2_FIELD_NONE;
655 return 0;
656}
657
658static const struct v4l2_subdev_internal_ops noon010_subdev_internal_ops = {
659 .open = noon010_open,
660};
661
662static const struct v4l2_ctrl_ops noon010_ctrl_ops = {
663 .s_ctrl = noon010_s_ctrl,
664};
665
666static const struct v4l2_subdev_core_ops noon010_core_ops = {
667 .s_power = noon010_s_power,
668 .log_status = noon010_log_status,
669};
670
671static const struct v4l2_subdev_pad_ops noon010_pad_ops = {
672 .enum_mbus_code = noon010_enum_mbus_code,
673 .get_fmt = noon010_get_fmt,
674 .set_fmt = noon010_set_fmt,
675};
676
677static const struct v4l2_subdev_video_ops noon010_video_ops = {
678 .s_stream = noon010_s_stream,
679};
680
681static const struct v4l2_subdev_ops noon010_ops = {
682 .core = &noon010_core_ops,
683 .pad = &noon010_pad_ops,
684 .video = &noon010_video_ops,
685};
686
687/* Return 0 if NOON010PC30L sensor type was detected or -ENODEV otherwise. */
688static int noon010_detect(struct i2c_client *client, struct noon010_info *info)
689{
690 int ret;
691
692 ret = power_enable(info);
693 if (ret)
694 return ret;
695
696 ret = i2c_smbus_read_byte_data(client, DEVICE_ID_REG);
697 if (ret < 0)
698 dev_err(&client->dev, "I2C read failed: 0x%X\n", ret);
699
700 power_disable(info);
701
702 return ret == NOON010PC30_ID ? 0 : -ENODEV;
703}
704
705static int noon010_probe(struct i2c_client *client)
706{
707 struct noon010_info *info;
708 struct v4l2_subdev *sd;
709 const struct noon010pc30_platform_data *pdata
710 = client->dev.platform_data;
711 int ret;
712 int i;
713
714 if (!pdata) {
715 dev_err(&client->dev, "No platform data!\n");
716 return -EIO;
717 }
718
719 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
720 if (!info)
721 return -ENOMEM;
722
723 mutex_init(&info->lock);
724 sd = &info->sd;
725 v4l2_i2c_subdev_init(sd, client, &noon010_ops);
726 /* Static name; NEVER use in new drivers! */
727 strscpy(sd->name, MODULE_NAME, sizeof(sd->name));
728
729 sd->internal_ops = &noon010_subdev_internal_ops;
730 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
731
732 v4l2_ctrl_handler_init(&info->hdl, 3);
733
734 v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
735 V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
736 v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
737 V4L2_CID_RED_BALANCE, 0, 127, 1, 64);
738 v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
739 V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64);
740
741 sd->ctrl_handler = &info->hdl;
742
743 ret = info->hdl.error;
744 if (ret)
745 goto np_err;
746
747 info->i2c_reg_page = -1;
748 info->curr_fmt = &noon010_formats[0];
749 info->curr_win = &noon010_sizes[0];
750
751 /* Request reset asserted so we get put into reset */
752 info->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
753 if (IS_ERR(info->reset)) {
754 ret = PTR_ERR(info->reset);
755 goto np_err;
756 }
757 gpiod_set_consumer_name(info->reset, "NOON010PC30 NRST");
758
759 /* Request standby asserted so we get put into standby */
760 info->stby = devm_gpiod_get(&client->dev, "standby", GPIOD_OUT_HIGH);
761 if (IS_ERR(info->stby)) {
762 ret = PTR_ERR(info->stby);
763 goto np_err;
764 }
765 gpiod_set_consumer_name(info->reset, "NOON010PC30 STBY");
766
767 for (i = 0; i < NOON010_NUM_SUPPLIES; i++)
768 info->supply[i].supply = noon010_supply_name[i];
769
770 ret = devm_regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES,
771 info->supply);
772 if (ret)
773 goto np_err;
774
775 info->pad.flags = MEDIA_PAD_FL_SOURCE;
776 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
777 ret = media_entity_pads_init(&sd->entity, 1, &info->pad);
778 if (ret < 0)
779 goto np_err;
780
781 ret = noon010_detect(client, info);
782 if (!ret)
783 return 0;
784
785np_err:
786 v4l2_ctrl_handler_free(&info->hdl);
787 v4l2_device_unregister_subdev(sd);
788 return ret;
789}
790
791static void noon010_remove(struct i2c_client *client)
792{
793 struct v4l2_subdev *sd = i2c_get_clientdata(client);
794 struct noon010_info *info = to_noon010(sd);
795
796 v4l2_device_unregister_subdev(sd);
797 v4l2_ctrl_handler_free(&info->hdl);
798 media_entity_cleanup(&sd->entity);
799}
800
801static const struct i2c_device_id noon010_id[] = {
802 { MODULE_NAME, 0 },
803 { },
804};
805MODULE_DEVICE_TABLE(i2c, noon010_id);
806
807
808static struct i2c_driver noon010_i2c_driver = {
809 .driver = {
810 .name = MODULE_NAME
811 },
812 .probe_new = noon010_probe,
813 .remove = noon010_remove,
814 .id_table = noon010_id,
815};
816
817module_i2c_driver(noon010_i2c_driver);
818
819MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver");
820MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
821MODULE_LICENSE("GPL");
drivers/media/i2c/ov13b10.c+47−28
@@ -243,7 +243,6 @@ static const struct ov13b10_reg mipi_data_rate_1120mbps[] = { · 242 unmodified lines
243 {0x5047, 0xa4},243 {0x5047, 0xa4},
244 {0x5048, 0x20},244 {0x5048, 0x20},
245 {0x5049, 0xa4},245 {0x5049, 0xa4},
246 {0x0100, 0x01},
247};246};
248 247
249static const struct ov13b10_reg mode_4208x3120_regs[] = {248static const struct ov13b10_reg mode_4208x3120_regs[] = {
@@ -589,6 +588,9 @@ struct ov13b10 { · 339 unmodified lines
589 588
590 /* Streaming on/off */589 /* Streaming on/off */
591 bool streaming;590 bool streaming;
591
592 /* True if the device has been identified */
593 bool identified;
592};594};
593 595
594#define to_ov13b10(_sd) container_of(_sd, struct ov13b10, sd)596#define to_ov13b10(_sd) container_of(_sd, struct ov13b10, sd)
@@ -1023,12 +1025,42 @@ ov13b10_set_pad_format(struct v4l2_subdev *sd, · 428 unmodified lines
1023 return 0;1025 return 0;
1024}1026}
1025 1027
1028/* Verify chip ID */
1029static int ov13b10_identify_module(struct ov13b10 *ov13b)
1030{
1031 struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
1032 int ret;
1033 u32 val;
1034
1035 if (ov13b->identified)
1036 return 0;
1037
1038 ret = ov13b10_read_reg(ov13b, OV13B10_REG_CHIP_ID,
1039 OV13B10_REG_VALUE_24BIT, &val);
1040 if (ret)
1041 return ret;
1042
1043 if (val != OV13B10_CHIP_ID) {
1044 dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
1045 OV13B10_CHIP_ID, val);
1046 return -EIO;
1047 }
1048
1049 ov13b->identified = true;
1050
1051 return 0;
1052}
1053
1026static int ov13b10_start_streaming(struct ov13b10 *ov13b)1054static int ov13b10_start_streaming(struct ov13b10 *ov13b)
1027{1055{
1028 struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);1056 struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
1029 const struct ov13b10_reg_list *reg_list;1057 const struct ov13b10_reg_list *reg_list;
1030 int ret, link_freq_index;1058 int ret, link_freq_index;
1031 1059
1060 ret = ov13b10_identify_module(ov13b);
1061 if (ret)
1062 return ret;
1063
1032 /* Get out of from software reset */1064 /* Get out of from software reset */
1033 ret = ov13b10_write_reg(ov13b, OV13B10_REG_SOFTWARE_RST,1065 ret = ov13b10_write_reg(ov13b, OV13B10_REG_SOFTWARE_RST,
1034 OV13B10_REG_VALUE_08BIT, OV13B10_SOFTWARE_RST);1066 OV13B10_REG_VALUE_08BIT, OV13B10_SOFTWARE_RST);
@@ -1144,27 +1176,6 @@ error: · 109 unmodified lines
1144 return ret;1176 return ret;
1145}1177}
1146 1178
1147/* Verify chip ID */
1148static int ov13b10_identify_module(struct ov13b10 *ov13b)
1149{
1150 struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
1151 int ret;
1152 u32 val;
1153
1154 ret = ov13b10_read_reg(ov13b, OV13B10_REG_CHIP_ID,
1155 OV13B10_REG_VALUE_24BIT, &val);
1156 if (ret)
1157 return ret;
1158
1159 if (val != OV13B10_CHIP_ID) {
1160 dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
1161 OV13B10_CHIP_ID, val);
1162 return -EIO;
1163 }
1164
1165 return 0;
1166}
1167
1168static const struct v4l2_subdev_video_ops ov13b10_video_ops = {1179static const struct v4l2_subdev_video_ops ov13b10_video_ops = {
1169 .s_stream = ov13b10_set_stream,1180 .s_stream = ov13b10_set_stream,
1170};1181};
@@ -1379,6 +1390,7 @@ out_err: · 208 unmodified lines
1379static int ov13b10_probe(struct i2c_client *client)1390static int ov13b10_probe(struct i2c_client *client)
1380{1391{
1381 struct ov13b10 *ov13b;1392 struct ov13b10 *ov13b;
1393 bool full_power;
1382 int ret;1394 int ret;
1383 1395
1384 /* Check HW config */1396 /* Check HW config */
@@ -1395,11 +1407,14 @@ static int ov13b10_probe(struct i2c_client *client) · 10 unmodified lines
1395 /* Initialize subdev */1407 /* Initialize subdev */
1396 v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops);1408 v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops);
1397 1409
1398 /* Check module identity */1410 full_power = acpi_dev_state_d0(&client->dev);
1399 ret = ov13b10_identify_module(ov13b);1411 if (full_power) {
1400 if (ret) {1412 /* Check module identity */
1401 dev_err(&client->dev, "failed to find sensor: %d\n", ret);1413 ret = ov13b10_identify_module(ov13b);
1402 return ret;1414 if (ret) {
1415 dev_err(&client->dev, "failed to find sensor: %d\n", ret);
1416 return ret;
1417 }
1403 }1418 }
1404 1419
1405 /* Set default mode to max resolution */1420 /* Set default mode to max resolution */
@@ -1431,7 +1446,10 @@ static int ov13b10_probe(struct i2c_client *client) · 25 unmodified lines
1431 * Device is already turned on by i2c-core with ACPI domain PM.1446 * Device is already turned on by i2c-core with ACPI domain PM.
1432 * Enable runtime PM and turn off the device.1447 * Enable runtime PM and turn off the device.
1433 */1448 */
1434 pm_runtime_set_active(&client->dev);1449
1450 /* Set the device's state to active if it's in D0 state. */
1451 if (full_power)
1452 pm_runtime_set_active(&client->dev);
1435 pm_runtime_enable(&client->dev);1453 pm_runtime_enable(&client->dev);
1436 pm_runtime_idle(&client->dev);1454 pm_runtime_idle(&client->dev);
1437 1455
@@ -1480,6 +1498,7 @@ static struct i2c_driver ov13b10_i2c_driver = { · 42 unmodified lines
1480 },1498 },
1481 .probe_new = ov13b10_probe,1499 .probe_new = ov13b10_probe,
1482 .remove = ov13b10_remove,1500 .remove = ov13b10_remove,
1501 .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
1483};1502};
1484 1503
1485module_i2c_driver(ov13b10_i2c_driver);1504module_i2c_driver(ov13b10_i2c_driver);
drivers/media/i2c/ov2685.c+77−3
@@ -17,6 +17,7 @@ · 16 unmodified lines
17#include <media/media-entity.h>17#include <media/media-entity.h>
18#include <media/v4l2-async.h>18#include <media/v4l2-async.h>
19#include <media/v4l2-ctrls.h>19#include <media/v4l2-ctrls.h>
20#include <media/v4l2-fwnode.h>
20#include <media/v4l2-subdev.h>21#include <media/v4l2-subdev.h>
21 22
22#define CHIP_ID 0x268523#define CHIP_ID 0x2685
@@ -55,6 +56,9 @@ · 32 unmodified lines
55#define OV2685_REG_VALUE_16BIT 256#define OV2685_REG_VALUE_16BIT 2
56#define OV2685_REG_VALUE_24BIT 357#define OV2685_REG_VALUE_24BIT 3
57 58
59#define OV2685_NATIVE_WIDTH 1616
60#define OV2685_NATIVE_HEIGHT 1216
61
58#define OV2685_LANES 162#define OV2685_LANES 1
59#define OV2685_BITS_PER_SAMPLE 1063#define OV2685_BITS_PER_SAMPLE 10
60 64
@@ -77,6 +81,7 @@ struct ov2685_mode { · 16 unmodified lines
77 u32 exp_def;81 u32 exp_def;
78 u32 hts_def;82 u32 hts_def;
79 u32 vts_def;83 u32 vts_def;
84 const struct v4l2_rect *analog_crop;
80 const struct regval *reg_list;85 const struct regval *reg_list;
81};86};
82 87
@@ -230,6 +235,13 @@ static const int ov2685_test_pattern_val[] = { · 147 unmodified lines
230 OV2685_TEST_PATTERN_COLOR_SQUARE,235 OV2685_TEST_PATTERN_COLOR_SQUARE,
231};236};
232 237
238static const struct v4l2_rect ov2685_analog_crop = {
239 .left = 8,
240 .top = 8,
241 .width = 1600,
242 .height = 1200,
243};
244
233static const struct ov2685_mode supported_modes[] = {245static const struct ov2685_mode supported_modes[] = {
234 {246 {
235 .width = 1600,247 .width = 1600,
@@ -237,6 +249,7 @@ static const struct ov2685_mode supported_modes[] = { · 1 unmodified line
237 .exp_def = 0x04ee,249 .exp_def = 0x04ee,
238 .hts_def = 0x06a4,250 .hts_def = 0x06a4,
239 .vts_def = 0x050e,251 .vts_def = 0x050e,
252 .analog_crop = &ov2685_analog_crop,
240 .reg_list = ov2685_1600x1200_regs,253 .reg_list = ov2685_1600x1200_regs,
241 },254 },
242};255};
@@ -383,6 +396,53 @@ static int ov2685_enum_frame_sizes(struct v4l2_subdev *sd, · 140 unmodified lines
383 return 0;396 return 0;
384}397}
385 398
399static const struct v4l2_rect *
400__ov2685_get_pad_crop(struct ov2685 *ov2685,
401 struct v4l2_subdev_state *state, unsigned int pad,
402 enum v4l2_subdev_format_whence which)
403{
404 const struct ov2685_mode *mode = ov2685->cur_mode;
405
406 switch (which) {
407 case V4L2_SUBDEV_FORMAT_TRY:
408 return v4l2_subdev_get_try_crop(&ov2685->subdev, state, pad);
409 case V4L2_SUBDEV_FORMAT_ACTIVE:
410 return mode->analog_crop;
411 }
412
413 return NULL;
414}
415
416static int ov2685_get_selection(struct v4l2_subdev *sd,
417 struct v4l2_subdev_state *sd_state,
418 struct v4l2_subdev_selection *sel)
419{
420 struct ov2685 *ov2685 = to_ov2685(sd);
421
422 switch (sel->target) {
423 case V4L2_SEL_TGT_CROP:
424 mutex_lock(&ov2685->mutex);
425 sel->r = *__ov2685_get_pad_crop(ov2685, sd_state, sel->pad,
426 sel->which);
427 mutex_unlock(&ov2685->mutex);
428 break;
429 case V4L2_SEL_TGT_NATIVE_SIZE:
430 case V4L2_SEL_TGT_CROP_BOUNDS:
431 sel->r.top = 0;
432 sel->r.left = 0;
433 sel->r.width = OV2685_NATIVE_WIDTH;
434 sel->r.height = OV2685_NATIVE_HEIGHT;
435 break;
436 case V4L2_SEL_TGT_CROP_DEFAULT:
437 sel->r = ov2685_analog_crop;
438 break;
439 default:
440 return -EINVAL;
441 }
442
443 return 0;
444}
445
386/* Calculate the delay in us by clock rate and clock cycles */446/* Calculate the delay in us by clock rate and clock cycles */
387static inline u32 ov2685_cal_delay(u32 cycles)447static inline u32 ov2685_cal_delay(u32 cycles)
388{448{
@@ -419,8 +479,10 @@ static int __ov2685_power_on(struct ov2685 *ov2685) · 30 unmodified lines
419 * writing register before .s_stream() as a workaround479 * writing register before .s_stream() as a workaround
420 */480 */
421 ret = ov2685_write_array(ov2685->client, ov2685->cur_mode->reg_list);481 ret = ov2685_write_array(ov2685->client, ov2685->cur_mode->reg_list);
422 if (ret)482 if (ret) {
483 dev_err(dev, "Failed to set regs for power on\n");
423 goto disable_supplies;484 goto disable_supplies;
485 }
424 486
425 return 0;487 return 0;
426 488
@@ -589,6 +651,8 @@ static const struct v4l2_subdev_pad_ops ov2685_pad_ops = { · 162 unmodified lines
589 .enum_frame_size = ov2685_enum_frame_sizes,651 .enum_frame_size = ov2685_enum_frame_sizes,
590 .get_fmt = ov2685_get_fmt,652 .get_fmt = ov2685_get_fmt,
591 .set_fmt = ov2685_set_fmt,653 .set_fmt = ov2685_set_fmt,
654 .get_selection = ov2685_get_selection,
655 .set_selection = ov2685_get_selection,
592};656};
593 657
594static const struct v4l2_subdev_ops ov2685_subdev_ops = {658static const struct v4l2_subdev_ops ov2685_subdev_ops = {
@@ -611,13 +675,14 @@ static int ov2685_initialize_controls(struct ov2685 *ov2685) · 16 unmodified lines
611 const struct ov2685_mode *mode;675 const struct ov2685_mode *mode;
612 struct v4l2_ctrl_handler *handler;676 struct v4l2_ctrl_handler *handler;
613 struct v4l2_ctrl *ctrl;677 struct v4l2_ctrl *ctrl;
678 struct v4l2_fwnode_device_properties props;
614 u64 exposure_max;679 u64 exposure_max;
615 u32 pixel_rate, h_blank;680 u32 pixel_rate, h_blank;
616 int ret;681 int ret;
617 682
618 handler = &ov2685->ctrl_handler;683 handler = &ov2685->ctrl_handler;
619 mode = ov2685->cur_mode;684 mode = ov2685->cur_mode;
620 ret = v4l2_ctrl_handler_init(handler, 8);685 ret = v4l2_ctrl_handler_init(handler, 10);
621 if (ret)686 if (ret)
622 return ret;687 return ret;
623 handler->lock = &ov2685->mutex;688 handler->lock = &ov2685->mutex;
@@ -659,6 +724,15 @@ static int ov2685_initialize_controls(struct ov2685 *ov2685) · 35 unmodified lines
659 ARRAY_SIZE(ov2685_test_pattern_menu) - 1,724 ARRAY_SIZE(ov2685_test_pattern_menu) - 1,
660 0, 0, ov2685_test_pattern_menu);725 0, 0, ov2685_test_pattern_menu);
661 726
727 /* set properties from fwnode (e.g. rotation, orientation) */
728 ret = v4l2_fwnode_device_parse(&ov2685->client->dev, &props);
729 if (ret)
730 goto err_free_handler;
731
732 ret = v4l2_ctrl_new_fwnode_properties(handler, &ov2685_ctrl_ops, &props);
733 if (ret)
734 goto err_free_handler;
735
662 if (handler->error) {736 if (handler->error) {
663 ret = handler->error;737 ret = handler->error;
664 dev_err(&ov2685->client->dev,738 dev_err(&ov2685->client->dev,
@@ -733,7 +807,7 @@ static int ov2685_probe(struct i2c_client *client) · 68 unmodified lines
733 if (clk_get_rate(ov2685->xvclk) != OV2685_XVCLK_FREQ)807 if (clk_get_rate(ov2685->xvclk) != OV2685_XVCLK_FREQ)
734 dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");808 dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
735 809
736 ov2685->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);810 ov2685->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
737 if (IS_ERR(ov2685->reset_gpio)) {811 if (IS_ERR(ov2685->reset_gpio)) {
738 dev_err(dev, "Failed to get reset-gpios\n");812 dev_err(dev, "Failed to get reset-gpios\n");
739 return -EINVAL;813 return -EINVAL;
drivers/media/i2c/ov5647.c+43−13
@@ -58,6 +58,7 @@ · 57 unmodified lines
58#define OV5647_REG_MIPI_CTRL00 0x480058#define OV5647_REG_MIPI_CTRL00 0x4800
59#define OV5647_REG_MIPI_CTRL14 0x481459#define OV5647_REG_MIPI_CTRL14 0x4814
60#define OV5647_REG_AWB 0x500160#define OV5647_REG_AWB 0x5001
61#define OV5647_REG_ISPCTRL3D 0x503d
61 62
62#define REG_TERM 0xfffe63#define REG_TERM 0xfffe
63#define VAL_TERM 0xfe64#define VAL_TERM 0xfe
@@ -116,6 +117,20 @@ static inline struct ov5647 *to_sensor(struct v4l2_subdev *sd) · 52 unmodified lines
116 return container_of(sd, struct ov5647, sd);117 return container_of(sd, struct ov5647, sd);
117}118}
118 119
120static const char * const ov5647_test_pattern_menu[] = {
121 "Disabled",
122 "Color Bars",
123 "Color Squares",
124 "Random Data",
125};
126
127static const u8 ov5647_test_pattern_val[] = {
128 0x00, /* Disabled */
129 0x80, /* Color Bars */
130 0x82, /* Color Squares */
131 0x81, /* Random Data */
132};
133
119static const struct regval_list sensor_oe_disable_regs[] = {134static const struct regval_list sensor_oe_disable_regs[] = {
120 {0x3000, 0x00},135 {0x3000, 0x00},
121 {0x3001, 0x00},136 {0x3001, 0x00},
@@ -614,23 +629,29 @@ static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val) · 492 unmodified lines
614 629
615static int ov5647_read(struct v4l2_subdev *sd, u16 reg, u8 *val)630static int ov5647_read(struct v4l2_subdev *sd, u16 reg, u8 *val)
616{631{
617 unsigned char data_w[2] = { reg >> 8, reg & 0xff };
618 struct i2c_client *client = v4l2_get_subdevdata(sd);632 struct i2c_client *client = v4l2_get_subdevdata(sd);
633 u8 buf[2] = { reg >> 8, reg & 0xff };
634 struct i2c_msg msg[2];
619 int ret;635 int ret;
620 636
621 ret = i2c_master_send(client, data_w, 2);637 msg[0].addr = client->addr;
622 if (ret < 0) {638 msg[0].flags = client->flags;
623 dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",639 msg[0].buf = buf;
624 __func__, reg);640 msg[0].len = sizeof(buf);
625 return ret;641
642 msg[1].addr = client->addr;
643 msg[1].flags = client->flags | I2C_M_RD;
644 msg[1].buf = buf;
645 msg[1].len = 1;
646
647 ret = i2c_transfer(client->adapter, msg, 2);
648 if (ret != 2) {
649 dev_err(&client->dev, "%s: i2c read error, reg: %x = %d\n",
650 __func__, reg, ret);
651 return ret >= 0 ? -EINVAL : ret;
626 }652 }
627 653
628 ret = i2c_master_recv(client, val, 1);654 *val = buf[0];
629 if (ret < 0) {
630 dev_dbg(&client->dev, "%s: i2c read error, reg: %x\n",
631 __func__, reg);
632 return ret;
633 }
634 655
635 return 0;656 return 0;
636}657}
@@ -1242,6 +1263,10 @@ static int ov5647_s_ctrl(struct v4l2_ctrl *ctrl) · 605 unmodified lines
1242 ret = ov5647_write16(sd, OV5647_REG_VTS_HI,1263 ret = ov5647_write16(sd, OV5647_REG_VTS_HI,
1243 sensor->mode->format.height + ctrl->val);1264 sensor->mode->format.height + ctrl->val);
1244 break;1265 break;
1266 case V4L2_CID_TEST_PATTERN:
1267 ret = ov5647_write(sd, OV5647_REG_ISPCTRL3D,
1268 ov5647_test_pattern_val[ctrl->val]);
1269 break;
1245 1270
1246 /* Read-only, but we adjust it based on mode. */1271 /* Read-only, but we adjust it based on mode. */
1247 case V4L2_CID_PIXEL_RATE:1272 case V4L2_CID_PIXEL_RATE:
@@ -1270,7 +1295,7 @@ static int ov5647_init_controls(struct ov5647 *sensor) · 22 unmodified lines
1270 struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);1295 struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
1271 int hblank, exposure_max, exposure_def;1296 int hblank, exposure_max, exposure_def;
1272 1297
1273 v4l2_ctrl_handler_init(&sensor->ctrls, 8);1298 v4l2_ctrl_handler_init(&sensor->ctrls, 9);
1274 1299
1275 v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,1300 v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
1276 V4L2_CID_AUTOGAIN, 0, 1, 1, 0);1301 V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
@@ -1314,6 +1339,11 @@ static int ov5647_init_controls(struct ov5647 *sensor) · 37 unmodified lines
1314 sensor->mode->vts -1339 sensor->mode->vts -
1315 sensor->mode->format.height);1340 sensor->mode->format.height);
1316 1341
1342 v4l2_ctrl_new_std_menu_items(&sensor->ctrls, &ov5647_ctrl_ops,
1343 V4L2_CID_TEST_PATTERN,
1344 ARRAY_SIZE(ov5647_test_pattern_menu) - 1,
1345 0, 0, ov5647_test_pattern_menu);
1346
1317 if (sensor->ctrls.error)1347 if (sensor->ctrls.error)
1318 goto handler_free;1348 goto handler_free;
1319 1349
drivers/media/i2c/ov5670.c+79−37
@@ -29,6 +29,12 @@ · 28 unmodified lines
29#define OV5670_REG_SOFTWARE_RST 0x010329#define OV5670_REG_SOFTWARE_RST 0x0103
30#define OV5670_SOFTWARE_RST 0x0130#define OV5670_SOFTWARE_RST 0x01
31 31
32#define OV5670_MIPI_SC_CTRL0_REG 0x3018
33#define OV5670_MIPI_SC_CTRL0_LANES(v) ((((v) - 1) << 5) & \
34 GENMASK(7, 5))
35#define OV5670_MIPI_SC_CTRL0_MIPI_EN BIT(4)
36#define OV5670_MIPI_SC_CTRL0_RESERVED BIT(1)
37
32/* vertical-timings from sensor */38/* vertical-timings from sensor */
33#define OV5670_REG_VTS 0x380e39#define OV5670_REG_VTS 0x380e
34#define OV5670_VTS_30FPS 0x0808 /* default for 30 fps */40#define OV5670_VTS_30FPS 0x0808 /* default for 30 fps */
@@ -92,7 +98,6 @@ struct ov5670_reg_list { · 57 unmodified lines
92};98};
93 99
94struct ov5670_link_freq_config {100struct ov5670_link_freq_config {
95 u32 pixel_rate;
96 const struct ov5670_reg_list reg_list;101 const struct ov5670_reg_list reg_list;
97};102};
98 103
@@ -163,7 +168,6 @@ static const struct ov5670_reg mode_2592x1944_regs[] = { · 64 unmodified lines
163 {0x3005, 0xf0},168 {0x3005, 0xf0},
164 {0x3007, 0x00},169 {0x3007, 0x00},
165 {0x3015, 0x0f},170 {0x3015, 0x0f},
166 {0x3018, 0x32},
167 {0x301a, 0xf0},171 {0x301a, 0xf0},
168 {0x301b, 0xf0},172 {0x301b, 0xf0},
169 {0x301c, 0xf0},173 {0x301c, 0xf0},
@@ -429,7 +433,6 @@ static const struct ov5670_reg mode_1296x972_regs[] = { · 259 unmodified lines
429 {0x3005, 0xf0},433 {0x3005, 0xf0},
430 {0x3007, 0x00},434 {0x3007, 0x00},
431 {0x3015, 0x0f},435 {0x3015, 0x0f},
432 {0x3018, 0x32},
433 {0x301a, 0xf0},436 {0x301a, 0xf0},
434 {0x301b, 0xf0},437 {0x301b, 0xf0},
435 {0x301c, 0xf0},438 {0x301c, 0xf0},
@@ -695,7 +698,6 @@ static const struct ov5670_reg mode_648x486_regs[] = { · 259 unmodified lines
695 {0x3005, 0xf0},698 {0x3005, 0xf0},
696 {0x3007, 0x00},699 {0x3007, 0x00},
697 {0x3015, 0x0f},700 {0x3015, 0x0f},
698 {0x3018, 0x32},
699 {0x301a, 0xf0},701 {0x301a, 0xf0},
700 {0x301b, 0xf0},702 {0x301b, 0xf0},
701 {0x301c, 0xf0},703 {0x301c, 0xf0},
@@ -961,7 +963,6 @@ static const struct ov5670_reg mode_2560x1440_regs[] = { · 259 unmodified lines
961 {0x3005, 0xf0},963 {0x3005, 0xf0},
962 {0x3007, 0x00},964 {0x3007, 0x00},
963 {0x3015, 0x0f},965 {0x3015, 0x0f},
964 {0x3018, 0x32},
965 {0x301a, 0xf0},966 {0x301a, 0xf0},
966 {0x301b, 0xf0},967 {0x301b, 0xf0},
967 {0x301c, 0xf0},968 {0x301c, 0xf0},
@@ -1226,7 +1227,6 @@ static const struct ov5670_reg mode_1280x720_regs[] = { · 258 unmodified lines
1226 {0x3005, 0xf0},1227 {0x3005, 0xf0},
1227 {0x3007, 0x00},1228 {0x3007, 0x00},
1228 {0x3015, 0x0f},1229 {0x3015, 0x0f},
1229 {0x3018, 0x32},
1230 {0x301a, 0xf0},1230 {0x301a, 0xf0},
1231 {0x301b, 0xf0},1231 {0x301b, 0xf0},
1232 {0x301c, 0xf0},1232 {0x301c, 0xf0},
@@ -1492,7 +1492,6 @@ static const struct ov5670_reg mode_640x360_regs[] = { · 259 unmodified lines
1492 {0x3005, 0xf0},1492 {0x3005, 0xf0},
1493 {0x3007, 0x00},1493 {0x3007, 0x00},
1494 {0x3015, 0x0f},1494 {0x3015, 0x0f},
1495 {0x3018, 0x32},
1496 {0x301a, 0xf0},1495 {0x301a, 0xf0},
1497 {0x301b, 0xf0},1496 {0x301b, 0xf0},
1498 {0x301c, 0xf0},1497 {0x301c, 0xf0},
@@ -1762,8 +1761,6 @@ static const char * const ov5670_test_pattern_menu[] = { · 263 unmodified lines
1762#define OV5670_LINK_FREQ_422MHZ_INDEX 01761#define OV5670_LINK_FREQ_422MHZ_INDEX 0
1763static const struct ov5670_link_freq_config link_freq_configs[] = {1762static const struct ov5670_link_freq_config link_freq_configs[] = {
1764 {1763 {
1765 /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
1766 .pixel_rate = (OV5670_LINK_FREQ_422MHZ * 2 * 2) / 10,
1767 .reg_list = {1764 .reg_list = {
1768 .num_of_regs = ARRAY_SIZE(mipi_data_rate_840mbps),1765 .num_of_regs = ARRAY_SIZE(mipi_data_rate_840mbps),
1769 .regs = mipi_data_rate_840mbps,1766 .regs = mipi_data_rate_840mbps,
@@ -1859,6 +1856,7 @@ static const struct ov5670_mode supported_modes[] = { · 89 unmodified lines
1859struct ov5670 {1856struct ov5670 {
1860 struct v4l2_subdev sd;1857 struct v4l2_subdev sd;
1861 struct media_pad pad;1858 struct media_pad pad;
1859 struct v4l2_fwnode_endpoint endpoint;
1862 1860
1863 struct v4l2_ctrl_handler ctrl_handler;1861 struct v4l2_ctrl_handler ctrl_handler;
1864 /* V4L2 Controls */1862 /* V4L2 Controls */
@@ -2101,9 +2099,13 @@ static const struct v4l2_ctrl_ops ov5670_ctrl_ops = { · 236 unmodified lines
2101/* Initialize control handlers */2099/* Initialize control handlers */
2102static int ov5670_init_controls(struct ov5670 *ov5670)2100static int ov5670_init_controls(struct ov5670 *ov5670)
2103{2101{
2102 struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 =
2103 &ov5670->endpoint.bus.mipi_csi2;
2104 struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd);2104 struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd);
2105 struct v4l2_fwnode_device_properties props;2105 struct v4l2_fwnode_device_properties props;
2106 struct v4l2_ctrl_handler *ctrl_hdlr;2106 struct v4l2_ctrl_handler *ctrl_hdlr;
2107 unsigned int lanes_count;
2108 s64 mipi_pixel_rate;
2107 s64 vblank_max;2109 s64 vblank_max;
2108 s64 vblank_def;2110 s64 vblank_def;
2109 s64 vblank_min;2111 s64 vblank_min;
@@ -2124,12 +2126,15 @@ static int ov5670_init_controls(struct ov5670 *ov5670) · 14 unmodified lines
2124 ov5670->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;2126 ov5670->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2125 2127
2126 /* By default, V4L2_CID_PIXEL_RATE is read only */2128 /* By default, V4L2_CID_PIXEL_RATE is read only */
2129 lanes_count = bus_mipi_csi2->num_data_lanes;
2130 mipi_pixel_rate = OV5670_LINK_FREQ_422MHZ * 2 * lanes_count / 10;
2131
2127 ov5670->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5670_ctrl_ops,2132 ov5670->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5670_ctrl_ops,
2128 V4L2_CID_PIXEL_RATE,2133 V4L2_CID_PIXEL_RATE,
2129 link_freq_configs[0].pixel_rate,2134 mipi_pixel_rate,
2130 link_freq_configs[0].pixel_rate,2135 mipi_pixel_rate,
2131 1,2136 1,
2132 link_freq_configs[0].pixel_rate);2137 mipi_pixel_rate);
2133 2138
2134 vblank_max = OV5670_VTS_MAX - ov5670->cur_mode->height;2139 vblank_max = OV5670_VTS_MAX - ov5670->cur_mode->height;
2135 vblank_def = ov5670->cur_mode->vts_def - ov5670->cur_mode->height;2140 vblank_def = ov5670->cur_mode->vts_def - ov5670->cur_mode->height;
@@ -2288,8 +2293,13 @@ static int ov5670_set_pad_format(struct v4l2_subdev *sd, · 152 unmodified lines
2288 struct v4l2_subdev_format *fmt)2293 struct v4l2_subdev_format *fmt)
2289{2294{
2290 struct ov5670 *ov5670 = to_ov5670(sd);2295 struct ov5670 *ov5670 = to_ov5670(sd);
2296 struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 =
2297 &ov5670->endpoint.bus.mipi_csi2;
2291 const struct ov5670_mode *mode;2298 const struct ov5670_mode *mode;
2299 unsigned int lanes_count;
2300 s64 mipi_pixel_rate;
2292 s32 vblank_def;2301 s32 vblank_def;
2302 s64 link_freq;
2293 s32 h_blank;2303 s32 h_blank;
2294 2304
2295 mutex_lock(&ov5670->mutex);2305 mutex_lock(&ov5670->mutex);
@@ -2306,9 +2316,14 @@ static int ov5670_set_pad_format(struct v4l2_subdev *sd, · 10 unmodified lines
2306 } else {2316 } else {
2307 ov5670->cur_mode = mode;2317 ov5670->cur_mode = mode;
2308 __v4l2_ctrl_s_ctrl(ov5670->link_freq, mode->link_freq_index);2318 __v4l2_ctrl_s_ctrl(ov5670->link_freq, mode->link_freq_index);
2319
2320 lanes_count = bus_mipi_csi2->num_data_lanes;
2321 link_freq = link_freq_menu_items[mode->link_freq_index];
2322 /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
2323 mipi_pixel_rate = div_s64(link_freq * 2 * lanes_count, 10);
2309 __v4l2_ctrl_s_ctrl_int64(2324 __v4l2_ctrl_s_ctrl_int64(
2310 ov5670->pixel_rate,2325 ov5670->pixel_rate,
2311 link_freq_configs[mode->link_freq_index].pixel_rate);2326 mipi_pixel_rate);
2312 /* Update limits and set FPS to default */2327 /* Update limits and set FPS to default */
2313 vblank_def = ov5670->cur_mode->vts_def -2328 vblank_def = ov5670->cur_mode->vts_def -
2314 ov5670->cur_mode->height;2329 ov5670->cur_mode->height;
@@ -2361,6 +2376,19 @@ static int ov5670_identify_module(struct ov5670 *ov5670) · 46 unmodified lines
2361 return 0;2376 return 0;
2362}2377}
2363 2378
2379static int ov5670_mipi_configure(struct ov5670 *ov5670)
2380{
2381 struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 =
2382 &ov5670->endpoint.bus.mipi_csi2;
2383 unsigned int lanes_count = bus_mipi_csi2->num_data_lanes;
2384
2385 return ov5670_write_reg(ov5670, OV5670_MIPI_SC_CTRL0_REG,
2386 OV5670_REG_VALUE_08BIT,
2387 OV5670_MIPI_SC_CTRL0_LANES(lanes_count) |
2388 OV5670_MIPI_SC_CTRL0_MIPI_EN |
2389 OV5670_MIPI_SC_CTRL0_RESERVED);
2390}
2391
2364/* Prepare streaming by writing default values and customized values */2392/* Prepare streaming by writing default values and customized values */
2365static int ov5670_start_streaming(struct ov5670 *ov5670)2393static int ov5670_start_streaming(struct ov5670 *ov5670)
2366{2394{
@@ -2399,6 +2427,12 @@ static int ov5670_start_streaming(struct ov5670 *ov5670) · 32 unmodified lines
2399 return ret;2427 return ret;
2400 }2428 }
2401 2429
2430 ret = ov5670_mipi_configure(ov5670);
2431 if (ret) {
2432 dev_err(&client->dev, "%s failed to configure MIPI\n", __func__);
2433 return ret;
2434 }
2435
2402 ret = __v4l2_ctrl_handler_setup(ov5670->sd.ctrl_handler);2436 ret = __v4l2_ctrl_handler_setup(ov5670->sd.ctrl_handler);
2403 if (ret)2437 if (ret)
2404 return ret;2438 return ret;
@@ -2647,23 +2681,20 @@ static int ov5670_gpio_probe(struct ov5670 *ov5670) · 242 unmodified lines
2647 2681
2648static int ov5670_probe(struct i2c_client *client)2682static int ov5670_probe(struct i2c_client *client)
2649{2683{
2684 struct fwnode_handle *handle;
2650 struct ov5670 *ov5670;2685 struct ov5670 *ov5670;
2651 const char *err_msg;
2652 u32 input_clk = 0;2686 u32 input_clk = 0;
2653 bool full_power;2687 bool full_power;
2654 int ret;2688 int ret;
2655 2689
2656 ov5670 = devm_kzalloc(&client->dev, sizeof(*ov5670), GFP_KERNEL);2690 ov5670 = devm_kzalloc(&client->dev, sizeof(*ov5670), GFP_KERNEL);
2657 if (!ov5670) {2691 if (!ov5670)
2658 ret = -ENOMEM;2692 return -ENOMEM;
2659 err_msg = "devm_kzalloc() error";
2660 goto error_print;
2661 }
2662 2693
2663 ov5670->xvclk = devm_clk_get(&client->dev, NULL);2694 ov5670->xvclk = devm_clk_get_optional(&client->dev, NULL);
2664 if (!IS_ERR_OR_NULL(ov5670->xvclk))2695 if (!IS_ERR_OR_NULL(ov5670->xvclk))
2665 input_clk = clk_get_rate(ov5670->xvclk);2696 input_clk = clk_get_rate(ov5670->xvclk);
2666 else if (PTR_ERR(ov5670->xvclk) == -ENOENT)2697 else if (!ov5670->xvclk || PTR_ERR(ov5670->xvclk) == -ENOENT)
2667 device_property_read_u32(&client->dev, "clock-frequency",2698 device_property_read_u32(&client->dev, "clock-frequency",
2668 &input_clk);2699 &input_clk);
2669 else2700 else
@@ -2680,29 +2711,38 @@ static int ov5670_probe(struct i2c_client *client) · 10 unmodified lines
2680 v4l2_i2c_subdev_init(&ov5670->sd, client, &ov5670_subdev_ops);2711 v4l2_i2c_subdev_init(&ov5670->sd, client, &ov5670_subdev_ops);
2681 2712
2682 ret = ov5670_regulators_probe(ov5670);2713 ret = ov5670_regulators_probe(ov5670);
2683 if (ret) {2714 if (ret)
2684 err_msg = "Regulators probe failed";2715 return dev_err_probe(&client->dev, ret, "Regulators probe failed\n");
2685 goto error_print;
2686 }
2687 2716
2688 ret = ov5670_gpio_probe(ov5670);2717 ret = ov5670_gpio_probe(ov5670);
2689 if (ret) {2718 if (ret)
2690 err_msg = "GPIO probe failed";2719 return dev_err_probe(&client->dev, ret, "GPIO probe failed\n");
2691 goto error_print;2720
2692 }2721 /* Graph Endpoint */
2722 handle = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
2723 if (!handle)
2724 return dev_err_probe(&client->dev, -ENXIO, "Endpoint for node get failed\n");
2725
2726 ov5670->endpoint.bus_type = V4L2_MBUS_CSI2_DPHY;
2727 ov5670->endpoint.bus.mipi_csi2.num_data_lanes = 2;
2728
2729 ret = v4l2_fwnode_endpoint_alloc_parse(handle, &ov5670->endpoint);
2730 fwnode_handle_put(handle);
2731 if (ret)
2732 return dev_err_probe(&client->dev, ret, "Endpoint parse failed\n");
2693 2733
2694 full_power = acpi_dev_state_d0(&client->dev);2734 full_power = acpi_dev_state_d0(&client->dev);
2695 if (full_power) {2735 if (full_power) {
2696 ret = ov5670_runtime_resume(&client->dev);2736 ret = ov5670_runtime_resume(&client->dev);
2697 if (ret) {2737 if (ret) {
2698 err_msg = "Power up failed";2738 dev_err_probe(&client->dev, ret, "Power up failed\n");
2699 goto error_print;2739 goto error_endpoint;
2700 }2740 }
2701 2741
2702 /* Check module identity */2742 /* Check module identity */
2703 ret = ov5670_identify_module(ov5670);2743 ret = ov5670_identify_module(ov5670);
2704 if (ret) {2744 if (ret) {
2705 err_msg = "ov5670_identify_module() error";2745 dev_err_probe(&client->dev, ret, "ov5670_identify_module() error\n");
2706 goto error_power_off;2746 goto error_power_off;
2707 }2747 }
2708 }2748 }
@@ -2714,7 +2754,7 @@ static int ov5670_probe(struct i2c_client *client) · 5 unmodified lines
2714 2754
2715 ret = ov5670_init_controls(ov5670);2755 ret = ov5670_init_controls(ov5670);
2716 if (ret) {2756 if (ret) {
2717 err_msg = "ov5670_init_controls() error";2757 dev_err_probe(&client->dev, ret, "ov5670_init_controls() error\n");
2718 goto error_mutex_destroy;2758 goto error_mutex_destroy;
2719 }2759 }
2720 2760
@@ -2727,7 +2767,7 @@ static int ov5670_probe(struct i2c_client *client) · 6 unmodified lines
2727 ov5670->pad.flags = MEDIA_PAD_FL_SOURCE;2767 ov5670->pad.flags = MEDIA_PAD_FL_SOURCE;
2728 ret = media_entity_pads_init(&ov5670->sd.entity, 1, &ov5670->pad);2768 ret = media_entity_pads_init(&ov5670->sd.entity, 1, &ov5670->pad);
2729 if (ret) {2769 if (ret) {
2730 err_msg = "media_entity_pads_init() error";2770 dev_err_probe(&client->dev, ret, "media_entity_pads_init() error\n");
2731 goto error_handler_free;2771 goto error_handler_free;
2732 }2772 }
2733 2773
@@ -2741,7 +2781,7 @@ static int ov5670_probe(struct i2c_client *client) · 7 unmodified lines
2741 /* Async register for subdev */2781 /* Async register for subdev */
2742 ret = v4l2_async_register_subdev_sensor(&ov5670->sd);2782 ret = v4l2_async_register_subdev_sensor(&ov5670->sd);
2743 if (ret < 0) {2783 if (ret < 0) {
2744 err_msg = "v4l2_async_register_subdev() error";2784 dev_err_probe(&client->dev, ret, "v4l2_async_register_subdev() error\n");
2745 goto error_pm_disable;2785 goto error_pm_disable;
2746 }2786 }
2747 2787
@@ -2764,8 +2804,8 @@ error_power_off: · 16 unmodified lines
2764 if (full_power)2804 if (full_power)
2765 ov5670_runtime_suspend(&client->dev);2805 ov5670_runtime_suspend(&client->dev);
2766 2806
2767error_print:2807error_endpoint:
2768 dev_err(&client->dev, "%s: %s %d\n", __func__, err_msg, ret);2808 v4l2_fwnode_endpoint_free(&ov5670->endpoint);
2769 2809
2770 return ret;2810 return ret;
2771}2811}
@@ -2782,6 +2822,8 @@ static void ov5670_remove(struct i2c_client *client) · 10 unmodified lines
2782 2822
2783 pm_runtime_disable(&client->dev);2823 pm_runtime_disable(&client->dev);
2784 ov5670_runtime_suspend(&client->dev);2824 ov5670_runtime_suspend(&client->dev);
2825
2826 v4l2_fwnode_endpoint_free(&ov5670->endpoint);
2785}2827}
2786 2828
2787static const struct dev_pm_ops ov5670_pm_ops = {2829static const struct dev_pm_ops ov5670_pm_ops = {
drivers/media/i2c/ov7670.c+3−8
@@ -1894,14 +1894,9 @@ static int ov7670_probe(struct i2c_client *client) · 1893 unmodified lines
1894 info->pclk_hb_disable = true;1894 info->pclk_hb_disable = true;
1895 }1895 }
1896 1896
1897 info->clk = devm_clk_get(&client->dev, "xclk"); /* optional */1897 info->clk = devm_clk_get_optional(&client->dev, "xclk");
1898 if (IS_ERR(info->clk)) {1898 if (IS_ERR(info->clk))
1899 ret = PTR_ERR(info->clk);1899 return PTR_ERR(info->clk);
1900 if (ret == -ENOENT)
1901 info->clk = NULL;
1902 else
1903 return ret;
1904 }
1905 1900
1906 ret = ov7670_init_gpio(client, info);1901 ret = ov7670_init_gpio(client, info);
1907 if (ret)1902 if (ret)
drivers/media/i2c/ov8856.c+0−40
@@ -1709,46 +1709,6 @@ static int ov8856_identify_module(struct ov8856 *ov8856) · 1708 unmodified lines
1709 return -ENXIO;1709 return -ENXIO;
1710 }1710 }
1711 1711
1712 ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
1713 OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING);
1714 if (ret)
1715 return ret;
1716
1717 ret = ov8856_write_reg(ov8856, OV8856_OTP_MODE_CTRL,
1718 OV8856_REG_VALUE_08BIT, OV8856_OTP_MODE_AUTO);
1719 if (ret) {
1720 dev_err(&client->dev, "failed to set otp mode");
1721 return ret;
1722 }
1723
1724 ret = ov8856_write_reg(ov8856, OV8856_OTP_LOAD_CTRL,
1725 OV8856_REG_VALUE_08BIT,
1726 OV8856_OTP_LOAD_CTRL_ENABLE);
1727 if (ret) {
1728 dev_err(&client->dev, "failed to enable load control");
1729 return ret;
1730 }
1731
1732 ret = ov8856_read_reg(ov8856, OV8856_MODULE_REVISION,
1733 OV8856_REG_VALUE_08BIT, &val);
1734 if (ret) {
1735 dev_err(&client->dev, "failed to read module revision");
1736 return ret;
1737 }
1738
1739 dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n",
1740 val,
1741 val == OV8856_2A_MODULE ? "2A" :
1742 val == OV8856_1B_MODULE ? "1B" : "unknown revision",
1743 client->addr);
1744
1745 ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
1746 OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY);
1747 if (ret) {
1748 dev_err(&client->dev, "failed to exit streaming mode");
1749 return ret;
1750 }
1751
1752 ov8856->identified = true;1712 ov8856->identified = true;
1753 1713
1754 return 0;1714 return 0;
drivers/media/i2c/s5k6aa.c+0−1652
@@ -1,1652 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Driver for Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor
4 * with embedded SoC ISP.
5 *
6 * Copyright (C) 2011, Samsung Electronics Co., Ltd.
7 * Sylwester Nawrocki <s.nawrocki@samsung.com>
8 *
9 * Based on a driver authored by Dongsoo Nathaniel Kim.
10 * Copyright (C) 2009, Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
11 */
12
13#include <linux/clk.h>
14#include <linux/delay.h>
15#include <linux/gpio.h>
16#include <linux/i2c.h>
17#include <linux/media.h>
18#include <linux/module.h>
19#include <linux/regulator/consumer.h>
20#include <linux/slab.h>
21
22#include <media/media-entity.h>
23#include <media/v4l2-ctrls.h>
24#include <media/v4l2-device.h>
25#include <media/v4l2-subdev.h>
26#include <media/v4l2-mediabus.h>
27#include <media/i2c/s5k6aa.h>
28
29static int debug;
30module_param(debug, int, 0644);
31
32#define DRIVER_NAME "S5K6AA"
33
34/* The token to indicate array termination */
35#define S5K6AA_TERM 0xffff
36#define S5K6AA_OUT_WIDTH_DEF 640
37#define S5K6AA_OUT_HEIGHT_DEF 480
38#define S5K6AA_WIN_WIDTH_MAX 1280
39#define S5K6AA_WIN_HEIGHT_MAX 1024
40#define S5K6AA_WIN_WIDTH_MIN 8
41#define S5K6AA_WIN_HEIGHT_MIN 8
42
43/*
44 * H/W register Interface (0xD0000000 - 0xD0000FFF)
45 */
46#define AHB_MSB_ADDR_PTR 0xfcfc
47#define GEN_REG_OFFSH 0xd000
48#define REG_CMDWR_ADDRH 0x0028
49#define REG_CMDWR_ADDRL 0x002a
50#define REG_CMDRD_ADDRH 0x002c
51#define REG_CMDRD_ADDRL 0x002e
52#define REG_CMDBUF0_ADDR 0x0f12
53#define REG_CMDBUF1_ADDR 0x0f10
54
55/*
56 * Host S/W Register interface (0x70000000 - 0x70002000)
57 * The value of the two most significant address bytes is 0x7000,
58 * (HOST_SWIF_OFFS_H). The register addresses below specify 2 LSBs.
59 */
60#define HOST_SWIF_OFFSH 0x7000
61
62/* Initialization parameters */
63/* Master clock frequency in KHz */
64#define REG_I_INCLK_FREQ_L 0x01b8
65#define REG_I_INCLK_FREQ_H 0x01ba
66#define MIN_MCLK_FREQ_KHZ 6000U
67#define MAX_MCLK_FREQ_KHZ 27000U
68#define REG_I_USE_NPVI_CLOCKS 0x01c6
69#define REG_I_USE_NMIPI_CLOCKS 0x01c8
70
71/* Clock configurations, n = 0..2. REG_I_* frequency unit is 4 kHz. */
72#define REG_I_OPCLK_4KHZ(n) ((n) * 6 + 0x01cc)
73#define REG_I_MIN_OUTRATE_4KHZ(n) ((n) * 6 + 0x01ce)
74#define REG_I_MAX_OUTRATE_4KHZ(n) ((n) * 6 + 0x01d0)
75#define SYS_PLL_OUT_FREQ (48000000 / 4000)
76#define PCLK_FREQ_MIN (24000000 / 4000)
77#define PCLK_FREQ_MAX (48000000 / 4000)
78#define REG_I_INIT_PARAMS_UPDATED 0x01e0
79#define REG_I_ERROR_INFO 0x01e2
80
81/* General purpose parameters */
82#define REG_USER_BRIGHTNESS 0x01e4
83#define REG_USER_CONTRAST 0x01e6
84#define REG_USER_SATURATION 0x01e8
85#define REG_USER_SHARPBLUR 0x01ea
86
87#define REG_G_SPEC_EFFECTS 0x01ee
88#define REG_G_ENABLE_PREV 0x01f0
89#define REG_G_ENABLE_PREV_CHG 0x01f2
90#define REG_G_NEW_CFG_SYNC 0x01f8
91#define REG_G_PREVZOOM_IN_WIDTH 0x020a
92#define REG_G_PREVZOOM_IN_HEIGHT 0x020c
93#define REG_G_PREVZOOM_IN_XOFFS 0x020e
94#define REG_G_PREVZOOM_IN_YOFFS 0x0210
95#define REG_G_INPUTS_CHANGE_REQ 0x021a
96#define REG_G_ACTIVE_PREV_CFG 0x021c
97#define REG_G_PREV_CFG_CHG 0x021e
98#define REG_G_PREV_OPEN_AFTER_CH 0x0220
99#define REG_G_PREV_CFG_ERROR 0x0222
100
101/* Preview control section. n = 0...4. */
102#define PREG(n, x) ((n) * 0x26 + x)
103#define REG_P_OUT_WIDTH(n) PREG(n, 0x0242)
104#define REG_P_OUT_HEIGHT(n) PREG(n, 0x0244)
105#define REG_P_FMT(n) PREG(n, 0x0246)
106#define REG_P_MAX_OUT_RATE(n) PREG(n, 0x0248)
107#define REG_P_MIN_OUT_RATE(n) PREG(n, 0x024a)
108#define REG_P_PVI_MASK(n) PREG(n, 0x024c)
109#define REG_P_CLK_INDEX(n) PREG(n, 0x024e)
110#define REG_P_FR_RATE_TYPE(n) PREG(n, 0x0250)
111#define FR_RATE_DYNAMIC 0
112#define FR_RATE_FIXED 1
113#define FR_RATE_FIXED_ACCURATE 2
114#define REG_P_FR_RATE_Q_TYPE(n) PREG(n, 0x0252)
115#define FR_RATE_Q_BEST_FRRATE 1 /* Binning enabled */
116#define FR_RATE_Q_BEST_QUALITY 2 /* Binning disabled */
117/* Frame period in 0.1 ms units */
118#define REG_P_MAX_FR_TIME(n) PREG(n, 0x0254)
119#define REG_P_MIN_FR_TIME(n) PREG(n, 0x0256)
120/* Conversion to REG_P_[MAX/MIN]_FR_TIME value; __t: time in us */
121#define US_TO_FR_TIME(__t) ((__t) / 100)
122#define S5K6AA_MIN_FR_TIME 33300 /* us */
123#define S5K6AA_MAX_FR_TIME 650000 /* us */
124#define S5K6AA_MAX_HIGHRES_FR_TIME 666 /* x100 us */
125/* The below 5 registers are for "device correction" values */
126#define REG_P_COLORTEMP(n) PREG(n, 0x025e)
127#define REG_P_PREV_MIRROR(n) PREG(n, 0x0262)
128
129/* Extended image property controls */
130/* Exposure time in 10 us units */
131#define REG_SF_USR_EXPOSURE_L 0x03c6
132#define REG_SF_USR_EXPOSURE_H 0x03c8
133#define REG_SF_USR_EXPOSURE_CHG 0x03ca
134#define REG_SF_USR_TOT_GAIN 0x03cc
135#define REG_SF_USR_TOT_GAIN_CHG 0x03ce
136#define REG_SF_RGAIN 0x03d0
137#define REG_SF_RGAIN_CHG 0x03d2
138#define REG_SF_GGAIN 0x03d4
139#define REG_SF_GGAIN_CHG 0x03d6
140#define REG_SF_BGAIN 0x03d8
141#define REG_SF_BGAIN_CHG 0x03da
142#define REG_SF_FLICKER_QUANT 0x03dc
143#define REG_SF_FLICKER_QUANT_CHG 0x03de
144
145/* Output interface (parallel/MIPI) setup */
146#define REG_OIF_EN_MIPI_LANES 0x03fa
147#define REG_OIF_EN_PACKETS 0x03fc
148#define REG_OIF_CFG_CHG 0x03fe
149
150/* Auto-algorithms enable mask */
151#define REG_DBG_AUTOALG_EN 0x0400
152#define AALG_ALL_EN_MASK (1 << 0)
153#define AALG_AE_EN_MASK (1 << 1)
154#define AALG_DIVLEI_EN_MASK (1 << 2)
155#define AALG_WB_EN_MASK (1 << 3)
156#define AALG_FLICKER_EN_MASK (1 << 5)
157#define AALG_FIT_EN_MASK (1 << 6)
158#define AALG_WRHW_EN_MASK (1 << 7)
159
160/* Firmware revision information */
161#define REG_FW_APIVER 0x012e
162#define S5K6AAFX_FW_APIVER 0x0001
163#define REG_FW_REVISION 0x0130
164
165/* For now we use only one user configuration register set */
166#define S5K6AA_MAX_PRESETS 1
167
168static const char * const s5k6aa_supply_names[] = {
169 "vdd_core", /* Digital core supply 1.5V (1.4V to 1.6V) */
170 "vdda", /* Analog power supply 2.8V (2.6V to 3.0V) */
171 "vdd_reg", /* Regulator input power 1.8V (1.7V to 1.9V)
172 or 2.8V (2.6V to 3.0) */
173 "vddio", /* I/O supply 1.8V (1.65V to 1.95V)
174 or 2.8V (2.5V to 3.1V) */
175};
176#define S5K6AA_NUM_SUPPLIES ARRAY_SIZE(s5k6aa_supply_names)
177
178enum s5k6aa_gpio_id {
179 STBY,
180 RSET,
181 GPIO_NUM,
182};
183
184struct s5k6aa_regval {
185 u16 addr;
186 u16 val;
187};
188
189struct s5k6aa_pixfmt {
190 u32 code;
191 u32 colorspace;
192 /* REG_P_FMT(x) register value */
193 u16 reg_p_fmt;
194};
195
196struct s5k6aa_preset {
197 /* output pixel format and resolution */
198 struct v4l2_mbus_framefmt mbus_fmt;
199 u8 clk_id;
200 u8 index;
201};
202
203struct s5k6aa_ctrls {
204 struct v4l2_ctrl_handler handler;
205 /* Auto / manual white balance cluster */
206 struct v4l2_ctrl *awb;
207 struct v4l2_ctrl *gain_red;
208 struct v4l2_ctrl *gain_blue;
209 struct v4l2_ctrl *gain_green;
210 /* Mirror cluster */
211 struct v4l2_ctrl *hflip;
212 struct v4l2_ctrl *vflip;
213 /* Auto exposure / manual exposure and gain cluster */
214 struct v4l2_ctrl *auto_exp;
215 struct v4l2_ctrl *exposure;
216 struct v4l2_ctrl *gain;
217};
218
219struct s5k6aa_interval {
220 u16 reg_fr_time;
221 struct v4l2_fract interval;
222 /* Maximum rectangle for the interval */
223 struct v4l2_frmsize_discrete size;
224};
225
226struct s5k6aa {
227 struct v4l2_subdev sd;
228 struct media_pad pad;
229
230 enum v4l2_mbus_type bus_type;
231 u8 mipi_lanes;
232
233 int (*s_power)(int enable);
234 struct regulator_bulk_data supplies[S5K6AA_NUM_SUPPLIES];
235 struct s5k6aa_gpio gpio[GPIO_NUM];
236
237 /* external master clock frequency */
238 unsigned long mclk_frequency;
239 /* ISP internal master clock frequency */
240 u16 clk_fop;
241 /* output pixel clock frequency range */
242 u16 pclk_fmin;
243 u16 pclk_fmax;
244
245 unsigned int inv_hflip:1;
246 unsigned int inv_vflip:1;
247
248 /* protects the struct members below */
249 struct mutex lock;
250
251 /* sensor matrix scan window */
252 struct v4l2_rect ccd_rect;
253
254 struct s5k6aa_ctrls ctrls;
255 struct s5k6aa_preset presets[S5K6AA_MAX_PRESETS];
256 struct s5k6aa_preset *preset;
257 const struct s5k6aa_interval *fiv;
258
259 unsigned int streaming:1;
260 unsigned int apply_cfg:1;
261 unsigned int apply_crop:1;
262 unsigned int power;
263};
264
265static struct s5k6aa_regval s5k6aa_analog_config[] = {
266 /* Analog settings */
267 { 0x112a, 0x0000 }, { 0x1132, 0x0000 },
268 { 0x113e, 0x0000 }, { 0x115c, 0x0000 },
269 { 0x1164, 0x0000 }, { 0x1174, 0x0000 },
270 { 0x1178, 0x0000 }, { 0x077a, 0x0000 },
271 { 0x077c, 0x0000 }, { 0x077e, 0x0000 },
272 { 0x0780, 0x0000 }, { 0x0782, 0x0000 },
273 { 0x0784, 0x0000 }, { 0x0786, 0x0000 },
274 { 0x0788, 0x0000 }, { 0x07a2, 0x0000 },
275 { 0x07a4, 0x0000 }, { 0x07a6, 0x0000 },
276 { 0x07a8, 0x0000 }, { 0x07b6, 0x0000 },
277 { 0x07b8, 0x0002 }, { 0x07ba, 0x0004 },
278 { 0x07bc, 0x0004 }, { 0x07be, 0x0005 },
279 { 0x07c0, 0x0005 }, { S5K6AA_TERM, 0 },
280};
281
282/* TODO: Add RGB888 and Bayer format */
283static const struct s5k6aa_pixfmt s5k6aa_formats[] = {
284 { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
285 /* range 16-240 */
286 { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_REC709, 6 },
287 { MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_JPEG, 0 },
288};
289
290static const struct s5k6aa_interval s5k6aa_intervals[] = {
291 { 1000, {10000, 1000000}, {1280, 1024} }, /* 10 fps */
292 { 666, {15000, 1000000}, {1280, 1024} }, /* 15 fps */
293 { 500, {20000, 1000000}, {1280, 720} }, /* 20 fps */
294 { 400, {25000, 1000000}, {640, 480} }, /* 25 fps */
295 { 333, {33300, 1000000}, {640, 480} }, /* 30 fps */
296};
297
298#define S5K6AA_INTERVAL_DEF_INDEX 1 /* 15 fps */
299
300static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
301{
302 return &container_of(ctrl->handler, struct s5k6aa, ctrls.handler)->sd;
303}
304
305static inline struct s5k6aa *to_s5k6aa(struct v4l2_subdev *sd)
306{
307 return container_of(sd, struct s5k6aa, sd);
308}
309
310/* Set initial values for all preview presets */
311static void s5k6aa_presets_data_init(struct s5k6aa *s5k6aa)
312{
313 struct s5k6aa_preset *preset = &s5k6aa->presets[0];
314 int i;
315
316 for (i = 0; i < S5K6AA_MAX_PRESETS; i++) {
317 preset->mbus_fmt.width = S5K6AA_OUT_WIDTH_DEF;
318 preset->mbus_fmt.height = S5K6AA_OUT_HEIGHT_DEF;
319 preset->mbus_fmt.code = s5k6aa_formats[0].code;
320 preset->index = i;
321 preset->clk_id = 0;
322 preset++;
323 }
324
325 s5k6aa->fiv = &s5k6aa_intervals[S5K6AA_INTERVAL_DEF_INDEX];
326 s5k6aa->preset = &s5k6aa->presets[0];
327}
328
329static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
330{
331 u8 wbuf[2] = {addr >> 8, addr & 0xFF};
332 struct i2c_msg msg[2];
333 u8 rbuf[2];
334 int ret;
335
336 msg[0].addr = client->addr;
337 msg[0].flags = 0;
338 msg[0].len = 2;
339 msg[0].buf = wbuf;
340
341 msg[1].addr = client->addr;
342 msg[1].flags = I2C_M_RD;
343 msg[1].len = 2;
344 msg[1].buf = rbuf;
345
346 ret = i2c_transfer(client->adapter, msg, 2);
347 *val = be16_to_cpu(*((__be16 *)rbuf));
348
349 v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
350
351 return ret == 2 ? 0 : ret;
352}
353
354static int s5k6aa_i2c_write(struct i2c_client *client, u16 addr, u16 val)
355{
356 u8 buf[4] = {addr >> 8, addr & 0xFF, val >> 8, val & 0xFF};
357
358 int ret = i2c_master_send(client, buf, 4);
359 v4l2_dbg(3, debug, client, "i2c_write: 0x%04X : 0x%04x\n", addr, val);
360
361 return ret == 4 ? 0 : ret;
362}
363
364/* The command register write, assumes Command_Wr_addH = 0x7000. */
365static int s5k6aa_write(struct i2c_client *c, u16 addr, u16 val)
366{
367 int ret = s5k6aa_i2c_write(c, REG_CMDWR_ADDRL, addr);
368 if (ret)
369 return ret;
370 return s5k6aa_i2c_write(c, REG_CMDBUF0_ADDR, val);
371}
372
373/* The command register read, assumes Command_Rd_addH = 0x7000. */
374static int s5k6aa_read(struct i2c_client *client, u16 addr, u16 *val)
375{
376 int ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRL, addr);
377 if (ret)
378 return ret;
379 return s5k6aa_i2c_read(client, REG_CMDBUF0_ADDR, val);
380}
381
382static int s5k6aa_write_array(struct v4l2_subdev *sd,
383 const struct s5k6aa_regval *msg)
384{
385 struct i2c_client *client = v4l2_get_subdevdata(sd);
386 u16 addr_incr = 0;
387 int ret = 0;
388
389 while (msg->addr != S5K6AA_TERM) {
390 if (addr_incr != 2)
391 ret = s5k6aa_i2c_write(client, REG_CMDWR_ADDRL,
392 msg->addr);
393 if (ret)
394 break;
395 ret = s5k6aa_i2c_write(client, REG_CMDBUF0_ADDR, msg->val);
396 if (ret)
397 break;
398 /* Assume that msg->addr is always less than 0xfffc */
399 addr_incr = (msg + 1)->addr - msg->addr;
400 msg++;
401 }
402
403 return ret;
404}
405
406/* Configure the AHB high address bytes for GTG registers access */
407static int s5k6aa_set_ahb_address(struct i2c_client *client)
408{
409 int ret = s5k6aa_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH);
410 if (ret)
411 return ret;
412 ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRH, HOST_SWIF_OFFSH);
413 if (ret)
414 return ret;
415 return s5k6aa_i2c_write(client, REG_CMDWR_ADDRH, HOST_SWIF_OFFSH);
416}
417
418/**
419 * s5k6aa_configure_pixel_clocks - apply ISP main clock/PLL configuration
420 * @s5k6aa: pointer to &struct s5k6aa describing the device
421 *
422 * Configure the internal ISP PLL for the required output frequency.
423 * Locking: called with s5k6aa.lock mutex held.
424 */
425static int s5k6aa_configure_pixel_clocks(struct s5k6aa *s5k6aa)
426{
427 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
428 unsigned long fmclk = s5k6aa->mclk_frequency / 1000;
429 u16 status;
430 int ret;
431
432 if (WARN(fmclk < MIN_MCLK_FREQ_KHZ || fmclk > MAX_MCLK_FREQ_KHZ,
433 "Invalid clock frequency: %ld\n", fmclk))
434 return -EINVAL;
435
436 s5k6aa->pclk_fmin = PCLK_FREQ_MIN;
437 s5k6aa->pclk_fmax = PCLK_FREQ_MAX;
438 s5k6aa->clk_fop = SYS_PLL_OUT_FREQ;
439
440 /* External input clock frequency in kHz */
441 ret = s5k6aa_write(c, REG_I_INCLK_FREQ_H, fmclk >> 16);
442 if (!ret)
443 ret = s5k6aa_write(c, REG_I_INCLK_FREQ_L, fmclk & 0xFFFF);
444 if (!ret)
445 ret = s5k6aa_write(c, REG_I_USE_NPVI_CLOCKS, 1);
446 /* Internal PLL frequency */
447 if (!ret)
448 ret = s5k6aa_write(c, REG_I_OPCLK_4KHZ(0), s5k6aa->clk_fop);
449 if (!ret)
450 ret = s5k6aa_write(c, REG_I_MIN_OUTRATE_4KHZ(0),
451 s5k6aa->pclk_fmin);
452 if (!ret)
453 ret = s5k6aa_write(c, REG_I_MAX_OUTRATE_4KHZ(0),
454 s5k6aa->pclk_fmax);
455 if (!ret)
456 ret = s5k6aa_write(c, REG_I_INIT_PARAMS_UPDATED, 1);
457 if (!ret)
458 ret = s5k6aa_read(c, REG_I_ERROR_INFO, &status);
459
460 return ret ? ret : (status ? -EINVAL : 0);
461}
462
463/* Set horizontal and vertical image flipping */
464static int s5k6aa_set_mirror(struct s5k6aa *s5k6aa, int horiz_flip)
465{
466 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
467 int index = s5k6aa->preset->index;
468
469 unsigned int vflip = s5k6aa->ctrls.vflip->val ^ s5k6aa->inv_vflip;
470 unsigned int flip = (horiz_flip ^ s5k6aa->inv_hflip) | (vflip << 1);
471
472 return s5k6aa_write(client, REG_P_PREV_MIRROR(index), flip);
473}
474
475/* Configure auto/manual white balance and R/G/B gains */
476static int s5k6aa_set_awb(struct s5k6aa *s5k6aa, int awb)
477{
478 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
479 struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
480 u16 reg;
481
482 int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &reg);
483
484 if (!ret && !awb) {
485 ret = s5k6aa_write(c, REG_SF_RGAIN, ctrls->gain_red->val);
486 if (!ret)
487 ret = s5k6aa_write(c, REG_SF_RGAIN_CHG, 1);
488 if (ret)
489 return ret;
490
491 ret = s5k6aa_write(c, REG_SF_GGAIN, ctrls->gain_green->val);
492 if (!ret)
493 ret = s5k6aa_write(c, REG_SF_GGAIN_CHG, 1);
494 if (ret)
495 return ret;
496
497 ret = s5k6aa_write(c, REG_SF_BGAIN, ctrls->gain_blue->val);
498 if (!ret)
499 ret = s5k6aa_write(c, REG_SF_BGAIN_CHG, 1);
500 }
501 if (!ret) {
502 reg = awb ? reg | AALG_WB_EN_MASK : reg & ~AALG_WB_EN_MASK;
503 ret = s5k6aa_write(c, REG_DBG_AUTOALG_EN, reg);
504 }
505
506 return ret;
507}
508
509/* Program FW with exposure time, 'exposure' in us units */
510static int s5k6aa_set_user_exposure(struct i2c_client *client, int exposure)
511{
512 unsigned int time = exposure / 10;
513
514 int ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_L, time & 0xffff);
515 if (!ret)
516 ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_H, time >> 16);
517 if (ret)
518 return ret;
519 return s5k6aa_write(client, REG_SF_USR_EXPOSURE_CHG, 1);
520}
521
522static int s5k6aa_set_user_gain(struct i2c_client *client, int gain)
523{
524 int ret = s5k6aa_write(client, REG_SF_USR_TOT_GAIN, gain);
525 if (ret)
526 return ret;
527 return s5k6aa_write(client, REG_SF_USR_TOT_GAIN_CHG, 1);
528}
529
530/* Set auto/manual exposure and total gain */
531static int s5k6aa_set_auto_exposure(struct s5k6aa *s5k6aa, int value)
532{
533 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
534 unsigned int exp_time = s5k6aa->ctrls.exposure->val;
535 u16 auto_alg;
536
537 int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &auto_alg);
538 if (ret)
539 return ret;
540
541 v4l2_dbg(1, debug, c, "man_exp: %d, auto_exp: %d, a_alg: 0x%x\n",
542 exp_time, value, auto_alg);
543
544 if (value == V4L2_EXPOSURE_AUTO) {
545 auto_alg |= AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK;
546 } else {
547 ret = s5k6aa_set_user_exposure(c, exp_time);
548 if (ret)
549 return ret;
550 ret = s5k6aa_set_user_gain(c, s5k6aa->ctrls.gain->val);
551 if (ret)
552 return ret;
553 auto_alg &= ~(AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK);
554 }
555
556 return s5k6aa_write(c, REG_DBG_AUTOALG_EN, auto_alg);
557}
558
559static int s5k6aa_set_anti_flicker(struct s5k6aa *s5k6aa, int value)
560{
561 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
562 u16 auto_alg;
563 int ret;
564
565 ret = s5k6aa_read(client, REG_DBG_AUTOALG_EN, &auto_alg);
566 if (ret)
567 return ret;
568
569 if (value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) {
570 auto_alg |= AALG_FLICKER_EN_MASK;
571 } else {
572 auto_alg &= ~AALG_FLICKER_EN_MASK;
573 /* The V4L2_CID_LINE_FREQUENCY control values match
574 * the register values */
575 ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT, value);
576 if (ret)
577 return ret;
578 ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT_CHG, 1);
579 if (ret)
580 return ret;
581 }
582
583 return s5k6aa_write(client, REG_DBG_AUTOALG_EN, auto_alg);
584}
585
586static int s5k6aa_set_colorfx(struct s5k6aa *s5k6aa, int val)
587{
588 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
589 static const struct v4l2_control colorfx[] = {
590 { V4L2_COLORFX_NONE, 0 },
591 { V4L2_COLORFX_BW, 1 },
592 { V4L2_COLORFX_NEGATIVE, 2 },
593 { V4L2_COLORFX_SEPIA, 3 },
594 { V4L2_COLORFX_SKY_BLUE, 4 },
595 { V4L2_COLORFX_SKETCH, 5 },
596 };
597 int i;
598
599 for (i = 0; i < ARRAY_SIZE(colorfx); i++) {
600 if (colorfx[i].id == val)
601 return s5k6aa_write(client, REG_G_SPEC_EFFECTS,
602 colorfx[i].value);
603 }
604 return -EINVAL;
605}
606
607static int s5k6aa_preview_config_status(struct i2c_client *client)
608{
609 u16 error = 0;
610 int ret = s5k6aa_read(client, REG_G_PREV_CFG_ERROR, &error);
611
612 v4l2_dbg(1, debug, client, "error: 0x%x (%d)\n", error, ret);
613 return ret ? ret : (error ? -EINVAL : 0);
614}
615
616static int s5k6aa_get_pixfmt_index(struct s5k6aa *s5k6aa,
617 struct v4l2_mbus_framefmt *mf)
618{
619 unsigned int i;
620
621 for (i = 0; i < ARRAY_SIZE(s5k6aa_formats); i++)
622 if (mf->colorspace == s5k6aa_formats[i].colorspace &&
623 mf->code == s5k6aa_formats[i].code)
624 return i;
625 return 0;
626}
627
628static int s5k6aa_set_output_framefmt(struct s5k6aa *s5k6aa,
629 struct s5k6aa_preset *preset)
630{
631 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
632 int fmt_index = s5k6aa_get_pixfmt_index(s5k6aa, &preset->mbus_fmt);
633 int ret;
634
635 ret = s5k6aa_write(client, REG_P_OUT_WIDTH(preset->index),
636 preset->mbus_fmt.width);
637 if (!ret)
638 ret = s5k6aa_write(client, REG_P_OUT_HEIGHT(preset->index),
639 preset->mbus_fmt.height);
640 if (!ret)
641 ret = s5k6aa_write(client, REG_P_FMT(preset->index),
642 s5k6aa_formats[fmt_index].reg_p_fmt);
643 return ret;
644}
645
646static int s5k6aa_set_input_params(struct s5k6aa *s5k6aa)
647{
648 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
649 struct v4l2_rect *r = &s5k6aa->ccd_rect;
650 int ret;
651
652 ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width);
653 if (!ret)
654 ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height);
655 if (!ret)
656 ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left);
657 if (!ret)
658 ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top);
659 if (!ret)
660 ret = s5k6aa_write(c, REG_G_INPUTS_CHANGE_REQ, 1);
661 if (!ret)
662 s5k6aa->apply_crop = 0;
663
664 return ret;
665}
666
667/**
668 * s5k6aa_configure_video_bus - configure the video output interface
669 * @s5k6aa: pointer to &struct s5k6aa describing the device
670 * @bus_type: video bus type: parallel or MIPI-CSI
671 * @nlanes: number of MIPI lanes to be used (MIPI-CSI only)
672 *
673 * Note: Only parallel bus operation has been tested.
674 */
675static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa,
676 enum v4l2_mbus_type bus_type, int nlanes)
677{
678 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
679 u16 cfg = 0;
680 int ret;
681
682 /*
683 * TODO: The sensor is supposed to support BT.601 and BT.656
684 * but there is nothing indicating how to switch between both
685 * in the datasheet. For now default BT.601 interface is assumed.
686 */
687 if (bus_type == V4L2_MBUS_CSI2_DPHY)
688 cfg = nlanes;
689 else if (bus_type != V4L2_MBUS_PARALLEL)
690 return -EINVAL;
691
692 ret = s5k6aa_write(client, REG_OIF_EN_MIPI_LANES, cfg);
693 if (ret)
694 return ret;
695 return s5k6aa_write(client, REG_OIF_CFG_CHG, 1);
696}
697
698/* This function should be called when switching to new user configuration set*/
699static int s5k6aa_new_config_sync(struct i2c_client *client, int timeout,
700 int cid)
701{
702 unsigned long end = jiffies + msecs_to_jiffies(timeout);
703 u16 reg = 1;
704 int ret;
705
706 ret = s5k6aa_write(client, REG_G_ACTIVE_PREV_CFG, cid);
707 if (!ret)
708 ret = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
709 if (!ret)
710 ret = s5k6aa_write(client, REG_G_NEW_CFG_SYNC, 1);
711 if (timeout == 0)
712 return ret;
713
714 while (ret >= 0 && time_is_after_jiffies(end)) {
715 ret = s5k6aa_read(client, REG_G_NEW_CFG_SYNC, &reg);
716 if (!reg)
717 return 0;
718 usleep_range(1000, 5000);
719 }
720 return ret ? ret : -ETIMEDOUT;
721}
722
723/**
724 * s5k6aa_set_prev_config - write user preview register set
725 * @s5k6aa: pointer to &struct s5k6aa describing the device
726 * @preset: s5kaa preset to be applied
727 *
728 * Configure output resolution and color format, pixel clock
729 * frequency range, device frame rate type and frame period range.
730 */
731static int s5k6aa_set_prev_config(struct s5k6aa *s5k6aa,
732 struct s5k6aa_preset *preset)
733{
734 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
735 int idx = preset->index;
736 u16 frame_rate_q;
737 int ret;
738
739 if (s5k6aa->fiv->reg_fr_time >= S5K6AA_MAX_HIGHRES_FR_TIME)
740 frame_rate_q = FR_RATE_Q_BEST_FRRATE;
741 else
742 frame_rate_q = FR_RATE_Q_BEST_QUALITY;
743
744 ret = s5k6aa_set_output_framefmt(s5k6aa, preset);
745 if (!ret)
746 ret = s5k6aa_write(client, REG_P_MAX_OUT_RATE(idx),
747 s5k6aa->pclk_fmax);
748 if (!ret)
749 ret = s5k6aa_write(client, REG_P_MIN_OUT_RATE(idx),
750 s5k6aa->pclk_fmin);
751 if (!ret)
752 ret = s5k6aa_write(client, REG_P_CLK_INDEX(idx),
753 preset->clk_id);
754 if (!ret)
755 ret = s5k6aa_write(client, REG_P_FR_RATE_TYPE(idx),
756 FR_RATE_DYNAMIC);
757 if (!ret)
758 ret = s5k6aa_write(client, REG_P_FR_RATE_Q_TYPE(idx),
759 frame_rate_q);
760 if (!ret)
761 ret = s5k6aa_write(client, REG_P_MAX_FR_TIME(idx),
762 s5k6aa->fiv->reg_fr_time + 33);
763 if (!ret)
764 ret = s5k6aa_write(client, REG_P_MIN_FR_TIME(idx),
765 s5k6aa->fiv->reg_fr_time - 33);
766 if (!ret)
767 ret = s5k6aa_new_config_sync(client, 250, idx);
768 if (!ret)
769 ret = s5k6aa_preview_config_status(client);
770 if (!ret)
771 s5k6aa->apply_cfg = 0;
772
773 v4l2_dbg(1, debug, client, "Frame interval: %d +/- 3.3ms. (%d)\n",
774 s5k6aa->fiv->reg_fr_time, ret);
775 return ret;
776}
777
778/**
779 * s5k6aa_initialize_isp - basic ISP MCU initialization
780 * @sd: pointer to V4L2 sub-device descriptor
781 *
782 * Configure AHB addresses for registers read/write; configure PLLs for
783 * required output pixel clock. The ISP power supply needs to be already
784 * enabled, with an optional H/W reset.
785 * Locking: called with s5k6aa.lock mutex held.
786 */
787static int s5k6aa_initialize_isp(struct v4l2_subdev *sd)
788{
789 struct i2c_client *client = v4l2_get_subdevdata(sd);
790 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
791 int ret;
792
793 s5k6aa->apply_crop = 1;
794 s5k6aa->apply_cfg = 1;
795 msleep(100);
796
797 ret = s5k6aa_set_ahb_address(client);
798 if (ret)
799 return ret;
800 ret = s5k6aa_configure_video_bus(s5k6aa, s5k6aa->bus_type,
801 s5k6aa->mipi_lanes);
802 if (ret)
803 return ret;
804 ret = s5k6aa_write_array(sd, s5k6aa_analog_config);
805 if (ret)
806 return ret;
807 msleep(20);
808
809 return s5k6aa_configure_pixel_clocks(s5k6aa);
810}
811
812static int s5k6aa_gpio_set_value(struct s5k6aa *priv, int id, u32 val)
813{
814 if (!gpio_is_valid(priv->gpio[id].gpio))
815 return 0;
816 gpio_set_value(priv->gpio[id].gpio, !!val);
817 return 1;
818}
819
820static int s5k6aa_gpio_assert(struct s5k6aa *priv, int id)
821{
822 return s5k6aa_gpio_set_value(priv, id, priv->gpio[id].level);
823}
824
825static int s5k6aa_gpio_deassert(struct s5k6aa *priv, int id)
826{
827 return s5k6aa_gpio_set_value(priv, id, !priv->gpio[id].level);
828}
829
830static int __s5k6aa_power_on(struct s5k6aa *s5k6aa)
831{
832 int ret;
833
834 ret = regulator_bulk_enable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
835 if (ret)
836 return ret;
837 if (s5k6aa_gpio_deassert(s5k6aa, STBY))
838 usleep_range(150, 200);
839
840 if (s5k6aa->s_power)
841 ret = s5k6aa->s_power(1);
842 usleep_range(4000, 5000);
843
844 if (s5k6aa_gpio_deassert(s5k6aa, RSET))
845 msleep(20);
846
847 return ret;
848}
849
850static int __s5k6aa_power_off(struct s5k6aa *s5k6aa)
851{
852 int ret;
853
854 if (s5k6aa_gpio_assert(s5k6aa, RSET))
855 usleep_range(100, 150);
856
857 if (s5k6aa->s_power) {
858 ret = s5k6aa->s_power(0);
859 if (ret)
860 return ret;
861 }
862 if (s5k6aa_gpio_assert(s5k6aa, STBY))
863 usleep_range(50, 100);
864 s5k6aa->streaming = 0;
865
866 return regulator_bulk_disable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
867}
868
869/*
870 * V4L2 subdev core and video operations
871 */
872static int s5k6aa_set_power(struct v4l2_subdev *sd, int on)
873{
874 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
875 int ret = 0;
876
877 mutex_lock(&s5k6aa->lock);
878
879 if (s5k6aa->power == !on) {
880 if (on) {
881 ret = __s5k6aa_power_on(s5k6aa);
882 if (!ret)
883 ret = s5k6aa_initialize_isp(sd);
884 } else {
885 ret = __s5k6aa_power_off(s5k6aa);
886 }
887
888 if (!ret)
889 s5k6aa->power += on ? 1 : -1;
890 }
891
892 mutex_unlock(&s5k6aa->lock);
893
894 if (!on || ret || s5k6aa->power != 1)
895 return ret;
896
897 return v4l2_ctrl_handler_setup(sd->ctrl_handler);
898}
899
900static int __s5k6aa_stream(struct s5k6aa *s5k6aa, int enable)
901{
902 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
903 int ret = 0;
904
905 ret = s5k6aa_write(client, REG_G_ENABLE_PREV, enable);
906 if (!ret)
907 ret = s5k6aa_write(client, REG_G_ENABLE_PREV_CHG, 1);
908 if (!ret)
909 s5k6aa->streaming = enable;
910
911 return ret;
912}
913
914static int s5k6aa_s_stream(struct v4l2_subdev *sd, int on)
915{
916 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
917 int ret = 0;
918
919 mutex_lock(&s5k6aa->lock);
920
921 if (s5k6aa->streaming == !on) {
922 if (!ret && s5k6aa->apply_cfg)
923 ret = s5k6aa_set_prev_config(s5k6aa, s5k6aa->preset);
924 if (s5k6aa->apply_crop)
925 ret = s5k6aa_set_input_params(s5k6aa);
926 if (!ret)
927 ret = __s5k6aa_stream(s5k6aa, !!on);
928 }
929 mutex_unlock(&s5k6aa->lock);
930
931 return ret;
932}
933
934static int s5k6aa_g_frame_interval(struct v4l2_subdev *sd,
935 struct v4l2_subdev_frame_interval *fi)
936{
937 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
938
939 mutex_lock(&s5k6aa->lock);
940 fi->interval = s5k6aa->fiv->interval;
941 mutex_unlock(&s5k6aa->lock);
942
943 return 0;
944}
945
946static int __s5k6aa_set_frame_interval(struct s5k6aa *s5k6aa,
947 struct v4l2_subdev_frame_interval *fi)
948{
949 struct v4l2_mbus_framefmt *mbus_fmt = &s5k6aa->preset->mbus_fmt;
950 const struct s5k6aa_interval *fiv = &s5k6aa_intervals[0];
951 unsigned int err, min_err = UINT_MAX;
952 unsigned int i, fr_time;
953
954 if (fi->interval.denominator == 0)
955 return -EINVAL;
956
957 fr_time = fi->interval.numerator * 10000 / fi->interval.denominator;
958
959 for (i = 0; i < ARRAY_SIZE(s5k6aa_intervals); i++) {
960 const struct s5k6aa_interval *iv = &s5k6aa_intervals[i];
961
962 if (mbus_fmt->width > iv->size.width ||
963 mbus_fmt->height > iv->size.height)
964 continue;
965
966 err = abs(iv->reg_fr_time - fr_time);
967 if (err < min_err) {
968 fiv = iv;
969 min_err = err;
970 }
971 }
972 s5k6aa->fiv = fiv;
973
974 v4l2_dbg(1, debug, &s5k6aa->sd, "Changed frame interval to %d us\n",
975 fiv->reg_fr_time * 100);
976 return 0;
977}
978
979static int s5k6aa_s_frame_interval(struct v4l2_subdev *sd,
980 struct v4l2_subdev_frame_interval *fi)
981{
982 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
983 int ret;
984
985 v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
986 fi->interval.numerator, fi->interval.denominator);
987
988 mutex_lock(&s5k6aa->lock);
989 ret = __s5k6aa_set_frame_interval(s5k6aa, fi);
990 s5k6aa->apply_cfg = 1;
991
992 mutex_unlock(&s5k6aa->lock);
993 return ret;
994}
995
996/*
997 * V4L2 subdev pad level and video operations
998 */
999static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
1000 struct v4l2_subdev_state *sd_state,
1001 struct v4l2_subdev_frame_interval_enum *fie)
1002{
1003 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1004 const struct s5k6aa_interval *fi;
1005 int ret = 0;
1006
1007 if (fie->index >= ARRAY_SIZE(s5k6aa_intervals))
1008 return -EINVAL;
1009
1010 v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN,
1011 S5K6AA_WIN_WIDTH_MAX, 1,
1012 &fie->height, S5K6AA_WIN_HEIGHT_MIN,
1013 S5K6AA_WIN_HEIGHT_MAX, 1, 0);
1014
1015 mutex_lock(&s5k6aa->lock);
1016 fi = &s5k6aa_intervals[fie->index];
1017 if (fie->width > fi->size.width || fie->height > fi->size.height)
1018 ret = -EINVAL;
1019 else
1020 fie->interval = fi->interval;
1021 mutex_unlock(&s5k6aa->lock);
1022
1023 return ret;
1024}
1025
1026static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd,
1027 struct v4l2_subdev_state *sd_state,
1028 struct v4l2_subdev_mbus_code_enum *code)
1029{
1030 if (code->index >= ARRAY_SIZE(s5k6aa_formats))
1031 return -EINVAL;
1032
1033 code->code = s5k6aa_formats[code->index].code;
1034 return 0;
1035}
1036
1037static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd,
1038 struct v4l2_subdev_state *sd_state,
1039 struct v4l2_subdev_frame_size_enum *fse)
1040{
1041 int i = ARRAY_SIZE(s5k6aa_formats);
1042
1043 if (fse->index > 0)
1044 return -EINVAL;
1045
1046 while (--i)
1047 if (fse->code == s5k6aa_formats[i].code)
1048 break;
1049
1050 fse->code = s5k6aa_formats[i].code;
1051 fse->min_width = S5K6AA_WIN_WIDTH_MIN;
1052 fse->max_width = S5K6AA_WIN_WIDTH_MAX;
1053 fse->max_height = S5K6AA_WIN_HEIGHT_MIN;
1054 fse->min_height = S5K6AA_WIN_HEIGHT_MAX;
1055
1056 return 0;
1057}
1058
1059static struct v4l2_rect *
1060__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa,
1061 struct v4l2_subdev_state *sd_state,
1062 enum v4l2_subdev_format_whence which)
1063{
1064 if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
1065 return &s5k6aa->ccd_rect;
1066
1067 WARN_ON(which != V4L2_SUBDEV_FORMAT_TRY);
1068 return v4l2_subdev_get_try_crop(&s5k6aa->sd, sd_state, 0);
1069}
1070
1071static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
1072 struct v4l2_mbus_framefmt *mf)
1073{
1074 unsigned int index;
1075
1076 v4l_bound_align_image(&mf->width, S5K6AA_WIN_WIDTH_MIN,
1077 S5K6AA_WIN_WIDTH_MAX, 1,
1078 &mf->height, S5K6AA_WIN_HEIGHT_MIN,
1079 S5K6AA_WIN_HEIGHT_MAX, 1, 0);
1080
1081 if (mf->colorspace != V4L2_COLORSPACE_JPEG &&
1082 mf->colorspace != V4L2_COLORSPACE_REC709)
1083 mf->colorspace = V4L2_COLORSPACE_JPEG;
1084
1085 index = s5k6aa_get_pixfmt_index(s5k6aa, mf);
1086
1087 mf->colorspace = s5k6aa_formats[index].colorspace;
1088 mf->code = s5k6aa_formats[index].code;
1089 mf->field = V4L2_FIELD_NONE;
1090}
1091
1092static int s5k6aa_get_fmt(struct v4l2_subdev *sd,
1093 struct v4l2_subdev_state *sd_state,
1094 struct v4l2_subdev_format *fmt)
1095{
1096 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1097 struct v4l2_mbus_framefmt *mf;
1098
1099 memset(fmt->reserved, 0, sizeof(fmt->reserved));
1100
1101 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1102 mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
1103 fmt->format = *mf;
1104 return 0;
1105 }
1106
1107 mutex_lock(&s5k6aa->lock);
1108 fmt->format = s5k6aa->preset->mbus_fmt;
1109 mutex_unlock(&s5k6aa->lock);
1110
1111 return 0;
1112}
1113
1114static int s5k6aa_set_fmt(struct v4l2_subdev *sd,
1115 struct v4l2_subdev_state *sd_state,
1116 struct v4l2_subdev_format *fmt)
1117{
1118 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1119 struct s5k6aa_preset *preset = s5k6aa->preset;
1120 struct v4l2_mbus_framefmt *mf;
1121 struct v4l2_rect *crop;
1122 int ret = 0;
1123
1124 mutex_lock(&s5k6aa->lock);
1125 s5k6aa_try_format(s5k6aa, &fmt->format);
1126
1127 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1128 mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
1129 crop = v4l2_subdev_get_try_crop(sd, sd_state, 0);
1130 } else {
1131 if (s5k6aa->streaming) {
1132 ret = -EBUSY;
1133 } else {
1134 mf = &preset->mbus_fmt;
1135 crop = &s5k6aa->ccd_rect;
1136 s5k6aa->apply_cfg = 1;
1137 }
1138 }
1139
1140 if (ret == 0) {
1141 struct v4l2_subdev_frame_interval fiv = {
1142 .interval = {0, 1}
1143 };
1144
1145 *mf = fmt->format;
1146 /*
1147 * Make sure the crop window is valid, i.e. its size is
1148 * greater than the output window, as the ISP supports
1149 * only down-scaling.
1150 */
1151 crop->width = clamp_t(unsigned int, crop->width, mf->width,
1152 S5K6AA_WIN_WIDTH_MAX);
1153 crop->height = clamp_t(unsigned int, crop->height, mf->height,
1154 S5K6AA_WIN_HEIGHT_MAX);
1155 crop->left = clamp_t(unsigned int, crop->left, 0,
1156 S5K6AA_WIN_WIDTH_MAX - crop->width);
1157 crop->top = clamp_t(unsigned int, crop->top, 0,
1158 S5K6AA_WIN_HEIGHT_MAX - crop->height);
1159
1160 /* Reset to minimum possible frame interval */
1161 ret = __s5k6aa_set_frame_interval(s5k6aa, &fiv);
1162 }
1163 mutex_unlock(&s5k6aa->lock);
1164
1165 return ret;
1166}
1167
1168static int s5k6aa_get_selection(struct v4l2_subdev *sd,
1169 struct v4l2_subdev_state *sd_state,
1170 struct v4l2_subdev_selection *sel)
1171{
1172 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1173 struct v4l2_rect *rect;
1174
1175 if (sel->target != V4L2_SEL_TGT_CROP)
1176 return -EINVAL;
1177
1178 memset(sel->reserved, 0, sizeof(sel->reserved));
1179
1180 mutex_lock(&s5k6aa->lock);
1181 rect = __s5k6aa_get_crop_rect(s5k6aa, sd_state, sel->which);
1182 sel->r = *rect;
1183 mutex_unlock(&s5k6aa->lock);
1184
1185 v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
1186 rect->left, rect->top, rect->width, rect->height);
1187
1188 return 0;
1189}
1190
1191static int s5k6aa_set_selection(struct v4l2_subdev *sd,
1192 struct v4l2_subdev_state *sd_state,
1193 struct v4l2_subdev_selection *sel)
1194{
1195 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1196 struct v4l2_mbus_framefmt *mf;
1197 unsigned int max_x, max_y;
1198 struct v4l2_rect *crop_r;
1199
1200 if (sel->target != V4L2_SEL_TGT_CROP)
1201 return -EINVAL;
1202
1203 mutex_lock(&s5k6aa->lock);
1204 crop_r = __s5k6aa_get_crop_rect(s5k6aa, sd_state, sel->which);
1205
1206 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1207 mf = &s5k6aa->preset->mbus_fmt;
1208 s5k6aa->apply_crop = 1;
1209 } else {
1210 mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
1211 }
1212 v4l_bound_align_image(&sel->r.width, mf->width,
1213 S5K6AA_WIN_WIDTH_MAX, 1,
1214 &sel->r.height, mf->height,
1215 S5K6AA_WIN_HEIGHT_MAX, 1, 0);
1216
1217 max_x = (S5K6AA_WIN_WIDTH_MAX - sel->r.width) & ~1;
1218 max_y = (S5K6AA_WIN_HEIGHT_MAX - sel->r.height) & ~1;
1219
1220 sel->r.left = clamp_t(unsigned int, sel->r.left, 0, max_x);
1221 sel->r.top = clamp_t(unsigned int, sel->r.top, 0, max_y);
1222
1223 *crop_r = sel->r;
1224
1225 mutex_unlock(&s5k6aa->lock);
1226
1227 v4l2_dbg(1, debug, sd, "Set crop rectangle: (%d,%d)/%dx%d\n",
1228 crop_r->left, crop_r->top, crop_r->width, crop_r->height);
1229
1230 return 0;
1231}
1232
1233static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
1234 .enum_mbus_code = s5k6aa_enum_mbus_code,
1235 .enum_frame_size = s5k6aa_enum_frame_size,
1236 .enum_frame_interval = s5k6aa_enum_frame_interval,
1237 .get_fmt = s5k6aa_get_fmt,
1238 .set_fmt = s5k6aa_set_fmt,
1239 .get_selection = s5k6aa_get_selection,
1240 .set_selection = s5k6aa_set_selection,
1241};
1242
1243static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
1244 .g_frame_interval = s5k6aa_g_frame_interval,
1245 .s_frame_interval = s5k6aa_s_frame_interval,
1246 .s_stream = s5k6aa_s_stream,
1247};
1248
1249/*
1250 * V4L2 subdev controls
1251 */
1252
1253static int s5k6aa_s_ctrl(struct v4l2_ctrl *ctrl)
1254{
1255 struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
1256 struct i2c_client *client = v4l2_get_subdevdata(sd);
1257 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1258 int idx, err = 0;
1259
1260 v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val);
1261
1262 mutex_lock(&s5k6aa->lock);
1263 /*
1264 * If the device is not powered up by the host driver do
1265 * not apply any controls to H/W at this time. Instead
1266 * the controls will be restored right after power-up.
1267 */
1268 if (s5k6aa->power == 0)
1269 goto unlock;
1270 idx = s5k6aa->preset->index;
1271
1272 switch (ctrl->id) {
1273 case V4L2_CID_AUTO_WHITE_BALANCE:
1274 err = s5k6aa_set_awb(s5k6aa, ctrl->val);
1275 break;
1276
1277 case V4L2_CID_BRIGHTNESS:
1278 err = s5k6aa_write(client, REG_USER_BRIGHTNESS, ctrl->val);
1279 break;
1280
1281 case V4L2_CID_COLORFX:
1282 err = s5k6aa_set_colorfx(s5k6aa, ctrl->val);
1283 break;
1284
1285 case V4L2_CID_CONTRAST:
1286 err = s5k6aa_write(client, REG_USER_CONTRAST, ctrl->val);
1287 break;
1288
1289 case V4L2_CID_EXPOSURE_AUTO:
1290 err = s5k6aa_set_auto_exposure(s5k6aa, ctrl->val);
1291 break;
1292
1293 case V4L2_CID_HFLIP:
1294 err = s5k6aa_set_mirror(s5k6aa, ctrl->val);
1295 if (err)
1296 break;
1297 err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
1298 break;
1299
1300 case V4L2_CID_POWER_LINE_FREQUENCY:
1301 err = s5k6aa_set_anti_flicker(s5k6aa, ctrl->val);
1302 break;
1303
1304 case V4L2_CID_SATURATION:
1305 err = s5k6aa_write(client, REG_USER_SATURATION, ctrl->val);
1306 break;
1307
1308 case V4L2_CID_SHARPNESS:
1309 err = s5k6aa_write(client, REG_USER_SHARPBLUR, ctrl->val);
1310 break;
1311
1312 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
1313 err = s5k6aa_write(client, REG_P_COLORTEMP(idx), ctrl->val);
1314 if (err)
1315 break;
1316 err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
1317 break;
1318 }
1319unlock:
1320 mutex_unlock(&s5k6aa->lock);
1321 return err;
1322}
1323
1324static const struct v4l2_ctrl_ops s5k6aa_ctrl_ops = {
1325 .s_ctrl = s5k6aa_s_ctrl,
1326};
1327
1328static int s5k6aa_log_status(struct v4l2_subdev *sd)
1329{
1330 v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
1331 return 0;
1332}
1333
1334#define V4L2_CID_RED_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1001)
1335#define V4L2_CID_GREEN_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1002)
1336#define V4L2_CID_BLUE_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1003)
1337
1338static const struct v4l2_ctrl_config s5k6aa_ctrls[] = {
1339 {
1340 .ops = &s5k6aa_ctrl_ops,
1341 .id = V4L2_CID_RED_GAIN,
1342 .type = V4L2_CTRL_TYPE_INTEGER,
1343 .name = "Gain, Red",
1344 .min = 0,
1345 .max = 256,
1346 .def = 127,
1347 .step = 1,
1348 }, {
1349 .ops = &s5k6aa_ctrl_ops,
1350 .id = V4L2_CID_GREEN_GAIN,
1351 .type = V4L2_CTRL_TYPE_INTEGER,
1352 .name = "Gain, Green",
1353 .min = 0,
1354 .max = 256,
1355 .def = 127,
1356 .step = 1,
1357 }, {
1358 .ops = &s5k6aa_ctrl_ops,
1359 .id = V4L2_CID_BLUE_GAIN,
1360 .type = V4L2_CTRL_TYPE_INTEGER,
1361 .name = "Gain, Blue",
1362 .min = 0,
1363 .max = 256,
1364 .def = 127,
1365 .step = 1,
1366 },
1367};
1368
1369static int s5k6aa_initialize_ctrls(struct s5k6aa *s5k6aa)
1370{
1371 const struct v4l2_ctrl_ops *ops = &s5k6aa_ctrl_ops;
1372 struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
1373 struct v4l2_ctrl_handler *hdl = &ctrls->handler;
1374
1375 int ret = v4l2_ctrl_handler_init(hdl, 16);
1376 if (ret)
1377 return ret;
1378 /* Auto white balance cluster */
1379 ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE,
1380 0, 1, 1, 1);
1381 ctrls->gain_red = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[0], NULL);
1382 ctrls->gain_green = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[1], NULL);
1383 ctrls->gain_blue = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[2], NULL);
1384 v4l2_ctrl_auto_cluster(4, &ctrls->awb, 0, false);
1385
1386 ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
1387 ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
1388 v4l2_ctrl_cluster(2, &ctrls->hflip);
1389
1390 ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
1391 V4L2_CID_EXPOSURE_AUTO,
1392 V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
1393 /* Exposure time: x 1 us */
1394 ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
1395 0, 6000000U, 1, 100000U);
1396 /* Total gain: 256 <=> 1x */
1397 ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
1398 0, 256, 1, 256);
1399 v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false);
1400
1401 v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_POWER_LINE_FREQUENCY,
1402 V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
1403 V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
1404
1405 v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX,
1406 V4L2_COLORFX_SKY_BLUE, ~0x6f, V4L2_COLORFX_NONE);
1407
1408 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_WHITE_BALANCE_TEMPERATURE,
1409 0, 256, 1, 0);
1410
1411 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0);
1412 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0);
1413 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0);
1414 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0);
1415
1416 if (hdl->error) {
1417 ret = hdl->error;
1418 v4l2_ctrl_handler_free(hdl);
1419 return ret;
1420 }
1421
1422 s5k6aa->sd.ctrl_handler = hdl;
1423 return 0;
1424}
1425
1426/*
1427 * V4L2 subdev internal operations
1428 */
1429static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1430{
1431 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
1432 fh->state,
1433 0);
1434 struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
1435
1436 format->colorspace = s5k6aa_formats[0].colorspace;
1437 format->code = s5k6aa_formats[0].code;
1438 format->width = S5K6AA_OUT_WIDTH_DEF;
1439 format->height = S5K6AA_OUT_HEIGHT_DEF;
1440 format->field = V4L2_FIELD_NONE;
1441
1442 crop->width = S5K6AA_WIN_WIDTH_MAX;
1443 crop->height = S5K6AA_WIN_HEIGHT_MAX;
1444 crop->left = 0;
1445 crop->top = 0;
1446
1447 return 0;
1448}
1449
1450static int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa)
1451{
1452 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
1453 u16 api_ver = 0, fw_rev = 0;
1454
1455 int ret = s5k6aa_set_ahb_address(client);
1456
1457 if (!ret)
1458 ret = s5k6aa_read(client, REG_FW_APIVER, &api_ver);
1459 if (!ret)
1460 ret = s5k6aa_read(client, REG_FW_REVISION, &fw_rev);
1461 if (ret) {
1462 v4l2_err(&s5k6aa->sd, "FW revision check failed!\n");
1463 return ret;
1464 }
1465
1466 v4l2_info(&s5k6aa->sd, "FW API ver.: 0x%X, FW rev.: 0x%X\n",
1467 api_ver, fw_rev);
1468
1469 return api_ver == S5K6AAFX_FW_APIVER ? 0 : -ENODEV;
1470}
1471
1472static int s5k6aa_registered(struct v4l2_subdev *sd)
1473{
1474 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1475 int ret;
1476
1477 mutex_lock(&s5k6aa->lock);
1478 ret = __s5k6aa_power_on(s5k6aa);
1479 if (!ret) {
1480 msleep(100);
1481 ret = s5k6aa_check_fw_revision(s5k6aa);
1482 __s5k6aa_power_off(s5k6aa);
1483 }
1484 mutex_unlock(&s5k6aa->lock);
1485
1486 return ret;
1487}
1488
1489static const struct v4l2_subdev_internal_ops s5k6aa_subdev_internal_ops = {
1490 .registered = s5k6aa_registered,
1491 .open = s5k6aa_open,
1492};
1493
1494static const struct v4l2_subdev_core_ops s5k6aa_core_ops = {
1495 .s_power = s5k6aa_set_power,
1496 .log_status = s5k6aa_log_status,
1497};
1498
1499static const struct v4l2_subdev_ops s5k6aa_subdev_ops = {
1500 .core = &s5k6aa_core_ops,
1501 .pad = &s5k6aa_pad_ops,
1502 .video = &s5k6aa_video_ops,
1503};
1504
1505/*
1506 * GPIO setup
1507 */
1508
1509static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
1510 const struct s5k6aa_platform_data *pdata)
1511{
1512 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
1513 const struct s5k6aa_gpio *gpio;
1514 unsigned long flags;
1515 int ret;
1516
1517 s5k6aa->gpio[STBY].gpio = -EINVAL;
1518 s5k6aa->gpio[RSET].gpio = -EINVAL;
1519
1520 gpio = &pdata->gpio_stby;
1521 if (gpio_is_valid(gpio->gpio)) {
1522 flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
1523 | GPIOF_EXPORT;
1524 ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags,
1525 "S5K6AA_STBY");
1526 if (ret < 0)
1527 return ret;
1528
1529 s5k6aa->gpio[STBY] = *gpio;
1530 }
1531
1532 gpio = &pdata->gpio_reset;
1533 if (gpio_is_valid(gpio->gpio)) {
1534 flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
1535 | GPIOF_EXPORT;
1536 ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags,
1537 "S5K6AA_RST");
1538 if (ret < 0)
1539 return ret;
1540
1541 s5k6aa->gpio[RSET] = *gpio;
1542 }
1543
1544 return 0;
1545}
1546
1547static int s5k6aa_probe(struct i2c_client *client)
1548{
1549 const struct s5k6aa_platform_data *pdata = client->dev.platform_data;
1550 struct v4l2_subdev *sd;
1551 struct s5k6aa *s5k6aa;
1552 int i, ret;
1553
1554 if (pdata == NULL) {
1555 dev_err(&client->dev, "Platform data not specified\n");
1556 return -EINVAL;
1557 }
1558
1559 if (pdata->mclk_frequency == 0) {
1560 dev_err(&client->dev, "MCLK frequency not specified\n");
1561 return -EINVAL;
1562 }
1563
1564 s5k6aa = devm_kzalloc(&client->dev, sizeof(*s5k6aa), GFP_KERNEL);
1565 if (!s5k6aa)
1566 return -ENOMEM;
1567
1568 mutex_init(&s5k6aa->lock);
1569
1570 s5k6aa->mclk_frequency = pdata->mclk_frequency;
1571 s5k6aa->bus_type = pdata->bus_type;
1572 s5k6aa->mipi_lanes = pdata->nlanes;
1573 s5k6aa->s_power = pdata->set_power;
1574 s5k6aa->inv_hflip = pdata->horiz_flip;
1575 s5k6aa->inv_vflip = pdata->vert_flip;
1576
1577 sd = &s5k6aa->sd;
1578 v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops);
1579 /* Static name; NEVER use in new drivers! */
1580 strscpy(sd->name, DRIVER_NAME, sizeof(sd->name));
1581
1582 sd->internal_ops = &s5k6aa_subdev_internal_ops;
1583 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1584
1585 s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE;
1586 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
1587 ret = media_entity_pads_init(&sd->entity, 1, &s5k6aa->pad);
1588 if (ret)
1589 return ret;
1590
1591 ret = s5k6aa_configure_gpios(s5k6aa, pdata);
1592 if (ret)
1593 goto out_err;
1594
1595 for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++)
1596 s5k6aa->supplies[i].supply = s5k6aa_supply_names[i];
1597
1598 ret = devm_regulator_bulk_get(&client->dev, S5K6AA_NUM_SUPPLIES,
1599 s5k6aa->supplies);
1600 if (ret) {
1601 dev_err(&client->dev, "Failed to get regulators\n");
1602 goto out_err;
1603 }
1604
1605 ret = s5k6aa_initialize_ctrls(s5k6aa);
1606 if (ret)
1607 goto out_err;
1608
1609 s5k6aa_presets_data_init(s5k6aa);
1610
1611 s5k6aa->ccd_rect.width = S5K6AA_WIN_WIDTH_MAX;
1612 s5k6aa->ccd_rect.height = S5K6AA_WIN_HEIGHT_MAX;
1613 s5k6aa->ccd_rect.left = 0;
1614 s5k6aa->ccd_rect.top = 0;
1615
1616 return 0;
1617
1618out_err:
1619 media_entity_cleanup(&s5k6aa->sd.entity);
1620 return ret;
1621}
1622
1623static void s5k6aa_remove(struct i2c_client *client)
1624{
1625 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1626
1627 v4l2_device_unregister_subdev(sd);
1628 v4l2_ctrl_handler_free(sd->ctrl_handler);
1629 media_entity_cleanup(&sd->entity);
1630}
1631
1632static const struct i2c_device_id s5k6aa_id[] = {
1633 { DRIVER_NAME, 0 },
1634 { },
1635};
1636MODULE_DEVICE_TABLE(i2c, s5k6aa_id);
1637
1638
1639static struct i2c_driver s5k6aa_i2c_driver = {
1640 .driver = {
1641 .name = DRIVER_NAME
1642 },
1643 .probe_new = s5k6aa_probe,
1644 .remove = s5k6aa_remove,
1645 .id_table = s5k6aa_id,
1646};
1647
1648module_i2c_driver(s5k6aa_i2c_driver);
1649
1650MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver");
1651MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1652MODULE_LICENSE("GPL");
drivers/media/i2c/sr030pc30.c+0−762
@@ -1,762 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Driver for SiliconFile SR030PC30 VGA (1/10-Inch) Image Sensor with ISP
4 *
5 * Copyright (C) 2010 Samsung Electronics Co., Ltd
6 * Author: Sylwester Nawrocki, s.nawrocki@samsung.com
7 *
8 * Based on original driver authored by Dongsoo Nathaniel Kim
9 * and HeungJun Kim <riverful.kim@samsung.com>.
10 *
11 * Based on mt9v011 Micron Digital Image Sensor driver
12 * Copyright (c) 2009 Mauro Carvalho Chehab
13 */
14
15#include <linux/i2c.h>
16#include <linux/delay.h>
17#include <linux/slab.h>
18#include <linux/module.h>
19#include <media/v4l2-device.h>
20#include <media/v4l2-subdev.h>
21#include <media/v4l2-mediabus.h>
22#include <media/v4l2-ctrls.h>
23#include <media/i2c/sr030pc30.h>
24
25static int debug;
26module_param(debug, int, 0644);
27
28#define MODULE_NAME "SR030PC30"
29
30/*
31 * Register offsets within a page
32 * b15..b8 - page id, b7..b0 - register address
33 */
34#define POWER_CTRL_REG 0x0001
35#define PAGEMODE_REG 0x03
36#define DEVICE_ID_REG 0x0004
37#define NOON010PC30_ID 0x86
38#define SR030PC30_ID 0x8C
39#define VDO_CTL1_REG 0x0010
40#define SUBSAMPL_NONE_VGA 0
41#define SUBSAMPL_QVGA 0x10
42#define SUBSAMPL_QQVGA 0x20
43#define VDO_CTL2_REG 0x0011
44#define SYNC_CTL_REG 0x0012
45#define WIN_ROWH_REG 0x0020
46#define WIN_ROWL_REG 0x0021
47#define WIN_COLH_REG 0x0022
48#define WIN_COLL_REG 0x0023
49#define WIN_HEIGHTH_REG 0x0024
50#define WIN_HEIGHTL_REG 0x0025
51#define WIN_WIDTHH_REG 0x0026
52#define WIN_WIDTHL_REG 0x0027
53#define HBLANKH_REG 0x0040
54#define HBLANKL_REG 0x0041
55#define VSYNCH_REG 0x0042
56#define VSYNCL_REG 0x0043
57/* page 10 */
58#define ISP_CTL_REG(n) (0x1010 + (n))
59#define YOFS_REG 0x1040
60#define DARK_YOFS_REG 0x1041
61#define AG_ABRTH_REG 0x1050
62#define SAT_CTL_REG 0x1060
63#define BSAT_REG 0x1061
64#define RSAT_REG 0x1062
65#define AG_SAT_TH_REG 0x1063
66/* page 11 */
67#define ZLPF_CTRL_REG 0x1110
68#define ZLPF_CTRL2_REG 0x1112
69#define ZLPF_AGH_THR_REG 0x1121
70#define ZLPF_THR_REG 0x1160
71#define ZLPF_DYN_THR_REG 0x1160
72/* page 12 */
73#define YCLPF_CTL1_REG 0x1240
74#define YCLPF_CTL2_REG 0x1241
75#define YCLPF_THR_REG 0x1250
76#define BLPF_CTL_REG 0x1270
77#define BLPF_THR1_REG 0x1274
78#define BLPF_THR2_REG 0x1275
79/* page 14 - Lens Shading Compensation */
80#define LENS_CTRL_REG 0x1410
81#define LENS_XCEN_REG 0x1420
82#define LENS_YCEN_REG 0x1421
83#define LENS_R_COMP_REG 0x1422
84#define LENS_G_COMP_REG 0x1423
85#define LENS_B_COMP_REG 0x1424
86/* page 15 - Color correction */
87#define CMC_CTL_REG 0x1510
88#define CMC_OFSGH_REG 0x1514
89#define CMC_OFSGL_REG 0x1516
90#define CMC_SIGN_REG 0x1517
91/* Color correction coefficients */
92#define CMC_COEF_REG(n) (0x1530 + (n))
93/* Color correction offset coefficients */
94#define CMC_OFS_REG(n) (0x1540 + (n))
95/* page 16 - Gamma correction */
96#define GMA_CTL_REG 0x1610
97/* Gamma correction coefficients 0.14 */
98#define GMA_COEF_REG(n) (0x1630 + (n))
99/* page 20 - Auto Exposure */
100#define AE_CTL1_REG 0x2010
101#define AE_CTL2_REG 0x2011
102#define AE_FRM_CTL_REG 0x2020
103#define AE_FINE_CTL_REG(n) (0x2028 + (n))
104#define EXP_TIMEH_REG 0x2083
105#define EXP_TIMEM_REG 0x2084
106#define EXP_TIMEL_REG 0x2085
107#define EXP_MMINH_REG 0x2086
108#define EXP_MMINL_REG 0x2087
109#define EXP_MMAXH_REG 0x2088
110#define EXP_MMAXM_REG 0x2089
111#define EXP_MMAXL_REG 0x208A
112/* page 22 - Auto White Balance */
113#define AWB_CTL1_REG 0x2210
114#define AWB_ENABLE 0x80
115#define AWB_CTL2_REG 0x2211
116#define MWB_ENABLE 0x01
117/* RGB gain control (manual WB) when AWB_CTL1[7]=0 */
118#define AWB_RGAIN_REG 0x2280
119#define AWB_GGAIN_REG 0x2281
120#define AWB_BGAIN_REG 0x2282
121#define AWB_RMAX_REG 0x2283
122#define AWB_RMIN_REG 0x2284
123#define AWB_BMAX_REG 0x2285
124#define AWB_BMIN_REG 0x2286
125/* R, B gain range in bright light conditions */
126#define AWB_RMAXB_REG 0x2287
127#define AWB_RMINB_REG 0x2288
128#define AWB_BMAXB_REG 0x2289
129#define AWB_BMINB_REG 0x228A
130/* manual white balance, when AWB_CTL2[0]=1 */
131#define MWB_RGAIN_REG 0x22B2
132#define MWB_BGAIN_REG 0x22B3
133/* the token to mark an array end */
134#define REG_TERM 0xFFFF
135
136/* Minimum and maximum exposure time in ms */
137#define EXPOS_MIN_MS 1
138#define EXPOS_MAX_MS 125
139
140struct sr030pc30_info {
141 struct v4l2_subdev sd;
142 struct v4l2_ctrl_handler hdl;
143 const struct sr030pc30_platform_data *pdata;
144 const struct sr030pc30_format *curr_fmt;
145 const struct sr030pc30_frmsize *curr_win;
146 unsigned int hflip:1;
147 unsigned int vflip:1;
148 unsigned int sleep:1;
149 struct {
150 /* auto whitebalance control cluster */
151 struct v4l2_ctrl *awb;
152 struct v4l2_ctrl *red;
153 struct v4l2_ctrl *blue;
154 };
155 struct {
156 /* auto exposure control cluster */
157 struct v4l2_ctrl *autoexp;
158 struct v4l2_ctrl *exp;
159 };
160 u8 i2c_reg_page;
161};
162
163struct sr030pc30_format {
164 u32 code;
165 enum v4l2_colorspace colorspace;
166 u16 ispctl1_reg;
167};
168
169struct sr030pc30_frmsize {
170 u16 width;
171 u16 height;
172 int vid_ctl1;
173};
174
175struct i2c_regval {
176 u16 addr;
177 u16 val;
178};
179
180/* supported resolutions */
181static const struct sr030pc30_frmsize sr030pc30_sizes[] = {
182 {
183 .width = 640,
184 .height = 480,
185 .vid_ctl1 = SUBSAMPL_NONE_VGA,
186 }, {
187 .width = 320,
188 .height = 240,
189 .vid_ctl1 = SUBSAMPL_QVGA,
190 }, {
191 .width = 160,
192 .height = 120,
193 .vid_ctl1 = SUBSAMPL_QQVGA,
194 },
195};
196
197/* supported pixel formats */
198static const struct sr030pc30_format sr030pc30_formats[] = {
199 {
200 .code = MEDIA_BUS_FMT_YUYV8_2X8,
201 .colorspace = V4L2_COLORSPACE_JPEG,
202 .ispctl1_reg = 0x03,
203 }, {
204 .code = MEDIA_BUS_FMT_YVYU8_2X8,

558 more lines aren’t shown here.

drivers/media/i2c/st-vgxy61.c+11−12

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

drivers/media/i2c/tc358746.c+2−2

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

drivers/media/i2c/vs6624.c+0−854

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

drivers/media/i2c/vs6624_regs.h+0−325

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

drivers/media/mc/mc-device.c+1−2

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

drivers/media/pci/bt8xx/Kconfig+1−1

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

drivers/media/pci/bt8xx/btcx-risc.c+0−153

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

drivers/media/pci/bt8xx/btcx-risc.h+0−9

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

drivers/media/pci/bt8xx/bttv-cards.c+0−15

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

drivers/media/pci/bt8xx/bttv-driver.c+9−427

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

drivers/media/pci/bt8xx/bttv-risc.c+0−131

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

drivers/media/pci/bt8xx/bttvp.h+1−27

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

drivers/media/pci/cobalt/cobalt-v4l2.c+13−8

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

drivers/media/pci/cx18/Kconfig+1−1

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

drivers/media/pci/cx18/cx18-driver.c+2−2

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

drivers/media/pci/cx18/cx18-driver.h+12−12

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

drivers/media/pci/cx18/cx18-fileops.c+16−69

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

drivers/media/pci/cx18/cx18-fileops.h+2−1

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

drivers/media/pci/cx18/cx18-ioctl.c+159−232

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

drivers/media/pci/cx18/cx18-mailbox.c+14−13

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

drivers/media/pci/cx18/cx18-streams.c+145−133

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

drivers/media/pci/cx23885/cx23885-core.c+3−1

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

drivers/media/pci/cx23885/cx23885-video.c+7−6

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

drivers/media/pci/dm1105/dm1105.c+1−0

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

drivers/media/pci/intel/ipu3/cio2-bridge.c+19−4

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

drivers/media/pci/intel/ipu3/cio2-bridge.h+2−1

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

drivers/media/pci/intel/ipu3/ipu3-cio2-main.c+1−0

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

drivers/media/pci/saa7134/saa7134-cards.c+0−1

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

drivers/media/pci/saa7134/saa7134-core.c+0−32

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

drivers/media/pci/saa7134/saa7134-empress.c+2−2

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

drivers/media/pci/saa7134/saa7134-ts.c+1−0

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

drivers/media/pci/saa7134/saa7134-vbi.c+1−0

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

drivers/media/pci/saa7134/saa7134-video.c+5−407

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

drivers/media/pci/saa7134/saa7134.h+0−13

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

drivers/media/pci/saa7146/hexium_gemini.c+12−11

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

drivers/media/pci/saa7146/hexium_orion.c+13−11

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

drivers/media/pci/saa7146/mxb.c+29−24

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

drivers/media/pci/ttpci/budget-av.c+3−2

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

drivers/media/pci/tw68/tw68-video.c+9−7

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

drivers/media/pci/zoran/zoran_device.h+0−2

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

drivers/media/platform/allegro-dvt/allegro-core.c+2−4

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

drivers/media/platform/amlogic/meson-ge2d/ge2d.c+2−4

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

drivers/media/platform/amphion/vdec.c+53−0

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

drivers/media/platform/amphion/vpu_codec.h+2−1

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

drivers/media/platform/amphion/vpu_core.c+2−4

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

drivers/media/platform/amphion/vpu_drv.c+2−4

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

drivers/media/platform/amphion/vpu_malone.c+44−1

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

drivers/media/platform/amphion/vpu_malone.h+1−0

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

drivers/media/platform/aspeed/aspeed-video.c+2−4

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

drivers/media/platform/atmel/atmel-isi.c+4−6

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

drivers/media/platform/cadence/cdns-csi2rx.c+2−4

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

drivers/media/platform/cadence/cdns-csi2tx.c+2−4

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

drivers/media/platform/chips-media/coda-common.c+2−3

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

drivers/media/platform/intel/pxa_camera.c+4−6

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

drivers/media/platform/m2m-deinterlace.c+2−4

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

drivers/media/platform/marvell/mcam-core.c+2−2

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

drivers/media/platform/marvell/mmp-driver.c+3−13

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

drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c+84−56

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

drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h+12−16

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

drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c+13−30

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

drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c+8−30

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

drivers/media/platform/mediatek/mdp/mtk_mdp_core.c+2−3

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

drivers/media/platform/mediatek/mdp3/Makefile+1−1

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

drivers/media/platform/mediatek/mdp3/mdp_cfg_data.c+453−0

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

drivers/media/platform/mediatek/mdp3/mdp_sm_mt8183.h+144−0

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

drivers/media/platform/mediatek/mdp3/mtk-img-ipi.h+24−165

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-cfg.h+20−0

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c+101−47

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c+346−193

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.h+22−2

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c+13−40

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.h+16−2

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.c+19−17

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-m2m.h+0−1

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-regs.c+27−266

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-regs.h+109−105

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-type.h+53−0

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.c+83−110

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

drivers/media/platform/mediatek/mdp3/mtk-mdp3-vpu.h+7−22

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

drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c+10−21

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

drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c+5−5

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

drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c+8−0

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

drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateful.c+11−1

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

drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c+8−6

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

drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c+1−1

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

drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c+15−8

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

drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c+1−1

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

drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c+1−1

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

drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c+82−13

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

drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h+12−0

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

drivers/media/platform/mediatek/vpu/mtk_vpu.c+2−4

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

drivers/media/platform/microchip/microchip-csi2dc.c+2−4

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

drivers/media/platform/microchip/microchip-isc-base.c+3−2

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

drivers/media/platform/microchip/microchip-sama5d2-isc.c+2−4

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

drivers/media/platform/microchip/microchip-sama7g5-isc.c+2−4

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

drivers/media/platform/nvidia/tegra-vde/vde.c+2−4

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

drivers/media/platform/nxp/Kconfig+2−0

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

drivers/media/platform/nxp/Makefile+1−0

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

drivers/media/platform/nxp/dw100/dw100.c+3−7

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

drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c+15−4

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

drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h+3−2

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

drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c+316−28

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

drivers/media/platform/nxp/imx-mipi-csis.c+2−4

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

drivers/media/platform/nxp/imx-pxp.c+2−4

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

drivers/media/platform/nxp/imx7-media-csi.c+19−14

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

drivers/media/platform/nxp/imx8-isi/Kconfig+22−0

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

drivers/media/platform/nxp/imx8-isi/Makefile+8−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c+539−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h+394−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c+529−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-debug.c+109−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c+650−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c+858−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c+867−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-regs.h+418−0

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

drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c+1512−0

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

drivers/media/platform/nxp/mx2_emmaprp.c+2−4

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

drivers/media/platform/qcom/camss/camss-csid-gen2.c+34−20

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

drivers/media/platform/qcom/camss/camss-csid.c+31−13

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

drivers/media/platform/qcom/camss/camss-csid.h+9−2

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

drivers/media/platform/qcom/camss/camss-vfe-170.c+2−2

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

drivers/media/platform/qcom/camss/camss-vfe-480.c+40−21

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

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

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

drivers/media/platform/qcom/camss/camss-vfe.c+1−0

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

drivers/media/platform/qcom/camss/camss-video.c+21−5

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

drivers/media/platform/qcom/camss/camss.c+3−5

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

drivers/media/platform/qcom/venus/core.c+2−4

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

drivers/media/platform/qcom/venus/core.h+9−1

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

drivers/media/platform/qcom/venus/helpers.c+2−2

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

drivers/media/platform/qcom/venus/hfi_cmds.c+23−0

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

drivers/media/platform/qcom/venus/hfi_helper.h+18−0

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

drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c+2−2

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

drivers/media/platform/qcom/venus/vdec.c+20−9

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

drivers/media/platform/qcom/venus/venc.c+103−12

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

drivers/media/platform/renesas/rcar-fcp.c+2−4

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

drivers/media/platform/renesas/rcar-isp.c+3−8

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

drivers/media/platform/renesas/rcar-vin/rcar-core.c+2−40

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

drivers/media/platform/renesas/rcar-vin/rcar-csi2.c+5−16

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

drivers/media/platform/renesas/rcar_drif.c+3−5

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

drivers/media/platform/renesas/rcar_fdp1.c+10−11

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

drivers/media/platform/renesas/rcar_jpu.c+2−4

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

drivers/media/platform/renesas/renesas-ceu.c+4−6

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

drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c+2−4

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

drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c+2−4

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

drivers/media/platform/renesas/sh_vou.c+2−3

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

drivers/media/platform/renesas/vsp1/vsp1_drm.c+15−11

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

drivers/media/platform/renesas/vsp1/vsp1_drv.c+12−5

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

drivers/media/platform/renesas/vsp1/vsp1_entity.c+5−6

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

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

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

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

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

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

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

drivers/media/platform/renesas/vsp1/vsp1_video.c+4−3

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

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

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

drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c+52−0

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

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

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

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

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

drivers/media/platform/samsung/exynos-gsc/gsc-core.c+2−3

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

drivers/media/platform/samsung/exynos4-is/fimc-capture.c+11−7

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

drivers/media/platform/samsung/exynos4-is/fimc-core.c+2−3

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

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

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

drivers/media/platform/samsung/exynos4-is/fimc-is-errno.h+1−1

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

drivers/media/platform/samsung/exynos4-is/fimc-is-i2c.c+2−4

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

drivers/media/platform/samsung/exynos4-is/fimc-is.c+2−4

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

drivers/media/platform/samsung/exynos4-is/fimc-isp-video.c+7−3

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

drivers/media/platform/samsung/exynos4-is/fimc-lite.c+8−6

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

drivers/media/platform/samsung/exynos4-is/media-dev.c+9−9

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

drivers/media/platform/samsung/exynos4-is/mipi-csis.c+2−4

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

drivers/media/platform/samsung/s3c-camif/camif-capture.c+3−2

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

drivers/media/platform/samsung/s3c-camif/camif-core.c+5−6

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

drivers/media/platform/samsung/s5p-g2d/g2d.c+2−3

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

drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c+2−4

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

drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c+2−3

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

drivers/media/platform/st/sti/bdisp/bdisp-v4l2.c+4−4

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

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

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

drivers/media/platform/st/sti/delta/delta-v4l2.c+2−4

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

drivers/media/platform/st/sti/hva/hva-v4l2.c+2−4

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

drivers/media/platform/st/stm32/dma2d/dma2d.c+3−8

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

drivers/media/platform/st/stm32/dma2d/dma2d.h+0−2

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

drivers/media/platform/st/stm32/stm32-dcmi.c+3−4

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

drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c+2−4

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

drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c+2−4

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

drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c+2−4

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

drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c+2−4

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

drivers/media/platform/sunxi/sun8i-di/sun8i-di.c+2−4

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

drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c+2−4

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

drivers/media/platform/ti/am437x/am437x-vpfe.c+21−20

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

drivers/media/platform/ti/cal/cal-video.c+20−17

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

drivers/media/platform/ti/cal/cal.c+2−4

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

drivers/media/platform/ti/davinci/vpif.c+2−4

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

drivers/media/platform/ti/davinci/vpif_capture.c+2−3

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

drivers/media/platform/ti/davinci/vpif_display.c+2−4

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

drivers/media/platform/ti/omap/omap_vout.c+2−3

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

drivers/media/platform/ti/omap3isp/isp.c+2−4

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

drivers/media/platform/ti/omap3isp/ispccdc.c+3−2

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

drivers/media/platform/ti/omap3isp/ispvideo.c+12−8

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

drivers/media/platform/ti/vpe/vpe.c+2−4

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

drivers/media/platform/verisilicon/hantro_drv.c+41−15

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

drivers/media/platform/verisilicon/hantro_postproc.c+1−1

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

drivers/media/platform/verisilicon/hantro_v4l2.c+45−55

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

drivers/media/platform/verisilicon/hantro_v4l2.h+2−1

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

drivers/media/platform/verisilicon/imx8m_vpu_hw.c+2−0

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

drivers/media/platform/via/via-camera.c+7−6

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

drivers/media/platform/video-mux.c+2−4

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

drivers/media/platform/xilinx/xilinx-csi2rxss.c+2−4

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

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

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

drivers/media/platform/xilinx/xilinx-tpg.c+2−4

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

drivers/media/platform/xilinx/xilinx-vipp.c+2−4

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

drivers/media/platform/xilinx/xilinx-vtc.c+3−5

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

drivers/media/radio/radio-si476x.c+2−4

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

drivers/media/radio/radio-timb.c+2−3

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

drivers/media/radio/radio-wl1273.c+2−4

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

drivers/media/radio/si4713/radio-platform-si4713.c+2−4

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

drivers/media/rc/gpio-ir-recv.c+4−4

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

drivers/media/rc/img-ir/img-ir-core.c+2−3

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

drivers/media/rc/ir-hix5hd2.c+2−3

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

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

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

drivers/media/rc/keymaps/rc-beelink-mxiii.c+57−0

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

drivers/media/rc/keymaps/rc-dreambox.c+151−0

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

drivers/media/rc/meson-ir-tx.c+2−4

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

drivers/media/rc/meson-ir.c+2−4

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

drivers/media/rc/mtk-cir.c+2−4

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

drivers/media/rc/st_rc.c+2−3

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

drivers/media/rc/sunxi-cir.c+2−4

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

drivers/media/test-drivers/vicodec/vicodec-core.c+2−4

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

drivers/media/test-drivers/vidtv/vidtv_bridge.c+2−4

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

drivers/media/test-drivers/vim2m.c+2−4

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

drivers/media/test-drivers/vimc/vimc-common.c+4−4

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

drivers/media/test-drivers/vimc/vimc-core.c+2−4

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

drivers/media/test-drivers/visl/visl-core.c+2−4

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

drivers/media/test-drivers/vivid/vivid-core.c+8−46

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

drivers/media/test-drivers/vivid/vivid-core.h+0−19

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

drivers/media/test-drivers/vivid/vivid-kthread-cap.c+1−130

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

drivers/media/test-drivers/vivid/vivid-vid-cap.c+0−272

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

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

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

drivers/media/test-drivers/vivid/vivid-vid-out.c+0−74

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

drivers/media/tuners/it913x.c+2−4

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

drivers/media/tuners/mxl5005s.c+8−4

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

drivers/media/usb/au0828/au0828-core.c+3−8

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

drivers/media/usb/au0828/au0828-dvb.c+2−2

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

drivers/media/usb/dvb-usb/cxusb-analog.c+7−7

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

drivers/media/usb/dvb-usb/pctv452e.c+2−0

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

drivers/media/usb/pvrusb2/Kconfig+1−1

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

drivers/media/usb/usbtv/usbtv-core.c+1−1

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

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

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

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

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

drivers/media/v4l2-core/v4l2-compat-ioctl32.c+12−73

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

drivers/media/v4l2-core/v4l2-dev.c+3−2

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

drivers/media/v4l2-core/v4l2-ioctl.c+34−52

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

drivers/media/v4l2-core/v4l2-mc.c+6−9

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

drivers/media/v4l2-core/v4l2-subdev.c+166−34

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

drivers/staging/media/atomisp/i2c/atomisp-gc0310.c+218−785

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

drivers/staging/media/atomisp/i2c/atomisp-ov2680.c+8−25

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

drivers/staging/media/atomisp/i2c/gc0310.h+165−251

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

drivers/staging/media/atomisp/i2c/ov2680.h+0−1

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

drivers/staging/media/atomisp/include/linux/atomisp.h+0−28

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

drivers/staging/media/atomisp/include/linux/atomisp_platform.h+5−6

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

drivers/staging/media/atomisp/pci/atomisp_cmd.c+142−936

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

drivers/staging/media/atomisp/pci/atomisp_cmd.h+0−9

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

drivers/staging/media/atomisp/pci/atomisp_compat.h+1−10

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

drivers/staging/media/atomisp/pci/atomisp_compat_css20.c+66−354

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

drivers/staging/media/atomisp/pci/atomisp_fops.c+5−114

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

drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c+270−19

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

drivers/staging/media/atomisp/pci/atomisp_internal.h+2−39

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

drivers/staging/media/atomisp/pci/atomisp_ioctl.c+21−205

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

drivers/staging/media/atomisp/pci/atomisp_ioctl.h+0−6

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

drivers/staging/media/atomisp/pci/atomisp_subdev.c+39−150

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

drivers/staging/media/atomisp/pci/atomisp_subdev.h+0−22

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

drivers/staging/media/atomisp/pci/atomisp_v4l2.c+15−60

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

drivers/staging/media/av7110/av7110.c+4−2

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

drivers/staging/media/av7110/av7110_av.c+2−2

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

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

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

drivers/staging/media/av7110/av7110_v4l.c+76−72

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

drivers/staging/media/deprecated/atmel/atmel-isc-base.c+5−4

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

drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c+3−7

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

drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c+3−7

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

drivers/staging/media/imx/imx-media-capture.c+22−18

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

drivers/staging/media/imx/imx-media-csi.c+2−4

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

drivers/staging/media/imx/imx-media-dev-common.c+0−14

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

drivers/staging/media/imx/imx-media-dev.c+2−4

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

drivers/staging/media/imx/imx-media-of.c+2−3

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

drivers/staging/media/imx/imx-media-utils.c+4−72

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

drivers/staging/media/imx/imx-media.h+0−13

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

drivers/staging/media/imx/imx6-mipi-csi2.c+2−4

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

drivers/staging/media/imx/imx8mq-mipi-csi2.c+60−98

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

drivers/staging/media/meson/vdec/vdec.c+2−4

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

drivers/staging/media/omap4iss/iss.c+2−4

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

drivers/staging/media/omap4iss/iss_video.c+9−7

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

drivers/staging/media/rkvdec/rkvdec.c+4−3

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

drivers/staging/media/sunxi/cedrus/cedrus.c+3−4

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

drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c+2−4

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

drivers/staging/media/tegra-video/vi.c+6−4

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

include/media/drv-intf/saa7146_vv.h+10−55

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

include/media/dvb_net.h+2−4

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

include/media/i2c/ad9389b.h+0−37

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

include/media/i2c/m5mols.h+0−25

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

include/media/i2c/mt9m032.h+0−22

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

include/media/i2c/mt9t001.h+0−10

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

include/media/i2c/noon010pc30.h+0−21

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

include/media/i2c/s5k6aa.h+0−48

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

include/media/i2c/sr030pc30.h+0−17

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

include/media/media-device.h+2−3

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

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

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

include/media/tveeprom.h+1−1

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

include/media/v4l2-ctrls.h+1−1

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

include/media/v4l2-mc.h+4−4

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

include/media/v4l2-subdev.h+28−5

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

include/uapi/linux/v4l2-subdev.h+21−0

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

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

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