aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig14
-rw-r--r--drivers/staging/Makefile9
-rw-r--r--drivers/staging/android/Kconfig19
-rw-r--r--drivers/staging/android/Makefile4
-rw-r--r--drivers/staging/android/TODO8
-rw-r--r--drivers/staging/android/ashmem.c970
-rw-r--r--drivers/staging/android/ashmem.h24
-rw-r--r--drivers/staging/android/uapi/ashmem.h43
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.c11
-rw-r--r--drivers/staging/fbtft/Kconfig6
-rw-r--r--drivers/staging/fbtft/Makefile1
-rw-r--r--drivers/staging/fbtft/fb_sh1106.c7
-rw-r--r--drivers/staging/fbtft/fb_st7789v.c2
-rw-r--r--drivers/staging/fbtft/fb_watterott.c302
-rw-r--r--drivers/staging/fbtft/fbtft-core.c29
-rw-r--r--drivers/staging/fbtft/fbtft.h82
-rw-r--r--drivers/staging/fieldbus/anybuss/host.c2
-rw-r--r--drivers/staging/gdm724x/gdm_lte.c8
-rw-r--r--drivers/staging/gdm724x/hci_packet.h2
-rw-r--r--drivers/staging/greybus/arche-apb-ctrl.c2
-rw-r--r--drivers/staging/greybus/arche-platform.c2
-rw-r--r--drivers/staging/greybus/audio_codec.c44
-rw-r--r--drivers/staging/greybus/audio_manager_module.c3
-rw-r--r--drivers/staging/greybus/audio_topology.c107
-rw-r--r--drivers/staging/greybus/gpio.c5
-rw-r--r--drivers/staging/greybus/pwm.c65
-rw-r--r--drivers/staging/greybus/sdio.c1
-rw-r--r--drivers/staging/greybus/tools/Makefile3
-rw-r--r--drivers/staging/greybus/tools/loopback_test.c2
-rw-r--r--drivers/staging/gs_fpgaboot/Kconfig8
-rw-r--r--drivers/staging/gs_fpgaboot/Makefile3
-rw-r--r--drivers/staging/gs_fpgaboot/README70
-rw-r--r--drivers/staging/gs_fpgaboot/TODO7
-rw-r--r--drivers/staging/gs_fpgaboot/gs_fpgaboot.c394
-rw-r--r--drivers/staging/gs_fpgaboot/gs_fpgaboot.h41
-rw-r--r--drivers/staging/gs_fpgaboot/io.c105
-rw-r--r--drivers/staging/gs_fpgaboot/io.h73
-rw-r--r--drivers/staging/iio/accel/adis16203.c1
-rw-r--r--drivers/staging/iio/accel/adis16240.c1
-rw-r--r--drivers/staging/iio/adc/Kconfig11
-rw-r--r--drivers/staging/iio/adc/Makefile1
-rw-r--r--drivers/staging/iio/adc/ad7280a.c1044
-rw-r--r--drivers/staging/iio/adc/ad7280a.h37
-rw-r--r--drivers/staging/iio/cdc/ad7746.c2
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c1
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c1
-rw-r--r--drivers/staging/ks7010/ks7010_sdio.c4
-rw-r--r--drivers/staging/ks7010/ks_hostif.c19
-rw-r--r--drivers/staging/ks7010/ks_wlan.h2
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/atomisp/Kconfig2
-rw-r--r--drivers/staging/media/atomisp/i2c/Kconfig14
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_acc.c28
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_css20.c4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c148
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c21
-rw-r--r--drivers/staging/media/atomisp/pci/hmm/hmm.c7
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_acc_types.h5
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_env.h9
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_event_public.h33
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_irq.h77
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5.host.c2
-rw-r--r--drivers/staging/media/atomisp/pci/isp2400_input_system_local.h2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h31
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/rmgr/src/rmgr_vbuf.c4
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_firmware.c4
-rw-r--r--drivers/staging/media/av7110/av7110_av.c46
-rw-r--r--drivers/staging/media/hantro/Kconfig2
-rw-r--r--drivers/staging/media/hantro/TODO15
-rw-r--r--drivers/staging/media/hantro/hantro.h3
-rw-r--r--drivers/staging/media/hantro/hantro_drv.c70
-rw-r--r--drivers/staging/media/hantro/hantro_g1_h264_dec.c38
-rw-r--r--drivers/staging/media/hantro/hantro_g2_hevc_dec.c63
-rw-r--r--drivers/staging/media/hantro/hantro_g2_regs.h6
-rw-r--r--drivers/staging/media/hantro/hantro_h1_jpeg_enc.c41
-rw-r--r--drivers/staging/media/hantro/hantro_h1_regs.h2
-rw-r--r--drivers/staging/media/hantro/hantro_h264.c134
-rw-r--r--drivers/staging/media/hantro/hantro_hevc.c46
-rw-r--r--drivers/staging/media/hantro/hantro_hw.h34
-rw-r--r--drivers/staging/media/hantro/hantro_jpeg.c86
-rw-r--r--drivers/staging/media/hantro/hantro_jpeg.h2
-rw-r--r--drivers/staging/media/hantro/hantro_postproc.c53
-rw-r--r--drivers/staging/media/hantro/hantro_v4l2.c184
-rw-r--r--drivers/staging/media/hantro/imx8m_vpu_hw.c62
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c98
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c44
-rw-r--r--drivers/staging/media/hantro/rockchip_vpu_hw.c20
-rw-r--r--drivers/staging/media/hantro/sunxi_vpu_hw.c4
-rw-r--r--drivers/staging/media/imx/Kconfig2
-rw-r--r--drivers/staging/media/imx/Makefile1
-rw-r--r--drivers/staging/media/imx/TODO25
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c7
-rw-r--r--drivers/staging/media/imx/imx6-mipi-csi2.c25
-rw-r--r--drivers/staging/media/imx/imx7-media-csi.c64
-rw-r--r--drivers/staging/media/imx/imx7-mipi-csis.c1494
-rw-r--r--drivers/staging/media/imx/imx8mq-mipi-csi2.c81
-rw-r--r--drivers/staging/media/ipu3/Kconfig2
-rw-r--r--drivers/staging/media/ipu3/ipu3-css-fw.c4
-rw-r--r--drivers/staging/media/ipu3/ipu3-css-fw.h4
-rw-r--r--drivers/staging/media/ipu3/ipu3-css-params.c20
-rw-r--r--drivers/staging/media/ipu3/ipu3-v4l2.c1
-rw-r--r--drivers/staging/media/ipu3/ipu3.c25
-rw-r--r--drivers/staging/media/max96712/Kconfig2
-rw-r--r--drivers/staging/media/max96712/max96712.c2
-rw-r--r--drivers/staging/media/meson/vdec/Kconfig2
-rw-r--r--drivers/staging/media/meson/vdec/esparser.c7
-rw-r--r--drivers/staging/media/meson/vdec/vdec_helpers.c8
-rw-r--r--drivers/staging/media/meson/vdec/vdec_helpers.h4
-rw-r--r--drivers/staging/media/meson/vdec/vdec_platform.c12
-rw-r--r--drivers/staging/media/omap4iss/Kconfig2
-rw-r--r--drivers/staging/media/rkvdec/Kconfig2
-rw-r--r--drivers/staging/media/rkvdec/TODO4
-rw-r--r--drivers/staging/media/rkvdec/rkvdec-h264.c157
-rw-r--r--drivers/staging/media/rkvdec/rkvdec.c35
-rw-r--r--drivers/staging/media/rkvdec/rkvdec.h2
-rw-r--r--drivers/staging/media/sunxi/cedrus/Kconfig2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.h3
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_dec.c4
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_h264.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_h265.c4
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_hw.c25
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_hw.h2
-rw-r--r--drivers/staging/media/tegra-vde/Kconfig10
-rw-r--r--drivers/staging/media/tegra-vde/Makefile3
-rw-r--r--drivers/staging/media/tegra-vde/TODO4
-rw-r--r--drivers/staging/media/tegra-vde/dmabuf-cache.c229
-rw-r--r--drivers/staging/media/tegra-vde/iommu.c157
-rw-r--r--drivers/staging/media/tegra-vde/trace.h95
-rw-r--r--drivers/staging/media/tegra-vde/uapi.h73
-rw-r--r--drivers/staging/media/tegra-vde/vde.c1358
-rw-r--r--drivers/staging/media/tegra-vde/vde.h125
-rw-r--r--drivers/staging/media/tegra-video/Kconfig2
-rw-r--r--drivers/staging/media/tegra-video/vi.c10
-rw-r--r--drivers/staging/media/zoran/Kconfig40
-rw-r--r--drivers/staging/media/zoran/Makefile8
-rw-r--r--drivers/staging/media/zoran/videocodec.c68
-rw-r--r--drivers/staging/media/zoran/videocodec.h4
-rw-r--r--drivers/staging/media/zoran/zoran.h18
-rw-r--r--drivers/staging/media/zoran/zoran_card.c398
-rw-r--r--drivers/staging/media/zoran/zoran_device.c15
-rw-r--r--drivers/staging/media/zoran/zoran_device.h2
-rw-r--r--drivers/staging/media/zoran/zoran_driver.c56
-rw-r--r--drivers/staging/media/zoran/zr36016.c25
-rw-r--r--drivers/staging/media/zoran/zr36016.h2
-rw-r--r--drivers/staging/media/zoran/zr36050.c24
-rw-r--r--drivers/staging/media/zoran/zr36050.h2
-rw-r--r--drivers/staging/media/zoran/zr36060.c23
-rw-r--r--drivers/staging/media/zoran/zr36060.h2
-rw-r--r--drivers/staging/most/dim2/dim2.c57
-rw-r--r--drivers/staging/most/net/net.c2
-rw-r--r--drivers/staging/most/video/Kconfig2
-rw-r--r--drivers/staging/most/video/video.c2
-rw-r--r--drivers/staging/mt7621-dma/Kconfig7
-rw-r--r--drivers/staging/mt7621-dma/Makefile4
-rw-r--r--drivers/staging/mt7621-dma/TODO5
-rw-r--r--drivers/staging/mt7621-dma/hsdma-mt7621.c758
-rw-r--r--drivers/staging/mt7621-dts/Kconfig11
-rw-r--r--drivers/staging/mt7621-dts/Makefile5
-rw-r--r--drivers/staging/mt7621-dts/TODO5
-rw-r--r--drivers/staging/mt7621-dts/gbpc1.dts128
-rw-r--r--drivers/staging/mt7621-dts/gbpc2.dts22
-rw-r--r--drivers/staging/mt7621-dts/mt7621.dtsi540
-rw-r--r--drivers/staging/nvec/nvec.c4
-rw-r--r--drivers/staging/olpc_dcon/Kconfig2
-rw-r--r--drivers/staging/pi433/TODO4
-rw-r--r--drivers/staging/pi433/pi433_if.c182
-rw-r--r--drivers/staging/pi433/pi433_if.h2
-rw-r--r--drivers/staging/pi433/rf69.c191
-rw-r--r--drivers/staging/pi433/rf69.h3
-rw-r--r--drivers/staging/pi433/rf69_enum.h32
-rw-r--r--drivers/staging/pi433/rf69_registers.h2
-rw-r--r--drivers/staging/qlge/qlge.h1
-rw-r--r--drivers/staging/qlge/qlge_main.c11
-rw-r--r--drivers/staging/r8188eu/Makefile5
-rw-r--r--drivers/staging/r8188eu/core/rtw_ap.c254
-rw-r--r--drivers/staging/r8188eu/core/rtw_br_ext.c169
-rw-r--r--drivers/staging/r8188eu/core/rtw_cmd.c402
-rw-r--r--drivers/staging/r8188eu/core/rtw_efuse.c221
-rw-r--r--drivers/staging/r8188eu/core/rtw_fw.c299
-rw-r--r--drivers/staging/r8188eu/core/rtw_ieee80211.c159
-rw-r--r--drivers/staging/r8188eu/core/rtw_ioctl_set.c27
-rw-r--r--drivers/staging/r8188eu/core/rtw_iol.c16
-rw-r--r--drivers/staging/r8188eu/core/rtw_led.c295
-rw-r--r--drivers/staging/r8188eu/core/rtw_mlme.c435
-rw-r--r--drivers/staging/r8188eu/core/rtw_mlme_ext.c1216
-rw-r--r--drivers/staging/r8188eu/core/rtw_p2p.c149
-rw-r--r--drivers/staging/r8188eu/core/rtw_pwrctrl.c160
-rw-r--r--drivers/staging/r8188eu/core/rtw_recv.c441
-rw-r--r--drivers/staging/r8188eu/core/rtw_rf.c62
-rw-r--r--drivers/staging/r8188eu/core/rtw_security.c191
-rw-r--r--drivers/staging/r8188eu/core/rtw_sta_mgt.c20
-rw-r--r--drivers/staging/r8188eu/core/rtw_wlan_util.c287
-rw-r--r--drivers/staging/r8188eu/core/rtw_xmit.c219
-rw-r--r--drivers/staging/r8188eu/hal/Hal8188EPwrSeq.c100
-rw-r--r--drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c27
-rw-r--r--drivers/staging/r8188eu/hal/HalHWImg8188E_BB.c7
-rw-r--r--drivers/staging/r8188eu/hal/HalHWImg8188E_MAC.c3
-rw-r--r--drivers/staging/r8188eu/hal/HalHWImg8188E_RF.c3
-rw-r--r--drivers/staging/r8188eu/hal/HalPhyRf_8188e.c528
-rw-r--r--drivers/staging/r8188eu/hal/HalPwrSeqCmd.c104
-rw-r--r--drivers/staging/r8188eu/hal/hal_com.c40
-rw-r--r--drivers/staging/r8188eu/hal/hal_intf.c3
-rw-r--r--drivers/staging/r8188eu/hal/odm.c907
-rw-r--r--drivers/staging/r8188eu/hal/odm_HWConfig.c72
-rw-r--r--drivers/staging/r8188eu/hal/odm_RTL8188E.c176
-rw-r--r--drivers/staging/r8188eu/hal/odm_RegConfig8188E.c61
-rw-r--r--drivers/staging/r8188eu/hal/odm_debug.c6
-rw-r--r--drivers/staging/r8188eu/hal/odm_interface.c93
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_cmd.c108
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_dm.c75
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_hal_init.c1394
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_phycfg.c349
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_rf6052.c79
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_rxdesc.c91
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188e_sreset.c37
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188eu_led.c94
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188eu_recv.c26
-rw-r--r--drivers/staging/r8188eu/hal/rtl8188eu_xmit.c32
-rw-r--r--drivers/staging/r8188eu/hal/usb_halinit.c1012
-rw-r--r--drivers/staging/r8188eu/hal/usb_ops_linux.c100
-rw-r--r--drivers/staging/r8188eu/include/Hal8188EPhyCfg.h66
-rw-r--r--drivers/staging/r8188eu/include/Hal8188EPwrSeq.h148
-rw-r--r--drivers/staging/r8188eu/include/HalPhyRf_8188e.h5
-rw-r--r--drivers/staging/r8188eu/include/HalPwrSeqCmd.h53
-rw-r--r--drivers/staging/r8188eu/include/HalVerDef.h41
-rw-r--r--drivers/staging/r8188eu/include/basic_types.h73
-rw-r--r--drivers/staging/r8188eu/include/drv_types.h68
-rw-r--r--drivers/staging/r8188eu/include/hal_com.h3
-rw-r--r--drivers/staging/r8188eu/include/hal_intf.h108
-rw-r--r--drivers/staging/r8188eu/include/ieee80211.h337
-rw-r--r--drivers/staging/r8188eu/include/ieee80211_ext.h271
-rw-r--r--drivers/staging/r8188eu/include/odm.h295
-rw-r--r--drivers/staging/r8188eu/include/odm_HWConfig.h39
-rw-r--r--drivers/staging/r8188eu/include/odm_RTL8188E.h6
-rw-r--r--drivers/staging/r8188eu/include/odm_RegConfig8188E.h3
-rw-r--r--drivers/staging/r8188eu/include/odm_interface.h59
-rw-r--r--drivers/staging/r8188eu/include/odm_precomp.h54
-rw-r--r--drivers/staging/r8188eu/include/osdep_service.h129
-rw-r--r--drivers/staging/r8188eu/include/recv_osdep.h5
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_dm.h10
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_hal.h198
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_led.h16
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_recv.h11
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_spec.h73
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_sreset.h13
-rw-r--r--drivers/staging/r8188eu/include/rtl8188e_xmit.h4
-rw-r--r--drivers/staging/r8188eu/include/rtw_br_ext.h5
-rw-r--r--drivers/staging/r8188eu/include/rtw_cmd.h27
-rw-r--r--drivers/staging/r8188eu/include/rtw_debug.h75
-rw-r--r--drivers/staging/r8188eu/include/rtw_eeprom.h34
-rw-r--r--drivers/staging/r8188eu/include/rtw_efuse.h104
-rw-r--r--drivers/staging/r8188eu/include/rtw_fw.h17
-rw-r--r--drivers/staging/r8188eu/include/rtw_io.h2
-rw-r--r--drivers/staging/r8188eu/include/rtw_ioctl.h79
-rw-r--r--drivers/staging/r8188eu/include/rtw_led.h116
-rw-r--r--drivers/staging/r8188eu/include/rtw_mlme.h34
-rw-r--r--drivers/staging/r8188eu/include/rtw_mlme_ext.h73
-rw-r--r--drivers/staging/r8188eu/include/rtw_pwrctrl.h32
-rw-r--r--drivers/staging/r8188eu/include/rtw_recv.h65
-rw-r--r--drivers/staging/r8188eu/include/rtw_rf.h34
-rw-r--r--drivers/staging/r8188eu/include/rtw_security.h112
-rw-r--r--drivers/staging/r8188eu/include/rtw_xmit.h4
-rw-r--r--drivers/staging/r8188eu/include/sta_info.h50
-rw-r--r--drivers/staging/r8188eu/include/usb_ops.h30
-rw-r--r--drivers/staging/r8188eu/include/usb_osintf.h5
-rw-r--r--drivers/staging/r8188eu/include/usb_vendor_req.h35
-rw-r--r--drivers/staging/r8188eu/include/wifi.h187
-rw-r--r--drivers/staging/r8188eu/include/wlan_bssdef.h2
-rw-r--r--drivers/staging/r8188eu/include/xmit_osdep.h2
-rw-r--r--drivers/staging/r8188eu/os_dep/ioctl_linux.c1032
-rw-r--r--drivers/staging/r8188eu/os_dep/mlme_linux.c5
-rw-r--r--drivers/staging/r8188eu/os_dep/os_intfs.c163
-rw-r--r--drivers/staging/r8188eu/os_dep/osdep_service.c29
-rw-r--r--drivers/staging/r8188eu/os_dep/recv_linux.c35
-rw-r--r--drivers/staging/r8188eu/os_dep/usb_intf.c168
-rw-r--r--drivers/staging/r8188eu/os_dep/usb_ops_linux.c49
-rw-r--r--drivers/staging/r8188eu/os_dep/xmit_linux.c22
-rw-r--r--drivers/staging/ralink-gdma/Kconfig8
-rw-r--r--drivers/staging/ralink-gdma/Makefile4
-rw-r--r--drivers/staging/ralink-gdma/ralink-gdma.c917
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c8
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c52
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c3
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c22
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c20
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BAProc.c5
-rw-r--r--drivers/staging/rtl8192e/rtllib.h4
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_ccmp.c10
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_tkip.c38
-rw-r--r--drivers/staging/rtl8192e/rtllib_debug.h54
-rw-r--r--drivers/staging/rtl8192e/rtllib_module.c17
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c24
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c69
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c4
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h11
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_module.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c34
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c8
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c15
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c58
-rw-r--r--drivers/staging/rtl8712/drv_types.h3
-rw-r--r--drivers/staging/rtl8712/ieee80211.c4
-rw-r--r--drivers/staging/rtl8712/os_intfs.c1
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h1
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c28
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.h4
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h3
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_regdef.h2
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h1
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c16
-rw-r--r--drivers/staging/rtl8712/rtl8712_security_bitdef.h1
-rw-r--r--drivers/staging/rtl8712/rtl8712_spec.h3
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h4
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_regdef.h2
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h1
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_bitdef.h1
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c4
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.h11
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl.h1
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c24
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.c1
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c3
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c102
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.h1
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h3
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c5
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.h8
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.c1
-rw-r--r--drivers/staging/rtl8712/sta_info.h1
-rw-r--r--drivers/staging/rtl8712/usb_intf.c14
-rw-r--r--drivers/staging/rtl8712/usb_ops.c27
-rw-r--r--drivers/staging/rtl8712/usb_ops_linux.c21
-rw-r--r--drivers/staging/rtl8712/wifi.h1
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c8
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_ap.c24
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_cmd.c69
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_efuse.c68
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_ieee80211.c44
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme.c68
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme_ext.c201
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_recv.c21
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_rf.c56
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_sta_mgt.c22
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_xmit.c21
-rw-r--r--drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h11
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_btcoex.c8
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_intf.c5
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c3
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c7
-rw-r--r--drivers/staging/rtl8723bs/hal/sdio_ops.c15
-rw-r--r--drivers/staging/rtl8723bs/include/HalVerDef.h10
-rw-r--r--drivers/staging/rtl8723bs/include/drv_types.h1
-rw-r--r--drivers/staging/rtl8723bs/include/hal_com_reg.h295
-rw-r--r--drivers/staging/rtl8723bs/include/ieee80211.h2
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_cmd.h2
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_ioctl.h72
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mlme.h8
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_recv.h11
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c100
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_linux.c6
-rw-r--r--drivers/staging/rtl8723bs/os_dep/os_intfs.c8
-rw-r--r--drivers/staging/rts5208/ms.c9
-rw-r--r--drivers/staging/rts5208/rtsx.c24
-rw-r--r--drivers/staging/rts5208/rtsx_transport.c12
-rw-r--r--drivers/staging/sm750fb/ddk750_dvi.c68
-rw-r--r--drivers/staging/sm750fb/ddk750_dvi.h64
-rw-r--r--drivers/staging/sm750fb/sm750_hw.c1
-rw-r--r--drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset89
-rw-r--r--drivers/staging/unisys/Documentation/overview.txt337
-rw-r--r--drivers/staging/unisys/Kconfig16
-rw-r--r--drivers/staging/unisys/MAINTAINERS5
-rw-r--r--drivers/staging/unisys/Makefile7
-rw-r--r--drivers/staging/unisys/TODO16
-rw-r--r--drivers/staging/unisys/include/iochannel.h571
-rw-r--r--drivers/staging/unisys/visorhba/Kconfig15
-rw-r--r--drivers/staging/unisys/visorhba/Makefile10
-rw-r--r--drivers/staging/unisys/visorhba/visorhba_main.c1142
-rw-r--r--drivers/staging/unisys/visorinput/Kconfig16
-rw-r--r--drivers/staging/unisys/visorinput/Makefile7
-rw-r--r--drivers/staging/unisys/visorinput/visorinput.c787
-rw-r--r--drivers/staging/unisys/visornic/Kconfig16
-rw-r--r--drivers/staging/unisys/visornic/Makefile10
-rw-r--r--drivers/staging/unisys/visornic/visornic_main.c2150
-rw-r--r--drivers/staging/vc04_services/Kconfig1
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/Kconfig8
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/TODO10
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c86
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c5
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c2
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835.c45
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835.h2
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/Kconfig6
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c123
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h12
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/controls.c176
-rw-r--r--drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h2
-rw-r--r--drivers/staging/vc04_services/interface/TODO60
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c85
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c137
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h5
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c4
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c20
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-common.h2
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h2
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h9
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h8
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h2
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h2
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h17
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c20
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h2
-rw-r--r--drivers/staging/vme/Makefile2
-rw-r--r--drivers/staging/vme_user/Kconfig (renamed from drivers/staging/vme/devices/Kconfig)2
-rw-r--r--drivers/staging/vme_user/Makefile (renamed from drivers/staging/vme/devices/Makefile)0
-rw-r--r--drivers/staging/vme_user/vme_user.c (renamed from drivers/staging/vme/devices/vme_user.c)2
-rw-r--r--drivers/staging/vme_user/vme_user.h (renamed from drivers/staging/vme/devices/vme_user.h)0
-rw-r--r--drivers/staging/vt6655/baseband.c95
-rw-r--r--drivers/staging/vt6655/card.c102
-rw-r--r--drivers/staging/vt6655/card.h2
-rw-r--r--drivers/staging/vt6655/channel.c93
-rw-r--r--drivers/staging/vt6655/device.h10
-rw-r--r--drivers/staging/vt6655/device_main.c49
-rw-r--r--drivers/staging/vt6655/dpc.c2
-rw-r--r--drivers/staging/vt6655/key.c1
-rw-r--r--drivers/staging/vt6655/mac.c1
-rw-r--r--drivers/staging/vt6655/mac.h271
-rw-r--r--drivers/staging/vt6655/rf.c450
-rw-r--r--drivers/staging/vt6655/rf.h2
-rw-r--r--drivers/staging/vt6655/rxtx.c8
-rw-r--r--drivers/staging/vt6655/srom.c19
-rw-r--r--drivers/staging/vt6655/tmacro.h43
-rw-r--r--drivers/staging/vt6655/upc.h25
-rw-r--r--drivers/staging/vt6656/baseband.c40
-rw-r--r--drivers/staging/vt6656/card.c18
-rw-r--r--drivers/staging/vt6656/channel.c97
-rw-r--r--drivers/staging/vt6656/device.h11
-rw-r--r--drivers/staging/vt6656/mac.c14
-rw-r--r--drivers/staging/vt6656/mac.h22
-rw-r--r--drivers/staging/vt6656/rf.c414
-rw-r--r--drivers/staging/vt6656/rxtx.c8
-rw-r--r--drivers/staging/vt6656/usbpipe.c4
-rw-r--r--drivers/staging/vt6656/wcmd.c13
-rw-r--r--drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml125
-rw-r--r--drivers/staging/wfx/Kconfig8
-rw-r--r--drivers/staging/wfx/Makefile25
-rw-r--r--drivers/staging/wfx/TODO6
-rw-r--r--drivers/staging/wfx/bh.c330
-rw-r--r--drivers/staging/wfx/bh.h33
-rw-r--r--drivers/staging/wfx/bus.h38
-rw-r--r--drivers/staging/wfx/bus_sdio.c272
-rw-r--r--drivers/staging/wfx/bus_spi.c271
-rw-r--r--drivers/staging/wfx/data_rx.c94
-rw-r--r--drivers/staging/wfx/data_rx.h18
-rw-r--r--drivers/staging/wfx/data_tx.c596
-rw-r--r--drivers/staging/wfx/data_tx.h68
-rw-r--r--drivers/staging/wfx/debug.c365
-rw-r--r--drivers/staging/wfx/debug.h19
-rw-r--r--drivers/staging/wfx/fwio.c405
-rw-r--r--drivers/staging/wfx/fwio.h15
-rw-r--r--drivers/staging/wfx/hif_api_cmd.h555
-rw-r--r--drivers/staging/wfx/hif_api_general.h262
-rw-r--r--drivers/staging/wfx/hif_api_mib.h346
-rw-r--r--drivers/staging/wfx/hif_rx.c416
-rw-r--r--drivers/staging/wfx/hif_rx.h17
-rw-r--r--drivers/staging/wfx/hif_tx.c513
-rw-r--r--drivers/staging/wfx/hif_tx.h60
-rw-r--r--drivers/staging/wfx/hif_tx_mib.c324
-rw-r--r--drivers/staging/wfx/hif_tx_mib.h49
-rw-r--r--drivers/staging/wfx/hwio.c352
-rw-r--r--drivers/staging/wfx/hwio.h75
-rw-r--r--drivers/staging/wfx/key.c241
-rw-r--r--drivers/staging/wfx/key.h20
-rw-r--r--drivers/staging/wfx/main.c506
-rw-r--r--drivers/staging/wfx/main.h43
-rw-r--r--drivers/staging/wfx/queue.c307
-rw-r--r--drivers/staging/wfx/queue.h45
-rw-r--r--drivers/staging/wfx/scan.c149
-rw-r--r--drivers/staging/wfx/scan.h22
-rw-r--r--drivers/staging/wfx/sta.c833
-rw-r--r--drivers/staging/wfx/sta.h73
-rw-r--r--drivers/staging/wfx/traces.h501
-rw-r--r--drivers/staging/wfx/wfx.h164
-rw-r--r--drivers/staging/wlan-ng/cfg80211.c10
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h4
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c34
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c4
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c8
-rw-r--r--drivers/staging/wlan-ng/prism2usb.c8
496 files changed, 6918 insertions, 39721 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 7fec86946131..0a993c47273e 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -58,18 +58,12 @@ source "drivers/staging/nvec/Kconfig"
source "drivers/staging/media/Kconfig"
-source "drivers/staging/android/Kconfig"
-
source "drivers/staging/board/Kconfig"
source "drivers/staging/gdm724x/Kconfig"
source "drivers/staging/fwserial/Kconfig"
-source "drivers/staging/gs_fpgaboot/Kconfig"
-
-source "drivers/staging/unisys/Kconfig"
-
source "drivers/staging/clocking-wizard/Kconfig"
source "drivers/staging/fbtft/Kconfig"
@@ -84,18 +78,12 @@ source "drivers/staging/vc04_services/Kconfig"
source "drivers/staging/pi433/Kconfig"
-source "drivers/staging/mt7621-dma/Kconfig"
-
-source "drivers/staging/ralink-gdma/Kconfig"
-
-source "drivers/staging/mt7621-dts/Kconfig"
-
source "drivers/staging/axis-fifo/Kconfig"
source "drivers/staging/fieldbus/Kconfig"
source "drivers/staging/qlge/Kconfig"
-source "drivers/staging/wfx/Kconfig"
+source "drivers/staging/vme_user/Kconfig"
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index e66e19c45425..2800ab9b2d1d 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -14,17 +14,14 @@ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_OCTEON_USB) += octeon-usb/
obj-$(CONFIG_VT6655) += vt6655/
obj-$(CONFIG_VT6656) += vt6656/
-obj-$(CONFIG_VME_BUS) += vme/
+obj-$(CONFIG_VME_BUS) += vme_user/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_FB_SM750) += sm750fb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
obj-$(CONFIG_MFD_NVEC) += nvec/
-obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_STAGING_BOARD) += board/
obj-$(CONFIG_LTE_GDM724X) += gdm724x/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
-obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/
-obj-$(CONFIG_UNISYSSPAR) += unisys/
obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/
obj-$(CONFIG_FB_TFT) += fbtft/
obj-$(CONFIG_MOST) += most/
@@ -32,10 +29,6 @@ obj-$(CONFIG_KS7010) += ks7010/
obj-$(CONFIG_GREYBUS) += greybus/
obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/
obj-$(CONFIG_PI433) += pi433/
-obj-$(CONFIG_SOC_MT7621) += mt7621-dma/
-obj-$(CONFIG_DMA_RALINK) += ralink-gdma/
-obj-$(CONFIG_SOC_MT7621) += mt7621-dts/
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/
obj-$(CONFIG_QLGE) += qlge/
-obj-$(CONFIG_WFX) += wfx/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
deleted file mode 100644
index 70498adb1575..000000000000
--- a/drivers/staging/android/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-menu "Android"
-
-if ANDROID
-
-config ASHMEM
- bool "Enable the Anonymous Shared Memory Subsystem"
- depends on SHMEM
- help
- The ashmem subsystem is a new shared memory allocator, similar to
- POSIX SHM but with different behavior and sporting a simpler
- file-based API.
-
- It is, in theory, a good memory allocator for low-memory devices,
- because it can discard shared memory units when under memory pressure.
-
-endif # if ANDROID
-
-endmenu
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
deleted file mode 100644
index e9a55a5e6529..000000000000
--- a/drivers/staging/android/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-ccflags-y += -I$(src) # needed for trace events
-
-obj-$(CONFIG_ASHMEM) += ashmem.o
diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO
deleted file mode 100644
index f74eb44d8e45..000000000000
--- a/drivers/staging/android/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-TODO:
- - sparse fixes
- - rename files to be not so "generic"
- - add proper arch dependencies as needed
- - audit userspace interfaces to make sure they are sane
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
-Arve Hjønnevåg <arve@android.com> and Riley Andrews <riandrews@android.com>
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
deleted file mode 100644
index ddbde3f8430e..000000000000
--- a/drivers/staging/android/ashmem.c
+++ /dev/null
@@ -1,970 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* mm/ashmem.c
- *
- * Anonymous Shared Memory Subsystem, ashmem
- *
- * Copyright (C) 2008 Google, Inc.
- *
- * Robert Love <rlove@google.com>
- */
-
-#define pr_fmt(fmt) "ashmem: " fmt
-
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/falloc.h>
-#include <linux/miscdevice.h>
-#include <linux/security.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/uaccess.h>
-#include <linux/personality.h>
-#include <linux/bitops.h>
-#include <linux/mutex.h>
-#include <linux/shmem_fs.h>
-#include "ashmem.h"
-
-#define ASHMEM_NAME_PREFIX "dev/ashmem/"
-#define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1)
-#define ASHMEM_FULL_NAME_LEN (ASHMEM_NAME_LEN + ASHMEM_NAME_PREFIX_LEN)
-
-/**
- * struct ashmem_area - The anonymous shared memory area
- * @name: The optional name in /proc/pid/maps
- * @unpinned_list: The list of all ashmem areas
- * @file: The shmem-based backing file
- * @size: The size of the mapping, in bytes
- * @prot_mask: The allowed protection bits, as vm_flags
- *
- * The lifecycle of this structure is from our parent file's open() until
- * its release(). It is also protected by 'ashmem_mutex'
- *
- * Warning: Mappings do NOT pin this structure; It dies on close()
- */
-struct ashmem_area {
- char name[ASHMEM_FULL_NAME_LEN];
- struct list_head unpinned_list;
- struct file *file;
- size_t size;
- unsigned long prot_mask;
-};
-
-/**
- * struct ashmem_range - A range of unpinned/evictable pages
- * @lru: The entry in the LRU list
- * @unpinned: The entry in its area's unpinned list
- * @asma: The associated anonymous shared memory area.
- * @pgstart: The starting page (inclusive)
- * @pgend: The ending page (inclusive)
- * @purged: The purge status (ASHMEM_NOT or ASHMEM_WAS_PURGED)
- *
- * The lifecycle of this structure is from unpin to pin.
- * It is protected by 'ashmem_mutex'
- */
-struct ashmem_range {
- struct list_head lru;
- struct list_head unpinned;
- struct ashmem_area *asma;
- size_t pgstart;
- size_t pgend;
- unsigned int purged;
-};
-
-/* LRU list of unpinned pages, protected by ashmem_mutex */
-static LIST_HEAD(ashmem_lru_list);
-
-static atomic_t ashmem_shrink_inflight = ATOMIC_INIT(0);
-static DECLARE_WAIT_QUEUE_HEAD(ashmem_shrink_wait);
-
-/*
- * long lru_count - The count of pages on our LRU list.
- *
- * This is protected by ashmem_mutex.
- */
-static unsigned long lru_count;
-
-/*
- * ashmem_mutex - protects the list of and each individual ashmem_area
- *
- * Lock Ordering: ashmex_mutex -> i_mutex -> i_alloc_sem
- */
-static DEFINE_MUTEX(ashmem_mutex);
-
-static struct kmem_cache *ashmem_area_cachep __read_mostly;
-static struct kmem_cache *ashmem_range_cachep __read_mostly;
-
-/*
- * A separate lockdep class for the backing shmem inodes to resolve the lockdep
- * warning about the race between kswapd taking fs_reclaim before inode_lock
- * and write syscall taking inode_lock and then fs_reclaim.
- * Note that such race is impossible because ashmem does not support write
- * syscalls operating on the backing shmem.
- */
-static struct lock_class_key backing_shmem_inode_class;
-
-static inline unsigned long range_size(struct ashmem_range *range)
-{
- return range->pgend - range->pgstart + 1;
-}
-
-static inline bool range_on_lru(struct ashmem_range *range)
-{
- return range->purged == ASHMEM_NOT_PURGED;
-}
-
-static inline bool page_range_subsumes_range(struct ashmem_range *range,
- size_t start, size_t end)
-{
- return (range->pgstart >= start) && (range->pgend <= end);
-}
-
-static inline bool page_range_subsumed_by_range(struct ashmem_range *range,
- size_t start, size_t end)
-{
- return (range->pgstart <= start) && (range->pgend >= end);
-}
-
-static inline bool page_in_range(struct ashmem_range *range, size_t page)
-{
- return (range->pgstart <= page) && (range->pgend >= page);
-}
-
-static inline bool page_range_in_range(struct ashmem_range *range,
- size_t start, size_t end)
-{
- return page_in_range(range, start) || page_in_range(range, end) ||
- page_range_subsumes_range(range, start, end);
-}
-
-static inline bool range_before_page(struct ashmem_range *range,
- size_t page)
-{
- return range->pgend < page;
-}
-
-#define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE)
-
-/**
- * lru_add() - Adds a range of memory to the LRU list
- * @range: The memory range being added.
- *
- * The range is first added to the end (tail) of the LRU list.
- * After this, the size of the range is added to @lru_count
- */
-static inline void lru_add(struct ashmem_range *range)
-{
- list_add_tail(&range->lru, &ashmem_lru_list);
- lru_count += range_size(range);
-}
-
-/**
- * lru_del() - Removes a range of memory from the LRU list
- * @range: The memory range being removed
- *
- * The range is first deleted from the LRU list.
- * After this, the size of the range is removed from @lru_count
- */
-static inline void lru_del(struct ashmem_range *range)
-{
- list_del(&range->lru);
- lru_count -= range_size(range);
-}
-
-/**
- * range_alloc() - Allocates and initializes a new ashmem_range structure
- * @asma: The associated ashmem_area
- * @prev_range: The previous ashmem_range in the sorted asma->unpinned list
- * @purged: Initial purge status (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED)
- * @start: The starting page (inclusive)
- * @end: The ending page (inclusive)
- * @new_range: The placeholder for the new range
- *
- * This function is protected by ashmem_mutex.
- */
-static void range_alloc(struct ashmem_area *asma,
- struct ashmem_range *prev_range, unsigned int purged,
- size_t start, size_t end,
- struct ashmem_range **new_range)
-{
- struct ashmem_range *range = *new_range;
-
- *new_range = NULL;
- range->asma = asma;
- range->pgstart = start;
- range->pgend = end;
- range->purged = purged;
-
- list_add_tail(&range->unpinned, &prev_range->unpinned);
-
- if (range_on_lru(range))
- lru_add(range);
-}
-
-/**
- * range_del() - Deletes and deallocates an ashmem_range structure
- * @range: The associated ashmem_range that has previously been allocated
- */
-static void range_del(struct ashmem_range *range)
-{
- list_del(&range->unpinned);
- if (range_on_lru(range))
- lru_del(range);
- kmem_cache_free(ashmem_range_cachep, range);
-}
-
-/**
- * range_shrink() - Shrinks an ashmem_range
- * @range: The associated ashmem_range being shrunk
- * @start: The starting byte of the new range
- * @end: The ending byte of the new range
- *
- * This does not modify the data inside the existing range in any way - It
- * simply shrinks the boundaries of the range.
- *
- * Theoretically, with a little tweaking, this could eventually be changed
- * to range_resize, and expand the lru_count if the new range is larger.
- */
-static inline void range_shrink(struct ashmem_range *range,
- size_t start, size_t end)
-{
- size_t pre = range_size(range);
-
- range->pgstart = start;
- range->pgend = end;
-
- if (range_on_lru(range))
- lru_count -= pre - range_size(range);
-}
-
-/**
- * ashmem_open() - Opens an Anonymous Shared Memory structure
- * @inode: The backing file's index node(?)
- * @file: The backing file
- *
- * Please note that the ashmem_area is not returned by this function - It is
- * instead written to "file->private_data".
- *
- * Return: 0 if successful, or another code if unsuccessful.
- */
-static int ashmem_open(struct inode *inode, struct file *file)
-{
- struct ashmem_area *asma;
- int ret;
-
- ret = generic_file_open(inode, file);
- if (ret)
- return ret;
-
- asma = kmem_cache_zalloc(ashmem_area_cachep, GFP_KERNEL);
- if (!asma)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&asma->unpinned_list);
- memcpy(asma->name, ASHMEM_NAME_PREFIX, ASHMEM_NAME_PREFIX_LEN);
- asma->prot_mask = PROT_MASK;
- file->private_data = asma;
-
- return 0;
-}
-
-/**
- * ashmem_release() - Releases an Anonymous Shared Memory structure
- * @ignored: The backing file's Index Node(?) - It is ignored here.
- * @file: The backing file
- *
- * Return: 0 if successful. If it is anything else, go have a coffee and
- * try again.
- */
-static int ashmem_release(struct inode *ignored, struct file *file)
-{
- struct ashmem_area *asma = file->private_data;
- struct ashmem_range *range, *next;
-
- mutex_lock(&ashmem_mutex);
- list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned)
- range_del(range);
- mutex_unlock(&ashmem_mutex);
-
- if (asma->file)
- fput(asma->file);
- kmem_cache_free(ashmem_area_cachep, asma);
-
- return 0;
-}
-
-static ssize_t ashmem_read_iter(struct kiocb *iocb, struct iov_iter *iter)
-{
- struct ashmem_area *asma = iocb->ki_filp->private_data;
- int ret = 0;
-
- mutex_lock(&ashmem_mutex);
-
- /* If size is not set, or set to 0, always return EOF. */
- if (asma->size == 0)
- goto out_unlock;
-
- if (!asma->file) {
- ret = -EBADF;
- goto out_unlock;
- }
-
- /*
- * asma and asma->file are used outside the lock here. We assume
- * once asma->file is set it will never be changed, and will not
- * be destroyed until all references to the file are dropped and
- * ashmem_release is called.
- */
- mutex_unlock(&ashmem_mutex);
- ret = vfs_iter_read(asma->file, iter, &iocb->ki_pos, 0);
- mutex_lock(&ashmem_mutex);
- if (ret > 0)
- asma->file->f_pos = iocb->ki_pos;
-out_unlock:
- mutex_unlock(&ashmem_mutex);
- return ret;
-}
-
-static loff_t ashmem_llseek(struct file *file, loff_t offset, int origin)
-{
- struct ashmem_area *asma = file->private_data;
- loff_t ret;
-
- mutex_lock(&ashmem_mutex);
-
- if (asma->size == 0) {
- mutex_unlock(&ashmem_mutex);
- return -EINVAL;
- }
-
- if (!asma->file) {
- mutex_unlock(&ashmem_mutex);
- return -EBADF;
- }
-
- mutex_unlock(&ashmem_mutex);
-
- ret = vfs_llseek(asma->file, offset, origin);
- if (ret < 0)
- return ret;
-
- /** Copy f_pos from backing file, since f_ops->llseek() sets it */
- file->f_pos = asma->file->f_pos;
- return ret;
-}
-
-static inline vm_flags_t calc_vm_may_flags(unsigned long prot)
-{
- return _calc_vm_trans(prot, PROT_READ, VM_MAYREAD) |
- _calc_vm_trans(prot, PROT_WRITE, VM_MAYWRITE) |
- _calc_vm_trans(prot, PROT_EXEC, VM_MAYEXEC);
-}
-
-static int ashmem_vmfile_mmap(struct file *file, struct vm_area_struct *vma)
-{
- /* do not allow to mmap ashmem backing shmem file directly */
- return -EPERM;
-}
-
-static unsigned long
-ashmem_vmfile_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff,
- unsigned long flags)
-{
- return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
-}
-
-static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
-{
- static struct file_operations vmfile_fops;
- struct ashmem_area *asma = file->private_data;
- int ret = 0;
-
- mutex_lock(&ashmem_mutex);
-
- /* user needs to SET_SIZE before mapping */
- if (!asma->size) {
- ret = -EINVAL;
- goto out;
- }
-
- /* requested mapping size larger than object size */
- if (vma->vm_end - vma->vm_start > PAGE_ALIGN(asma->size)) {
- ret = -EINVAL;
- goto out;
- }
-
- /* requested protection bits must match our allowed protection mask */
- if ((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask, 0)) &
- calc_vm_prot_bits(PROT_MASK, 0)) {
- ret = -EPERM;
- goto out;
- }
- vma->vm_flags &= ~calc_vm_may_flags(~asma->prot_mask);
-
- if (!asma->file) {
- char *name = ASHMEM_NAME_DEF;
- struct file *vmfile;
- struct inode *inode;
-
- if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0')
- name = asma->name;
-
- /* ... and allocate the backing shmem file */
- vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);
- if (IS_ERR(vmfile)) {
- ret = PTR_ERR(vmfile);
- goto out;
- }
- vmfile->f_mode |= FMODE_LSEEK;
- inode = file_inode(vmfile);
- lockdep_set_class(&inode->i_rwsem, &backing_shmem_inode_class);
- asma->file = vmfile;
- /*
- * override mmap operation of the vmfile so that it can't be
- * remapped which would lead to creation of a new vma with no
- * asma permission checks. Have to override get_unmapped_area
- * as well to prevent VM_BUG_ON check for f_ops modification.
- */
- if (!vmfile_fops.mmap) {
- vmfile_fops = *vmfile->f_op;
- vmfile_fops.mmap = ashmem_vmfile_mmap;
- vmfile_fops.get_unmapped_area =
- ashmem_vmfile_get_unmapped_area;
- }
- vmfile->f_op = &vmfile_fops;
- }
- get_file(asma->file);
-
- /*
- * XXX - Reworked to use shmem_zero_setup() instead of
- * shmem_set_file while we're in staging. -jstultz
- */
- if (vma->vm_flags & VM_SHARED) {
- ret = shmem_zero_setup(vma);
- if (ret) {
- fput(asma->file);
- goto out;
- }
- } else {
- vma_set_anonymous(vma);
- }
-
- vma_set_file(vma, asma->file);
- /* XXX: merge this with the get_file() above if possible */
- fput(asma->file);
-
-out:
- mutex_unlock(&ashmem_mutex);
- return ret;
-}
-
-/*
- * ashmem_shrink - our cache shrinker, called from mm/vmscan.c
- *
- * 'nr_to_scan' is the number of objects to scan for freeing.
- *
- * 'gfp_mask' is the mask of the allocation that got us into this mess.
- *
- * Return value is the number of objects freed or -1 if we cannot
- * proceed without risk of deadlock (due to gfp_mask).
- *
- * We approximate LRU via least-recently-unpinned, jettisoning unpinned partial
- * chunks of ashmem regions LRU-wise one-at-a-time until we hit 'nr_to_scan'
- * pages freed.
- */
-static unsigned long
-ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
-{
- unsigned long freed = 0;
-
- /* We might recurse into filesystem code, so bail out if necessary */
- if (!(sc->gfp_mask & __GFP_FS))
- return SHRINK_STOP;
-
- if (!mutex_trylock(&ashmem_mutex))
- return -1;
-
- while (!list_empty(&ashmem_lru_list)) {
- struct ashmem_range *range =
- list_first_entry(&ashmem_lru_list, typeof(*range), lru);
- loff_t start = range->pgstart * PAGE_SIZE;
- loff_t end = (range->pgend + 1) * PAGE_SIZE;
- struct file *f = range->asma->file;
-
- get_file(f);
- atomic_inc(&ashmem_shrink_inflight);
- range->purged = ASHMEM_WAS_PURGED;
- lru_del(range);
-
- freed += range_size(range);
- mutex_unlock(&ashmem_mutex);
- f->f_op->fallocate(f,
- FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
- start, end - start);
- fput(f);
- if (atomic_dec_and_test(&ashmem_shrink_inflight))
- wake_up_all(&ashmem_shrink_wait);
- if (!mutex_trylock(&ashmem_mutex))
- goto out;
- if (--sc->nr_to_scan <= 0)
- break;
- }
- mutex_unlock(&ashmem_mutex);
-out:
- return freed;
-}
-
-static unsigned long
-ashmem_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
-{
- /*
- * note that lru_count is count of pages on the lru, not a count of
- * objects on the list. This means the scan function needs to return the
- * number of pages freed, not the number of objects scanned.
- */
- return lru_count;
-}
-
-static struct shrinker ashmem_shrinker = {
- .count_objects = ashmem_shrink_count,
- .scan_objects = ashmem_shrink_scan,
- /*
- * XXX (dchinner): I wish people would comment on why they need on
- * significant changes to the default value here
- */
- .seeks = DEFAULT_SEEKS * 4,
-};
-
-static int set_prot_mask(struct ashmem_area *asma, unsigned long prot)
-{
- int ret = 0;
-
- mutex_lock(&ashmem_mutex);
-
- /* the user can only remove, not add, protection bits */
- if ((asma->prot_mask & prot) != prot) {
- ret = -EINVAL;
- goto out;
- }
-
- /* does the application expect PROT_READ to imply PROT_EXEC? */
- if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
- prot |= PROT_EXEC;
-
- asma->prot_mask = prot;
-
-out:
- mutex_unlock(&ashmem_mutex);
- return ret;
-}
-
-static int set_name(struct ashmem_area *asma, void __user *name)
-{
- int len;
- int ret = 0;
- char local_name[ASHMEM_NAME_LEN];
-
- /*
- * Holding the ashmem_mutex while doing a copy_from_user might cause
- * an data abort which would try to access mmap_lock. If another
- * thread has invoked ashmem_mmap then it will be holding the
- * semaphore and will be waiting for ashmem_mutex, there by leading to
- * deadlock. We'll release the mutex and take the name to a local
- * variable that does not need protection and later copy the local
- * variable to the structure member with lock held.
- */
- len = strncpy_from_user(local_name, name, ASHMEM_NAME_LEN);
- if (len < 0)
- return len;
-
- mutex_lock(&ashmem_mutex);
- /* cannot change an existing mapping's name */
- if (asma->file)
- ret = -EINVAL;
- else
- strscpy(asma->name + ASHMEM_NAME_PREFIX_LEN, local_name,
- ASHMEM_NAME_LEN);
-
- mutex_unlock(&ashmem_mutex);
- return ret;
-}
-
-static int get_name(struct ashmem_area *asma, void __user *name)
-{
- int ret = 0;
- size_t len;
- /*
- * Have a local variable to which we'll copy the content
- * from asma with the lock held. Later we can copy this to the user
- * space safely without holding any locks. So even if we proceed to
- * wait for mmap_lock, it won't lead to deadlock.
- */
- char local_name[ASHMEM_NAME_LEN];
-
- mutex_lock(&ashmem_mutex);
- if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') {
- /*
- * Copying only `len', instead of ASHMEM_NAME_LEN, bytes
- * prevents us from revealing one user's stack to another.
- */
- len = strlen(asma->name + ASHMEM_NAME_PREFIX_LEN) + 1;
- memcpy(local_name, asma->name + ASHMEM_NAME_PREFIX_LEN, len);
- } else {
- len = sizeof(ASHMEM_NAME_DEF);
- memcpy(local_name, ASHMEM_NAME_DEF, len);
- }
- mutex_unlock(&ashmem_mutex);
-
- /*
- * Now we are just copying from the stack variable to userland
- * No lock held
- */
- if (copy_to_user(name, local_name, len))
- ret = -EFAULT;
- return ret;
-}
-
-/*
- * ashmem_pin - pin the given ashmem region, returning whether it was
- * previously purged (ASHMEM_WAS_PURGED) or not (ASHMEM_NOT_PURGED).
- *
- * Caller must hold ashmem_mutex.
- */
-static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend,
- struct ashmem_range **new_range)
-{
- struct ashmem_range *range, *next;
- int ret = ASHMEM_NOT_PURGED;
-
- list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) {
- /* moved past last applicable page; we can short circuit */
- if (range_before_page(range, pgstart))
- break;
-
- /*
- * The user can ask us to pin pages that span multiple ranges,
- * or to pin pages that aren't even unpinned, so this is messy.
- *
- * Four cases:
- * 1. The requested range subsumes an existing range, so we
- * just remove the entire matching range.
- * 2. The requested range overlaps the start of an existing
- * range, so we just update that range.
- * 3. The requested range overlaps the end of an existing
- * range, so we just update that range.
- * 4. The requested range punches a hole in an existing range,
- * so we have to update one side of the range and then
- * create a new range for the other side.
- */
- if (page_range_in_range(range, pgstart, pgend)) {
- ret |= range->purged;
-
- /* Case #1: Easy. Just nuke the whole thing. */
- if (page_range_subsumes_range(range, pgstart, pgend)) {
- range_del(range);
- continue;
- }
-
- /* Case #2: We overlap from the start, so adjust it */
- if (range->pgstart >= pgstart) {
- range_shrink(range, pgend + 1, range->pgend);
- continue;
- }
-
- /* Case #3: We overlap from the rear, so adjust it */
- if (range->pgend <= pgend) {
- range_shrink(range, range->pgstart,
- pgstart - 1);
- continue;
- }
-
- /*
- * Case #4: We eat a chunk out of the middle. A bit
- * more complicated, we allocate a new range for the
- * second half and adjust the first chunk's endpoint.
- */
- range_alloc(asma, range, range->purged,
- pgend + 1, range->pgend, new_range);
- range_shrink(range, range->pgstart, pgstart - 1);
- break;
- }
- }
-
- return ret;
-}
-
-/*
- * ashmem_unpin - unpin the given range of pages. Returns zero on success.
- *
- * Caller must hold ashmem_mutex.
- */
-static int ashmem_unpin(struct ashmem_area *asma, size_t pgstart, size_t pgend,
- struct ashmem_range **new_range)
-{
- struct ashmem_range *range, *next;
- unsigned int purged = ASHMEM_NOT_PURGED;
-
-restart:
- list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) {
- /* short circuit: this is our insertion point */
- if (range_before_page(range, pgstart))
- break;
-
- /*
- * The user can ask us to unpin pages that are already entirely
- * or partially pinned. We handle those two cases here.
- */
- if (page_range_subsumed_by_range(range, pgstart, pgend))
- return 0;
- if (page_range_in_range(range, pgstart, pgend)) {
- pgstart = min(range->pgstart, pgstart);
- pgend = max(range->pgend, pgend);
- purged |= range->purged;
- range_del(range);
- goto restart;
- }
- }
-
- range_alloc(asma, range, purged, pgstart, pgend, new_range);
- return 0;
-}
-
-/*
- * ashmem_get_pin_status - Returns ASHMEM_IS_UNPINNED if _any_ pages in the
- * given interval are unpinned and ASHMEM_IS_PINNED otherwise.
- *
- * Caller must hold ashmem_mutex.
- */
-static int ashmem_get_pin_status(struct ashmem_area *asma, size_t pgstart,
- size_t pgend)
-{
- struct ashmem_range *range;
- int ret = ASHMEM_IS_PINNED;
-
- list_for_each_entry(range, &asma->unpinned_list, unpinned) {
- if (range_before_page(range, pgstart))
- break;
- if (page_range_in_range(range, pgstart, pgend)) {
- ret = ASHMEM_IS_UNPINNED;
- break;
- }
- }
-
- return ret;
-}
-
-static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
- void __user *p)
-{
- struct ashmem_pin pin;
- size_t pgstart, pgend;
- int ret = -EINVAL;
- struct ashmem_range *range = NULL;
-
- if (copy_from_user(&pin, p, sizeof(pin)))
- return -EFAULT;
-
- if (cmd == ASHMEM_PIN || cmd == ASHMEM_UNPIN) {
- range = kmem_cache_zalloc(ashmem_range_cachep, GFP_KERNEL);
- if (!range)
- return -ENOMEM;
- }
-
- mutex_lock(&ashmem_mutex);
- wait_event(ashmem_shrink_wait, !atomic_read(&ashmem_shrink_inflight));
-
- if (!asma->file)
- goto out_unlock;
-
- /* per custom, you can pass zero for len to mean "everything onward" */
- if (!pin.len)
- pin.len = PAGE_ALIGN(asma->size) - pin.offset;
-
- if ((pin.offset | pin.len) & ~PAGE_MASK)
- goto out_unlock;
-
- if (((__u32)-1) - pin.offset < pin.len)
- goto out_unlock;
-
- if (PAGE_ALIGN(asma->size) < pin.offset + pin.len)
- goto out_unlock;
-
- pgstart = pin.offset / PAGE_SIZE;
- pgend = pgstart + (pin.len / PAGE_SIZE) - 1;
-
- switch (cmd) {
- case ASHMEM_PIN:
- ret = ashmem_pin(asma, pgstart, pgend, &range);
- break;
- case ASHMEM_UNPIN:
- ret = ashmem_unpin(asma, pgstart, pgend, &range);
- break;
- case ASHMEM_GET_PIN_STATUS:
- ret = ashmem_get_pin_status(asma, pgstart, pgend);
- break;
- }
-
-out_unlock:
- mutex_unlock(&ashmem_mutex);
- if (range)
- kmem_cache_free(ashmem_range_cachep, range);
-
- return ret;
-}
-
-static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct ashmem_area *asma = file->private_data;
- long ret = -ENOTTY;
-
- switch (cmd) {
- case ASHMEM_SET_NAME:
- ret = set_name(asma, (void __user *)arg);
- break;
- case ASHMEM_GET_NAME:
- ret = get_name(asma, (void __user *)arg);
- break;
- case ASHMEM_SET_SIZE:
- ret = -EINVAL;
- mutex_lock(&ashmem_mutex);
- if (!asma->file) {
- ret = 0;
- asma->size = (size_t)arg;
- }
- mutex_unlock(&ashmem_mutex);
- break;
- case ASHMEM_GET_SIZE:
- ret = asma->size;
- break;
- case ASHMEM_SET_PROT_MASK:
- ret = set_prot_mask(asma, arg);
- break;
- case ASHMEM_GET_PROT_MASK:
- ret = asma->prot_mask;
- break;
- case ASHMEM_PIN:
- case ASHMEM_UNPIN:
- case ASHMEM_GET_PIN_STATUS:
- ret = ashmem_pin_unpin(asma, cmd, (void __user *)arg);
- break;
- case ASHMEM_PURGE_ALL_CACHES:
- ret = -EPERM;
- if (capable(CAP_SYS_ADMIN)) {
- struct shrink_control sc = {
- .gfp_mask = GFP_KERNEL,
- .nr_to_scan = LONG_MAX,
- };
- ret = ashmem_shrink_count(&ashmem_shrinker, &sc);
- ashmem_shrink_scan(&ashmem_shrinker, &sc);
- }
- break;
- }
-
- return ret;
-}
-
-/* support of 32bit userspace on 64bit platforms */
-#ifdef CONFIG_COMPAT
-static long compat_ashmem_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- switch (cmd) {
- case COMPAT_ASHMEM_SET_SIZE:
- cmd = ASHMEM_SET_SIZE;
- break;
- case COMPAT_ASHMEM_SET_PROT_MASK:
- cmd = ASHMEM_SET_PROT_MASK;
- break;
- }
- return ashmem_ioctl(file, cmd, arg);
-}
-#endif
-#ifdef CONFIG_PROC_FS
-static void ashmem_show_fdinfo(struct seq_file *m, struct file *file)
-{
- struct ashmem_area *asma = file->private_data;
-
- mutex_lock(&ashmem_mutex);
-
- if (asma->file)
- seq_printf(m, "inode:\t%ld\n", file_inode(asma->file)->i_ino);
-
- if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0')
- seq_printf(m, "name:\t%s\n",
- asma->name + ASHMEM_NAME_PREFIX_LEN);
-
- seq_printf(m, "size:\t%zu\n", asma->size);
-
- mutex_unlock(&ashmem_mutex);
-}
-#endif
-static const struct file_operations ashmem_fops = {
- .owner = THIS_MODULE,
- .open = ashmem_open,
- .release = ashmem_release,
- .read_iter = ashmem_read_iter,
- .llseek = ashmem_llseek,
- .mmap = ashmem_mmap,
- .unlocked_ioctl = ashmem_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = compat_ashmem_ioctl,
-#endif
-#ifdef CONFIG_PROC_FS
- .show_fdinfo = ashmem_show_fdinfo,
-#endif
-};
-
-static struct miscdevice ashmem_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "ashmem",
- .fops = &ashmem_fops,
-};
-
-static int __init ashmem_init(void)
-{
- int ret = -ENOMEM;
-
- ashmem_area_cachep = kmem_cache_create("ashmem_area_cache",
- sizeof(struct ashmem_area),
- 0, 0, NULL);
- if (!ashmem_area_cachep) {
- pr_err("failed to create slab cache\n");
- goto out;
- }
-
- ashmem_range_cachep = kmem_cache_create("ashmem_range_cache",
- sizeof(struct ashmem_range),
- 0, SLAB_RECLAIM_ACCOUNT, NULL);
- if (!ashmem_range_cachep) {
- pr_err("failed to create slab cache\n");
- goto out_free1;
- }
-
- ret = misc_register(&ashmem_misc);
- if (ret) {
- pr_err("failed to register misc device!\n");
- goto out_free2;
- }
-
- ret = register_shrinker(&ashmem_shrinker);
- if (ret) {
- pr_err("failed to register shrinker!\n");
- goto out_demisc;
- }
-
- pr_info("initialized\n");
-
- return 0;
-
-out_demisc:
- misc_deregister(&ashmem_misc);
-out_free2:
- kmem_cache_destroy(ashmem_range_cachep);
-out_free1:
- kmem_cache_destroy(ashmem_area_cachep);
-out:
- return ret;
-}
-device_initcall(ashmem_init);
diff --git a/drivers/staging/android/ashmem.h b/drivers/staging/android/ashmem.h
deleted file mode 100644
index 1a478173cd21..000000000000
--- a/drivers/staging/android/ashmem.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
-/*
- * include/linux/ashmem.h
- *
- * Copyright 2008 Google Inc.
- * Author: Robert Love
- */
-
-#ifndef _LINUX_ASHMEM_H
-#define _LINUX_ASHMEM_H
-
-#include <linux/limits.h>
-#include <linux/ioctl.h>
-#include <linux/compat.h>
-
-#include "uapi/ashmem.h"
-
-/* support of 32bit userspace on 64bit platforms */
-#ifdef CONFIG_COMPAT
-#define COMPAT_ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, compat_size_t)
-#define COMPAT_ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned int)
-#endif
-
-#endif /* _LINUX_ASHMEM_H */
diff --git a/drivers/staging/android/uapi/ashmem.h b/drivers/staging/android/uapi/ashmem.h
deleted file mode 100644
index 134efacb3219..000000000000
--- a/drivers/staging/android/uapi/ashmem.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
-/*
- * Copyright 2008 Google Inc.
- * Author: Robert Love
- */
-
-#ifndef _UAPI_LINUX_ASHMEM_H
-#define _UAPI_LINUX_ASHMEM_H
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-#define ASHMEM_NAME_LEN 256
-
-#define ASHMEM_NAME_DEF "dev/ashmem"
-
-/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
-#define ASHMEM_NOT_PURGED 0
-#define ASHMEM_WAS_PURGED 1
-
-/* Return values from ASHMEM_GET_PIN_STATUS: Is the mapping pinned? */
-#define ASHMEM_IS_UNPINNED 0
-#define ASHMEM_IS_PINNED 1
-
-struct ashmem_pin {
- __u32 offset; /* offset into region, in bytes, page-aligned */
- __u32 len; /* length forward from offset, in bytes, page-aligned */
-};
-
-#define __ASHMEMIOC 0x77
-
-#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
-#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
-#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
-#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4)
-#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long)
-#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6)
-#define ASHMEM_PIN _IOW(__ASHMEMIOC, 7, struct ashmem_pin)
-#define ASHMEM_UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin)
-#define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9)
-#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
-
-#endif /* _UAPI_LINUX_ASHMEM_H */
diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c
index 632f140dddbc..dfd2b357f484 100644
--- a/drivers/staging/axis-fifo/axis-fifo.c
+++ b/drivers/staging/axis-fifo/axis-fifo.c
@@ -809,7 +809,6 @@ end:
static int axis_fifo_probe(struct platform_device *pdev)
{
- struct resource *r_irq; /* interrupt resources */
struct resource *r_mem; /* IO mem resources */
struct device *dev = &pdev->dev; /* OS device (from device tree) */
struct axis_fifo *fifo = NULL;
@@ -882,16 +881,12 @@ static int axis_fifo_probe(struct platform_device *pdev)
*/
/* get IRQ resource */
- r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!r_irq) {
- dev_err(fifo->dt_device, "no IRQ found for 0x%pa\n",
- &r_mem->start);
- rc = -EIO;
+ rc = platform_get_irq(pdev, 0);
+ if (rc < 0)
goto err_initial;
- }
/* request IRQ */
- fifo->irq = r_irq->start;
+ fifo->irq = rc;
rc = devm_request_irq(fifo->dt_device, fifo->irq, &axis_fifo_irq, 0,
DRIVER_NAME, fifo);
if (rc) {
diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig
index dad1ddcd7b0c..4d29e8c1014e 100644
--- a/drivers/staging/fbtft/Kconfig
+++ b/drivers/staging/fbtft/Kconfig
@@ -200,9 +200,3 @@ config FB_TFT_UPD161704
depends on FB_TFT
help
Generic Framebuffer support for uPD161704
-
-config FB_TFT_WATTEROTT
- tristate "FB driver for the WATTEROTT LCD Controller"
- depends on FB_TFT
- help
- Generic Framebuffer support for WATTEROTT
diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile
index e87193f7df14..e9cdf0f0a7da 100644
--- a/drivers/staging/fbtft/Makefile
+++ b/drivers/staging/fbtft/Makefile
@@ -36,4 +36,3 @@ obj-$(CONFIG_FB_TFT_TLS8204) += fb_tls8204.o
obj-$(CONFIG_FB_TFT_UC1611) += fb_uc1611.o
obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o
obj-$(CONFIG_FB_TFT_UPD161704) += fb_upd161704.o
-obj-$(CONFIG_FB_TFT_WATTEROTT) += fb_watterott.o
diff --git a/drivers/staging/fbtft/fb_sh1106.c b/drivers/staging/fbtft/fb_sh1106.c
index 7b9ab39e1c1a..9685ca516a0e 100644
--- a/drivers/staging/fbtft/fb_sh1106.c
+++ b/drivers/staging/fbtft/fb_sh1106.c
@@ -173,12 +173,7 @@ static struct fbtft_display display = {
},
};
-FBTFT_REGISTER_DRIVER(DRVNAME, "sinowealth,sh1106", &display);
-
-MODULE_ALIAS("spi:" DRVNAME);
-MODULE_ALIAS("platform:" DRVNAME);
-MODULE_ALIAS("spi:sh1106");
-MODULE_ALIAS("platform:sh1106");
+FBTFT_REGISTER_SPI_DRIVER(DRVNAME, "sinowealth", "sh1106", &display);
MODULE_DESCRIPTION("SH1106 OLED Driver");
MODULE_AUTHOR("Heiner Kallweit");
diff --git a/drivers/staging/fbtft/fb_st7789v.c b/drivers/staging/fbtft/fb_st7789v.c
index abe9395a0aef..861a154144e6 100644
--- a/drivers/staging/fbtft/fb_st7789v.c
+++ b/drivers/staging/fbtft/fb_st7789v.c
@@ -144,6 +144,8 @@ static int init_display(struct fbtft_par *par)
{
int rc;
+ par->fbtftops.reset(par);
+
rc = init_tearing_effect_line(par);
if (rc)
return rc;
diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c
deleted file mode 100644
index a57e1f4feef3..000000000000
--- a/drivers/staging/fbtft/fb_watterott.c
+++ /dev/null
@@ -1,302 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * FB driver for the Watterott LCD Controller
- *
- * Copyright (C) 2013 Noralf Tronnes
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include "fbtft.h"
-
-#define DRVNAME "fb_watterott"
-#define WIDTH 320
-#define HEIGHT 240
-#define FPS 5
-#define TXBUFLEN 1024
-#define DEFAULT_BRIGHTNESS 50
-
-#define CMD_VERSION 0x01
-#define CMD_LCD_LED 0x10
-#define CMD_LCD_RESET 0x11
-#define CMD_LCD_ORIENTATION 0x20
-#define CMD_LCD_DRAWIMAGE 0x27
-#define COLOR_RGB323 8
-#define COLOR_RGB332 9
-#define COLOR_RGB233 10
-#define COLOR_RGB565 16
-
-static short mode = 565;
-module_param(mode, short, 0000);
-MODULE_PARM_DESC(mode, "RGB color transfer mode: 332, 565 (default)");
-
-static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
-{
- va_list args;
- int i, ret;
- u8 *buf = par->buf;
-
- va_start(args, len);
- for (i = 0; i < len; i++)
- *buf++ = (u8)va_arg(args, unsigned int);
- va_end(args);
-
- fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par,
- par->info->device, u8, par->buf,
- len, "%s: ", __func__);
-
- ret = par->fbtftops.write(par, par->buf, len);
- if (ret < 0) {
- dev_err(par->info->device,
- "write() failed and returned %d\n", ret);
- return;
- }
-}
-
-static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
-{
- unsigned int start_line, end_line;
- u16 *vmem16 = (u16 *)(par->info->screen_buffer + offset);
- __be16 *pos = par->txbuf.buf + 1;
- __be16 *buf16 = par->txbuf.buf + 10;
- int i, j;
- int ret = 0;
-
- start_line = offset / par->info->fix.line_length;
- end_line = start_line + (len / par->info->fix.line_length) - 1;
-
- /* Set command header. pos: x, y, w, h */
- ((u8 *)par->txbuf.buf)[0] = CMD_LCD_DRAWIMAGE;
- pos[0] = 0;
- pos[2] = cpu_to_be16(par->info->var.xres);
- pos[3] = cpu_to_be16(1);
- ((u8 *)par->txbuf.buf)[9] = COLOR_RGB565;
-
- for (i = start_line; i <= end_line; i++) {
- pos[1] = cpu_to_be16(i);
- for (j = 0; j < par->info->var.xres; j++)
- buf16[j] = cpu_to_be16(*vmem16++);
- ret = par->fbtftops.write(par,
- par->txbuf.buf, 10 + par->info->fix.line_length);
- if (ret < 0)
- return ret;
- udelay(300);
- }
-
- return 0;
-}
-
-static inline int rgb565_to_rgb332(u16 c)
-{
- return ((c & 0xE000) >> 8) | ((c & 000700) >> 6) | ((c & 0x0018) >> 3);
-}
-
-static int write_vmem_8bit(struct fbtft_par *par, size_t offset, size_t len)
-{
- unsigned int start_line, end_line;
- u16 *vmem16 = (u16 *)(par->info->screen_buffer + offset);
- __be16 *pos = par->txbuf.buf + 1;
- u8 *buf8 = par->txbuf.buf + 10;
- int i, j;
- int ret = 0;
-
- start_line = offset / par->info->fix.line_length;
- end_line = start_line + (len / par->info->fix.line_length) - 1;
-
- /* Set command header. pos: x, y, w, h */
- ((u8 *)par->txbuf.buf)[0] = CMD_LCD_DRAWIMAGE;
- pos[0] = 0;
- pos[2] = cpu_to_be16(par->info->var.xres);
- pos[3] = cpu_to_be16(1);
- ((u8 *)par->txbuf.buf)[9] = COLOR_RGB332;
-
- for (i = start_line; i <= end_line; i++) {
- pos[1] = cpu_to_be16(i);
- for (j = 0; j < par->info->var.xres; j++) {
- buf8[j] = rgb565_to_rgb332(*vmem16);
- vmem16++;
- }
- ret = par->fbtftops.write(par,
- par->txbuf.buf, 10 + par->info->var.xres);
- if (ret < 0)
- return ret;
- udelay(700);
- }
-
- return 0;
-}
-
-static unsigned int firmware_version(struct fbtft_par *par)
-{
- u8 rxbuf[4] = {0, };
-
- write_reg(par, CMD_VERSION);
- par->fbtftops.read(par, rxbuf, 4);
- if (rxbuf[1] != '.')
- return 0;
-
- return (rxbuf[0] - '0') << 8 | (rxbuf[2] - '0') << 4 | (rxbuf[3] - '0');
-}
-
-static int init_display(struct fbtft_par *par)
-{
- int ret;
- unsigned int version;
- u8 save_mode;
-
- /* enable SPI interface by having CS and MOSI low during reset */
- save_mode = par->spi->mode;
- /*
- * Set CS active inverse polarity: just setting SPI_CS_HIGH does not
- * work with GPIO based chip selects that are logically active high
- * but inverted inside the GPIO library, so enforce inverted
- * semantics.
- */
- par->spi->mode ^= SPI_CS_HIGH;
- ret = spi_setup(par->spi);
- if (ret) {
- dev_err(par->info->device,
- "Could not set inverse CS polarity\n");
- return ret;
- }
- write_reg(par, 0x00); /* make sure mode is set */
-
- mdelay(50);
- par->fbtftops.reset(par);
- mdelay(1000);
- par->spi->mode = save_mode;
- ret = spi_setup(par->spi);
- if (ret) {
- dev_err(par->info->device, "Could not restore SPI mode\n");
- return ret;
- }
- write_reg(par, 0x00);
-
- version = firmware_version(par);
- fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "Firmware version: %x.%02x\n",
- version >> 8, version & 0xFF);
-
- if (mode == 332)
- par->fbtftops.write_vmem = write_vmem_8bit;
- return 0;
-}
-
-static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
-{
- /* not used on this controller */
-}
-
-static int set_var(struct fbtft_par *par)
-{
- u8 rotate;
-
- /* this controller rotates clock wise */
- switch (par->info->var.rotate) {
- case 90:
- rotate = 27;
- break;
- case 180:
- rotate = 18;
- break;
- case 270:
- rotate = 9;
- break;
- default:
- rotate = 0;
- }
- write_reg(par, CMD_LCD_ORIENTATION, rotate);
-
- return 0;
-}
-
-static int verify_gpios(struct fbtft_par *par)
-{
- if (!par->gpio.reset) {
- dev_err(par->info->device, "Missing 'reset' gpio. Aborting.\n");
- return -EINVAL;
- }
- return 0;
-}
-
-#ifdef CONFIG_FB_BACKLIGHT
-static int backlight_chip_update_status(struct backlight_device *bd)
-{
- struct fbtft_par *par = bl_get_data(bd);
- int brightness = bd->props.brightness;
-
- fbtft_par_dbg(DEBUG_BACKLIGHT, par,
- "%s: brightness=%d, power=%d, fb_blank=%d\n", __func__,
- bd->props.brightness, bd->props.power,
- bd->props.fb_blank);
-
- if (bd->props.power != FB_BLANK_UNBLANK)
- brightness = 0;
-
- if (bd->props.fb_blank != FB_BLANK_UNBLANK)
- brightness = 0;
-
- write_reg(par, CMD_LCD_LED, brightness);
-
- return 0;
-}
-
-static const struct backlight_ops bl_ops = {
- .update_status = backlight_chip_update_status,
-};
-
-static void register_chip_backlight(struct fbtft_par *par)
-{
- struct backlight_device *bd;
- struct backlight_properties bl_props = { 0, };
-
- bl_props.type = BACKLIGHT_RAW;
- bl_props.power = FB_BLANK_POWERDOWN;
- bl_props.max_brightness = 100;
- bl_props.brightness = DEFAULT_BRIGHTNESS;
-
- bd = backlight_device_register(dev_driver_string(par->info->device),
- par->info->device, par, &bl_ops,
- &bl_props);
- if (IS_ERR(bd)) {
- dev_err(par->info->device,
- "cannot register backlight device (%ld)\n",
- PTR_ERR(bd));
- return;
- }
- par->info->bl_dev = bd;
-
- if (!par->fbtftops.unregister_backlight)
- par->fbtftops.unregister_backlight = fbtft_unregister_backlight;
-}
-#else
-#define register_chip_backlight NULL
-#endif
-
-static struct fbtft_display display = {
- .regwidth = 8,
- .buswidth = 8,
- .width = WIDTH,
- .height = HEIGHT,
- .fps = FPS,
- .txbuflen = TXBUFLEN,
- .fbtftops = {
- .write_register = write_reg8_bus8,
- .write_vmem = write_vmem,
- .init_display = init_display,
- .set_addr_win = set_addr_win,
- .set_var = set_var,
- .verify_gpios = verify_gpios,
- .register_backlight = register_chip_backlight,
- },
-};
-
-FBTFT_REGISTER_DRIVER(DRVNAME, "watterott,openlcd", &display);
-
-MODULE_ALIAS("spi:" DRVNAME);
-
-MODULE_DESCRIPTION("FB driver for the Watterott LCD Controller");
-MODULE_AUTHOR("Noralf Tronnes");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index f2684d2d6851..60b2278d8b16 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -49,7 +49,7 @@ int fbtft_write_buf_dc(struct fbtft_par *par, void *buf, size_t len, int dc)
EXPORT_SYMBOL(fbtft_write_buf_dc);
void fbtft_dbg_hex(const struct device *dev, int groupsize,
- void *buf, size_t len, const char *fmt, ...)
+ const void *buf, size_t len, const char *fmt, ...)
{
va_list args;
static char textbuf[512];
@@ -322,12 +322,11 @@ static void fbtft_mkdirty(struct fb_info *info, int y, int height)
schedule_delayed_work(&info->deferred_work, fbdefio->delay);
}
-static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist)
+static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagereflist)
{
struct fbtft_par *par = info->par;
unsigned int dirty_lines_start, dirty_lines_end;
- struct page *page;
- unsigned long index;
+ struct fb_deferred_io_pageref *pageref;
unsigned int y_low = 0, y_high = 0;
int count = 0;
@@ -340,14 +339,13 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist)
spin_unlock(&par->dirty_lock);
/* Mark display lines as dirty */
- list_for_each_entry(page, pagelist, lru) {
+ list_for_each_entry(pageref, pagereflist, list) {
count++;
- index = page->index << PAGE_SHIFT;
- y_low = index / info->fix.line_length;
- y_high = (index + PAGE_SIZE - 1) / info->fix.line_length;
+ y_low = pageref->offset / info->fix.line_length;
+ y_high = (pageref->offset + PAGE_SIZE - 1) / info->fix.line_length;
dev_dbg(info->device,
"page->index=%lu y_low=%d y_high=%d\n",
- page->index, y_low, y_high);
+ pageref->page->index, y_low, y_high);
if (y_high > info->var.yres - 1)
y_high = info->var.yres - 1;
if (y_low < dirty_lines_start)
@@ -652,9 +650,11 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
fbops->fb_imageblit = fbtft_fb_imageblit;
fbops->fb_setcolreg = fbtft_fb_setcolreg;
fbops->fb_blank = fbtft_fb_blank;
+ fbops->fb_mmap = fb_deferred_io_mmap;
- fbdefio->delay = HZ / fps;
- fbdefio->deferred_io = fbtft_deferred_io;
+ fbdefio->delay = HZ / fps;
+ fbdefio->sort_pagereflist = true;
+ fbdefio->deferred_io = fbtft_deferred_io;
fb_deferred_io_init(info);
snprintf(info->fix.id, sizeof(info->fix.id), "%s", dev->driver->name);
@@ -1034,10 +1034,9 @@ int fbtft_init_display(struct fbtft_par *par)
for (j = 0; par->init_sequence[i + 1 + j] >= 0; j++)
;
- fbtft_par_dbg(DEBUG_INIT_DISPLAY, par,
- "init: write(0x%02X) %*ph\n",
- par->init_sequence[i], j,
- &par->init_sequence[i + 1]);
+ fbtft_par_dbg_hex(DEBUG_INIT_DISPLAY, par, par->info->device,
+ s16, &par->init_sequence[i + 1], j,
+ "init: write(0x%02X)", par->init_sequence[i]);
/* Write */
j = 0;
diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h
index 6869f3603b0e..2c2b5f1c1df3 100644
--- a/drivers/staging/fbtft/fbtft.h
+++ b/drivers/staging/fbtft/fbtft.h
@@ -240,7 +240,7 @@ struct fbtft_par {
int fbtft_write_buf_dc(struct fbtft_par *par, void *buf, size_t len, int dc);
__printf(5, 6)
void fbtft_dbg_hex(const struct device *dev, int groupsize,
- void *buf, size_t len, const char *fmt, ...);
+ const void *buf, size_t len, const char *fmt, ...);
struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
struct device *dev,
struct fbtft_platform_data *pdata);
@@ -272,21 +272,39 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...);
void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);
void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...);
+#define FBTFT_DT_TABLE(_compatible) \
+static const struct of_device_id dt_ids[] = { \
+ { .compatible = _compatible }, \
+ {}, \
+}; \
+MODULE_DEVICE_TABLE(of, dt_ids);
+
+#define FBTFT_SPI_DRIVER(_name, _compatible, _display, _spi_ids) \
+ \
+static int fbtft_driver_probe_spi(struct spi_device *spi) \
+{ \
+ return fbtft_probe_common(_display, spi, NULL); \
+} \
+ \
+static void fbtft_driver_remove_spi(struct spi_device *spi) \
+{ \
+ struct fb_info *info = spi_get_drvdata(spi); \
+ \
+ fbtft_remove_common(&spi->dev, info); \
+} \
+ \
+static struct spi_driver fbtft_driver_spi_driver = { \
+ .driver = { \
+ .name = _name, \
+ .of_match_table = dt_ids, \
+ }, \
+ .id_table = _spi_ids, \
+ .probe = fbtft_driver_probe_spi, \
+ .remove = fbtft_driver_remove_spi, \
+};
+
#define FBTFT_REGISTER_DRIVER(_name, _compatible, _display) \
\
-static int fbtft_driver_probe_spi(struct spi_device *spi) \
-{ \
- return fbtft_probe_common(_display, spi, NULL); \
-} \
- \
-static int fbtft_driver_remove_spi(struct spi_device *spi) \
-{ \
- struct fb_info *info = spi_get_drvdata(spi); \
- \
- fbtft_remove_common(&spi->dev, info); \
- return 0; \
-} \
- \
static int fbtft_driver_probe_pdev(struct platform_device *pdev) \
{ \
return fbtft_probe_common(_display, NULL, pdev); \
@@ -300,22 +318,9 @@ static int fbtft_driver_remove_pdev(struct platform_device *pdev) \
return 0; \
} \
\
-static const struct of_device_id dt_ids[] = { \
- { .compatible = _compatible }, \
- {}, \
-}; \
- \
-MODULE_DEVICE_TABLE(of, dt_ids); \
- \
+FBTFT_DT_TABLE(_compatible) \
\
-static struct spi_driver fbtft_driver_spi_driver = { \
- .driver = { \
- .name = _name, \
- .of_match_table = dt_ids, \
- }, \
- .probe = fbtft_driver_probe_spi, \
- .remove = fbtft_driver_remove_spi, \
-}; \
+FBTFT_SPI_DRIVER(_name, _compatible, _display, NULL) \
\
static struct platform_driver fbtft_driver_platform_driver = { \
.driver = { \
@@ -334,7 +339,10 @@ static int __init fbtft_driver_module_init(void) \
ret = spi_register_driver(&fbtft_driver_spi_driver); \
if (ret < 0) \
return ret; \
- return platform_driver_register(&fbtft_driver_platform_driver); \
+ ret = platform_driver_register(&fbtft_driver_platform_driver); \
+ if (ret < 0) \
+ spi_unregister_driver(&fbtft_driver_spi_driver); \
+ return ret; \
} \
\
static void __exit fbtft_driver_module_exit(void) \
@@ -346,6 +354,20 @@ static void __exit fbtft_driver_module_exit(void) \
module_init(fbtft_driver_module_init); \
module_exit(fbtft_driver_module_exit);
+#define FBTFT_REGISTER_SPI_DRIVER(_name, _comp_vend, _comp_dev, _display) \
+ \
+FBTFT_DT_TABLE(_comp_vend "," _comp_dev) \
+ \
+static const struct spi_device_id spi_ids[] = { \
+ { .name = _comp_dev }, \
+ {}, \
+}; \
+MODULE_DEVICE_TABLE(spi, spi_ids); \
+ \
+FBTFT_SPI_DRIVER(_name, _comp_vend "," _comp_dev, _display, spi_ids) \
+ \
+module_spi_driver(fbtft_driver_spi_driver);
+
/* Debug macros */
/* shorthand debug levels */
diff --git a/drivers/staging/fieldbus/anybuss/host.c b/drivers/staging/fieldbus/anybuss/host.c
index a344410e48fe..cd86b9c9e345 100644
--- a/drivers/staging/fieldbus/anybuss/host.c
+++ b/drivers/staging/fieldbus/anybuss/host.c
@@ -1384,7 +1384,7 @@ anybuss_host_common_probe(struct device *dev,
goto err_device;
return cd;
err_device:
- device_unregister(&cd->client->dev);
+ put_device(&cd->client->dev);
err_kthread:
kthread_stop(cd->qthread);
err_reset:
diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c
index 493ed4821515..671ee8843c88 100644
--- a/drivers/staging/gdm724x/gdm_lte.c
+++ b/drivers/staging/gdm724x/gdm_lte.c
@@ -76,14 +76,15 @@ static void tx_complete(void *arg)
static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type)
{
- int ret;
+ int ret, len;
- ret = netif_rx_ni(skb);
+ len = skb->len + ETH_HLEN;
+ ret = netif_rx(skb);
if (ret == NET_RX_DROP) {
nic->stats.rx_dropped++;
} else {
nic->stats.rx_packets++;
- nic->stats.rx_bytes += skb->len + ETH_HLEN;
+ nic->stats.rx_bytes += len;
}
return 0;
@@ -194,7 +195,6 @@ static __sum16 icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len)
pseudo_header.ph.ph_len = be16_to_cpu(ipv6->payload_len);
pseudo_header.ph.ph_nxt = ipv6->nexthdr;
- w = (u16 *)&pseudo_header;
for (i = 0; i < ARRAY_SIZE(pseudo_header.pa); i++) {
pa = pseudo_header.pa[i];
sum = csum_add(sum, csum_unfold((__force __sum16)pa));
diff --git a/drivers/staging/gdm724x/hci_packet.h b/drivers/staging/gdm724x/hci_packet.h
index faecdfbc664f..3bb01e94f3b5 100644
--- a/drivers/staging/gdm724x/hci_packet.h
+++ b/drivers/staging/gdm724x/hci_packet.h
@@ -34,7 +34,7 @@ struct hci_packet {
struct tlv {
u8 type;
u8 len;
- u8 *data[1];
+ u8 *data[];
} __packed;
struct sdu_header {
diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c
index bbf3ba744fc4..45afa208d004 100644
--- a/drivers/staging/greybus/arche-apb-ctrl.c
+++ b/drivers/staging/greybus/arche-apb-ctrl.c
@@ -445,7 +445,7 @@ static int __maybe_unused arche_apb_ctrl_suspend(struct device *dev)
static int __maybe_unused arche_apb_ctrl_resume(struct device *dev)
{
/*
- * Atleast for ES2 we have to meet the delay requirement between
+ * At least for ES2 we have to meet the delay requirement between
* unipro switch and AP bridge init, depending on whether bridge is in
* OFF state or standby state.
*
diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c
index e374dfc0c92f..fcbd5f71eff2 100644
--- a/drivers/staging/greybus/arche-platform.c
+++ b/drivers/staging/greybus/arche-platform.c
@@ -591,7 +591,7 @@ static __maybe_unused int arche_platform_suspend(struct device *dev)
static __maybe_unused int arche_platform_resume(struct device *dev)
{
/*
- * Atleast for ES2 we have to meet the delay requirement between
+ * At least for ES2 we have to meet the delay requirement between
* unipro switch and AP bridge init, depending on whether bridge is in
* OFF state or standby state.
*
diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c
index b589cf6b1d03..0ad8aeabccbf 100644
--- a/drivers/staging/greybus/audio_codec.c
+++ b/drivers/staging/greybus/audio_codec.c
@@ -497,7 +497,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
int ret;
- struct gbaudio_module_info *module;
+ struct gbaudio_module_info *module = NULL, *iter;
struct gbaudio_data_connection *data;
struct gb_bundle *bundle;
struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
@@ -511,11 +511,13 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
return -ENODEV;
}
- list_for_each_entry(module, &codec->module_list, list) {
+ list_for_each_entry(iter, &codec->module_list, list) {
/* find the dai */
- data = find_data(module, dai->id);
- if (data)
+ data = find_data(iter, dai->id);
+ if (data) {
+ module = iter;
break;
+ }
}
if (!data) {
dev_err(dai->dev, "DATA connection missing\n");
@@ -563,7 +565,7 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
{
int ret;
struct gbaudio_data_connection *data;
- struct gbaudio_module_info *module;
+ struct gbaudio_module_info *module = NULL, *iter;
struct gb_bundle *bundle;
struct gbaudio_codec_info *codec = dev_get_drvdata(dai->dev);
struct gbaudio_stream_params *params;
@@ -592,15 +594,17 @@ static int gbcodec_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
return ret;
}
- list_for_each_entry(module, &codec->module_list, list) {
+ list_for_each_entry(iter, &codec->module_list, list) {
/* find the dai */
- data = find_data(module, dai->id);
- if (data)
+ data = find_data(iter, dai->id);
+ if (data) {
+ module = iter;
break;
+ }
}
if (!data) {
- dev_err(dai->dev, "%s:%s DATA connection missing\n",
- dai->name, module->name);
+ dev_err(dai->dev, "%s DATA connection missing\n",
+ dai->name);
mutex_unlock(&codec->lock);
return -ENODEV;
}
@@ -702,8 +706,9 @@ static int gbaudio_init_jack(struct gbaudio_module_info *module,
headset->pin = module->jack_name;
headset->mask = module->jack_mask;
- ret = snd_soc_card_jack_new(card, module->jack_name, module->jack_mask,
- &module->headset.jack, headset, 1);
+ ret = snd_soc_card_jack_new_pins(card, module->jack_name,
+ module->jack_mask,
+ &module->headset.jack, headset, 1);
if (ret) {
dev_err(module->dev, "Failed to create new jack\n");
return ret;
@@ -725,9 +730,10 @@ static int gbaudio_init_jack(struct gbaudio_module_info *module,
button->pin = module->button_name;
button->mask = module->button_mask;
- ret = snd_soc_card_jack_new(card, module->button_name,
- module->button_mask, &module->button.jack,
- button, 1);
+ ret = snd_soc_card_jack_new_pins(card, module->button_name,
+ module->button_mask,
+ &module->button.jack,
+ button, 1);
if (ret) {
dev_err(module->dev, "Failed to create button jack\n");
goto free_jacks;
@@ -1025,12 +1031,6 @@ static int gbcodec_probe(struct snd_soc_component *comp)
return 0;
}
-static void gbcodec_remove(struct snd_soc_component *comp)
-{
- /* Empty function for now */
- return;
-}
-
static int gbcodec_write(struct snd_soc_component *comp, unsigned int reg,
unsigned int value)
{
@@ -1045,8 +1045,6 @@ static unsigned int gbcodec_read(struct snd_soc_component *comp,
static const struct snd_soc_component_driver soc_codec_dev_gbaudio = {
.probe = gbcodec_probe,
- .remove = gbcodec_remove,
-
.read = gbcodec_read,
.write = gbcodec_write,
};
diff --git a/drivers/staging/greybus/audio_manager_module.c b/drivers/staging/greybus/audio_manager_module.c
index 525cf8f8394f..0a0f0a394c84 100644
--- a/drivers/staging/greybus/audio_manager_module.c
+++ b/drivers/staging/greybus/audio_manager_module.c
@@ -142,11 +142,12 @@ static struct attribute *gb_audio_module_default_attrs[] = {
&gb_audio_module_op_devices_attribute.attr,
NULL, /* need to NULL terminate the list of attributes */
};
+ATTRIBUTE_GROUPS(gb_audio_module_default);
static struct kobj_type gb_audio_module_type = {
.sysfs_ops = &gb_audio_module_sysfs_ops,
.release = gb_audio_module_release,
- .default_attrs = gb_audio_module_default_attrs,
+ .default_groups = gb_audio_module_default_groups,
};
static void send_add_uevent(struct gb_audio_manager_module *module)
diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c
index 1e613d42d823..62d7674852be 100644
--- a/drivers/staging/greybus/audio_topology.c
+++ b/drivers/staging/greybus/audio_topology.c
@@ -147,6 +147,9 @@ static const char **gb_generate_enum_strings(struct gbaudio_module_info *gb,
items = le32_to_cpu(gbenum->items);
strings = devm_kcalloc(gb->dev, items, sizeof(char *), GFP_KERNEL);
+ if (!strings)
+ return NULL;
+
data = gbenum->names;
for (i = 0; i < items; i++) {
@@ -655,6 +658,8 @@ static int gbaudio_tplg_create_enum_kctl(struct gbaudio_module_info *gb,
/* since count=1, and reg is dummy */
gbe->items = le32_to_cpu(gb_enum->items);
gbe->texts = gb_generate_enum_strings(gb, gb_enum);
+ if (!gbe->texts)
+ return -ENOMEM;
/* debug enum info */
dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gbe->items,
@@ -862,6 +867,8 @@ static int gbaudio_tplg_create_enum_ctl(struct gbaudio_module_info *gb,
/* since count=1, and reg is dummy */
gbe->items = le32_to_cpu(gb_enum->items);
gbe->texts = gb_generate_enum_strings(gb, gb_enum);
+ if (!gbe->texts)
+ return -ENOMEM;
/* debug enum info */
dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gbe->items,
@@ -974,6 +981,44 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w,
return ret;
}
+static const struct snd_soc_dapm_widget gbaudio_widgets[] = {
+ [snd_soc_dapm_spk] = SND_SOC_DAPM_SPK(NULL, gbcodec_event_spk),
+ [snd_soc_dapm_hp] = SND_SOC_DAPM_HP(NULL, gbcodec_event_hp),
+ [snd_soc_dapm_mic] = SND_SOC_DAPM_MIC(NULL, gbcodec_event_int_mic),
+ [snd_soc_dapm_output] = SND_SOC_DAPM_OUTPUT(NULL),
+ [snd_soc_dapm_input] = SND_SOC_DAPM_INPUT(NULL),
+ [snd_soc_dapm_switch] = SND_SOC_DAPM_SWITCH_E(NULL, SND_SOC_NOPM,
+ 0, 0, NULL,
+ gbaudio_widget_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ [snd_soc_dapm_pga] = SND_SOC_DAPM_PGA_E(NULL, SND_SOC_NOPM,
+ 0, 0, NULL, 0,
+ gbaudio_widget_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ [snd_soc_dapm_mixer] = SND_SOC_DAPM_MIXER_E(NULL, SND_SOC_NOPM,
+ 0, 0, NULL, 0,
+ gbaudio_widget_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ [snd_soc_dapm_mux] = SND_SOC_DAPM_MUX_E(NULL, SND_SOC_NOPM,
+ 0, 0, NULL,
+ gbaudio_widget_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ [snd_soc_dapm_aif_in] = SND_SOC_DAPM_AIF_IN_E(NULL, NULL, 0,
+ SND_SOC_NOPM, 0, 0,
+ gbaudio_widget_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ [snd_soc_dapm_aif_out] = SND_SOC_DAPM_AIF_OUT_E(NULL, NULL, 0,
+ SND_SOC_NOPM, 0, 0,
+ gbaudio_widget_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+};
+
static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module,
struct snd_soc_dapm_widget *dw,
struct gb_audio_widget *w, int *w_size)
@@ -1034,6 +1079,10 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module,
csize += le16_to_cpu(gbenum->names_length);
control->texts = (const char * const *)
gb_generate_enum_strings(module, gbenum);
+ if (!control->texts) {
+ ret = -ENOMEM;
+ goto error;
+ }
control->items = le32_to_cpu(gbenum->items);
} else {
csize = sizeof(struct gb_audio_control);
@@ -1052,77 +1101,37 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module,
switch (w->type) {
case snd_soc_dapm_spk:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_SPK(w->name, gbcodec_event_spk);
+ *dw = gbaudio_widgets[w->type];
module->op_devices |= GBAUDIO_DEVICE_OUT_SPEAKER;
break;
case snd_soc_dapm_hp:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_HP(w->name, gbcodec_event_hp);
+ *dw = gbaudio_widgets[w->type];
module->op_devices |= (GBAUDIO_DEVICE_OUT_WIRED_HEADSET
| GBAUDIO_DEVICE_OUT_WIRED_HEADPHONE);
module->ip_devices |= GBAUDIO_DEVICE_IN_WIRED_HEADSET;
break;
case snd_soc_dapm_mic:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_MIC(w->name, gbcodec_event_int_mic);
+ *dw = gbaudio_widgets[w->type];
module->ip_devices |= GBAUDIO_DEVICE_IN_BUILTIN_MIC;
break;
case snd_soc_dapm_output:
- *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_OUTPUT(w->name);
- break;
case snd_soc_dapm_input:
- *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_INPUT(w->name);
- break;
case snd_soc_dapm_switch:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_SWITCH_E(w->name, SND_SOC_NOPM, 0, 0,
- widget_kctls,
- gbaudio_widget_event,
- SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD);
- break;
case snd_soc_dapm_pga:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_PGA_E(w->name, SND_SOC_NOPM, 0, 0, NULL, 0,
- gbaudio_widget_event,
- SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD);
- break;
case snd_soc_dapm_mixer:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_MIXER_E(w->name, SND_SOC_NOPM, 0, 0, NULL,
- 0, gbaudio_widget_event,
- SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD);
- break;
case snd_soc_dapm_mux:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_MUX_E(w->name, SND_SOC_NOPM, 0, 0,
- widget_kctls, gbaudio_widget_event,
- SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD);
+ *dw = gbaudio_widgets[w->type];
break;
case snd_soc_dapm_aif_in:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_AIF_IN_E(w->name, w->sname, 0,
- SND_SOC_NOPM,
- 0, 0, gbaudio_widget_event,
- SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD);
- break;
case snd_soc_dapm_aif_out:
- *dw = (struct snd_soc_dapm_widget)
- SND_SOC_DAPM_AIF_OUT_E(w->name, w->sname, 0,
- SND_SOC_NOPM,
- 0, 0, gbaudio_widget_event,
- SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD);
+ *dw = gbaudio_widgets[w->type];
+ dw->sname = w->sname;
break;
default:
ret = -EINVAL;
goto error;
}
+ dw->name = w->name;
dev_dbg(module->dev, "%s: widget of type %d created\n", dw->name,
dw->id);
@@ -1183,6 +1192,10 @@ static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module,
csize += le16_to_cpu(gbenum->names_length);
control->texts = (const char * const *)
gb_generate_enum_strings(module, gbenum);
+ if (!control->texts) {
+ ret = -ENOMEM;
+ goto error;
+ }
control->items = le32_to_cpu(gbenum->items);
} else {
csize = sizeof(struct gb_audio_control);
diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c
index 7e6347fe93f9..8a7cf1d0e968 100644
--- a/drivers/staging/greybus/gpio.c
+++ b/drivers/staging/greybus/gpio.c
@@ -391,10 +391,7 @@ static int gb_gpio_request_handler(struct gb_operation *op)
return -EINVAL;
}
- local_irq_disable();
- ret = generic_handle_irq(irq);
- local_irq_enable();
-
+ ret = generic_handle_irq_safe(irq);
if (ret)
dev_err(dev, "failed to invoke irq handler\n");
diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c
index 891a6a672378..3fda172239d2 100644
--- a/drivers/staging/greybus/pwm.c
+++ b/drivers/staging/greybus/pwm.c
@@ -204,43 +204,59 @@ static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
gb_pwm_deactivate_operation(pwmc, pwm->hwpwm);
}
-static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
- int duty_ns, int period_ns)
+static int gb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
{
+ int err;
+ bool enabled = pwm->state.enabled;
+ u64 period = state->period;
+ u64 duty_cycle = state->duty_cycle;
struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
- return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns);
-};
+ /* Set polarity */
+ if (state->polarity != pwm->state.polarity) {
+ if (enabled) {
+ gb_pwm_disable_operation(pwmc, pwm->hwpwm);
+ enabled = false;
+ }
+ err = gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, state->polarity);
+ if (err)
+ return err;
+ }
-static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
- enum pwm_polarity polarity)
-{
- struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
+ if (!state->enabled) {
+ if (enabled)
+ gb_pwm_disable_operation(pwmc, pwm->hwpwm);
+ return 0;
+ }
- return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity);
-};
+ /*
+ * Set period and duty cycle
+ *
+ * PWM privodes 64-bit period and duty_cycle, but greybus only accepts
+ * 32-bit, so their values have to be limited to U32_MAX.
+ */
+ if (period > U32_MAX)
+ period = U32_MAX;
-static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
- struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
+ if (duty_cycle > period)
+ duty_cycle = period;
- return gb_pwm_enable_operation(pwmc, pwm->hwpwm);
-};
+ err = gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_cycle, period);
+ if (err)
+ return err;
-static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
- struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
+ /* enable/disable */
+ if (!enabled)
+ return gb_pwm_enable_operation(pwmc, pwm->hwpwm);
- gb_pwm_disable_operation(pwmc, pwm->hwpwm);
-};
+ return 0;
+}
static const struct pwm_ops gb_pwm_ops = {
.request = gb_pwm_request,
.free = gb_pwm_free,
- .config = gb_pwm_config,
- .set_polarity = gb_pwm_set_polarity,
- .enable = gb_pwm_enable,
- .disable = gb_pwm_disable,
+ .apply = gb_pwm_apply,
.owner = THIS_MODULE,
};
@@ -281,7 +297,6 @@ static int gb_pwm_probe(struct gbphy_device *gbphy_dev,
pwm->dev = &gbphy_dev->dev;
pwm->ops = &gb_pwm_ops;
- pwm->base = -1; /* Allocate base dynamically */
pwm->npwm = pwmc->pwm_max + 1;
ret = pwmchip_add(pwm);
diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c
index 37bf04c22dbc..25bee5335c70 100644
--- a/drivers/staging/greybus/sdio.c
+++ b/drivers/staging/greybus/sdio.c
@@ -858,7 +858,6 @@ static void gb_sdio_remove(struct gbphy_device *gbphy_dev)
gb_connection_set_data(connection, NULL);
mutex_unlock(&host->lock);
- flush_workqueue(host->mrq_workqueue);
destroy_workqueue(host->mrq_workqueue);
gb_connection_disable_rx(connection);
mmc_remove_host(mmc);
diff --git a/drivers/staging/greybus/tools/Makefile b/drivers/staging/greybus/tools/Makefile
index ad0ae8053b79..a3bbd73171f2 100644
--- a/drivers/staging/greybus/tools/Makefile
+++ b/drivers/staging/greybus/tools/Makefile
@@ -12,7 +12,8 @@ CFLAGS += -std=gnu99 -Wall -Wextra -g \
-Wredundant-decls \
-Wcast-align \
-Wsign-compare \
- -Wno-missing-field-initializers
+ -Wno-missing-field-initializers \
+ -Wno-shift-negative-value
CC := $(CROSS_COMPILE)gcc
diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c
index 867bf289df2e..4c42e393cd3d 100644
--- a/drivers/staging/greybus/tools/loopback_test.c
+++ b/drivers/staging/greybus/tools/loopback_test.c
@@ -533,7 +533,7 @@ static int log_results(struct loopback_test *t)
fd = open(file_name, O_WRONLY | O_CREAT | O_APPEND, 0644);
if (fd < 0) {
- fprintf(stderr, "unable to open %s for appendation\n", file_name);
+ fprintf(stderr, "unable to open %s for appending\n", file_name);
abort();
}
diff --git a/drivers/staging/gs_fpgaboot/Kconfig b/drivers/staging/gs_fpgaboot/Kconfig
deleted file mode 100644
index 968a153c4ab6..000000000000
--- a/drivers/staging/gs_fpgaboot/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# "xilinx FPGA firmware download, fpgaboot"
-#
-config GS_FPGABOOT
- tristate "Xilinx FPGA firmware download module"
- help
- Xilinx FPGA firmware download module
diff --git a/drivers/staging/gs_fpgaboot/Makefile b/drivers/staging/gs_fpgaboot/Makefile
deleted file mode 100644
index 33e238be63d6..000000000000
--- a/drivers/staging/gs_fpgaboot/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-gs_fpga-y += gs_fpgaboot.o io.o
-obj-$(CONFIG_GS_FPGABOOT) += gs_fpga.o
diff --git a/drivers/staging/gs_fpgaboot/README b/drivers/staging/gs_fpgaboot/README
deleted file mode 100644
index ec1235a21bcc..000000000000
--- a/drivers/staging/gs_fpgaboot/README
+++ /dev/null
@@ -1,70 +0,0 @@
-==============================================================================
-Linux Driver Source for Xilinx FPGA firmware download
-==============================================================================
-
-
-TABLE OF CONTENTS.
-
-1. SUMMARY
-2. BACKGROUND
-3. DESIGN
-4. HOW TO USE
-5. REFERENCE
-
-1. SUMMARY
-
- - Download Xilinx FPGA firmware
- - This module downloads Xilinx FPGA firmware using gpio pins.
-
-2. BACKGROUND
-
- An FPGA (Field Programmable Gate Array) is a programmable hardware that is
- used in various applications. Hardware design needs to programmed through
- a dedicated device or CPU assisted way (serial or parallel).
- This driver provides a way to download FPGA firmware.
-
-3. DESIGN
-
- - load Xilinx FPGA bitstream format[1] firmware image file using
- kernel firmware framework, request_firmware()
- - program the Xilinx FPGA using SelectMAP (parallel) mode [2]
- - FPGA prgram is done by gpio based bit-banging, as an example
- - platform independent file: gs_fpgaboot.c
- - platform dependent file: io.c
-
-4. HOW TO USE
-
- $ insmod gs_fpga.ko file="xlinx_fpga_top_bitstream.bit"
- $ rmmod gs_fpga
-
-5. USE CASE (from a mailing list discussion with Greg)
-
- a. As an FPGA development support tool,
- During FPGA firmware development, you need to download a new FPGA
- image frequently.
- You would do that with a dedicated JTAG, which usually a limited
- resource in the lab.
- However, if you use my driver, you don't have to have a dedicated JTAG.
- This is a real gain :)
-
- b. For the FPGA that runs without config after the download, which
- doesn't talk to any of Linux interfaces (such as PCIE).
-
- We download FPGA firmware from user triggered or some other way, and that's it.
- Since that FPGA runs on its own, it doesn't require a linux driver
- after the download.
-
- c. For the FPGA that requires config after the download, which talk to
- any of linux interfaces (such as PCIE)
-
- Then, this type of FPGA config can be put into device tree and have a
- separate driver (pcie or others), then THAT driver calls my driver to
- download FPGA firmware during the Linux boot, the take over the device
- through the interface.
-
-6. REFERENCE
-
- 1. Xilinx APP NOTE XAPP583:
- https://www.xilinx.com/support/documentation/application_notes/xapp583-fpga-configuration.pdf
- 2. bitstream file info:
- http://home.earthlink.net/~davesullins/software/bitinfo.html
diff --git a/drivers/staging/gs_fpgaboot/TODO b/drivers/staging/gs_fpgaboot/TODO
deleted file mode 100644
index 2d9fb17d606d..000000000000
--- a/drivers/staging/gs_fpgaboot/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
- - get bus width input instead of hardcoded bus width
- - get it reviewed
-
-Please send any patches for this driver to Insop Song<insop.song@gainspeed.com>
-and Greg Kroah-Hartman <gregkh@linuxfoundation.org>.
-And please CC to "Staging subsystem" mail list <devel@driverdev.osuosl.org> too.
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
deleted file mode 100644
index 3e154562c64d..000000000000
--- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c
+++ /dev/null
@@ -1,394 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/firmware.h>
-#include <asm/unaligned.h>
-
-#include "gs_fpgaboot.h"
-#include "io.h"
-
-#define DEVICE_NAME "device"
-#define CLASS_NAME "fpgaboot"
-
-static u8 bits_magic[] = {
- 0x0, 0x9, 0xf, 0xf0, 0xf, 0xf0,
- 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x1};
-
-/* fake device for request_firmware */
-static struct platform_device *firmware_pdev;
-
-static char *file = "xlinx_fpga_firmware.bit";
-module_param(file, charp, 0444);
-MODULE_PARM_DESC(file, "Xilinx FPGA firmware file.");
-
-static void read_bitstream(u8 *bitdata, u8 *buf, int *offset, int rdsize)
-{
- memcpy(buf, bitdata + *offset, rdsize);
- *offset += rdsize;
-}
-
-static int readinfo_bitstream(u8 *bitdata, u8 *buf, int size, int *offset)
-{
- u8 tbuf[2];
- u16 len;
-
- /* read section char */
- read_bitstream(bitdata, tbuf, offset, 1);
-
- /* read length */
- read_bitstream(bitdata, tbuf, offset, 2);
-
- len = get_unaligned_be16(tbuf);
- if (len >= size) {
- pr_err("error: readinfo buffer too small\n");
- return -EINVAL;
- }
-
- read_bitstream(bitdata, buf, offset, len);
- buf[len] = '\0';
-
- return 0;
-}
-
-/*
- * read bitdata length
- */
-static int readlength_bitstream(u8 *bitdata, int *lendata, int *offset)
-{
- u8 tbuf[4];
-
- /* read section char */
- read_bitstream(bitdata, tbuf, offset, 1);
-
- /* make sure it is section 'e' */
- if (tbuf[0] != 'e') {
- pr_err("error: length section is not 'e', but %c\n", tbuf[0]);
- return -EINVAL;
- }
-
- /* read 4bytes length */
- read_bitstream(bitdata, tbuf, offset, 4);
-
- *lendata = get_unaligned_be32(tbuf);
-
- return 0;
-}
-
-/*
- * read first 13 bytes to check bitstream magic number
- */
-static int readmagic_bitstream(u8 *bitdata, int *offset)
-{
- u8 buf[13];
- int r;
-
- read_bitstream(bitdata, buf, offset, 13);
- r = memcmp(buf, bits_magic, 13);
- if (r) {
- pr_err("error: corrupted header\n");
- return -EINVAL;
- }
- pr_info("bitstream file magic number Ok\n");
-
- *offset = 13; /* magic length */
-
- return 0;
-}
-
-/*
- * NOTE: supports only bitstream format
- */
-static enum fmt_image get_imageformat(void)
-{
- return f_bit;
-}
-
-static void gs_print_header(struct fpgaimage *fimage)
-{
- pr_info("file: %s\n", fimage->filename);
- pr_info("part: %s\n", fimage->part);
- pr_info("date: %s\n", fimage->date);
- pr_info("time: %s\n", fimage->time);
- pr_info("lendata: %d\n", fimage->lendata);
-}
-
-static int gs_read_bitstream(struct fpgaimage *fimage)
-{
- u8 *bitdata;
- int offset;
- int err;
-
- offset = 0;
- bitdata = (u8 *)fimage->fw_entry->data;
-
- err = readmagic_bitstream(bitdata, &offset);
- if (err)
- return err;
-
- err = readinfo_bitstream(bitdata, fimage->filename, MAX_STR, &offset);
- if (err)
- return err;
- err = readinfo_bitstream(bitdata, fimage->part, MAX_STR, &offset);
- if (err)
- return err;
- err = readinfo_bitstream(bitdata, fimage->date, MAX_STR, &offset);
- if (err)
- return err;
- err = readinfo_bitstream(bitdata, fimage->time, MAX_STR, &offset);
- if (err)
- return err;
-
- err = readlength_bitstream(bitdata, &fimage->lendata, &offset);
- if (err)
- return err;
-
- fimage->fpgadata = bitdata + offset;
-
- return 0;
-}
-
-static int gs_read_image(struct fpgaimage *fimage)
-{
- int img_fmt;
- int err;
-
- img_fmt = get_imageformat();
-
- switch (img_fmt) {
- case f_bit:
- pr_info("image is bitstream format\n");
- err = gs_read_bitstream(fimage);
- if (err)
- return err;
- break;
- default:
- pr_err("unsupported fpga image format\n");
- return -EINVAL;
- }
-
- gs_print_header(fimage);
-
- return 0;
-}
-
-static int gs_load_image(struct fpgaimage *fimage, char *fw_file)
-{
- int err;
-
- pr_info("load fpgaimage %s\n", fw_file);
-
- err = request_firmware(&fimage->fw_entry, fw_file, &firmware_pdev->dev);
- if (err != 0) {
- pr_err("firmware %s is missing, cannot continue.\n", fw_file);
- return err;
- }
-
- return 0;
-}
-
-static int gs_download_image(struct fpgaimage *fimage, enum wbus bus_bytes)
-{
- u8 *bitdata;
- int size, i, cnt;
-
- cnt = 0;
- bitdata = (u8 *)fimage->fpgadata;
- size = fimage->lendata;
-
-#ifdef DEBUG_FPGA
- print_hex_dump_bytes("bitfile sample: ", DUMP_PREFIX_OFFSET,
- bitdata, 0x100);
-#endif /* DEBUG_FPGA */
- if (!xl_supported_prog_bus_width(bus_bytes)) {
- pr_err("unsupported program bus width %d\n",
- bus_bytes);
- return -EINVAL;
- }
-
- /* Bring csi_b, rdwr_b Low and program_b High */
- xl_program_b(1);
- xl_rdwr_b(0);
- xl_csi_b(0);
-
- /* Configuration reset */
- xl_program_b(0);
- msleep(20);
- xl_program_b(1);
-
- /* Wait for Device Initialization */
- while (xl_get_init_b() == 0)
- ;
-
- pr_info("device init done\n");
-
- for (i = 0; i < size; i += bus_bytes)
- xl_shift_bytes_out(bus_bytes, bitdata + i);
-
- pr_info("program done\n");
-
- /* Check INIT_B */
- if (xl_get_init_b() == 0) {
- pr_err("init_b 0\n");
- return -EIO;
- }
-
- while (xl_get_done_b() == 0) {
- if (cnt++ > MAX_WAIT_DONE) {
- pr_err("init_B %d\n", xl_get_init_b());
- break;
- }
- }
-
- if (cnt > MAX_WAIT_DONE) {
- pr_err("fpga download fail\n");
- return -EIO;
- }
-
- pr_info("download fpgaimage\n");
-
- /* Compensate for Special Startup Conditions */
- xl_shift_cclk(8);
-
- return 0;
-}
-
-static int gs_release_image(struct fpgaimage *fimage)
-{
- release_firmware(fimage->fw_entry);
- pr_info("release fpgaimage\n");
-
- return 0;
-}
-
-/*
- * NOTE: supports systemmap parallel programming
- */
-static int gs_set_download_method(struct fpgaimage *fimage)
-{
- pr_info("set program method\n");
-
- fimage->dmethod = m_systemmap;
-
- pr_info("systemmap program method\n");
-
- return 0;
-}
-
-static int init_driver(void)
-{
- firmware_pdev = platform_device_register_simple("fpgaboot", -1,
- NULL, 0);
- return PTR_ERR_OR_ZERO(firmware_pdev);
-}
-
-static int gs_fpgaboot(void)
-{
- int err;
- struct fpgaimage *fimage;
-
- fimage = kmalloc(sizeof(*fimage), GFP_KERNEL);
- if (!fimage)
- return -ENOMEM;
-
- err = gs_load_image(fimage, file);
- if (err) {
- pr_err("gs_load_image error\n");
- goto err_out1;
- }
-
- err = gs_read_image(fimage);
- if (err) {
- pr_err("gs_read_image error\n");
- goto err_out2;
- }
-
- err = gs_set_download_method(fimage);
- if (err) {
- pr_err("gs_set_download_method error\n");
- goto err_out2;
- }
-
- err = gs_download_image(fimage, bus_2byte);
- if (err) {
- pr_err("gs_download_image error\n");
- goto err_out2;
- }
-
- err = gs_release_image(fimage);
- if (err) {
- pr_err("gs_release_image error\n");
- goto err_out1;
- }
-
- kfree(fimage);
- return 0;
-
-err_out2:
- err = gs_release_image(fimage);
- if (err)
- pr_err("gs_release_image error\n");
-err_out1:
- kfree(fimage);
-
- return err;
-}
-
-static int __init gs_fpgaboot_init(void)
-{
- int err;
-
- pr_info("FPGA DOWNLOAD --->\n");
-
- pr_info("FPGA image file name: %s\n", file);
-
- err = init_driver();
- if (err) {
- pr_err("FPGA DRIVER INIT FAIL!!\n");
- return err;
- }
-
- err = xl_init_io();
- if (err) {
- pr_err("GPIO INIT FAIL!!\n");
- goto errout;
- }
-
- err = gs_fpgaboot();
- if (err) {
- pr_err("FPGA DOWNLOAD FAIL!!\n");
- goto errout;
- }
-
- pr_info("FPGA DOWNLOAD DONE <---\n");
-
- return 0;
-
-errout:
- platform_device_unregister(firmware_pdev);
-
- return err;
-}
-
-static void __exit gs_fpgaboot_exit(void)
-{
- platform_device_unregister(firmware_pdev);
- pr_info("FPGA image download module removed\n");
-}
-
-module_init(gs_fpgaboot_init);
-module_exit(gs_fpgaboot_exit);
-
-MODULE_AUTHOR("Insop Song");
-MODULE_DESCRIPTION("Xlinix FPGA firmware download");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h
deleted file mode 100644
index 5cf12c14cca4..000000000000
--- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-
-#include <linux/firmware.h>
-
-#define MAX_STR 256
-
-enum fmt_image {
- f_bit, /* only bitstream is supported */
- f_rbt,
- f_bin,
- f_mcs,
- f_hex,
-};
-
-enum mdownload {
- m_systemmap, /* only system map is supported */
- m_serial,
- m_jtag,
-};
-
-/*
- * xilinx fpgaimage information
- * NOTE: use MAX_STR instead of dynamic alloc for simplicity
- */
-struct fpgaimage {
- enum fmt_image fmt_img;
- enum mdownload dmethod;
-
- const struct firmware *fw_entry;
-
- /*
- * the following can be read from bitstream,
- * but other image format should have as well
- */
- char filename[MAX_STR];
- char part[MAX_STR];
- char date[MAX_STR];
- char time[MAX_STR];
- int lendata;
- u8 *fpgadata;
-};
diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c
deleted file mode 100644
index 80903ec36b76..000000000000
--- a/drivers/staging/gs_fpgaboot/io.c
+++ /dev/null
@@ -1,105 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/firmware.h>
-#include <linux/io.h>
-
-#include "io.h"
-
-static inline void byte0_out(unsigned char data);
-static inline void byte1_out(unsigned char data);
-static inline void xl_cclk_b(int32_t i);
-
-/* Assert and Deassert CCLK */
-void xl_shift_cclk(int count)
-{
- int i;
-
- for (i = 0; i < count; i++) {
- xl_cclk_b(1);
- xl_cclk_b(0);
- }
-}
-
-int xl_supported_prog_bus_width(enum wbus bus_bytes)
-{
- switch (bus_bytes) {
- case bus_1byte:
- break;
- case bus_2byte:
- break;
- default:
- pr_err("unsupported program bus width %d\n", bus_bytes);
- return 0;
- }
-
- return 1;
-}
-
-/* Serialize byte and clock each bit on target's DIN and CCLK pins */
-void xl_shift_bytes_out(enum wbus bus_byte, unsigned char *pdata)
-{
- /*
- * supports 1 and 2 bytes programming mode
- */
- if (likely(bus_byte == bus_2byte))
- byte0_out(pdata[0]);
-
- byte1_out(pdata[1]);
- xl_shift_cclk(1);
-}
-
-/*
- * generic bit swap for xilinx SYSTEMMAP FPGA programming
- */
-void xl_program_b(int32_t i)
-{
-}
-
-void xl_rdwr_b(int32_t i)
-{
-}
-
-void xl_csi_b(int32_t i)
-{
-}
-
-int xl_get_init_b(void)
-{
- return -1;
-}
-
-int xl_get_done_b(void)
-{
- return -1;
-}
-
-static inline void byte0_out(unsigned char data)
-{
-}
-
-static inline void byte1_out(unsigned char data)
-{
-}
-
-static inline void xl_cclk_b(int32_t i)
-{
-}
-
-/*
- * configurable per device type for different I/O config
- */
-int xl_init_io(void)
-{
- return -1;
-}
diff --git a/drivers/staging/gs_fpgaboot/io.h b/drivers/staging/gs_fpgaboot/io.h
deleted file mode 100644
index 9bd86a92e90f..000000000000
--- a/drivers/staging/gs_fpgaboot/io.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-
-#define GPDIR 0
-#define GPCFG 4 /* open drain or not */
-#define GPDAT 8
-
-/*
- * gpio port and pin definitions
- * NOTE: port number starts from 0
- */
-#define XL_INITN_PORT 1
-#define XL_INITN_PIN 14
-#define XL_RDWRN_PORT 1
-#define XL_RDWRN_PIN 13
-#define XL_CCLK_PORT 1
-#define XL_CCLK_PIN 10
-#define XL_PROGN_PORT 1
-#define XL_PROGN_PIN 25
-#define XL_CSIN_PORT 1
-#define XL_CSIN_PIN 26
-#define XL_DONE_PORT 1
-#define XL_DONE_PIN 27
-
-/*
- * gpio mapping
- *
- XL_config_D0 – gpio1_31
- Xl_config_d1 – gpio1_30
- Xl_config_d2 – gpio1_29
- Xl_config_d3 – gpio1_28
- Xl_config_d4 – gpio1_27
- Xl_config_d5 – gpio1_26
- Xl_config_d6 – gpio1_25
- Xl_config_d7 – gpio1_24
- Xl_config_d8 – gpio1_23
- Xl_config_d9 – gpio1_22
- Xl_config_d10 – gpio1_21
- Xl_config_d11 – gpio1_20
- Xl_config_d12 – gpio1_19
- Xl_config_d13 – gpio1_18
- Xl_config_d14 – gpio1_16
- Xl_config_d15 – gpio1_14
-*
-*/
-
-/*
- * program bus width in bytes
- */
-enum wbus {
- bus_1byte = 1,
- bus_2byte = 2,
-};
-
-#define MAX_WAIT_DONE 10000
-
-struct gpiobus {
- int ngpio;
- void __iomem *r[4];
-};
-
-int xl_supported_prog_bus_width(enum wbus bus_bytes);
-
-void xl_program_b(int32_t i);
-void xl_rdwr_b(int32_t i);
-void xl_csi_b(int32_t i);
-
-int xl_get_init_b(void);
-int xl_get_done_b(void);
-
-void xl_shift_cclk(int count);
-void xl_shift_bytes_out(enum wbus bus_byte, unsigned char *pdata);
-
-int xl_init_io(void);
diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c
index 1d3026dae827..62d5397ff1f9 100644
--- a/drivers/staging/iio/accel/adis16203.c
+++ b/drivers/staging/iio/accel/adis16203.c
@@ -312,3 +312,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:adis16203");
+MODULE_IMPORT_NS(IIO_ADISLIB);
diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c
index 2a8aa83b8d9e..bca857eef92e 100644
--- a/drivers/staging/iio/accel/adis16240.c
+++ b/drivers/staging/iio/accel/adis16240.c
@@ -440,3 +440,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:adis16240");
+MODULE_IMPORT_NS(IIO_ADISLIB);
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index b25f41053fac..2f0d6cf048d2 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -15,15 +15,4 @@ config AD7816
To compile this driver as a module, choose M here: the
module will be called ad7816.
-config AD7280
- tristate "Analog Devices AD7280A Lithium Ion Battery Monitoring System"
- depends on SPI
- select CRC8
- help
- Say yes here to build support for Analog Devices AD7280A
- Lithium Ion Battery Monitoring System.
-
- To compile this driver as a module, choose M here: the
- module will be called ad7280a
-
endmenu
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 6436a62b6278..1e2a94c4db84 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -4,4 +4,3 @@
#
obj-$(CONFIG_AD7816) += ad7816.o
-obj-$(CONFIG_AD7280) += ad7280a.o
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
deleted file mode 100644
index fef0055b8990..000000000000
--- a/drivers/staging/iio/adc/ad7280a.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * AD7280A Lithium Ion Battery Monitoring System
- *
- * Copyright 2011 Analog Devices Inc.
- */
-
-#include <linux/crc8.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/spi/spi.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
-
-#include "ad7280a.h"
-
-/* Registers */
-#define AD7280A_CELL_VOLTAGE_1 0x0 /* D11 to D0, Read only */
-#define AD7280A_CELL_VOLTAGE_2 0x1 /* D11 to D0, Read only */
-#define AD7280A_CELL_VOLTAGE_3 0x2 /* D11 to D0, Read only */
-#define AD7280A_CELL_VOLTAGE_4 0x3 /* D11 to D0, Read only */
-#define AD7280A_CELL_VOLTAGE_5 0x4 /* D11 to D0, Read only */
-#define AD7280A_CELL_VOLTAGE_6 0x5 /* D11 to D0, Read only */
-#define AD7280A_AUX_ADC_1 0x6 /* D11 to D0, Read only */
-#define AD7280A_AUX_ADC_2 0x7 /* D11 to D0, Read only */
-#define AD7280A_AUX_ADC_3 0x8 /* D11 to D0, Read only */
-#define AD7280A_AUX_ADC_4 0x9 /* D11 to D0, Read only */
-#define AD7280A_AUX_ADC_5 0xA /* D11 to D0, Read only */
-#define AD7280A_AUX_ADC_6 0xB /* D11 to D0, Read only */
-#define AD7280A_SELF_TEST 0xC /* D11 to D0, Read only */
-#define AD7280A_CONTROL_HB 0xD /* D15 to D8, Read/write */
-#define AD7280A_CONTROL_LB 0xE /* D7 to D0, Read/write */
-#define AD7280A_CELL_OVERVOLTAGE 0xF /* D7 to D0, Read/write */
-#define AD7280A_CELL_UNDERVOLTAGE 0x10 /* D7 to D0, Read/write */
-#define AD7280A_AUX_ADC_OVERVOLTAGE 0x11 /* D7 to D0, Read/write */
-#define AD7280A_AUX_ADC_UNDERVOLTAGE 0x12 /* D7 to D0, Read/write */
-#define AD7280A_ALERT 0x13 /* D7 to D0, Read/write */
-#define AD7280A_CELL_BALANCE 0x14 /* D7 to D0, Read/write */
-#define AD7280A_CB1_TIMER 0x15 /* D7 to D0, Read/write */
-#define AD7280A_CB2_TIMER 0x16 /* D7 to D0, Read/write */
-#define AD7280A_CB3_TIMER 0x17 /* D7 to D0, Read/write */
-#define AD7280A_CB4_TIMER 0x18 /* D7 to D0, Read/write */
-#define AD7280A_CB5_TIMER 0x19 /* D7 to D0, Read/write */
-#define AD7280A_CB6_TIMER 0x1A /* D7 to D0, Read/write */
-#define AD7280A_PD_TIMER 0x1B /* D7 to D0, Read/write */
-#define AD7280A_READ 0x1C /* D7 to D0, Read/write */
-#define AD7280A_CNVST_CONTROL 0x1D /* D7 to D0, Read/write */
-
-/* Bits and Masks */
-#define AD7280A_CTRL_HB_CONV_INPUT_ALL 0
-#define AD7280A_CTRL_HB_CONV_INPUT_6CELL_AUX1_3_4 BIT(6)
-#define AD7280A_CTRL_HB_CONV_INPUT_6CELL BIT(7)
-#define AD7280A_CTRL_HB_CONV_INPUT_SELF_TEST (BIT(7) | BIT(6))
-#define AD7280A_CTRL_HB_CONV_RES_READ_ALL 0
-#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL_AUX1_3_4 BIT(4)
-#define AD7280A_CTRL_HB_CONV_RES_READ_6CELL BIT(5)
-#define AD7280A_CTRL_HB_CONV_RES_READ_NO (BIT(5) | BIT(4))
-#define AD7280A_CTRL_HB_CONV_START_CNVST 0
-#define AD7280A_CTRL_HB_CONV_START_CS BIT(3)
-#define AD7280A_CTRL_HB_CONV_AVG_DIS 0
-#define AD7280A_CTRL_HB_CONV_AVG_2 BIT(1)
-#define AD7280A_CTRL_HB_CONV_AVG_4 BIT(2)
-#define AD7280A_CTRL_HB_CONV_AVG_8 (BIT(2) | BIT(1))
-#define AD7280A_CTRL_HB_CONV_AVG(x) ((x) << 1)
-#define AD7280A_CTRL_HB_PWRDN_SW BIT(0)
-
-#define AD7280A_CTRL_LB_SWRST BIT(7)
-#define AD7280A_CTRL_LB_ACQ_TIME_400ns 0
-#define AD7280A_CTRL_LB_ACQ_TIME_800ns BIT(5)
-#define AD7280A_CTRL_LB_ACQ_TIME_1200ns BIT(6)
-#define AD7280A_CTRL_LB_ACQ_TIME_1600ns (BIT(6) | BIT(5))
-#define AD7280A_CTRL_LB_ACQ_TIME(x) ((x) << 5)
-#define AD7280A_CTRL_LB_MUST_SET BIT(4)
-#define AD7280A_CTRL_LB_THERMISTOR_EN BIT(3)
-#define AD7280A_CTRL_LB_LOCK_DEV_ADDR BIT(2)
-#define AD7280A_CTRL_LB_INC_DEV_ADDR BIT(1)
-#define AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN BIT(0)
-
-#define AD7280A_ALERT_GEN_STATIC_HIGH BIT(6)
-#define AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN (BIT(7) | BIT(6))
-
-#define AD7280A_ALL_CELLS (0xAD << 16)
-
-#define AD7280A_MAX_SPI_CLK_HZ 700000 /* < 1MHz */
-#define AD7280A_MAX_CHAIN 8
-#define AD7280A_CELLS_PER_DEV 6
-#define AD7280A_BITS 12
-#define AD7280A_NUM_CH (AD7280A_AUX_ADC_6 - \
- AD7280A_CELL_VOLTAGE_1 + 1)
-
-#define AD7280A_CALC_VOLTAGE_CHAN_NUM(d, c) (((d) * AD7280A_CELLS_PER_DEV) + \
- (c))
-#define AD7280A_CALC_TEMP_CHAN_NUM(d, c) (((d) * AD7280A_CELLS_PER_DEV) + \
- (c) - AD7280A_CELLS_PER_DEV)
-
-#define AD7280A_DEVADDR_MASTER 0
-#define AD7280A_DEVADDR_ALL 0x1F
-/* 5-bit device address is sent LSB first */
-static unsigned int ad7280a_devaddr(unsigned int addr)
-{
- return ((addr & 0x1) << 4) |
- ((addr & 0x2) << 3) |
- (addr & 0x4) |
- ((addr & 0x8) >> 3) |
- ((addr & 0x10) >> 4);
-}
-
-/* During a read a valid write is mandatory.
- * So writing to the highest available address (Address 0x1F)
- * and setting the address all parts bit to 0 is recommended
- * So the TXVAL is AD7280A_DEVADDR_ALL + CRC
- */
-#define AD7280A_READ_TXVAL 0xF800030A
-
-/*
- * AD7280 CRC
- *
- * P(x) = x^8 + x^5 + x^3 + x^2 + x^1 + x^0 = 0b100101111 => 0x2F
- */
-#define POLYNOM 0x2F
-
-struct ad7280_state {
- struct spi_device *spi;
- struct iio_chan_spec *channels;
- struct iio_dev_attr *iio_attr;
- int slave_num;
- int scan_cnt;
- int readback_delay_us;
- unsigned char crc_tab[CRC8_TABLE_SIZE];
- unsigned char ctrl_hb;
- unsigned char ctrl_lb;
- unsigned char cell_threshhigh;
- unsigned char cell_threshlow;
- unsigned char aux_threshhigh;
- unsigned char aux_threshlow;
- unsigned char cb_mask[AD7280A_MAX_CHAIN];
- struct mutex lock; /* protect sensor state */
-
- __be32 buf[2] ____cacheline_aligned;
-};
-
-static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned int val)
-{
- unsigned char crc;
-
- crc = crc_tab[val >> 16 & 0xFF];
- crc = crc_tab[crc ^ (val >> 8 & 0xFF)];
-
- return crc ^ (val & 0xFF);
-}
-
-static int ad7280_check_crc(struct ad7280_state *st, unsigned int val)
-{
- unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10);
-
- if (crc != ((val >> 2) & 0xFF))
- return -EIO;
-
- return 0;
-}
-
-/* After initiating a conversion sequence we need to wait until the
- * conversion is done. The delay is typically in the range of 15..30 us
- * however depending an the number of devices in the daisy chain and the
- * number of averages taken, conversion delays and acquisition time options
- * it may take up to 250us, in this case we better sleep instead of busy
- * wait.
- */
-
-static void ad7280_delay(struct ad7280_state *st)
-{
- if (st->readback_delay_us < 50)
- udelay(st->readback_delay_us);
- else
- usleep_range(250, 500);
-}
-
-static int __ad7280_read32(struct ad7280_state *st, unsigned int *val)
-{
- int ret;
- struct spi_transfer t = {
- .tx_buf = &st->buf[0],
- .rx_buf = &st->buf[1],
- .len = 4,
- };
-
- st->buf[0] = cpu_to_be32(AD7280A_READ_TXVAL);
-
- ret = spi_sync_transfer(st->spi, &t, 1);
- if (ret)
- return ret;
-
- *val = be32_to_cpu(st->buf[1]);
-
- return 0;
-}
-
-static int ad7280_write(struct ad7280_state *st, unsigned int devaddr,
- unsigned int addr, bool all, unsigned int val)
-{
- unsigned int reg = devaddr << 27 | addr << 21 |
- (val & 0xFF) << 13 | all << 12;
-
- reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2;
- st->buf[0] = cpu_to_be32(reg);
-
- return spi_write(st->spi, &st->buf[0], 4);
-}
-
-static int ad7280_read(struct ad7280_state *st, unsigned int devaddr,
- unsigned int addr)
-{
- int ret;
- unsigned int tmp;
-
- /* turns off the read operation on all parts */
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
- AD7280A_CTRL_HB_CONV_INPUT_ALL |
- AD7280A_CTRL_HB_CONV_RES_READ_NO |
- st->ctrl_hb);
- if (ret)
- return ret;
-
- /* turns on the read operation on the addressed part */
- ret = ad7280_write(st, devaddr, AD7280A_CONTROL_HB, 0,
- AD7280A_CTRL_HB_CONV_INPUT_ALL |
- AD7280A_CTRL_HB_CONV_RES_READ_ALL |
- st->ctrl_hb);
- if (ret)
- return ret;
-
- /* Set register address on the part to be read from */
- ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2);
- if (ret)
- return ret;
-
- ret = __ad7280_read32(st, &tmp);
- if (ret)
- return ret;
-
- if (ad7280_check_crc(st, tmp))
- return -EIO;
-
- if (((tmp >> 27) != devaddr) || (((tmp >> 21) & 0x3F) != addr))
- return -EFAULT;
-
- return (tmp >> 13) & 0xFF;
-}
-
-static int ad7280_read_channel(struct ad7280_state *st, unsigned int devaddr,
- unsigned int addr)
-{
- int ret;
- unsigned int tmp;
-
- ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2);
- if (ret)
- return ret;
-
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
- AD7280A_CTRL_HB_CONV_INPUT_ALL |
- AD7280A_CTRL_HB_CONV_RES_READ_NO |
- st->ctrl_hb);
- if (ret)
- return ret;
-
- ret = ad7280_write(st, devaddr, AD7280A_CONTROL_HB, 0,
- AD7280A_CTRL_HB_CONV_INPUT_ALL |
- AD7280A_CTRL_HB_CONV_RES_READ_ALL |
- AD7280A_CTRL_HB_CONV_START_CS |
- st->ctrl_hb);
- if (ret)
- return ret;
-
- ad7280_delay(st);
-
- ret = __ad7280_read32(st, &tmp);
- if (ret)
- return ret;
-
- if (ad7280_check_crc(st, tmp))
- return -EIO;
-
- if (((tmp >> 27) != devaddr) || (((tmp >> 23) & 0xF) != addr))
- return -EFAULT;
-
- return (tmp >> 11) & 0xFFF;
-}
-
-static int ad7280_read_all_channels(struct ad7280_state *st, unsigned int cnt,
- unsigned int *array)
-{
- int i, ret;
- unsigned int tmp, sum = 0;
-
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1,
- AD7280A_CELL_VOLTAGE_1 << 2);
- if (ret)
- return ret;
-
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
- AD7280A_CTRL_HB_CONV_INPUT_ALL |
- AD7280A_CTRL_HB_CONV_RES_READ_ALL |
- AD7280A_CTRL_HB_CONV_START_CS |
- st->ctrl_hb);
- if (ret)
- return ret;
-
- ad7280_delay(st);
-
- for (i = 0; i < cnt; i++) {
- ret = __ad7280_read32(st, &tmp);
- if (ret)
- return ret;
-
- if (ad7280_check_crc(st, tmp))
- return -EIO;
-
- if (array)
- array[i] = tmp;
- /* only sum cell voltages */
- if (((tmp >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6)
- sum += ((tmp >> 11) & 0xFFF);
- }
-
- return sum;
-}
-
-static void ad7280_sw_power_down(void *data)
-{
- struct ad7280_state *st = data;
-
- ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
- AD7280A_CTRL_HB_PWRDN_SW | st->ctrl_hb);
-}
-
-static int ad7280_chain_setup(struct ad7280_state *st)
-{
- unsigned int val, n;
- int ret;
-
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1,
- AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN |
- AD7280A_CTRL_LB_LOCK_DEV_ADDR |
- AD7280A_CTRL_LB_MUST_SET |
- AD7280A_CTRL_LB_SWRST |
- st->ctrl_lb);
- if (ret)
- return ret;
-
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1,
- AD7280A_CTRL_LB_DAISY_CHAIN_RB_EN |
- AD7280A_CTRL_LB_LOCK_DEV_ADDR |
- AD7280A_CTRL_LB_MUST_SET |
- st->ctrl_lb);
- if (ret)
- goto error_power_down;
-
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1,
- AD7280A_CONTROL_LB << 2);
- if (ret)
- goto error_power_down;
-
- for (n = 0; n <= AD7280A_MAX_CHAIN; n++) {
- ret = __ad7280_read32(st, &val);
- if (ret)
- goto error_power_down;
-
- if (val == 0)
- return n - 1;
-
- if (ad7280_check_crc(st, val)) {
- ret = -EIO;
- goto error_power_down;
- }
-
- if (n != ad7280a_devaddr(val >> 27)) {
- ret = -EIO;
- goto error_power_down;
- }
- }
- ret = -EFAULT;
-
-error_power_down:
- ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
- AD7280A_CTRL_HB_PWRDN_SW | st->ctrl_hb);
-
- return ret;
-}
-
-static ssize_t ad7280_show_balance_sw(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad7280_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- return sprintf(buf, "%d\n",
- !!(st->cb_mask[this_attr->address >> 8] &
- (1 << ((this_attr->address & 0xFF) + 2))));
-}
-
-static ssize_t ad7280_store_balance_sw(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad7280_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- bool readin;
- int ret;
- unsigned int devaddr, ch;
-
- ret = strtobool(buf, &readin);
- if (ret)
- return ret;
-
- devaddr = this_attr->address >> 8;
- ch = this_attr->address & 0xFF;
-
- mutex_lock(&st->lock);
- if (readin)
- st->cb_mask[devaddr] |= 1 << (ch + 2);
- else
- st->cb_mask[devaddr] &= ~(1 << (ch + 2));
-
- ret = ad7280_write(st, devaddr, AD7280A_CELL_BALANCE,
- 0, st->cb_mask[devaddr]);
- mutex_unlock(&st->lock);
-
- return ret ? ret : len;
-}
-
-static ssize_t ad7280_show_balance_timer(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad7280_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- int ret;
- unsigned int msecs;
-
- mutex_lock(&st->lock);
- ret = ad7280_read(st, this_attr->address >> 8,
- this_attr->address & 0xFF);
- mutex_unlock(&st->lock);
-
- if (ret < 0)
- return ret;
-
- msecs = (ret >> 3) * 71500;
-
- return sprintf(buf, "%u\n", msecs);
-}
-
-static ssize_t ad7280_store_balance_timer(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad7280_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- unsigned long val;
- int ret;
-
- ret = kstrtoul(buf, 10, &val);
- if (ret)
- return ret;
-
- val /= 71500;
-
- if (val > 31)
- return -EINVAL;
-
- mutex_lock(&st->lock);
- ret = ad7280_write(st, this_attr->address >> 8,
- this_attr->address & 0xFF,
- 0, (val & 0x1F) << 3);
- mutex_unlock(&st->lock);
-
- return ret ? ret : len;
-}
-
-static struct attribute *ad7280_attributes[AD7280A_MAX_CHAIN *
- AD7280A_CELLS_PER_DEV * 2 + 1];
-
-static const struct attribute_group ad7280_attrs_group = {
- .attrs = ad7280_attributes,
-};
-
-static void ad7280_voltage_channel_init(struct iio_chan_spec *chan, int i)
-{
- chan->type = IIO_VOLTAGE;
- chan->differential = 1;
- chan->channel = i;
- chan->channel2 = chan->channel + 1;
-}
-
-static void ad7280_temp_channel_init(struct iio_chan_spec *chan, int i)
-{
- chan->type = IIO_TEMP;
- chan->channel = i;
-}
-
-static void ad7280_common_fields_init(struct iio_chan_spec *chan, int addr,
- int cnt)
-{
- chan->indexed = 1;
- chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
- chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
- chan->address = addr;
- chan->scan_index = cnt;
- chan->scan_type.sign = 'u';
- chan->scan_type.realbits = 12;
- chan->scan_type.storagebits = 32;
-}
-
-static void ad7280_total_voltage_channel_init(struct iio_chan_spec *chan,
- int cnt, int dev)
-{
- chan->type = IIO_VOLTAGE;
- chan->differential = 1;
- chan->channel = 0;
- chan->channel2 = dev * AD7280A_CELLS_PER_DEV;
- chan->address = AD7280A_ALL_CELLS;
- chan->indexed = 1;
- chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
- chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
- chan->scan_index = cnt;
- chan->scan_type.sign = 'u';
- chan->scan_type.realbits = 32;
- chan->scan_type.storagebits = 32;
-}
-
-static void ad7280_timestamp_channel_init(struct iio_chan_spec *chan, int cnt)
-{
- chan->type = IIO_TIMESTAMP;
- chan->channel = -1;
- chan->scan_index = cnt;
- chan->scan_type.sign = 's';
- chan->scan_type.realbits = 64;
- chan->scan_type.storagebits = 64;
-}
-
-static void ad7280_init_dev_channels(struct ad7280_state *st, int dev, int *cnt)
-{
- int addr, ch, i;
- struct iio_chan_spec *chan;
-
- for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; ch++) {
- chan = &st->channels[*cnt];
-
- if (ch < AD7280A_AUX_ADC_1) {
- i = AD7280A_CALC_VOLTAGE_CHAN_NUM(dev, ch);
- ad7280_voltage_channel_init(chan, i);
- } else {
- i = AD7280A_CALC_TEMP_CHAN_NUM(dev, ch);
- ad7280_temp_channel_init(chan, i);
- }
-
- addr = ad7280a_devaddr(dev) << 8 | ch;
- ad7280_common_fields_init(chan, addr, *cnt);
-
- (*cnt)++;
- }
-}
-
-static int ad7280_channel_init(struct ad7280_state *st)
-{
- int dev, cnt = 0;
-
- st->channels = devm_kcalloc(&st->spi->dev, (st->slave_num + 1) * 12 + 2,
- sizeof(*st->channels), GFP_KERNEL);
- if (!st->channels)
- return -ENOMEM;
-
- for (dev = 0; dev <= st->slave_num; dev++)
- ad7280_init_dev_channels(st, dev, &cnt);
-
- ad7280_total_voltage_channel_init(&st->channels[cnt], cnt, dev);
- cnt++;
- ad7280_timestamp_channel_init(&st->channels[cnt], cnt);
-
- return cnt + 1;
-}
-
-static int ad7280_balance_switch_attr_init(struct iio_dev_attr *attr,
- struct device *dev, int addr, int i)
-{
- attr->address = addr;
- attr->dev_attr.attr.mode = 0644;
- attr->dev_attr.show = ad7280_show_balance_sw;
- attr->dev_attr.store = ad7280_store_balance_sw;
- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
- "in%d-in%d_balance_switch_en",
- i, i + 1);
- if (!attr->dev_attr.attr.name)
- return -ENOMEM;
-
- return 0;
-}
-
-static int ad7280_balance_timer_attr_init(struct iio_dev_attr *attr,
- struct device *dev, int addr, int i)
-{
- attr->address = addr;
- attr->dev_attr.attr.mode = 0644;
- attr->dev_attr.show = ad7280_show_balance_timer;
- attr->dev_attr.store = ad7280_store_balance_timer;
- attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL,
- "in%d-in%d_balance_timer",
- i, i + 1);
- if (!attr->dev_attr.attr.name)
- return -ENOMEM;
-
- return 0;
-}
-
-static int ad7280_init_dev_attrs(struct ad7280_state *st, int dev, int *cnt)
-{
- int addr, ch, i, ret;
- struct iio_dev_attr *iio_attr;
- struct device *sdev = &st->spi->dev;
-
- for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; ch++) {
- iio_attr = &st->iio_attr[*cnt];
- addr = ad7280a_devaddr(dev) << 8 | ch;
- i = dev * AD7280A_CELLS_PER_DEV + ch;
-
- ret = ad7280_balance_switch_attr_init(iio_attr, sdev, addr, i);
- if (ret < 0)
- return ret;
-
- ad7280_attributes[*cnt] = &iio_attr->dev_attr.attr;
-
- (*cnt)++;
- iio_attr = &st->iio_attr[*cnt];
- addr = ad7280a_devaddr(dev) << 8 | (AD7280A_CB1_TIMER + ch);
-
- ret = ad7280_balance_timer_attr_init(iio_attr, sdev, addr, i);
- if (ret < 0)
- return ret;
-
- ad7280_attributes[*cnt] = &iio_attr->dev_attr.attr;
- (*cnt)++;
- }
-
- ad7280_attributes[*cnt] = NULL;
-
- return 0;
-}
-
-static int ad7280_attr_init(struct ad7280_state *st)
-{
- int dev, cnt = 0, ret;
-
- st->iio_attr = devm_kcalloc(&st->spi->dev, 2, sizeof(*st->iio_attr) *
- (st->slave_num + 1) * AD7280A_CELLS_PER_DEV,
- GFP_KERNEL);
- if (!st->iio_attr)
- return -ENOMEM;
-
- for (dev = 0; dev <= st->slave_num; dev++) {
- ret = ad7280_init_dev_attrs(st, dev, &cnt);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-static ssize_t ad7280_read_channel_config(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad7280_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- unsigned int val;
-
- switch (this_attr->address) {
- case AD7280A_CELL_OVERVOLTAGE:
- val = 1000 + (st->cell_threshhigh * 1568) / 100;
- break;
- case AD7280A_CELL_UNDERVOLTAGE:
- val = 1000 + (st->cell_threshlow * 1568) / 100;
- break;
- case AD7280A_AUX_ADC_OVERVOLTAGE:
- val = (st->aux_threshhigh * 196) / 10;
- break;
- case AD7280A_AUX_ADC_UNDERVOLTAGE:
- val = (st->aux_threshlow * 196) / 10;
- break;
- default:
- return -EINVAL;
- }
-
- return sprintf(buf, "%u\n", val);
-}
-
-static ssize_t ad7280_write_channel_config(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct ad7280_state *st = iio_priv(indio_dev);
- struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
- long val;
- int ret;
-
- ret = kstrtol(buf, 10, &val);
- if (ret)
- return ret;
-
- switch (this_attr->address) {
- case AD7280A_CELL_OVERVOLTAGE:
- case AD7280A_CELL_UNDERVOLTAGE:
- val = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */
- break;
- case AD7280A_AUX_ADC_OVERVOLTAGE:
- case AD7280A_AUX_ADC_UNDERVOLTAGE:
- val = (val * 10) / 196; /* LSB 19.6mV */
- break;
- default:
- return -EFAULT;
- }
-
- val = clamp(val, 0L, 0xFFL);
-
- mutex_lock(&st->lock);
- switch (this_attr->address) {
- case AD7280A_CELL_OVERVOLTAGE:
- st->cell_threshhigh = val;
- break;
- case AD7280A_CELL_UNDERVOLTAGE:
- st->cell_threshlow = val;
- break;
- case AD7280A_AUX_ADC_OVERVOLTAGE:
- st->aux_threshhigh = val;
- break;
- case AD7280A_AUX_ADC_UNDERVOLTAGE:
- st->aux_threshlow = val;
- break;
- }
-
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER,
- this_attr->address, 1, val);
-
- mutex_unlock(&st->lock);
-
- return ret ? ret : len;
-}
-
-static irqreturn_t ad7280_event_handler(int irq, void *private)
-{
- struct iio_dev *indio_dev = private;
- struct ad7280_state *st = iio_priv(indio_dev);
- unsigned int *channels;
- int i, ret;
-
- channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL);
- if (!channels)
- return IRQ_HANDLED;
-
- ret = ad7280_read_all_channels(st, st->scan_cnt, channels);
- if (ret < 0)
- goto out;
-
- for (i = 0; i < st->scan_cnt; i++) {
- if (((channels[i] >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) {
- if (((channels[i] >> 11) & 0xFFF) >=
- st->cell_threshhigh) {
- u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0);
- iio_push_event(indio_dev, tmp,
- iio_get_time_ns(indio_dev));
- } else if (((channels[i] >> 11) & 0xFFF) <=
- st->cell_threshlow) {
- u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0);
- iio_push_event(indio_dev, tmp,
- iio_get_time_ns(indio_dev));
- }
- } else {
- if (((channels[i] >> 11) & 0xFFF) >=
- st->aux_threshhigh) {
- u64 tmp = IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_RISING);
- iio_push_event(indio_dev, tmp,
- iio_get_time_ns(indio_dev));
- } else if (((channels[i] >> 11) & 0xFFF) <=
- st->aux_threshlow) {
- u64 tmp = IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_FALLING);
- iio_push_event(indio_dev, tmp,
- iio_get_time_ns(indio_dev));
- }
- }
- }
-
-out:
- kfree(channels);
-
- return IRQ_HANDLED;
-}
-
-/* Note: No need to fix checkpatch warning that reads:
- * CHECK: spaces preferred around that '-' (ctx:VxV)
- * The function argument is stringified and doesn't need a fix
- */
-static IIO_DEVICE_ATTR_NAMED(in_thresh_low_value,
- in_voltage-voltage_thresh_low_value,
- 0644,
- ad7280_read_channel_config,
- ad7280_write_channel_config,
- AD7280A_CELL_UNDERVOLTAGE);
-
-static IIO_DEVICE_ATTR_NAMED(in_thresh_high_value,
- in_voltage-voltage_thresh_high_value,
- 0644,
- ad7280_read_channel_config,
- ad7280_write_channel_config,
- AD7280A_CELL_OVERVOLTAGE);
-
-static IIO_DEVICE_ATTR(in_temp_thresh_low_value,
- 0644,
- ad7280_read_channel_config,
- ad7280_write_channel_config,
- AD7280A_AUX_ADC_UNDERVOLTAGE);
-
-static IIO_DEVICE_ATTR(in_temp_thresh_high_value,
- 0644,
- ad7280_read_channel_config,
- ad7280_write_channel_config,
- AD7280A_AUX_ADC_OVERVOLTAGE);
-
-static struct attribute *ad7280_event_attributes[] = {
- &iio_dev_attr_in_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in_thresh_high_value.dev_attr.attr,
- &iio_dev_attr_in_temp_thresh_low_value.dev_attr.attr,
- &iio_dev_attr_in_temp_thresh_high_value.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group ad7280_event_attrs_group = {
- .attrs = ad7280_event_attributes,
-};
-
-static int ad7280_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val,
- int *val2,
- long m)
-{
- struct ad7280_state *st = iio_priv(indio_dev);
- int ret;
-
- switch (m) {
- case IIO_CHAN_INFO_RAW:
- mutex_lock(&st->lock);
- if (chan->address == AD7280A_ALL_CELLS)
- ret = ad7280_read_all_channels(st, st->scan_cnt, NULL);
- else
- ret = ad7280_read_channel(st, chan->address >> 8,
- chan->address & 0xFF);
- mutex_unlock(&st->lock);
-
- if (ret < 0)
- return ret;
-
- *val = ret;
-
- return IIO_VAL_INT;
- case IIO_CHAN_INFO_SCALE:
- if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6)
- *val = 4000;
- else
- *val = 5000;
-
- *val2 = AD7280A_BITS;
- return IIO_VAL_FRACTIONAL_LOG2;
- }
- return -EINVAL;
-}
-
-static const struct iio_info ad7280_info = {
- .read_raw = ad7280_read_raw,
- .event_attrs = &ad7280_event_attrs_group,
- .attrs = &ad7280_attrs_group,
-};
-
-static const struct ad7280_platform_data ad7793_default_pdata = {
- .acquisition_time = AD7280A_ACQ_TIME_400ns,
- .conversion_averaging = AD7280A_CONV_AVG_DIS,
- .thermistor_term_en = true,
-};
-
-static int ad7280_probe(struct spi_device *spi)
-{
- const struct ad7280_platform_data *pdata = dev_get_platdata(&spi->dev);
- struct ad7280_state *st;
- int ret;
- const unsigned short t_acq_ns[4] = {465, 1010, 1460, 1890};
- const unsigned short n_avg[4] = {1, 2, 4, 8};
- struct iio_dev *indio_dev;
-
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
- if (!indio_dev)
- return -ENOMEM;
-
- st = iio_priv(indio_dev);
- spi_set_drvdata(spi, indio_dev);
- st->spi = spi;
- mutex_init(&st->lock);
-
- if (!pdata)
- pdata = &ad7793_default_pdata;
-
- crc8_populate_msb(st->crc_tab, POLYNOM);
-
- st->spi->max_speed_hz = AD7280A_MAX_SPI_CLK_HZ;
- st->spi->mode = SPI_MODE_1;
- spi_setup(st->spi);
-
- st->ctrl_lb = AD7280A_CTRL_LB_ACQ_TIME(pdata->acquisition_time & 0x3);
- st->ctrl_hb = AD7280A_CTRL_HB_CONV_AVG(pdata->conversion_averaging
- & 0x3) | (pdata->thermistor_term_en ?
- AD7280A_CTRL_LB_THERMISTOR_EN : 0);
-
- ret = ad7280_chain_setup(st);
- if (ret < 0)
- return ret;
-
- st->slave_num = ret;
- st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH;
- st->cell_threshhigh = 0xFF;
- st->aux_threshhigh = 0xFF;
-
- ret = devm_add_action_or_reset(&spi->dev, ad7280_sw_power_down, st);
- if (ret)
- return ret;
-
- /*
- * Total Conversion Time = ((tACQ + tCONV) *
- * (Number of Conversions per Part)) −
- * tACQ + ((N - 1) * tDELAY)
- *
- * Readback Delay = Total Conversion Time + tWAIT
- */
-
- st->readback_delay_us =
- ((t_acq_ns[pdata->acquisition_time & 0x3] + 695) *
- (AD7280A_NUM_CH * n_avg[pdata->conversion_averaging & 0x3])) -
- t_acq_ns[pdata->acquisition_time & 0x3] + st->slave_num * 250;
-
- /* Convert to usecs */
- st->readback_delay_us = DIV_ROUND_UP(st->readback_delay_us, 1000);
- st->readback_delay_us += 5; /* Add tWAIT */
-
- indio_dev->name = spi_get_device_id(spi)->name;
- indio_dev->modes = INDIO_DIRECT_MODE;
-
- ret = ad7280_channel_init(st);
- if (ret < 0)
- return ret;
-
- indio_dev->num_channels = ret;
- indio_dev->channels = st->channels;
- indio_dev->info = &ad7280_info;
-
- ret = ad7280_attr_init(st);
- if (ret < 0)
- return ret;
-
- ret = devm_iio_device_register(&spi->dev, indio_dev);
- if (ret)
- return ret;
-
- if (spi->irq > 0) {
- ret = ad7280_write(st, AD7280A_DEVADDR_MASTER,
- AD7280A_ALERT, 1,
- AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN);
- if (ret)
- return ret;
-
- ret = ad7280_write(st, ad7280a_devaddr(st->slave_num),
- AD7280A_ALERT, 0,
- AD7280A_ALERT_GEN_STATIC_HIGH |
- (pdata->chain_last_alert_ignore & 0xF));
- if (ret)
- return ret;
-
- ret = devm_request_threaded_irq(&spi->dev, spi->irq,
- NULL,
- ad7280_event_handler,
- IRQF_TRIGGER_FALLING |
- IRQF_ONESHOT,
- indio_dev->name,
- indio_dev);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static const struct spi_device_id ad7280_id[] = {
- {"ad7280a", 0},
- {}
-};
-MODULE_DEVICE_TABLE(spi, ad7280_id);
-
-static struct spi_driver ad7280_driver = {
- .driver = {
- .name = "ad7280",
- },
- .probe = ad7280_probe,
- .id_table = ad7280_id,
-};
-module_spi_driver(ad7280_driver);
-
-MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
-MODULE_DESCRIPTION("Analog Devices AD7280A");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7280a.h b/drivers/staging/iio/adc/ad7280a.h
deleted file mode 100644
index 23f18bb9e279..000000000000
--- a/drivers/staging/iio/adc/ad7280a.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * AD7280A Lithium Ion Battery Monitoring System
- *
- * Copyright 2011 Analog Devices Inc.
- */
-
-#ifndef IIO_ADC_AD7280_H_
-#define IIO_ADC_AD7280_H_
-
-/*
- * TODO: struct ad7280_platform_data needs to go into include/linux/iio
- */
-
-#define AD7280A_ACQ_TIME_400ns 0
-#define AD7280A_ACQ_TIME_800ns 1
-#define AD7280A_ACQ_TIME_1200ns 2
-#define AD7280A_ACQ_TIME_1600ns 3
-
-#define AD7280A_CONV_AVG_DIS 0
-#define AD7280A_CONV_AVG_2 1
-#define AD7280A_CONV_AVG_4 2
-#define AD7280A_CONV_AVG_8 3
-
-#define AD7280A_ALERT_REMOVE_VIN5 BIT(2)
-#define AD7280A_ALERT_REMOVE_VIN4_VIN5 BIT(3)
-#define AD7280A_ALERT_REMOVE_AUX5 BIT(0)
-#define AD7280A_ALERT_REMOVE_AUX4_AUX5 BIT(1)
-
-struct ad7280_platform_data {
- unsigned int acquisition_time;
- unsigned int conversion_averaging;
- unsigned int chain_last_alert_ignore;
- bool thermistor_term_en;
-};
-
-#endif /* IIO_ADC_AD7280_H_ */
diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
index 71c709771676..52b8957c19c9 100644
--- a/drivers/staging/iio/cdc/ad7746.c
+++ b/drivers/staging/iio/cdc/ad7746.c
@@ -290,7 +290,7 @@ static inline ssize_t ad7746_start_calib(struct device *dev,
int ret, timeout = 10;
bool doit;
- ret = strtobool(buf, &doit);
+ ret = kstrtobool(buf, &doit);
if (ret < 0)
return ret;
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 793918e1c45f..f177b20f0f2d 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -749,7 +749,6 @@ static int ad5933_probe(struct i2c_client *client,
indio_dev->num_channels = ARRAY_SIZE(ad5933_channels);
ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev,
- INDIO_BUFFER_SOFTWARE,
&ad5933_ring_setup_ops);
if (ret)
return ret;
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index 74adb82f37c3..c0b2716d0511 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -499,7 +499,6 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT;
break;
case IIO_ANGL_VEL:
- negative = st->rx[0] & 0x80;
vel = be16_to_cpup((__be16 *)st->rx);
vel >>= 16 - st->resolution;
if (vel & 0x8000) {
diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c
index 98d759e7cc95..9fb118e77a1f 100644
--- a/drivers/staging/ks7010/ks7010_sdio.c
+++ b/drivers/staging/ks7010/ks7010_sdio.c
@@ -1102,10 +1102,8 @@ static void ks7010_sdio_remove(struct sdio_func *func)
if (ret) /* memory allocation failure */
goto err_free_card;
- if (priv->wq) {
- flush_workqueue(priv->wq);
+ if (priv->wq)
destroy_workqueue(priv->wq);
- }
hostif_exit(priv);
diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c
index 1c63d595313d..9429ee155910 100644
--- a/drivers/staging/ks7010/ks_hostif.c
+++ b/drivers/staging/ks7010/ks_hostif.c
@@ -84,10 +84,6 @@ static void ks_wlan_hw_wakeup_task(struct work_struct *work)
return;
}
}
-
- /* power save */
- if (atomic_read(&priv->sme_task.count) > 0)
- tasklet_enable(&priv->sme_task);
}
static void ks_wlan_do_power_save(struct ks_wlan_private *priv)
@@ -2200,10 +2196,11 @@ static void hostif_sme_execute(struct ks_wlan_private *priv, int event)
}
}
-static
-void hostif_sme_task(struct tasklet_struct *t)
+static void hostif_sme_work(struct work_struct *work)
{
- struct ks_wlan_private *priv = from_tasklet(priv, t, sme_task);
+ struct ks_wlan_private *priv;
+
+ priv = container_of(work, struct ks_wlan_private, sme_work);
if (priv->dev_state < DEVICE_STATE_BOOT)
return;
@@ -2214,7 +2211,7 @@ void hostif_sme_task(struct tasklet_struct *t)
hostif_sme_execute(priv, priv->sme_i.event_buff[priv->sme_i.qhead]);
inc_smeqhead(priv);
if (cnt_smeqbody(priv) > 0)
- tasklet_schedule(&priv->sme_task);
+ schedule_work(&priv->sme_work);
}
/* send to Station Management Entity module */
@@ -2229,7 +2226,7 @@ void hostif_sme_enqueue(struct ks_wlan_private *priv, u16 event)
netdev_err(priv->net_dev, "sme queue buffer overflow\n");
}
- tasklet_schedule(&priv->sme_task);
+ schedule_work(&priv->sme_work);
}
static inline void hostif_aplist_init(struct ks_wlan_private *priv)
@@ -2254,7 +2251,7 @@ static inline void hostif_sme_init(struct ks_wlan_private *priv)
priv->sme_i.qtail = 0;
spin_lock_init(&priv->sme_i.sme_spin);
priv->sme_i.sme_flag = 0;
- tasklet_setup(&priv->sme_task, hostif_sme_task);
+ INIT_WORK(&priv->sme_work, hostif_sme_work);
}
static inline void hostif_wpa_init(struct ks_wlan_private *priv)
@@ -2312,5 +2309,5 @@ int hostif_init(struct ks_wlan_private *priv)
void hostif_exit(struct ks_wlan_private *priv)
{
- tasklet_kill(&priv->sme_task);
+ cancel_work_sync(&priv->sme_work);
}
diff --git a/drivers/staging/ks7010/ks_wlan.h b/drivers/staging/ks7010/ks_wlan.h
index 7aaf8d780939..3e9a91b5131c 100644
--- a/drivers/staging/ks7010/ks_wlan.h
+++ b/drivers/staging/ks7010/ks_wlan.h
@@ -449,7 +449,7 @@ struct ks_wlan_private {
struct sme_info sme_i;
u8 *rxp;
unsigned int rx_size;
- struct tasklet_struct sme_task;
+ struct work_struct sme_work;
struct work_struct wakeup_work;
int scan_ind_count;
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index b81cfa74edb7..1fd6a0c6e1d8 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -36,8 +36,6 @@ source "drivers/staging/media/rkvdec/Kconfig"
source "drivers/staging/media/sunxi/Kconfig"
-source "drivers/staging/media/tegra-vde/Kconfig"
-
source "drivers/staging/media/zoran/Kconfig"
source "drivers/staging/media/tegra-video/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 7e2c86e3695d..66d6f6d51c86 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/
obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/
-obj-$(CONFIG_TEGRA_VDE) += tegra-vde/
obj-$(CONFIG_VIDEO_HANTRO) += hantro/
obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/
obj-$(CONFIG_VIDEO_ZORAN) += zoran/
diff --git a/drivers/staging/media/atomisp/Kconfig b/drivers/staging/media/atomisp/Kconfig
index aeed5803dfb1..2c8d7fdcc5f7 100644
--- a/drivers/staging/media/atomisp/Kconfig
+++ b/drivers/staging/media/atomisp/Kconfig
@@ -11,7 +11,7 @@ menuconfig INTEL_ATOMISP
config VIDEO_ATOMISP
tristate "Intel Atom Image Signal Processor Driver"
- depends on VIDEO_V4L2 && INTEL_ATOMISP
+ depends on VIDEO_DEV && INTEL_ATOMISP
depends on PMIC_OPREGION
select IOSF_MBI
select VIDEOBUF_VMALLOC
diff --git a/drivers/staging/media/atomisp/i2c/Kconfig b/drivers/staging/media/atomisp/i2c/Kconfig
index a772b833a85f..e726101b24e4 100644
--- a/drivers/staging/media/atomisp/i2c/Kconfig
+++ b/drivers/staging/media/atomisp/i2c/Kconfig
@@ -6,7 +6,7 @@
config VIDEO_ATOMISP_OV2722
tristate "OVT ov2722 sensor support"
depends on ACPI
- depends on I2C && VIDEO_V4L2
+ depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor-level driver for the OVT
OV2722 raw camera.
@@ -18,7 +18,7 @@ config VIDEO_ATOMISP_OV2722
config VIDEO_ATOMISP_GC2235
tristate "Galaxy gc2235 sensor support"
depends on ACPI
- depends on I2C && VIDEO_V4L2
+ depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor-level driver for the OVT
GC2235 raw camera.
@@ -40,7 +40,7 @@ config VIDEO_ATOMISP_MSRLIST_HELPER
config VIDEO_ATOMISP_MT9M114
tristate "Aptina mt9m114 sensor support"
depends on ACPI
- depends on I2C && VIDEO_V4L2
+ depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor-level driver for the Micron
mt9m114 1.3 Mpixel camera.
@@ -52,7 +52,7 @@ config VIDEO_ATOMISP_MT9M114
config VIDEO_ATOMISP_GC0310
tristate "GC0310 sensor support"
depends on ACPI
- depends on I2C && VIDEO_V4L2
+ depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor-level driver for the Galaxycore
GC0310 0.3MP sensor.
@@ -60,7 +60,7 @@ config VIDEO_ATOMISP_GC0310
config VIDEO_ATOMISP_OV2680
tristate "Omnivision OV2680 sensor support"
depends on ACPI
- depends on I2C && VIDEO_V4L2
+ depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor-level driver for the Omnivision
OV2680 raw camera.
@@ -72,7 +72,7 @@ config VIDEO_ATOMISP_OV2680
config VIDEO_ATOMISP_OV5693
tristate "Omnivision ov5693 sensor support"
depends on ACPI
- depends on I2C && VIDEO_V4L2
+ depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor-level driver for the Micron
ov5693 5 Mpixel camera.
@@ -88,7 +88,7 @@ config VIDEO_ATOMISP_OV5693
config VIDEO_ATOMISP_LM3554
tristate "LM3554 flash light driver"
depends on ACPI
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_DEV && I2C
help
This is a Video4Linux2 sub-dev driver for the LM3554
flash light driver.
diff --git a/drivers/staging/media/atomisp/pci/atomisp_acc.c b/drivers/staging/media/atomisp/pci/atomisp_acc.c
index 9a1751895ab0..28cb271663c4 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_acc.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_acc.c
@@ -439,6 +439,18 @@ int atomisp_acc_s_mapped_arg(struct atomisp_sub_device *asd,
return 0;
}
+static void atomisp_acc_unload_some_extensions(struct atomisp_sub_device *asd,
+ int i,
+ struct atomisp_acc_fw *acc_fw)
+{
+ while (--i >= 0) {
+ if (acc_fw->flags & acc_flag_to_pipe[i].flag) {
+ atomisp_css_unload_acc_extension(asd, acc_fw->fw,
+ acc_flag_to_pipe[i].pipe_id);
+ }
+ }
+}
+
/*
* Appends the loaded acceleration binary extensions to the
* current ISP mode. Must be called just before sh_css_start().
@@ -479,16 +491,20 @@ int atomisp_acc_load_extensions(struct atomisp_sub_device *asd)
acc_fw->fw,
acc_flag_to_pipe[i].pipe_id,
acc_fw->type);
- if (ret)
+ if (ret) {
+ atomisp_acc_unload_some_extensions(asd, i, acc_fw);
goto error;
+ }
ext_loaded = true;
}
}
ret = atomisp_css_set_acc_parameters(acc_fw);
- if (ret < 0)
+ if (ret < 0) {
+ atomisp_acc_unload_some_extensions(asd, i, acc_fw);
goto error;
+ }
}
if (!ext_loaded)
@@ -497,6 +513,7 @@ int atomisp_acc_load_extensions(struct atomisp_sub_device *asd)
ret = atomisp_css_update_stream(asd);
if (ret) {
dev_err(isp->dev, "%s: update stream failed.\n", __func__);
+ atomisp_acc_unload_extensions(asd);
goto error;
}
@@ -504,13 +521,6 @@ int atomisp_acc_load_extensions(struct atomisp_sub_device *asd)
return 0;
error:
- while (--i >= 0) {
- if (acc_fw->flags & acc_flag_to_pipe[i].flag) {
- atomisp_css_unload_acc_extension(asd, acc_fw->fw,
- acc_flag_to_pipe[i].pipe_id);
- }
- }
-
list_for_each_entry_continue_reverse(acc_fw, &asd->acc.fw, list) {
if (acc_fw->type != ATOMISP_ACC_FW_LOAD_TYPE_OUTPUT &&
acc_fw->type != ATOMISP_ACC_FW_LOAD_TYPE_VIEWFINDER)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
index 1173be0e72b0..781a11cca599 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c
@@ -963,7 +963,7 @@ int atomisp_css_irq_translate(struct atomisp_device *isp,
void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
unsigned int *infos)
{
-#ifndef IS_ISP2401
+#ifndef ISP2401
ia_css_isys_rx_get_irq_info(port, infos);
#else
*infos = 0;
@@ -973,7 +973,7 @@ void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
unsigned int infos)
{
-#ifndef IS_ISP2401
+#ifndef ISP2401
ia_css_isys_rx_clear_irq_info(port, infos);
#endif
}
diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
index 1cc581074ba7..7e47db82de07 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c
@@ -38,7 +38,7 @@ enum clock_rate {
#define ELDO_CTRL_REG 0x12
#define ELDO1_SEL_REG 0x19
-#define ELDO1_1P8V 0x16
+#define ELDO1_1P6V 0x12
#define ELDO1_CTRL_SHIFT 0x00
#define ELDO2_SEL_REG 0x1a
@@ -89,7 +89,7 @@ struct gmin_subdev {
u8 pwm_i2c_addr;
/* For PMIC AXP */
- int eldo1_sel_reg, eldo1_1p8v, eldo1_ctrl_shift;
+ int eldo1_sel_reg, eldo1_1p6v, eldo1_ctrl_shift;
int eldo2_sel_reg, eldo2_1p8v, eldo2_ctrl_shift;
};
@@ -118,6 +118,10 @@ static const char *pmic_name[] = {
[PMIC_CRYSTALCOVE] = "Crystal Cove PMIC",
};
+static DEFINE_MUTEX(gmin_regulator_mutex);
+static int gmin_v1p8_enable_count;
+static int gmin_v2p8_enable_count;
+
/* The atomisp uses type==0 for the end-of-list marker, so leave space. */
static struct intel_v4l2_subdev_table pdata_subdevs[MAX_SUBDEVS + 1];
@@ -536,7 +540,7 @@ static int gmin_subdev_add(struct gmin_subdev *gs)
struct i2c_client *client = v4l2_get_subdevdata(gs->subdev);
struct device *dev = &client->dev;
struct acpi_device *adev = ACPI_COMPANION(dev);
- int ret, clock_num = -1;
+ int ret, default_val, clock_num = -1;
dev_info(dev, "%s: ACPI path is %pfw\n", __func__, dev_fwnode(dev));
@@ -544,7 +548,20 @@ static int gmin_subdev_add(struct gmin_subdev *gs)
gs->clock_src = gmin_get_var_int(dev, false, "ClkSrc",
VLV2_CLK_PLL_19P2MHZ);
- gs->csi_port = gmin_get_var_int(dev, false, "CsiPort", 0);
+ /*
+ * Get ACPI _PR0 derived clock here already because it is used
+ * to determine the csi_port default.
+ */
+ if (acpi_device_power_manageable(adev))
+ clock_num = atomisp_get_acpi_power(dev);
+
+ /* Compare clock to CsiPort 1 pmc-clock used in the CHT/BYT reference designs */
+ if (IS_ISP2401)
+ default_val = clock_num == 4 ? 1 : 0;
+ else
+ default_val = clock_num == 0 ? 1 : 0;
+
+ gs->csi_port = gmin_get_var_int(dev, false, "CsiPort", default_val);
gs->csi_lanes = gmin_get_var_int(dev, false, "CsiLanes", 1);
gs->gpio0 = gpiod_get_index(dev, NULL, 0, GPIOD_OUT_LOW);
@@ -625,11 +642,7 @@ static int gmin_subdev_add(struct gmin_subdev *gs)
* otherwise.
*/
- /* Try first to use ACPI to get the clock resource */
- if (acpi_device_power_manageable(adev))
- clock_num = atomisp_get_acpi_power(dev);
-
- /* Fall-back use EFI and/or DMI match */
+ /* If getting the clock from _PR0 above failed, fall-back to EFI and/or DMI match */
if (clock_num < 0)
clock_num = gmin_get_var_int(dev, false, "CamClk", 0);
@@ -681,9 +694,9 @@ static int gmin_subdev_add(struct gmin_subdev *gs)
break;
case PMIC_AXP:
- gs->eldo1_1p8v = gmin_get_var_int(dev, false,
+ gs->eldo1_1p6v = gmin_get_var_int(dev, false,
"eldo1_1p8v",
- ELDO1_1P8V);
+ ELDO1_1P6V);
gs->eldo1_sel_reg = gmin_get_var_int(dev, false,
"eldo1_sel_reg",
ELDO1_SEL_REG);
@@ -741,13 +754,28 @@ static int axp_regulator_set(struct device *dev, struct gmin_subdev *gs,
val = on ? 1 << shift : 0;
- ret = gmin_i2c_write(dev, gs->pwm_i2c_addr, sel_reg, val, 1 << shift);
+ ret = gmin_i2c_write(dev, gs->pwm_i2c_addr, ctrl_reg, val, 1 << shift);
if (ret)
return ret;
return 0;
}
+/*
+ * Some boards contain a hw-bug where turning eldo2 back on after having turned
+ * it off causes the CPLM3218 ambient-light-sensor on the image-sensor's I2C bus
+ * to crash, hanging the bus. Do not turn eldo2 off on these systems.
+ */
+static const struct dmi_system_id axp_leave_eldo2_on_ids[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab duo W1 10.1 (VT4)"),
+ },
+ },
+ { }
+};
+
static int axp_v1p8_on(struct device *dev, struct gmin_subdev *gs)
{
int ret;
@@ -763,13 +791,8 @@ static int axp_v1p8_on(struct device *dev, struct gmin_subdev *gs)
*/
usleep_range(110, 150);
- ret = axp_regulator_set(dev, gs, gs->eldo1_sel_reg, gs->eldo1_1p8v,
- ELDO_CTRL_REG, gs->eldo1_ctrl_shift, true);
- if (ret)
- return ret;
-
- ret = axp_regulator_set(dev, gs, gs->eldo2_sel_reg, gs->eldo2_1p8v,
- ELDO_CTRL_REG, gs->eldo2_ctrl_shift, false);
+ ret = axp_regulator_set(dev, gs, gs->eldo1_sel_reg, gs->eldo1_1p6v,
+ ELDO_CTRL_REG, gs->eldo1_ctrl_shift, true);
return ret;
}
@@ -777,11 +800,14 @@ static int axp_v1p8_off(struct device *dev, struct gmin_subdev *gs)
{
int ret;
- ret = axp_regulator_set(dev, gs, gs->eldo1_sel_reg, gs->eldo1_1p8v,
+ ret = axp_regulator_set(dev, gs, gs->eldo1_sel_reg, gs->eldo1_1p6v,
ELDO_CTRL_REG, gs->eldo1_ctrl_shift, false);
if (ret)
return ret;
+ if (dmi_check_system(axp_leave_eldo2_on_ids))
+ return 0;
+
ret = axp_regulator_set(dev, gs, gs->eldo2_sel_reg, gs->eldo2_1p8v,
ELDO_CTRL_REG, gs->eldo2_ctrl_shift, false);
return ret;
@@ -851,38 +877,58 @@ static int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on)
gs->v1p8_on = on;
+ ret = 0;
+ mutex_lock(&gmin_regulator_mutex);
+ if (on) {
+ gmin_v1p8_enable_count++;
+ if (gmin_v1p8_enable_count > 1)
+ goto out; /* Already on */
+ } else {
+ gmin_v1p8_enable_count--;
+ if (gmin_v1p8_enable_count > 0)
+ goto out; /* Still needed */
+ }
+
if (gs->v1p8_gpio >= 0)
gpio_set_value(gs->v1p8_gpio, on);
if (gs->v1p8_reg) {
regulator_set_voltage(gs->v1p8_reg, 1800000, 1800000);
if (on)
- return regulator_enable(gs->v1p8_reg);
+ ret = regulator_enable(gs->v1p8_reg);
else
- return regulator_disable(gs->v1p8_reg);
+ ret = regulator_disable(gs->v1p8_reg);
+
+ goto out;
}
switch (pmic_id) {
case PMIC_AXP:
if (on)
- return axp_v1p8_on(subdev->dev, gs);
+ ret = axp_v1p8_on(subdev->dev, gs);
else
- return axp_v1p8_off(subdev->dev, gs);
+ ret = axp_v1p8_off(subdev->dev, gs);
+ break;
case PMIC_TI:
value = on ? LDO_1P8V_ON : LDO_1P8V_OFF;
- return gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
- LDO10_REG, value, 0xff);
+ ret = gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
+ LDO10_REG, value, 0xff);
+ break;
case PMIC_CRYSTALCOVE:
value = on ? CRYSTAL_ON : CRYSTAL_OFF;
- return gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
- CRYSTAL_1P8V_REG, value, 0xff);
+ ret = gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
+ CRYSTAL_1P8V_REG, value, 0xff);
+ break;
default:
- dev_err(subdev->dev, "Couldn't set power mode for v1p2\n");
+ dev_err(subdev->dev, "Couldn't set power mode for v1p8\n");
+ ret = -EINVAL;
}
- return -EINVAL;
+out:
+ mutex_unlock(&gmin_regulator_mutex);
+ return ret;
}
static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on)
@@ -908,37 +954,57 @@ static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on)
return 0;
gs->v2p8_on = on;
+ ret = 0;
+ mutex_lock(&gmin_regulator_mutex);
+ if (on) {
+ gmin_v2p8_enable_count++;
+ if (gmin_v2p8_enable_count > 1)
+ goto out; /* Already on */
+ } else {
+ gmin_v2p8_enable_count--;
+ if (gmin_v2p8_enable_count > 0)
+ goto out; /* Still needed */
+ }
+
if (gs->v2p8_gpio >= 0)
gpio_set_value(gs->v2p8_gpio, on);
if (gs->v2p8_reg) {
regulator_set_voltage(gs->v2p8_reg, 2900000, 2900000);
if (on)
- return regulator_enable(gs->v2p8_reg);
+ ret = regulator_enable(gs->v2p8_reg);
else
- return regulator_disable(gs->v2p8_reg);
+ ret = regulator_disable(gs->v2p8_reg);
+
+ goto out;
}
switch (pmic_id) {
case PMIC_AXP:
- return axp_regulator_set(subdev->dev, gs, ALDO1_SEL_REG,
- ALDO1_2P8V, ALDO1_CTRL3_REG,
- ALDO1_CTRL3_SHIFT, on);
+ ret = axp_regulator_set(subdev->dev, gs, ALDO1_SEL_REG,
+ ALDO1_2P8V, ALDO1_CTRL3_REG,
+ ALDO1_CTRL3_SHIFT, on);
+ break;
case PMIC_TI:
value = on ? LDO_2P8V_ON : LDO_2P8V_OFF;
- return gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
- LDO9_REG, value, 0xff);
+ ret = gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
+ LDO9_REG, value, 0xff);
+ break;
case PMIC_CRYSTALCOVE:
value = on ? CRYSTAL_ON : CRYSTAL_OFF;
- return gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
- CRYSTAL_2P8V_REG, value, 0xff);
+ ret = gmin_i2c_write(subdev->dev, gs->pwm_i2c_addr,
+ CRYSTAL_2P8V_REG, value, 0xff);
+ break;
default:
- dev_err(subdev->dev, "Couldn't set power mode for v1p2\n");
+ dev_err(subdev->dev, "Couldn't set power mode for v2p8\n");
+ ret = -EINVAL;
}
- return -EINVAL;
+out:
+ mutex_unlock(&gmin_regulator_mutex);
+ return ret;
}
static int gmin_acpi_pm_ctrl(struct v4l2_subdev *subdev, int on)
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
index 1b240891a6e2..49ccfb1646da 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
@@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/interrupt.h>
+#include <linux/bits.h>
#include <asm/iosf_mbi.h>
@@ -626,11 +627,11 @@ static int atomisp_mrfld_pre_power_down(struct atomisp_device *isp)
* IRQ, if so, waiting for it to be served
*/
pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- irq = irq & 1 << INTR_IIR;
+ irq &= BIT(INTR_IIR);
pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- if (!(irq & (1 << INTR_IIR)))
+ if (!(irq & BIT(INTR_IIR)))
goto done;
atomisp_css2_hw_store_32(MRFLD_INTR_CLEAR_REG, 0xFFFFFFFF);
@@ -643,11 +644,11 @@ static int atomisp_mrfld_pre_power_down(struct atomisp_device *isp)
return -EAGAIN;
} else {
pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- irq = irq & 1 << INTR_IIR;
+ irq &= BIT(INTR_IIR);
pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- if (!(irq & (1 << INTR_IIR))) {
+ if (!(irq & BIT(INTR_IIR))) {
atomisp_css2_hw_store_32(MRFLD_INTR_ENABLE_REG, 0x0);
goto done;
}
@@ -666,7 +667,7 @@ done:
* HW sighting:4568410.
*/
pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- irq &= ~(1 << INTR_IER);
+ irq &= ~BIT(INTR_IER);
pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
atomisp_msi_irq_uninit(isp);
@@ -1467,7 +1468,7 @@ static bool is_valid_device(struct pci_dev *pdev, const struct pci_device_id *id
* remove the if once the driver become generic
*/
-#if defined(ISP2400)
+#ifndef ISP2401
if (IS_ISP2401) {
dev_err(&pdev->dev, "Support for %s (ISP2401) was disabled at compile time\n",
name);
@@ -1549,7 +1550,7 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
start = pci_resource_start(pdev, ATOM_ISP_PCI_BAR);
dev_dbg(&pdev->dev, "start: 0x%x\n", start);
- err = pcim_iomap_regions(pdev, 1 << ATOM_ISP_PCI_BAR, pci_name(pdev));
+ err = pcim_iomap_regions(pdev, BIT(ATOM_ISP_PCI_BAR), pci_name(pdev));
if (err) {
dev_err(&pdev->dev, "Failed to I/O memory remapping (%d)\n", err);
goto ioremap_fail;
@@ -1838,11 +1839,11 @@ load_fw_fail:
*/
pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- irq = irq & 1 << INTR_IIR;
+ irq &= BIT(INTR_IIR);
pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- irq &= ~(1 << INTR_IER);
+ irq &= ~BIT(INTR_IER);
pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
atomisp_msi_irq_uninit(isp);
@@ -1854,7 +1855,7 @@ load_fw_fail:
dev_err(&pdev->dev, "Failed to switch off ISP\n");
atomisp_dev_alloc_fail:
- pcim_iounmap_regions(pdev, 1 << ATOM_ISP_PCI_BAR);
+ pcim_iounmap_regions(pdev, BIT(ATOM_ISP_PCI_BAR));
ioremap_fail:
return err;
diff --git a/drivers/staging/media/atomisp/pci/hmm/hmm.c b/drivers/staging/media/atomisp/pci/hmm/hmm.c
index 6a5ee4607089..c1cda16f2dc0 100644
--- a/drivers/staging/media/atomisp/pci/hmm/hmm.c
+++ b/drivers/staging/media/atomisp/pci/hmm/hmm.c
@@ -39,7 +39,7 @@
struct hmm_bo_device bo_device;
struct hmm_pool dynamic_pool;
struct hmm_pool reserved_pool;
-static ia_css_ptr dummy_ptr;
+static ia_css_ptr dummy_ptr = mmgr_EXCEPTION;
static bool hmm_initialized;
struct _hmm_mem_stat hmm_mem_stat;
@@ -209,7 +209,7 @@ int hmm_init(void)
void hmm_cleanup(void)
{
- if (!dummy_ptr)
+ if (dummy_ptr == mmgr_EXCEPTION)
return;
sysfs_remove_group(&atomisp_dev->kobj, atomisp_attribute_group);
@@ -288,7 +288,8 @@ void hmm_free(ia_css_ptr virt)
dev_dbg(atomisp_dev, "%s: free 0x%08x\n", __func__, virt);
- WARN_ON(!virt);
+ if (WARN_ON(virt == mmgr_EXCEPTION))
+ return;
bo = hmm_bo_device_search_start(&bo_device, (unsigned int)virt);
diff --git a/drivers/staging/media/atomisp/pci/ia_css_acc_types.h b/drivers/staging/media/atomisp/pci/ia_css_acc_types.h
index d0ce2f8ba653..a20879aedef6 100644
--- a/drivers/staging/media/atomisp/pci/ia_css_acc_types.h
+++ b/drivers/staging/media/atomisp/pci/ia_css_acc_types.h
@@ -24,6 +24,7 @@
#include <type_support.h>
#include <platform_support.h>
#include <debug_global.h>
+#include <linux/bits.h>
#include "ia_css_types.h"
#include "ia_css_frame_format.h"
@@ -466,7 +467,7 @@ struct ia_css_acc_fw {
enum ia_css_sp_sleep_mode {
SP_DISABLE_SLEEP_MODE = 0,
- SP_SLEEP_AFTER_FRAME = 1 << 0,
- SP_SLEEP_AFTER_IRQ = 1 << 1
+ SP_SLEEP_AFTER_FRAME = BIT(0),
+ SP_SLEEP_AFTER_IRQ = BIT(1),
};
#endif /* _IA_CSS_ACC_TYPES_H */
diff --git a/drivers/staging/media/atomisp/pci/ia_css_env.h b/drivers/staging/media/atomisp/pci/ia_css_env.h
index 3b89bbd837a0..42bb1ec1c22d 100644
--- a/drivers/staging/media/atomisp/pci/ia_css_env.h
+++ b/drivers/staging/media/atomisp/pci/ia_css_env.h
@@ -18,6 +18,7 @@
#include <type_support.h>
#include <linux/stdarg.h> /* va_list */
+#include <linux/bits.h>
#include "ia_css_types.h"
#include "ia_css_acc_types.h"
@@ -28,10 +29,10 @@
/* Memory allocation attributes, for use in ia_css_css_mem_env. */
enum ia_css_mem_attr {
- IA_CSS_MEM_ATTR_CACHED = 1 << 0,
- IA_CSS_MEM_ATTR_ZEROED = 1 << 1,
- IA_CSS_MEM_ATTR_PAGEALIGN = 1 << 2,
- IA_CSS_MEM_ATTR_CONTIGUOUS = 1 << 3,
+ IA_CSS_MEM_ATTR_CACHED = BIT(0),
+ IA_CSS_MEM_ATTR_ZEROED = BIT(1),
+ IA_CSS_MEM_ATTR_PAGEALIGN = BIT(2),
+ IA_CSS_MEM_ATTR_CONTIGUOUS = BIT(3),
};
/* Environment with function pointers for local IA memory allocation.
diff --git a/drivers/staging/media/atomisp/pci/ia_css_event_public.h b/drivers/staging/media/atomisp/pci/ia_css_event_public.h
index 76219d741d2e..b052648d4fc2 100644
--- a/drivers/staging/media/atomisp/pci/ia_css_event_public.h
+++ b/drivers/staging/media/atomisp/pci/ia_css_event_public.h
@@ -24,6 +24,7 @@
#include <ia_css_err.h> /* ia_css_err */
#include <ia_css_types.h> /* ia_css_pipe */
#include <ia_css_timer.h> /* ia_css_timer */
+#include <linux/bits.h>
/* The event type, distinguishes the kind of events that
* can are generated by the CSS system.
@@ -35,38 +36,38 @@
* 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
*/
enum ia_css_event_type {
- IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE = 1 << 0,
+ IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE = BIT(0),
/** Output frame ready. */
- IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE = 1 << 1,
+ IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE = BIT(1),
/** Second output frame ready. */
- IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE = 1 << 2,
+ IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE = BIT(2),
/** Viewfinder Output frame ready. */
- IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE = 1 << 3,
+ IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE = BIT(3),
/** Second viewfinder Output frame ready. */
- IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE = 1 << 4,
+ IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE = BIT(4),
/** Indication that 3A statistics are available. */
- IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE = 1 << 5,
+ IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE = BIT(5),
/** Indication that DIS statistics are available. */
- IA_CSS_EVENT_TYPE_PIPELINE_DONE = 1 << 6,
+ IA_CSS_EVENT_TYPE_PIPELINE_DONE = BIT(6),
/** Pipeline Done event, sent after last pipeline stage. */
- IA_CSS_EVENT_TYPE_FRAME_TAGGED = 1 << 7,
+ IA_CSS_EVENT_TYPE_FRAME_TAGGED = BIT(7),
/** Frame tagged. */
- IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE = 1 << 8,
+ IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE = BIT(8),
/** Input frame ready. */
- IA_CSS_EVENT_TYPE_METADATA_DONE = 1 << 9,
+ IA_CSS_EVENT_TYPE_METADATA_DONE = BIT(9),
/** Metadata ready. */
- IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE = 1 << 10,
+ IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE = BIT(10),
/** Indication that LACE statistics are available. */
- IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE = 1 << 11,
+ IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE = BIT(11),
/** Extension stage complete. */
- IA_CSS_EVENT_TYPE_TIMER = 1 << 12,
+ IA_CSS_EVENT_TYPE_TIMER = BIT(12),
/** Timer event for measuring the SP side latencies. It contains the
32-bit timer value from the SP */
- IA_CSS_EVENT_TYPE_PORT_EOF = 1 << 13,
+ IA_CSS_EVENT_TYPE_PORT_EOF = BIT(13),
/** End Of Frame event, sent when in buffered sensor mode. */
- IA_CSS_EVENT_TYPE_FW_WARNING = 1 << 14,
+ IA_CSS_EVENT_TYPE_FW_WARNING = BIT(14),
/** Performance warning encounter by FW */
- IA_CSS_EVENT_TYPE_FW_ASSERT = 1 << 15,
+ IA_CSS_EVENT_TYPE_FW_ASSERT = BIT(15),
/** Assertion hit by FW */
};
diff --git a/drivers/staging/media/atomisp/pci/ia_css_irq.h b/drivers/staging/media/atomisp/pci/ia_css_irq.h
index 3b81a39cfe97..26b1b3c8ba62 100644
--- a/drivers/staging/media/atomisp/pci/ia_css_irq.h
+++ b/drivers/staging/media/atomisp/pci/ia_css_irq.h
@@ -23,6 +23,7 @@
#include "ia_css_err.h"
#include "ia_css_pipe_public.h"
#include "ia_css_input_port.h"
+#include <linux/bits.h>
/* Interrupt types, these enumerate all supported interrupt types.
*/
@@ -46,49 +47,49 @@ enum ia_css_irq_type {
* (SW) interrupts
*/
enum ia_css_irq_info {
- IA_CSS_IRQ_INFO_CSS_RECEIVER_ERROR = 1 << 0,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_ERROR = BIT(0),
/** the css receiver has encountered an error */
- IA_CSS_IRQ_INFO_CSS_RECEIVER_FIFO_OVERFLOW = 1 << 1,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_FIFO_OVERFLOW = BIT(1),
/** the FIFO in the csi receiver has overflown */
- IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF = 1 << 2,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF = BIT(2),
/** the css receiver received the start of frame */
- IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF = 1 << 3,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF = BIT(3),
/** the css receiver received the end of frame */
- IA_CSS_IRQ_INFO_CSS_RECEIVER_SOL = 1 << 4,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_SOL = BIT(4),
/** the css receiver received the start of line */
- IA_CSS_IRQ_INFO_EVENTS_READY = 1 << 5,
+ IA_CSS_IRQ_INFO_EVENTS_READY = BIT(5),
/** One or more events are available in the PSYS event queue */
- IA_CSS_IRQ_INFO_CSS_RECEIVER_EOL = 1 << 6,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_EOL = BIT(6),
/** the css receiver received the end of line */
- IA_CSS_IRQ_INFO_CSS_RECEIVER_SIDEBAND_CHANGED = 1 << 7,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_SIDEBAND_CHANGED = BIT(7),
/** the css receiver received a change in side band signals */
- IA_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_0 = 1 << 8,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_0 = BIT(8),
/** generic short packets (0) */
- IA_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_1 = 1 << 9,
+ IA_CSS_IRQ_INFO_CSS_RECEIVER_GEN_SHORT_1 = BIT(9),
/** generic short packets (1) */
- IA_CSS_IRQ_INFO_IF_PRIM_ERROR = 1 << 10,
+ IA_CSS_IRQ_INFO_IF_PRIM_ERROR = BIT(10),
/** the primary input formatter (A) has encountered an error */
- IA_CSS_IRQ_INFO_IF_PRIM_B_ERROR = 1 << 11,
+ IA_CSS_IRQ_INFO_IF_PRIM_B_ERROR = BIT(11),
/** the primary input formatter (B) has encountered an error */
- IA_CSS_IRQ_INFO_IF_SEC_ERROR = 1 << 12,
+ IA_CSS_IRQ_INFO_IF_SEC_ERROR = BIT(12),
/** the secondary input formatter has encountered an error */
- IA_CSS_IRQ_INFO_STREAM_TO_MEM_ERROR = 1 << 13,
+ IA_CSS_IRQ_INFO_STREAM_TO_MEM_ERROR = BIT(13),
/** the stream-to-memory device has encountered an error */
- IA_CSS_IRQ_INFO_SW_0 = 1 << 14,
+ IA_CSS_IRQ_INFO_SW_0 = BIT(14),
/** software interrupt 0 */
- IA_CSS_IRQ_INFO_SW_1 = 1 << 15,
+ IA_CSS_IRQ_INFO_SW_1 = BIT(15),
/** software interrupt 1 */
- IA_CSS_IRQ_INFO_SW_2 = 1 << 16,
+ IA_CSS_IRQ_INFO_SW_2 = BIT(16),
/** software interrupt 2 */
- IA_CSS_IRQ_INFO_ISP_BINARY_STATISTICS_READY = 1 << 17,
+ IA_CSS_IRQ_INFO_ISP_BINARY_STATISTICS_READY = BIT(17),
/** ISP binary statistics are ready */
- IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR = 1 << 18,
+ IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR = BIT(18),
/** the input system in in error */
- IA_CSS_IRQ_INFO_IF_ERROR = 1 << 19,
+ IA_CSS_IRQ_INFO_IF_ERROR = BIT(19),
/** the input formatter in in error */
- IA_CSS_IRQ_INFO_DMA_ERROR = 1 << 20,
+ IA_CSS_IRQ_INFO_DMA_ERROR = BIT(20),
/** the dma in in error */
- IA_CSS_IRQ_INFO_ISYS_EVENTS_READY = 1 << 21,
+ IA_CSS_IRQ_INFO_ISYS_EVENTS_READY = BIT(21),
/** end-of-frame events are ready in the isys_event queue */
};
@@ -103,23 +104,23 @@ enum ia_css_irq_info {
* different receiver types, or possibly none in case of tests systems.
*/
enum ia_css_rx_irq_info {
- IA_CSS_RX_IRQ_INFO_BUFFER_OVERRUN = 1U << 0, /** buffer overrun */
- IA_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE = 1U << 1, /** entering sleep mode */
- IA_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE = 1U << 2, /** exited sleep mode */
- IA_CSS_RX_IRQ_INFO_ECC_CORRECTED = 1U << 3, /** ECC corrected */
- IA_CSS_RX_IRQ_INFO_ERR_SOT = 1U << 4,
+ IA_CSS_RX_IRQ_INFO_BUFFER_OVERRUN = BIT(0), /** buffer overrun */
+ IA_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE = BIT(1), /** entering sleep mode */
+ IA_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE = BIT(2), /** exited sleep mode */
+ IA_CSS_RX_IRQ_INFO_ECC_CORRECTED = BIT(3), /** ECC corrected */
+ IA_CSS_RX_IRQ_INFO_ERR_SOT = BIT(4),
/** Start of transmission */
- IA_CSS_RX_IRQ_INFO_ERR_SOT_SYNC = 1U << 5, /** SOT sync (??) */
- IA_CSS_RX_IRQ_INFO_ERR_CONTROL = 1U << 6, /** Control (??) */
- IA_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE = 1U << 7, /** Double ECC */
- IA_CSS_RX_IRQ_INFO_ERR_CRC = 1U << 8, /** CRC error */
- IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID = 1U << 9, /** Unknown ID */
- IA_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC = 1U << 10,/** Frame sync error */
- IA_CSS_RX_IRQ_INFO_ERR_FRAME_DATA = 1U << 11,/** Frame data error */
- IA_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT = 1U << 12,/** Timeout occurred */
- IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC = 1U << 13,/** Unknown escape seq. */
- IA_CSS_RX_IRQ_INFO_ERR_LINE_SYNC = 1U << 14,/** Line Sync error */
- IA_CSS_RX_IRQ_INFO_INIT_TIMEOUT = 1U << 15,
+ IA_CSS_RX_IRQ_INFO_ERR_SOT_SYNC = BIT(5), /** SOT sync (??) */
+ IA_CSS_RX_IRQ_INFO_ERR_CONTROL = BIT(6), /** Control (??) */
+ IA_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE = BIT(7), /** Double ECC */
+ IA_CSS_RX_IRQ_INFO_ERR_CRC = BIT(8), /** CRC error */
+ IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID = BIT(9), /** Unknown ID */
+ IA_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC = BIT(10), /** Frame sync error */
+ IA_CSS_RX_IRQ_INFO_ERR_FRAME_DATA = BIT(11), /** Frame data error */
+ IA_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT = BIT(12), /** Timeout occurred */
+ IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC = BIT(13), /** Unknown escape seq. */
+ IA_CSS_RX_IRQ_INFO_ERR_LINE_SYNC = BIT(14), /** Line Sync error */
+ IA_CSS_RX_IRQ_INFO_INIT_TIMEOUT = BIT(15),
};
/* Interrupt info structure. This structure contains information about an
diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5.host.c b/drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5.host.c
index 562662ab8a44..a70bce1179da 100644
--- a/drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5.host.c
+++ b/drivers/staging/media/atomisp/pci/isp/kernels/macc/macc1_5/ia_css_macc1_5.host.c
@@ -44,7 +44,7 @@ ia_css_macc1_5_vmem_encode(
unsigned int size)
{
unsigned int i, j, k, idx;
- unsigned int idx_map[] = {
+ static const unsigned int idx_map[] = {
0, 1, 3, 2, 6, 7, 5, 4, 12, 13, 15, 14, 10, 11, 9, 8
};
diff --git a/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h b/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h
index 6880c9b6aa65..c3ae5014a039 100644
--- a/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h
+++ b/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h
@@ -29,8 +29,6 @@
#include "isp_acquisition_defs.h"
#include "input_system_ctrl_defs.h"
-typedef struct input_system_cfg2400_s input_system_cfg2400_t;
-
struct target_cfg2400_s {
input_switch_cfg_channel_t input_switch_channel_cfg;
target_isp_cfg_t target_isp_cfg;
diff --git a/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h b/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h
index e37ef4232c55..fff89e9b4b01 100644
--- a/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h
+++ b/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h
@@ -20,6 +20,7 @@
#include <type_support.h>
#include <linux/stdarg.h>
+#include <linux/bits.h>
#include "ia_css_types.h"
#include "ia_css_binary.h"
#include "ia_css_frame_public.h"
@@ -53,21 +54,21 @@ extern int dbg_level;
* Values can be combined to dump a combination of sets.
*/
enum ia_css_debug_enable_param_dump {
- IA_CSS_DEBUG_DUMP_FPN = 1 << 0, /** FPN table */
- IA_CSS_DEBUG_DUMP_OB = 1 << 1, /** OB table */
- IA_CSS_DEBUG_DUMP_SC = 1 << 2, /** Shading table */
- IA_CSS_DEBUG_DUMP_WB = 1 << 3, /** White balance */
- IA_CSS_DEBUG_DUMP_DP = 1 << 4, /** Defect Pixel */
- IA_CSS_DEBUG_DUMP_BNR = 1 << 5, /** Bayer Noise Reductions */
- IA_CSS_DEBUG_DUMP_S3A = 1 << 6, /** 3A Statistics */
- IA_CSS_DEBUG_DUMP_DE = 1 << 7, /** De Mosaicing */
- IA_CSS_DEBUG_DUMP_YNR = 1 << 8, /** Luma Noise Reduction */
- IA_CSS_DEBUG_DUMP_CSC = 1 << 9, /** Color Space Conversion */
- IA_CSS_DEBUG_DUMP_GC = 1 << 10, /** Gamma Correction */
- IA_CSS_DEBUG_DUMP_TNR = 1 << 11, /** Temporal Noise Reduction */
- IA_CSS_DEBUG_DUMP_ANR = 1 << 12, /** Advanced Noise Reduction */
- IA_CSS_DEBUG_DUMP_CE = 1 << 13, /** Chroma Enhancement */
- IA_CSS_DEBUG_DUMP_ALL = 1 << 14 /** Dump all device parameters */
+ IA_CSS_DEBUG_DUMP_FPN = BIT(0), /** FPN table */
+ IA_CSS_DEBUG_DUMP_OB = BIT(1), /** OB table */
+ IA_CSS_DEBUG_DUMP_SC = BIT(2), /** Shading table */
+ IA_CSS_DEBUG_DUMP_WB = BIT(3), /** White balance */
+ IA_CSS_DEBUG_DUMP_DP = BIT(4), /** Defect Pixel */
+ IA_CSS_DEBUG_DUMP_BNR = BIT(5), /** Bayer Noise Reductions */
+ IA_CSS_DEBUG_DUMP_S3A = BIT(6), /** 3A Statistics */
+ IA_CSS_DEBUG_DUMP_DE = BIT(7), /** De Mosaicing */
+ IA_CSS_DEBUG_DUMP_YNR = BIT(8), /** Luma Noise Reduction */
+ IA_CSS_DEBUG_DUMP_CSC = BIT(9), /** Color Space Conversion */
+ IA_CSS_DEBUG_DUMP_GC = BIT(10), /** Gamma Correction */
+ IA_CSS_DEBUG_DUMP_TNR = BIT(11), /** Temporal Noise Reduction */
+ IA_CSS_DEBUG_DUMP_ANR = BIT(12), /** Advanced Noise Reduction */
+ IA_CSS_DEBUG_DUMP_CE = BIT(13), /** Chroma Enhancement */
+ IA_CSS_DEBUG_DUMP_ALL = BIT(14), /** Dump all device parameters */
};
#define IA_CSS_ERROR(fmt, ...) \
diff --git a/drivers/staging/media/atomisp/pci/runtime/rmgr/src/rmgr_vbuf.c b/drivers/staging/media/atomisp/pci/runtime/rmgr/src/rmgr_vbuf.c
index d96aaa4bc75d..39604752785b 100644
--- a/drivers/staging/media/atomisp/pci/runtime/rmgr/src/rmgr_vbuf.c
+++ b/drivers/staging/media/atomisp/pci/runtime/rmgr/src/rmgr_vbuf.c
@@ -254,7 +254,7 @@ void rmgr_pop_handle(struct ia_css_rmgr_vbuf_pool *pool,
void ia_css_rmgr_acq_vbuf(struct ia_css_rmgr_vbuf_pool *pool,
struct ia_css_rmgr_vbuf_handle **handle)
{
- struct ia_css_rmgr_vbuf_handle h;
+ struct ia_css_rmgr_vbuf_handle h = { 0 };
if ((!pool) || (!handle) || (!*handle)) {
IA_CSS_LOG("Invalid inputs");
@@ -272,7 +272,7 @@ void ia_css_rmgr_acq_vbuf(struct ia_css_rmgr_vbuf_pool *pool,
h.size = (*handle)->size;
/* release ref to current buffer */
ia_css_rmgr_refcount_release_vbuf(handle);
- *handle = &h;
+ **handle = h;
}
/* get new buffer for needed size */
if ((*handle)->vptr == 0x0) {
diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c
index 94149647b98b..dd688f8ab649 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c
@@ -56,7 +56,11 @@ static struct firmware_header *firmware_header;
* which will be replaced with the actual RELEASE_VERSION
* during package generation. Please do not modify
*/
+#ifdef ISP2401
static const char *release_version = STR(irci_stable_candrpv_0415_20150521_0458);
+#else
+static const char *release_version = STR(irci_stable_candrpv_0415_20150423_1753);
+#endif
#define MAX_FW_REL_VER_NAME 300
static char FW_rel_ver_name[MAX_FW_REL_VER_NAME] = "---";
diff --git a/drivers/staging/media/av7110/av7110_av.c b/drivers/staging/media/av7110/av7110_av.c
index 91f4866c7e59..ab7cf496b454 100644
--- a/drivers/staging/media/av7110/av7110_av.c
+++ b/drivers/staging/media/av7110/av7110_av.c
@@ -595,10 +595,10 @@ static int find_pes_header(u8 const *buf, long int length, int *frags)
case PROG_STREAM_MAP:
case PRIVATE_STREAM2:
case PROG_STREAM_DIR:
- case ECM_STREAM :
- case EMM_STREAM :
- case PADDING_STREAM :
- case DSM_CC_STREAM :
+ case ECM_STREAM:
+ case EMM_STREAM:
+ case PADDING_STREAM:
+ case DSM_CC_STREAM:
case ISO13522_STREAM:
case PRIVATE_STREAM1:
case AUDIO_STREAM_S ... AUDIO_STREAM_E:
@@ -659,10 +659,10 @@ void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t
case PROG_STREAM_MAP:
case PRIVATE_STREAM2:
case PROG_STREAM_DIR:
- case ECM_STREAM :
- case EMM_STREAM :
- case PADDING_STREAM :
- case DSM_CC_STREAM :
+ case ECM_STREAM:
+ case EMM_STREAM:
+ case PADDING_STREAM:
+ case DSM_CC_STREAM:
case ISO13522_STREAM:
case PRIVATE_STREAM1:
case AUDIO_STREAM_S ... AUDIO_STREAM_E:
@@ -770,22 +770,22 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
if (length > 3 &&
buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01)
switch (buf[3]) {
- case PROG_STREAM_MAP:
- case PRIVATE_STREAM2:
- case PROG_STREAM_DIR:
- case ECM_STREAM :
- case EMM_STREAM :
- case PADDING_STREAM :
- case DSM_CC_STREAM :
- case ISO13522_STREAM:
- case PRIVATE_STREAM1:
- case AUDIO_STREAM_S ... AUDIO_STREAM_E:
- case VIDEO_STREAM_S ... VIDEO_STREAM_E:
- pes_start = 1;
- break;
+ case PROG_STREAM_MAP:
+ case PRIVATE_STREAM2:
+ case PROG_STREAM_DIR:
+ case ECM_STREAM:
+ case EMM_STREAM:
+ case PADDING_STREAM:
+ case DSM_CC_STREAM:
+ case ISO13522_STREAM:
+ case PRIVATE_STREAM1:
+ case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+ case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+ pes_start = 1;
+ break;
- default:
- break;
+ default:
+ break;
}
while (c < length) {
diff --git a/drivers/staging/media/hantro/Kconfig b/drivers/staging/media/hantro/Kconfig
index 3c5d833322c8..0172a6822ec2 100644
--- a/drivers/staging/media/hantro/Kconfig
+++ b/drivers/staging/media/hantro/Kconfig
@@ -2,7 +2,7 @@
config VIDEO_HANTRO
tristate "Hantro VPU driver"
depends on ARCH_MXC || ARCH_ROCKCHIP || ARCH_AT91 || ARCH_SUNXI || COMPILE_TEST
- depends on VIDEO_DEV && VIDEO_V4L2
+ depends on VIDEO_DEV
select MEDIA_CONTROLLER
select MEDIA_CONTROLLER_REQUEST_API
select VIDEOBUF2_DMA_CONTIG
diff --git a/drivers/staging/media/hantro/TODO b/drivers/staging/media/hantro/TODO
index fa0c94057007..8483ff482146 100644
--- a/drivers/staging/media/hantro/TODO
+++ b/drivers/staging/media/hantro/TODO
@@ -1,13 +1,2 @@
-* Support for VP8, VP9 and H264 is planned for this driver.
-
- Given the V4L controls for those CODECs will be part of
- the uABI, it will be required to have the driver in staging.
-
- For this reason, we are keeping this driver in staging for now.
-
-* Add support for the S_SELECTION API.
- See the comment for VEPU_REG_ENC_OVER_FILL_STRM_OFFSET.
-
-* Instead of having a DMA bounce buffer, it could be possible to use a
- normal buffer and memmove() the payload to make space for the header.
- This might need to use extra JPEG markers for padding reasons.
+The V4L controls for the HEVC CODEC are not yet part of the stable uABI,
+we are keeping this driver in staging until the HEVC uABI has been merged.
diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h
index 06d0f3597694..26308bb29adc 100644
--- a/drivers/staging/media/hantro/hantro.h
+++ b/drivers/staging/media/hantro/hantro.h
@@ -259,7 +259,6 @@ struct hantro_ctx {
/* Specific for particular codec modes. */
union {
struct hantro_h264_dec_hw_ctx h264_dec;
- struct hantro_jpeg_enc_hw_ctx jpeg_enc;
struct hantro_mpeg2_dec_hw_ctx mpeg2_dec;
struct hantro_vp8_dec_hw_ctx vp8_dec;
struct hantro_hevc_dec_hw_ctx hevc_dec;
@@ -476,5 +475,7 @@ void hantro_postproc_disable(struct hantro_ctx *ctx);
void hantro_postproc_enable(struct hantro_ctx *ctx);
void hantro_postproc_free(struct hantro_ctx *ctx);
int hantro_postproc_alloc(struct hantro_ctx *ctx);
+int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
+ struct v4l2_frmsizeenum *fsize);
#endif /* HANTRO_H_ */
diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
index 6a51f39dde56..ac232b5f7825 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -56,6 +56,10 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts)
return hantro_get_dec_buf_addr(ctx, buf);
}
+static const struct v4l2_event hantro_eos_event = {
+ .type = V4L2_EVENT_EOS
+};
+
static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
struct hantro_ctx *ctx,
enum vb2_buffer_state result)
@@ -73,6 +77,12 @@ static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
src->sequence = ctx->sequence_out++;
dst->sequence = ctx->sequence_cap++;
+ if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src)) {
+ dst->flags |= V4L2_BUF_FLAG_LAST;
+ v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);
+ v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
+ }
+
v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx,
result);
}
@@ -219,21 +229,15 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
if (ret)
return ret;
+ dst_vq->bidirectional = true;
+ dst_vq->mem_ops = &vb2_dma_contig_memops;
+ dst_vq->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES;
/*
- * When encoding, the CAPTURE queue doesn't need dma memory,
- * as the CPU needs to create the JPEG frames, from the
- * hardware-produced JPEG payload.
- *
- * For the DMA destination buffer, we use a bounce buffer.
+ * The Kernel needs access to the JPEG destination buffer for the
+ * JPEG encoder to fill in the JPEG headers.
*/
- if (ctx->is_encoder) {
- dst_vq->mem_ops = &vb2_vmalloc_memops;
- } else {
- dst_vq->bidirectional = true;
- dst_vq->mem_ops = &vb2_dma_contig_memops;
- dst_vq->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES |
- DMA_ATTR_NO_KERNEL_MAPPING;
- }
+ if (!ctx->is_encoder)
+ dst_vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
@@ -332,6 +336,11 @@ static const struct v4l2_ctrl_ops hantro_hevc_ctrl_ops = {
.s_ctrl = hantro_hevc_s_ctrl,
};
+#define HANTRO_JPEG_ACTIVE_MARKERS (V4L2_JPEG_ACTIVE_MARKER_APP0 | \
+ V4L2_JPEG_ACTIVE_MARKER_COM | \
+ V4L2_JPEG_ACTIVE_MARKER_DQT | \
+ V4L2_JPEG_ACTIVE_MARKER_DHT)
+
static const struct hantro_ctrl controls[] = {
{
.codec = HANTRO_JPEG_ENCODER,
@@ -344,6 +353,22 @@ static const struct hantro_ctrl controls[] = {
.ops = &hantro_jpeg_ctrl_ops,
},
}, {
+ .codec = HANTRO_JPEG_ENCODER,
+ .cfg = {
+ .id = V4L2_CID_JPEG_ACTIVE_MARKER,
+ .max = HANTRO_JPEG_ACTIVE_MARKERS,
+ .def = HANTRO_JPEG_ACTIVE_MARKERS,
+ /*
+ * Changing the set of active markers/segments also
+ * messes up the alignment of the JPEG header, which
+ * is needed to allow the hardware to write directly
+ * to the output buffer. Implementing this introduces
+ * a lot of complexity for little gain, as the markers
+ * enabled is already the minimum required set.
+ */
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ },
+ }, {
.codec = HANTRO_MPEG2_DECODER,
.cfg = {
.id = V4L2_CID_STATELESS_MPEG2_SEQUENCE,
@@ -613,9 +638,12 @@ static const struct of_device_id of_hantro_match[] = {
{ .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, },
{ .compatible = "rockchip,rk3328-vpu", .data = &rk3328_vpu_variant, },
{ .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, },
+ { .compatible = "rockchip,rk3568-vpu", .data = &rk3568_vpu_variant, },
#endif
#ifdef CONFIG_VIDEO_HANTRO_IMX8M
+ { .compatible = "nxp,imx8mm-vpu-g1", .data = &imx8mm_vpu_g1_variant, },
{ .compatible = "nxp,imx8mq-vpu", .data = &imx8mq_vpu_variant, },
+ { .compatible = "nxp,imx8mq-vpu-g1", .data = &imx8mq_vpu_g1_variant },
{ .compatible = "nxp,imx8mq-vpu-g2", .data = &imx8mq_vpu_g2_variant },
#endif
#ifdef CONFIG_VIDEO_HANTRO_SAMA5D4
@@ -792,10 +820,13 @@ static int hantro_add_func(struct hantro_dev *vpu, unsigned int funcid)
snprintf(vfd->name, sizeof(vfd->name), "%s-%s", match->compatible,
funcid == MEDIA_ENT_F_PROC_VIDEO_ENCODER ? "enc" : "dec");
- if (funcid == MEDIA_ENT_F_PROC_VIDEO_ENCODER)
+ if (funcid == MEDIA_ENT_F_PROC_VIDEO_ENCODER) {
vpu->encoder = func;
- else
+ } else {
vpu->decoder = func;
+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
+ }
video_set_drvdata(vfd, vpu);
@@ -890,6 +921,15 @@ static int hantro_probe(struct platform_device *pdev)
match = of_match_node(of_hantro_match, pdev->dev.of_node);
vpu->variant = match->data;
+ /*
+ * Support for nxp,imx8mq-vpu is kept for backwards compatibility
+ * but it's deprecated. Please update your DTS file to use
+ * nxp,imx8mq-vpu-g1 or nxp,imx8mq-vpu-g2 instead.
+ */
+ if (of_device_is_compatible(pdev->dev.of_node, "nxp,imx8mq-vpu"))
+ dev_warn(&pdev->dev, "%s compatible is deprecated\n",
+ match->compatible);
+
INIT_DELAYED_WORK(&vpu->watchdog_work, hantro_watchdog);
vpu->clocks = devm_kcalloc(&pdev->dev, vpu->variant->num_clocks,
diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
index f49dbfb8a843..9de7f05eff2a 100644
--- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c
+++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c
@@ -126,7 +126,7 @@ static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
static void set_ref(struct hantro_ctx *ctx)
{
- const u8 *b0_reflist, *b1_reflist, *p_reflist;
+ const struct v4l2_h264_reference *b0_reflist, *b1_reflist, *p_reflist;
struct hantro_dev *vpu = ctx->dev;
int reg_num;
u32 reg;
@@ -157,12 +157,12 @@ static void set_ref(struct hantro_ctx *ctx)
*/
reg_num = 0;
for (i = 0; i < 15; i += 3) {
- reg = G1_REG_BD_REF_PIC_BINIT_RLIST_F0(b0_reflist[i]) |
- G1_REG_BD_REF_PIC_BINIT_RLIST_F1(b0_reflist[i + 1]) |
- G1_REG_BD_REF_PIC_BINIT_RLIST_F2(b0_reflist[i + 2]) |
- G1_REG_BD_REF_PIC_BINIT_RLIST_B0(b1_reflist[i]) |
- G1_REG_BD_REF_PIC_BINIT_RLIST_B1(b1_reflist[i + 1]) |
- G1_REG_BD_REF_PIC_BINIT_RLIST_B2(b1_reflist[i + 2]);
+ reg = G1_REG_BD_REF_PIC_BINIT_RLIST_F0(b0_reflist[i].index) |
+ G1_REG_BD_REF_PIC_BINIT_RLIST_F1(b0_reflist[i + 1].index) |
+ G1_REG_BD_REF_PIC_BINIT_RLIST_F2(b0_reflist[i + 2].index) |
+ G1_REG_BD_REF_PIC_BINIT_RLIST_B0(b1_reflist[i].index) |
+ G1_REG_BD_REF_PIC_BINIT_RLIST_B1(b1_reflist[i + 1].index) |
+ G1_REG_BD_REF_PIC_BINIT_RLIST_B2(b1_reflist[i + 2].index);
vdpu_write_relaxed(vpu, reg, G1_REG_BD_REF_PIC(reg_num++));
}
@@ -171,12 +171,12 @@ static void set_ref(struct hantro_ctx *ctx)
* of forward and backward reference picture lists and first 4 entries
* of P forward picture list.
*/
- reg = G1_REG_BD_P_REF_PIC_BINIT_RLIST_F15(b0_reflist[15]) |
- G1_REG_BD_P_REF_PIC_BINIT_RLIST_B15(b1_reflist[15]) |
- G1_REG_BD_P_REF_PIC_PINIT_RLIST_F0(p_reflist[0]) |
- G1_REG_BD_P_REF_PIC_PINIT_RLIST_F1(p_reflist[1]) |
- G1_REG_BD_P_REF_PIC_PINIT_RLIST_F2(p_reflist[2]) |
- G1_REG_BD_P_REF_PIC_PINIT_RLIST_F3(p_reflist[3]);
+ reg = G1_REG_BD_P_REF_PIC_BINIT_RLIST_F15(b0_reflist[15].index) |
+ G1_REG_BD_P_REF_PIC_BINIT_RLIST_B15(b1_reflist[15].index) |
+ G1_REG_BD_P_REF_PIC_PINIT_RLIST_F0(p_reflist[0].index) |
+ G1_REG_BD_P_REF_PIC_PINIT_RLIST_F1(p_reflist[1].index) |
+ G1_REG_BD_P_REF_PIC_PINIT_RLIST_F2(p_reflist[2].index) |
+ G1_REG_BD_P_REF_PIC_PINIT_RLIST_F3(p_reflist[3].index);
vdpu_write_relaxed(vpu, reg, G1_REG_BD_P_REF_PIC);
/*
@@ -185,12 +185,12 @@ static void set_ref(struct hantro_ctx *ctx)
*/
reg_num = 0;
for (i = 4; i < HANTRO_H264_DPB_SIZE; i += 6) {
- reg = G1_REG_FWD_PIC_PINIT_RLIST_F0(p_reflist[i]) |
- G1_REG_FWD_PIC_PINIT_RLIST_F1(p_reflist[i + 1]) |
- G1_REG_FWD_PIC_PINIT_RLIST_F2(p_reflist[i + 2]) |
- G1_REG_FWD_PIC_PINIT_RLIST_F3(p_reflist[i + 3]) |
- G1_REG_FWD_PIC_PINIT_RLIST_F4(p_reflist[i + 4]) |
- G1_REG_FWD_PIC_PINIT_RLIST_F5(p_reflist[i + 5]);
+ reg = G1_REG_FWD_PIC_PINIT_RLIST_F0(p_reflist[i].index) |
+ G1_REG_FWD_PIC_PINIT_RLIST_F1(p_reflist[i + 1].index) |
+ G1_REG_FWD_PIC_PINIT_RLIST_F2(p_reflist[i + 2].index) |
+ G1_REG_FWD_PIC_PINIT_RLIST_F3(p_reflist[i + 3].index) |
+ G1_REG_FWD_PIC_PINIT_RLIST_F4(p_reflist[i + 4].index) |
+ G1_REG_FWD_PIC_PINIT_RLIST_F5(p_reflist[i + 5].index);
vdpu_write_relaxed(vpu, reg, G1_REG_FWD_PIC(reg_num++));
}
diff --git a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
index 99d8ea7543da..5df6f08e26f5 100644
--- a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
+++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
@@ -8,6 +8,20 @@
#include "hantro_hw.h"
#include "hantro_g2_regs.h"
+#define G2_ALIGN 16
+
+static size_t hantro_hevc_chroma_offset(struct hantro_ctx *ctx)
+{
+ return ctx->dst_fmt.width * ctx->dst_fmt.height;
+}
+
+static size_t hantro_hevc_motion_vectors_offset(struct hantro_ctx *ctx)
+{
+ size_t cr_offset = hantro_hevc_chroma_offset(ctx);
+
+ return ALIGN((cr_offset * 3) / 2, G2_ALIGN);
+}
+
static void prepare_tile_info_buffer(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
@@ -60,7 +74,7 @@ static void prepare_tile_info_buffer(struct hantro_ctx *ctx)
no_chroma = 1;
for (j = 0, tmp_w = 0; j < num_tile_cols - 1; j++) {
tmp_w += pps->column_width_minus1[j] + 1;
- *p++ = pps->column_width_minus1[j + 1];
+ *p++ = pps->column_width_minus1[j] + 1;
*p++ = h;
if (i == 0 && h == 1 && ctb_size == 16)
no_chroma = 1;
@@ -180,13 +194,8 @@ static void set_params(struct hantro_ctx *ctx)
hantro_reg_write(vpu, &g2_max_cu_qpd_depth, 0);
}
- if (pps->flags & V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT) {
- hantro_reg_write(vpu, &g2_cb_qp_offset, pps->pps_cb_qp_offset);
- hantro_reg_write(vpu, &g2_cr_qp_offset, pps->pps_cr_qp_offset);
- } else {
- hantro_reg_write(vpu, &g2_cb_qp_offset, 0);
- hantro_reg_write(vpu, &g2_cr_qp_offset, 0);
- }
+ hantro_reg_write(vpu, &g2_cb_qp_offset, pps->pps_cb_qp_offset);
+ hantro_reg_write(vpu, &g2_cr_qp_offset, pps->pps_cr_qp_offset);
hantro_reg_write(vpu, &g2_filt_offset_beta, pps->pps_beta_offset_div2);
hantro_reg_write(vpu, &g2_filt_offset_tc, pps->pps_tc_offset_div2);
@@ -255,24 +264,11 @@ static void set_params(struct hantro_ctx *ctx)
hantro_reg_write(vpu, &g2_apf_threshold, 8);
}
-static int find_ref_pic_index(const struct v4l2_hevc_dpb_entry *dpb, int pic_order_cnt)
-{
- int i;
-
- for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
- if (dpb[i].pic_order_cnt[0] == pic_order_cnt)
- return i;
- }
-
- return 0x0;
-}
-
static void set_ref_pic_list(struct hantro_ctx *ctx)
{
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
struct hantro_dev *vpu = ctx->dev;
const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
- const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
u32 list0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {};
u32 list1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX] = {};
static const struct hantro_reg ref_pic_regs0[] = {
@@ -316,11 +312,11 @@ static void set_ref_pic_list(struct hantro_ctx *ctx)
/* List 0 contains: short term before, short term after and long term */
j = 0;
for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list0); i++)
- list0[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_before[i]);
+ list0[j++] = decode_params->poc_st_curr_before[i];
for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list0); i++)
- list0[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_after[i]);
+ list0[j++] = decode_params->poc_st_curr_after[i];
for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list0); i++)
- list0[j++] = find_ref_pic_index(dpb, decode_params->poc_lt_curr[i]);
+ list0[j++] = decode_params->poc_lt_curr[i];
/* Fill the list, copying over and over */
i = 0;
@@ -329,11 +325,11 @@ static void set_ref_pic_list(struct hantro_ctx *ctx)
j = 0;
for (i = 0; i < decode_params->num_poc_st_curr_after && j < ARRAY_SIZE(list1); i++)
- list1[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_after[i]);
+ list1[j++] = decode_params->poc_st_curr_after[i];
for (i = 0; i < decode_params->num_poc_st_curr_before && j < ARRAY_SIZE(list1); i++)
- list1[j++] = find_ref_pic_index(dpb, decode_params->poc_st_curr_before[i]);
+ list1[j++] = decode_params->poc_st_curr_before[i];
for (i = 0; i < decode_params->num_poc_lt_curr && j < ARRAY_SIZE(list1); i++)
- list1[j++] = find_ref_pic_index(dpb, decode_params->poc_lt_curr[i]);
+ list1[j++] = decode_params->poc_lt_curr[i];
i = 0;
while (j < ARRAY_SIZE(list1))
@@ -348,7 +344,6 @@ static void set_ref_pic_list(struct hantro_ctx *ctx)
static int set_ref(struct hantro_ctx *ctx)
{
const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
- const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps;
const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps;
const struct v4l2_ctrl_hevc_decode_params *decode_params = ctrls->decode_params;
const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
@@ -356,8 +351,8 @@ static int set_ref(struct hantro_ctx *ctx)
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *vb2_dst;
struct hantro_decoded_buffer *dst;
- size_t cr_offset = hantro_hevc_chroma_offset(sps);
- size_t mv_offset = hantro_hevc_motion_vectors_offset(sps);
+ size_t cr_offset = hantro_hevc_chroma_offset(ctx);
+ size_t mv_offset = hantro_hevc_motion_vectors_offset(ctx);
u32 max_ref_frames;
u16 dpb_longterm_e;
static const struct hantro_reg cur_poc[] = {
@@ -419,8 +414,8 @@ static int set_ref(struct hantro_ctx *ctx)
set_ref_pic_list(ctx);
- /* We will only keep the references picture that are still used */
- ctx->hevc_dec.ref_bufs_used = 0;
+ /* We will only keep the reference pictures that are still used */
+ hantro_hevc_ref_init(ctx);
/* Set up addresses of DPB buffers */
dpb_longterm_e = 0;
@@ -433,7 +428,7 @@ static int set_ref(struct hantro_ctx *ctx)
chroma_addr = luma_addr + cr_offset;
mv_addr = luma_addr + mv_offset;
- if (dpb[i].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR)
+ if (dpb[i].flags & V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE)
dpb_longterm_e |= BIT(V4L2_HEVC_DPB_ENTRIES_NUM_MAX - 1 - i);
hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), luma_addr);
@@ -461,8 +456,6 @@ static int set_ref(struct hantro_ctx *ctx)
hantro_write_addr(vpu, G2_OUT_CHROMA_ADDR, chroma_addr);
hantro_write_addr(vpu, G2_OUT_MV_ADDR, mv_addr);
- hantro_hevc_ref_remove_unused(ctx);
-
for (; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
hantro_write_addr(vpu, G2_REF_LUMA_ADDR(i), 0);
hantro_write_addr(vpu, G2_REF_CHROMA_ADDR(i), 0);
diff --git a/drivers/staging/media/hantro/hantro_g2_regs.h b/drivers/staging/media/hantro/hantro_g2_regs.h
index b7c6f9877b9d..877d663a8181 100644
--- a/drivers/staging/media/hantro/hantro_g2_regs.h
+++ b/drivers/staging/media/hantro/hantro_g2_regs.h
@@ -290,6 +290,10 @@
#define g2_buswidth G2_DEC_REG(58, 8, 0x7)
#define g2_max_burst G2_DEC_REG(58, 0, 0xff)
+#define g2_down_scale_e G2_DEC_REG(184, 7, 0x1)
+#define g2_down_scale_y G2_DEC_REG(184, 2, 0x3)
+#define g2_down_scale_x G2_DEC_REG(184, 0, 0x3)
+
#define G2_REG_CONFIG G2_SWREG(58)
#define G2_REG_CONFIG_DEC_CLK_GATE_E BIT(16)
#define G2_REG_CONFIG_DEC_CLK_GATE_IDLE_E BIT(17)
@@ -312,6 +316,8 @@
#define G2_TILE_FILTER_ADDR (G2_SWREG(179))
#define G2_TILE_SAO_ADDR (G2_SWREG(181))
#define G2_TILE_BSD_ADDR (G2_SWREG(183))
+#define G2_DS_DST (G2_SWREG(186))
+#define G2_DS_DST_CHR (G2_SWREG(188))
#define g2_strm_buffer_len G2_DEC_REG(258, 0, 0xffffffff)
#define g2_strm_start_offset G2_DEC_REG(259, 0, 0xffffffff)
diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
index 1450013d3685..12d69503d6ba 100644
--- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
+++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c
@@ -18,29 +18,44 @@
static void hantro_h1_set_src_img_ctrl(struct hantro_dev *vpu,
struct hantro_ctx *ctx)
{
- struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
+ u32 overfill_r, overfill_b;
u32 reg;
- reg = H1_REG_IN_IMG_CTRL_ROW_LEN(pix_fmt->width)
- | H1_REG_IN_IMG_CTRL_OVRFLR_D4(0)
- | H1_REG_IN_IMG_CTRL_OVRFLB_D4(0)
+ /*
+ * The format width and height are already macroblock aligned
+ * by .vidioc_s_fmt_vid_cap_mplane() callback. Destination
+ * format width and height can be further modified by
+ * .vidioc_s_selection(), and the width is 4-aligned.
+ */
+ overfill_r = ctx->src_fmt.width - ctx->dst_fmt.width;
+ overfill_b = ctx->src_fmt.height - ctx->dst_fmt.height;
+
+ reg = H1_REG_IN_IMG_CTRL_ROW_LEN(ctx->src_fmt.width)
+ | H1_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r / 4)
+ | H1_REG_IN_IMG_CTRL_OVRFLB(overfill_b)
| H1_REG_IN_IMG_CTRL_FMT(ctx->vpu_src_fmt->enc_fmt);
vepu_write_relaxed(vpu, reg, H1_REG_IN_IMG_CTRL);
}
static void hantro_h1_jpeg_enc_set_buffers(struct hantro_dev *vpu,
struct hantro_ctx *ctx,
- struct vb2_buffer *src_buf)
+ struct vb2_buffer *src_buf,
+ struct vb2_buffer *dst_buf)
{
struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
dma_addr_t src[3];
+ u32 size_left;
+
+ size_left = vb2_plane_size(dst_buf, 0) - ctx->vpu_dst_fmt->header_size;
+ if (WARN_ON(vb2_plane_size(dst_buf, 0) < ctx->vpu_dst_fmt->header_size))
+ size_left = 0;
WARN_ON(pix_fmt->num_planes > 3);
- vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.dma,
+ vepu_write_relaxed(vpu, vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
+ ctx->vpu_dst_fmt->header_size,
H1_REG_ADDR_OUTPUT_STREAM);
- vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.size,
- H1_REG_STR_BUF_LIMIT);
+ vepu_write_relaxed(vpu, size_left, H1_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
@@ -112,7 +127,8 @@ int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx)
H1_REG_ENC_CTRL);
hantro_h1_set_src_img_ctrl(vpu, ctx);
- hantro_h1_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf);
+ hantro_h1_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf,
+ &dst_buf->vb2_buf);
hantro_h1_jpeg_enc_set_qtable(vpu, jpeg_ctx.hw_luma_qtable,
jpeg_ctx.hw_chroma_qtable);
@@ -145,13 +161,6 @@ void hantro_h1_jpeg_enc_done(struct hantro_ctx *ctx)
u32 bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8;
struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx);
- /*
- * TODO: Rework the JPEG encoder to eliminate the need
- * for a bounce buffer.
- */
- memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) +
- ctx->vpu_dst_fmt->header_size,
- ctx->jpeg_enc.bounce_buffer.cpu, bytesused);
vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
ctx->vpu_dst_fmt->header_size + bytesused);
}
diff --git a/drivers/staging/media/hantro/hantro_h1_regs.h b/drivers/staging/media/hantro/hantro_h1_regs.h
index d6e9825bb5c7..30e7e7b920b5 100644
--- a/drivers/staging/media/hantro/hantro_h1_regs.h
+++ b/drivers/staging/media/hantro/hantro_h1_regs.h
@@ -47,7 +47,7 @@
#define H1_REG_IN_IMG_CTRL 0x03c
#define H1_REG_IN_IMG_CTRL_ROW_LEN(x) ((x) << 12)
#define H1_REG_IN_IMG_CTRL_OVRFLR_D4(x) ((x) << 10)
-#define H1_REG_IN_IMG_CTRL_OVRFLB_D4(x) ((x) << 6)
+#define H1_REG_IN_IMG_CTRL_OVRFLB(x) ((x) << 6)
#define H1_REG_IN_IMG_CTRL_FMT(x) ((x) << 2)
#define H1_REG_ENC_CTRL0 0x040
#define H1_REG_ENC_CTRL0_INIT_QP(x) ((x) << 26)
diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c
index 0b4d2491be3b..4e9a0ecf5c13 100644
--- a/drivers/staging/media/hantro/hantro_h264.c
+++ b/drivers/staging/media/hantro/hantro_h264.c
@@ -22,6 +22,12 @@
#define POC_BUFFER_SIZE 34
#define SCALING_LIST_SIZE (6 * 16 + 2 * 64)
+/*
+ * For valid and long term reference marking, index are reversed, so bit 31
+ * indicates the status of the picture 0.
+ */
+#define REF_BIT(i) BIT(32 - 1 - (i))
+
/* Data structure describing auxiliary buffer format. */
struct hantro_h264_dec_priv_tbl {
u32 cabac_table[CABAC_INIT_BUFFER_SIZE];
@@ -227,6 +233,7 @@ static void prepare_table(struct hantro_ctx *ctx)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
+ const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu;
const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
u32 dpb_longterm = 0;
@@ -237,20 +244,45 @@ static void prepare_table(struct hantro_ctx *ctx)
tbl->poc[i * 2] = dpb[i].top_field_order_cnt;
tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt;
+ if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_VALID))
+ continue;
+
/*
* Set up bit maps of valid and long term DPBs.
- * NOTE: The bits are reversed, i.e. MSb is DPB 0.
+ * NOTE: The bits are reversed, i.e. MSb is DPB 0. For frame
+ * decoding, bit 31 to 15 are used, while for field decoding,
+ * all bits are used, with bit 31 being a top field, 30 a bottom
+ * field and so on.
*/
- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
- dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i);
- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
- dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i);
+ if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) {
+ if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF)
+ dpb_valid |= REF_BIT(i * 2);
+
+ if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF)
+ dpb_valid |= REF_BIT(i * 2 + 1);
+
+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) {
+ dpb_longterm |= REF_BIT(i * 2);
+ dpb_longterm |= REF_BIT(i * 2 + 1);
+ }
+ } else {
+ dpb_valid |= REF_BIT(i);
+
+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
+ dpb_longterm |= REF_BIT(i);
+ }
+ }
+ ctx->h264_dec.dpb_valid = dpb_valid;
+ ctx->h264_dec.dpb_longterm = dpb_longterm;
+
+ if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) ||
+ !(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) {
+ tbl->poc[32] = ctx->h264_dec.cur_poc;
+ tbl->poc[33] = 0;
+ } else {
+ tbl->poc[32] = dec_param->top_field_order_cnt;
+ tbl->poc[33] = dec_param->bottom_field_order_cnt;
}
- ctx->h264_dec.dpb_valid = dpb_valid << 16;
- ctx->h264_dec.dpb_longterm = dpb_longterm << 16;
-
- tbl->poc[32] = dec_param->top_field_order_cnt;
- tbl->poc[33] = dec_param->bottom_field_order_cnt;
assemble_scaling_list(ctx);
}
@@ -258,8 +290,7 @@ static void prepare_table(struct hantro_ctx *ctx)
static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a,
const struct v4l2_h264_dpb_entry *b)
{
- return a->top_field_order_cnt == b->top_field_order_cnt &&
- a->bottom_field_order_cnt == b->bottom_field_order_cnt;
+ return a->reference_ts == b->reference_ts;
}
static void update_dpb(struct hantro_ctx *ctx)
@@ -273,13 +304,13 @@ static void update_dpb(struct hantro_ctx *ctx)
/* Disable all entries by default. */
for (i = 0; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++)
- ctx->h264_dec.dpb[i].flags &= ~V4L2_H264_DPB_ENTRY_FLAG_ACTIVE;
+ ctx->h264_dec.dpb[i].flags = 0;
/* Try to match new DPB entries with existing ones by their POCs. */
for (i = 0; i < ARRAY_SIZE(dec_param->dpb); i++) {
const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i];
- if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
+ if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID))
continue;
/*
@@ -290,8 +321,7 @@ static void update_dpb(struct hantro_ctx *ctx)
struct v4l2_h264_dpb_entry *cdpb;
cdpb = &ctx->h264_dec.dpb[j];
- if (cdpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE ||
- !dpb_entry_match(cdpb, ndpb))
+ if (!dpb_entry_match(cdpb, ndpb))
continue;
*cdpb = *ndpb;
@@ -328,6 +358,8 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
{
struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
dma_addr_t dma_addr = 0;
+ s32 cur_poc = ctx->h264_dec.cur_poc;
+ u32 flags;
if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
dma_addr = hantro_get_ref(ctx, dpb[dpb_idx].reference_ts);
@@ -345,7 +377,12 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
dma_addr = hantro_get_dec_buf_addr(ctx, buf);
}
- return dma_addr;
+ flags = dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD ? 0x2 : 0;
+ flags |= abs(dpb[dpb_idx].top_field_order_cnt - cur_poc) <
+ abs(dpb[dpb_idx].bottom_field_order_cnt - cur_poc) ?
+ 0x1 : 0;
+
+ return dma_addr | flags;
}
u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, unsigned int dpb_idx)
@@ -354,11 +391,50 @@ u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, unsigned int dpb_idx)
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
return 0;
- if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
- return dpb->pic_num;
return dpb->frame_num;
}
+/*
+ * Removes all references with the same parity as the current picture from the
+ * reference list. The remaining list will have references with the opposite
+ * parity. This is effectively a deduplication of references since each buffer
+ * stores two fields. For this reason, each buffer is found twice in the
+ * reference list.
+ *
+ * This technique has been chosen through trial and error. This simple approach
+ * resulted in the highest conformance score. Note that this method may suffer
+ * worse quality in the case an opposite reference frame has been lost. If this
+ * becomes a problem in the future, it should be possible to add a preprocessing
+ * to identify un-paired fields and avoid removing them.
+ */
+static void deduplicate_reflist(struct v4l2_h264_reflist_builder *b,
+ struct v4l2_h264_reference *reflist)
+{
+ int write_idx = 0;
+ int i;
+
+ if (b->cur_pic_fields == V4L2_H264_FRAME_REF) {
+ write_idx = b->num_valid;
+ goto done;
+ }
+
+ for (i = 0; i < b->num_valid; i++) {
+ if (!(b->cur_pic_fields == reflist[i].fields)) {
+ reflist[write_idx++] = reflist[i];
+ continue;
+ }
+ }
+
+done:
+ /* Should not happen unless we have a bug in the reflist builder. */
+ if (WARN_ON(write_idx > 16))
+ write_idx = 16;
+
+ /* Clear the remaining, some streams fails otherwise */
+ for (; write_idx < 16; write_idx++)
+ reflist[write_idx].index = 15;
+}
+
int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
{
struct hantro_h264_dec_hw_ctx *h264_ctx = &ctx->h264_dec;
@@ -390,15 +466,29 @@ int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
/* Update the DPB with new refs. */
update_dpb(ctx);
- /* Prepare data in memory. */
- prepare_table(ctx);
-
/* Build the P/B{0,1} ref lists. */
v4l2_h264_init_reflist_builder(&reflist_builder, ctrls->decode,
ctrls->sps, ctx->h264_dec.dpb);
+ h264_ctx->cur_poc = reflist_builder.cur_pic_order_count;
+
+ /* Prepare data in memory. */
+ prepare_table(ctx);
+
v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
h264_ctx->reflists.b1);
+
+ /*
+ * Reduce ref lists to at most 16 entries, Hantro hardware will deduce
+ * the actual picture lists in field through the dpb_valid,
+ * dpb_longterm bitmap along with the current frame parity.
+ */
+ if (reflist_builder.cur_pic_fields != V4L2_H264_FRAME_REF) {
+ deduplicate_reflist(&reflist_builder, h264_ctx->reflists.p);
+ deduplicate_reflist(&reflist_builder, h264_ctx->reflists.b0);
+ deduplicate_reflist(&reflist_builder, h264_ctx->reflists.b1);
+ }
+
return 0;
}
diff --git a/drivers/staging/media/hantro/hantro_hevc.c b/drivers/staging/media/hantro/hantro_hevc.c
index b49a41d7ae91..f86c98e19177 100644
--- a/drivers/staging/media/hantro/hantro_hevc.c
+++ b/drivers/staging/media/hantro/hantro_hevc.c
@@ -25,32 +25,11 @@
#define MAX_TILE_COLS 20
#define MAX_TILE_ROWS 22
-#define UNUSED_REF -1
-
-#define G2_ALIGN 16
-
-size_t hantro_hevc_chroma_offset(const struct v4l2_ctrl_hevc_sps *sps)
-{
- int bytes_per_pixel = sps->bit_depth_luma_minus8 == 0 ? 1 : 2;
-
- return sps->pic_width_in_luma_samples *
- sps->pic_height_in_luma_samples * bytes_per_pixel;
-}
-
-size_t hantro_hevc_motion_vectors_offset(const struct v4l2_ctrl_hevc_sps *sps)
-{
- size_t cr_offset = hantro_hevc_chroma_offset(sps);
-
- return ALIGN((cr_offset * 3) / 2, G2_ALIGN);
-}
-
-static void hantro_hevc_ref_init(struct hantro_ctx *ctx)
+void hantro_hevc_ref_init(struct hantro_ctx *ctx)
{
struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
- int i;
- for (i = 0; i < NUM_REF_PICTURES; i++)
- hevc_dec->ref_bufs_poc[i] = UNUSED_REF;
+ hevc_dec->ref_bufs_used = 0;
}
dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx,
@@ -59,7 +38,7 @@ dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx,
struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
int i;
- /* Find the reference buffer in already know ones */
+ /* Find the reference buffer in already known ones */
for (i = 0; i < NUM_REF_PICTURES; i++) {
if (hevc_dec->ref_bufs_poc[i] == poc) {
hevc_dec->ref_bufs_used |= 1 << i;
@@ -77,7 +56,7 @@ int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr)
/* Add a new reference buffer */
for (i = 0; i < NUM_REF_PICTURES; i++) {
- if (hevc_dec->ref_bufs_poc[i] == UNUSED_REF) {
+ if (!(hevc_dec->ref_bufs_used & 1 << i)) {
hevc_dec->ref_bufs_used |= 1 << i;
hevc_dec->ref_bufs_poc[i] = poc;
hevc_dec->ref_bufs[i].dma = addr;
@@ -88,23 +67,6 @@ int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr)
return -EINVAL;
}
-void hantro_hevc_ref_remove_unused(struct hantro_ctx *ctx)
-{
- struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec;
- int i;
-
- /* Just tag buffer as unused, do not free them */
- for (i = 0; i < NUM_REF_PICTURES; i++) {
- if (hevc_dec->ref_bufs_poc[i] == UNUSED_REF)
- continue;
-
- if (hevc_dec->ref_bufs_used & (1 << i))
- continue;
-
- hevc_dec->ref_bufs_poc[i] = UNUSED_REF;
- }
-}
-
static int tile_buffer_reallocate(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h
index 4a19ae8940b9..52a960f6fa4a 100644
--- a/drivers/staging/media/hantro/hantro_hw.h
+++ b/drivers/staging/media/hantro/hantro_hw.h
@@ -43,15 +43,6 @@ struct hantro_aux_buf {
unsigned long attrs;
};
-/**
- * struct hantro_jpeg_enc_hw_ctx
- *
- * @bounce_buffer: Bounce buffer
- */
-struct hantro_jpeg_enc_hw_ctx {
- struct hantro_aux_buf bounce_buffer;
-};
-
/* Max. number of entries in the DPB (HW limitation). */
#define HANTRO_H264_DPB_SIZE 16
@@ -78,9 +69,9 @@ struct hantro_h264_dec_ctrls {
* @b1: B1 reflist
*/
struct hantro_h264_dec_reflists {
- u8 p[HANTRO_H264_DPB_SIZE];
- u8 b0[HANTRO_H264_DPB_SIZE];
- u8 b1[HANTRO_H264_DPB_SIZE];
+ struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN];
+ struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN];
+ struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN];
};
/**
@@ -92,6 +83,7 @@ struct hantro_h264_dec_reflists {
* @ctrls: V4L2 controls attached to a run
* @dpb_longterm: DPB long-term
* @dpb_valid: DPB valid
+ * @cur_poc: Current picture order count
*/
struct hantro_h264_dec_hw_ctx {
struct hantro_aux_buf priv;
@@ -100,6 +92,7 @@ struct hantro_h264_dec_hw_ctx {
struct hantro_h264_dec_ctrls ctrls;
u32 dpb_longterm;
u32 dpb_valid;
+ s32 cur_poc;
};
/**
@@ -254,12 +247,16 @@ struct hantro_postproc_ctx {
/**
* struct hantro_postproc_ops - post-processor operations
*
- * @enable: Enable the post-processor block. Optional.
- * @disable: Disable the post-processor block. Optional.
+ * @enable: Enable the post-processor block. Optional.
+ * @disable: Disable the post-processor block. Optional.
+ * @enum_framesizes: Enumerate possible scaled output formats.
+ * Returns zero if OK, a negative value in error cases.
+ * Optional.
*/
struct hantro_postproc_ops {
void (*enable)(struct hantro_ctx *ctx);
void (*disable)(struct hantro_ctx *ctx);
+ int (*enum_framesizes)(struct hantro_ctx *ctx, struct v4l2_frmsizeenum *fsize);
};
/**
@@ -299,6 +296,8 @@ enum hantro_enc_fmt {
ROCKCHIP_VPU_ENC_FMT_UYVY422 = 3,
};
+extern const struct hantro_variant imx8mm_vpu_g1_variant;
+extern const struct hantro_variant imx8mq_vpu_g1_variant;
extern const struct hantro_variant imx8mq_vpu_g2_variant;
extern const struct hantro_variant imx8mq_vpu_variant;
extern const struct hantro_variant px30_vpu_variant;
@@ -307,6 +306,7 @@ extern const struct hantro_variant rk3066_vpu_variant;
extern const struct hantro_variant rk3288_vpu_variant;
extern const struct hantro_variant rk3328_vpu_variant;
extern const struct hantro_variant rk3399_vpu_variant;
+extern const struct hantro_variant rk3568_vpu_variant;
extern const struct hantro_variant sama5d4_vdec_variant;
extern const struct hantro_variant sunxi_vpu_variant;
@@ -327,8 +327,6 @@ void hantro_g1_reset(struct hantro_ctx *ctx);
int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx);
int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx);
-int hantro_jpeg_enc_init(struct hantro_ctx *ctx);
-void hantro_jpeg_enc_exit(struct hantro_ctx *ctx);
void hantro_h1_jpeg_enc_done(struct hantro_ctx *ctx);
void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx);
@@ -346,11 +344,9 @@ int hantro_hevc_dec_init(struct hantro_ctx *ctx);
void hantro_hevc_dec_exit(struct hantro_ctx *ctx);
int hantro_g2_hevc_dec_run(struct hantro_ctx *ctx);
int hantro_hevc_dec_prepare_run(struct hantro_ctx *ctx);
+void hantro_hevc_ref_init(struct hantro_ctx *ctx);
dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, int poc);
int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr);
-void hantro_hevc_ref_remove_unused(struct hantro_ctx *ctx);
-size_t hantro_hevc_chroma_offset(const struct v4l2_ctrl_hevc_sps *sps);
-size_t hantro_hevc_motion_vectors_offset(const struct v4l2_ctrl_hevc_sps *sps);
static inline unsigned short hantro_vp9_num_sbs(unsigned short dimension)
{
diff --git a/drivers/staging/media/hantro/hantro_jpeg.c b/drivers/staging/media/hantro/hantro_jpeg.c
index df62fbdff7c9..d07b1b449b61 100644
--- a/drivers/staging/media/hantro/hantro_jpeg.c
+++ b/drivers/staging/media/hantro/hantro_jpeg.c
@@ -6,21 +6,23 @@
* Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
* Copyright (C) 2014 Philipp Zabel, Pengutronix
*/
-#include <linux/dma-mapping.h>
+
+#include <linux/align.h>
+#include <linux/build_bug.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include "hantro_jpeg.h"
#include "hantro.h"
-#define LUMA_QUANT_OFF 7
-#define CHROMA_QUANT_OFF 72
-#define HEIGHT_OFF 141
-#define WIDTH_OFF 143
+#define LUMA_QUANT_OFF 25
+#define CHROMA_QUANT_OFF 90
+#define HEIGHT_OFF 159
+#define WIDTH_OFF 161
-#define HUFF_LUMA_DC_OFF 160
-#define HUFF_LUMA_AC_OFF 193
-#define HUFF_CHROMA_DC_OFF 376
-#define HUFF_CHROMA_AC_OFF 409
+#define HUFF_LUMA_DC_OFF 178
+#define HUFF_LUMA_AC_OFF 211
+#define HUFF_CHROMA_DC_OFF 394
+#define HUFF_CHROMA_AC_OFF 427
/* Default tables from JPEG ITU-T.81
* (ISO/IEC 10918-1) Annex K, tables K.1 and K.2
@@ -47,7 +49,7 @@ static const unsigned char chroma_q_table[] = {
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
};
-static const unsigned char zigzag[64] = {
+static const unsigned char zigzag[] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
@@ -58,7 +60,7 @@ static const unsigned char zigzag[64] = {
53, 60, 61, 54, 47, 55, 62, 63
};
-static const u32 hw_reorder[64] = {
+static const u32 hw_reorder[] = {
0, 8, 16, 24, 1, 9, 17, 25,
32, 40, 48, 56, 33, 41, 49, 57,
2, 10, 18, 26, 3, 11, 19, 27,
@@ -140,10 +142,15 @@ static const unsigned char chroma_ac_table[] = {
* and we'll use fixed offsets to change the width, height
* quantization tables, etc.
*/
-static const unsigned char hantro_jpeg_header[JPEG_HEADER_SIZE] = {
+static const unsigned char hantro_jpeg_header[] = {
/* SOI */
0xff, 0xd8,
+ /* JFIF-APP0 */
+ 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46,
+ 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x00,
+
/* DQT */
0xff, 0xdb, 0x00, 0x84,
@@ -242,11 +249,29 @@ static const unsigned char hantro_jpeg_header[JPEG_HEADER_SIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* COM */
+ 0xff, 0xfe, 0x00, 0x03, 0x00,
+
/* SOS */
0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
};
+/*
+ * JPEG_HEADER_SIZE is used in other parts of the driver in lieu of
+ * "sizeof(hantro_jpeg_header)". The two must be equal.
+ */
+static_assert(sizeof(hantro_jpeg_header) == JPEG_HEADER_SIZE);
+
+/*
+ * hantro_jpeg_header is padded with a COM segment, so that the payload
+ * of the SOS segment (the entropy-encoded image scan), which should
+ * trail the whole header, is 8-byte aligned for the hardware to write
+ * to directly.
+ */
+static_assert(IS_ALIGNED(sizeof(hantro_jpeg_header), 8),
+ "Hantro JPEG header size needs to be 8-byte aligned.");
+
static unsigned char jpeg_scale_qp(const unsigned char qp, int scale)
{
unsigned int temp;
@@ -267,7 +292,10 @@ jpeg_scale_quant_table(unsigned char *file_q_tab,
{
int i;
- for (i = 0; i < 64; i++) {
+ BUILD_BUG_ON(ARRAY_SIZE(zigzag) != JPEG_QUANT_SIZE);
+ BUILD_BUG_ON(ARRAY_SIZE(hw_reorder) != JPEG_QUANT_SIZE);
+
+ for (i = 0; i < JPEG_QUANT_SIZE; i++) {
file_q_tab[i] = jpeg_scale_qp(tab[zigzag[i]], scale);
reordered_q_tab[i] = jpeg_scale_qp(tab[hw_reorder[i]], scale);
}
@@ -286,6 +314,11 @@ static void jpeg_set_quality(struct hantro_jpeg_ctx *ctx)
else
scale = 200 - 2 * ctx->quality;
+ BUILD_BUG_ON(ARRAY_SIZE(luma_q_table) != JPEG_QUANT_SIZE);
+ BUILD_BUG_ON(ARRAY_SIZE(chroma_q_table) != JPEG_QUANT_SIZE);
+ BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_luma_qtable) != JPEG_QUANT_SIZE);
+ BUILD_BUG_ON(ARRAY_SIZE(ctx->hw_chroma_qtable) != JPEG_QUANT_SIZE);
+
jpeg_scale_quant_table(ctx->buffer + LUMA_QUANT_OFF,
ctx->hw_luma_qtable, luma_q_table, scale);
jpeg_scale_quant_table(ctx->buffer + CHROMA_QUANT_OFF,
@@ -313,30 +346,3 @@ void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx)
jpeg_set_quality(ctx);
}
-
-int hantro_jpeg_enc_init(struct hantro_ctx *ctx)
-{
- ctx->jpeg_enc.bounce_buffer.size =
- ctx->dst_fmt.plane_fmt[0].sizeimage -
- ctx->vpu_dst_fmt->header_size;
-
- ctx->jpeg_enc.bounce_buffer.cpu =
- dma_alloc_attrs(ctx->dev->dev,
- ctx->jpeg_enc.bounce_buffer.size,
- &ctx->jpeg_enc.bounce_buffer.dma,
- GFP_KERNEL,
- DMA_ATTR_ALLOC_SINGLE_PAGES);
- if (!ctx->jpeg_enc.bounce_buffer.cpu)
- return -ENOMEM;
-
- return 0;
-}
-
-void hantro_jpeg_enc_exit(struct hantro_ctx *ctx)
-{
- dma_free_attrs(ctx->dev->dev,
- ctx->jpeg_enc.bounce_buffer.size,
- ctx->jpeg_enc.bounce_buffer.cpu,
- ctx->jpeg_enc.bounce_buffer.dma,
- DMA_ATTR_ALLOC_SINGLE_PAGES);
-}
diff --git a/drivers/staging/media/hantro/hantro_jpeg.h b/drivers/staging/media/hantro/hantro_jpeg.h
index 035ab25b803f..0b49d0b82caa 100644
--- a/drivers/staging/media/hantro/hantro_jpeg.h
+++ b/drivers/staging/media/hantro/hantro_jpeg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
-#define JPEG_HEADER_SIZE 601
+#define JPEG_HEADER_SIZE 624
#define JPEG_QUANT_SIZE 64
struct hantro_jpeg_ctx {
diff --git a/drivers/staging/media/hantro/hantro_postproc.c b/drivers/staging/media/hantro/hantro_postproc.c
index 248abe5423f0..ab168c1c0d28 100644
--- a/drivers/staging/media/hantro/hantro_postproc.c
+++ b/drivers/staging/media/hantro/hantro_postproc.c
@@ -100,21 +100,58 @@ static void hantro_postproc_g1_enable(struct hantro_ctx *ctx)
HANTRO_PP_REG_WRITE(vpu, display_width, ctx->dst_fmt.width);
}
+static int down_scale_factor(struct hantro_ctx *ctx)
+{
+ if (ctx->src_fmt.width == ctx->dst_fmt.width)
+ return 0;
+
+ return DIV_ROUND_CLOSEST(ctx->src_fmt.width, ctx->dst_fmt.width);
+}
+
static void hantro_postproc_g2_enable(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct vb2_v4l2_buffer *dst_buf;
size_t chroma_offset = ctx->dst_fmt.width * ctx->dst_fmt.height;
+ int down_scale = down_scale_factor(ctx);
dma_addr_t dst_dma;
dst_buf = hantro_get_dst_buf(ctx);
dst_dma = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
- hantro_write_addr(vpu, G2_RS_OUT_LUMA_ADDR, dst_dma);
- hantro_write_addr(vpu, G2_RS_OUT_CHROMA_ADDR, dst_dma + chroma_offset);
+ if (down_scale) {
+ hantro_reg_write(vpu, &g2_down_scale_e, 1);
+ hantro_reg_write(vpu, &g2_down_scale_y, down_scale >> 2);
+ hantro_reg_write(vpu, &g2_down_scale_x, down_scale >> 2);
+ hantro_write_addr(vpu, G2_DS_DST, dst_dma);
+ hantro_write_addr(vpu, G2_DS_DST_CHR, dst_dma + (chroma_offset >> down_scale));
+ } else {
+ hantro_write_addr(vpu, G2_RS_OUT_LUMA_ADDR, dst_dma);
+ hantro_write_addr(vpu, G2_RS_OUT_CHROMA_ADDR, dst_dma + chroma_offset);
+ }
hantro_reg_write(vpu, &g2_out_rs_e, 1);
}
+static int hantro_postproc_g2_enum_framesizes(struct hantro_ctx *ctx,
+ struct v4l2_frmsizeenum *fsize)
+{
+ /**
+ * G2 scaler can scale down by 0, 2, 4 or 8
+ * use fsize->index has power of 2 diviser
+ **/
+ if (fsize->index > 3)
+ return -EINVAL;
+
+ if (!ctx->src_fmt.width || !ctx->src_fmt.height)
+ return -EINVAL;
+
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = ctx->src_fmt.width >> fsize->index;
+ fsize->discrete.height = ctx->src_fmt.height >> fsize->index;
+
+ return 0;
+}
+
void hantro_postproc_free(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
@@ -197,6 +234,17 @@ void hantro_postproc_enable(struct hantro_ctx *ctx)
vpu->variant->postproc_ops->enable(ctx);
}
+int hanto_postproc_enum_framesizes(struct hantro_ctx *ctx,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct hantro_dev *vpu = ctx->dev;
+
+ if (vpu->variant->postproc_ops && vpu->variant->postproc_ops->enum_framesizes)
+ return vpu->variant->postproc_ops->enum_framesizes(ctx, fsize);
+
+ return -EINVAL;
+}
+
const struct hantro_postproc_ops hantro_g1_postproc_ops = {
.enable = hantro_postproc_g1_enable,
.disable = hantro_postproc_g1_disable,
@@ -205,4 +253,5 @@ const struct hantro_postproc_ops hantro_g1_postproc_ops = {
const struct hantro_postproc_ops hantro_g2_postproc_ops = {
.enable = hantro_postproc_g2_enable,
.disable = hantro_postproc_g2_disable,
+ .enum_framesizes = hantro_postproc_g2_enum_framesizes,
};
diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c
index e595905b3bd7..22ad182ee972 100644
--- a/drivers/staging/media/hantro/hantro_v4l2.c
+++ b/drivers/staging/media/hantro/hantro_v4l2.c
@@ -116,12 +116,6 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
struct hantro_ctx *ctx = fh_to_ctx(priv);
const struct hantro_fmt *fmt;
- if (fsize->index != 0) {
- vpu_debug(0, "invalid frame size index (expected 0, got %d)\n",
- fsize->index);
- return -EINVAL;
- }
-
fmt = hantro_find_format(ctx, fsize->pixel_format);
if (!fmt) {
vpu_debug(0, "unsupported bitstream format (%08x)\n",
@@ -129,9 +123,14 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
return -EINVAL;
}
- /* This only makes sense for coded formats */
- if (fmt->codec_mode == HANTRO_MODE_NONE)
+ /* For non-coded formats check if postprocessing scaling is possible */
+ if (fmt->codec_mode == HANTRO_MODE_NONE && hantro_needs_postproc(ctx, fmt)) {
+ return hanto_postproc_enum_framesizes(ctx, fsize);
+ } else if (fsize->index != 0) {
+ vpu_debug(0, "invalid frame size index (expected 0, got %d)\n",
+ fsize->index);
return -EINVAL;
+ }
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
fsize->stepwise = fmt->frmsize;
@@ -409,6 +408,30 @@ hantro_update_requires_request(struct hantro_ctx *ctx, u32 fourcc)
}
}
+static void
+hantro_update_requires_hold_capture_buf(struct hantro_ctx *ctx, u32 fourcc)
+{
+ struct vb2_queue *vq;
+
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+
+ switch (fourcc) {
+ case V4L2_PIX_FMT_JPEG:
+ case V4L2_PIX_FMT_MPEG2_SLICE:
+ case V4L2_PIX_FMT_VP8_FRAME:
+ case V4L2_PIX_FMT_HEVC_SLICE:
+ case V4L2_PIX_FMT_VP9_FRAME:
+ vq->subsystem_flags &= ~(VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF);
+ break;
+ case V4L2_PIX_FMT_H264_SLICE:
+ vq->subsystem_flags |= VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
+ break;
+ default:
+ break;
+ }
+}
+
static int hantro_set_fmt_out(struct hantro_ctx *ctx,
struct v4l2_pix_format_mplane *pix_mp)
{
@@ -472,6 +495,7 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx,
ctx->dst_fmt.quantization = pix_mp->quantization;
hantro_update_requires_request(ctx, pix_mp->pixelformat);
+ hantro_update_requires_hold_capture_buf(ctx, pix_mp->pixelformat);
vpu_debug(0, "OUTPUT codec mode: %d\n", ctx->vpu_src_fmt->codec_mode);
vpu_debug(0, "fmt - w: %d, h: %d\n",
@@ -554,6 +578,112 @@ vidioc_s_fmt_cap_mplane(struct file *file, void *priv, struct v4l2_format *f)
return hantro_set_fmt_cap(fh_to_ctx(priv), &f->fmt.pix_mp);
}
+static int vidioc_g_selection(struct file *file, void *priv,
+ struct v4l2_selection *sel)
+{
+ struct hantro_ctx *ctx = fh_to_ctx(priv);
+
+ /* Crop only supported on source. */
+ if (!ctx->is_encoder ||
+ sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = ctx->src_fmt.width;
+ sel->r.height = ctx->src_fmt.height;
+ break;
+ case V4L2_SEL_TGT_CROP:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = ctx->dst_fmt.width;
+ sel->r.height = ctx->dst_fmt.height;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vidioc_s_selection(struct file *file, void *priv,
+ struct v4l2_selection *sel)
+{
+ struct hantro_ctx *ctx = fh_to_ctx(priv);
+ struct v4l2_rect *rect = &sel->r;
+ struct vb2_queue *vq;
+
+ /* Crop only supported on source. */
+ if (!ctx->is_encoder ||
+ sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+
+ /* Change not allowed if the queue is streaming. */
+ vq = v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx);
+ if (vb2_is_streaming(vq))
+ return -EBUSY;
+
+ if (sel->target != V4L2_SEL_TGT_CROP)
+ return -EINVAL;
+
+ /*
+ * We do not support offsets, and we can crop only inside
+ * right-most or bottom-most macroblocks.
+ */
+ if (rect->left != 0 || rect->top != 0 ||
+ round_up(rect->width, MB_DIM) != ctx->src_fmt.width ||
+ round_up(rect->height, MB_DIM) != ctx->src_fmt.height) {
+ /* Default to full frame for incorrect settings. */
+ rect->left = 0;
+ rect->top = 0;
+ rect->width = ctx->src_fmt.width;
+ rect->height = ctx->src_fmt.height;
+ } else {
+ /* We support widths aligned to 4 pixels and arbitrary heights. */
+ rect->width = round_up(rect->width, 4);
+ }
+
+ ctx->dst_fmt.width = rect->width;
+ ctx->dst_fmt.height = rect->height;
+
+ return 0;
+}
+
+static const struct v4l2_event hantro_eos_event = {
+ .type = V4L2_EVENT_EOS
+};
+
+static int vidioc_encoder_cmd(struct file *file, void *priv,
+ struct v4l2_encoder_cmd *ec)
+{
+ struct hantro_ctx *ctx = fh_to_ctx(priv);
+ int ret;
+
+ ret = v4l2_m2m_ioctl_try_encoder_cmd(file, priv, ec);
+ if (ret < 0)
+ return ret;
+
+ if (!vb2_is_streaming(v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx)) ||
+ !vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx)))
+ return 0;
+
+ ret = v4l2_m2m_ioctl_encoder_cmd(file, priv, ec);
+ if (ret < 0)
+ return ret;
+
+ if (ec->cmd == V4L2_ENC_CMD_STOP &&
+ v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
+ v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);
+
+ if (ec->cmd == V4L2_ENC_CMD_START)
+ vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
+
+ return 0;
+}
+
const struct v4l2_ioctl_ops hantro_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_framesizes = vidioc_enum_framesizes,
@@ -580,6 +710,12 @@ const struct v4l2_ioctl_ops hantro_ioctl_ops = {
.vidioc_streamon = v4l2_m2m_ioctl_streamon,
.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+
+ .vidioc_g_selection = vidioc_g_selection,
+ .vidioc_s_selection = vidioc_s_selection,
+
+ .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
+ .vidioc_encoder_cmd = vidioc_encoder_cmd,
};
static int
@@ -656,8 +792,12 @@ static int hantro_buf_prepare(struct vb2_buffer *vb)
* (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
* it to buffer length).
*/
- if (V4L2_TYPE_IS_CAPTURE(vq->type))
- vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);
+ if (V4L2_TYPE_IS_CAPTURE(vq->type)) {
+ if (ctx->is_encoder)
+ vb2_set_plane_payload(vb, 0, 0);
+ else
+ vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);
+ }
return 0;
}
@@ -667,6 +807,22 @@ static void hantro_buf_queue(struct vb2_buffer *vb)
struct hantro_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
+ vb2_is_streaming(vb->vb2_queue) &&
+ v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
+ unsigned int i;
+
+ for (i = 0; i < vb->num_planes; i++)
+ vb2_set_plane_payload(vb, i, 0);
+
+ vbuf->field = V4L2_FIELD_NONE;
+ vbuf->sequence = ctx->sequence_cap++;
+
+ v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
+ v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);
+ return;
+ }
+
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
@@ -682,6 +838,8 @@ static int hantro_start_streaming(struct vb2_queue *q, unsigned int count)
struct hantro_ctx *ctx = vb2_get_drv_priv(q);
int ret = 0;
+ v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
+
if (V4L2_TYPE_IS_OUTPUT(q->type))
ctx->sequence_out = 0;
else
@@ -754,6 +912,12 @@ static void hantro_stop_streaming(struct vb2_queue *q)
hantro_return_bufs(q, v4l2_m2m_src_buf_remove);
else
hantro_return_bufs(q, v4l2_m2m_dst_buf_remove);
+
+ v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
+
+ if (V4L2_TYPE_IS_OUTPUT(q->type) &&
+ v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
+ v4l2_event_queue_fh(&ctx->fh, &hantro_eos_event);
}
static void hantro_buf_request_complete(struct vb2_buffer *vb)
diff --git a/drivers/staging/media/hantro/imx8m_vpu_hw.c b/drivers/staging/media/hantro/imx8m_vpu_hw.c
index f5991b8e553a..9802508bade2 100644
--- a/drivers/staging/media/hantro/imx8m_vpu_hw.c
+++ b/drivers/staging/media/hantro/imx8m_vpu_hw.c
@@ -205,13 +205,6 @@ static void imx8m_vpu_g1_reset(struct hantro_ctx *ctx)
imx8m_soft_reset(vpu, RESET_G1);
}
-static void imx8m_vpu_g2_reset(struct hantro_ctx *ctx)
-{
- struct hantro_dev *vpu = ctx->dev;
-
- imx8m_soft_reset(vpu, RESET_G2);
-}
-
/*
* Supported codec ops.
*/
@@ -237,17 +230,33 @@ static const struct hantro_codec_ops imx8mq_vpu_codec_ops[] = {
},
};
+static const struct hantro_codec_ops imx8mq_vpu_g1_codec_ops[] = {
+ [HANTRO_MODE_MPEG2_DEC] = {
+ .run = hantro_g1_mpeg2_dec_run,
+ .init = hantro_mpeg2_dec_init,
+ .exit = hantro_mpeg2_dec_exit,
+ },
+ [HANTRO_MODE_VP8_DEC] = {
+ .run = hantro_g1_vp8_dec_run,
+ .init = hantro_vp8_dec_init,
+ .exit = hantro_vp8_dec_exit,
+ },
+ [HANTRO_MODE_H264_DEC] = {
+ .run = hantro_g1_h264_dec_run,
+ .init = hantro_h264_dec_init,
+ .exit = hantro_h264_dec_exit,
+ },
+};
+
static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = {
[HANTRO_MODE_HEVC_DEC] = {
.run = hantro_g2_hevc_dec_run,
- .reset = imx8m_vpu_g2_reset,
.init = hantro_hevc_dec_init,
.exit = hantro_hevc_dec_exit,
},
[HANTRO_MODE_VP9_DEC] = {
.run = hantro_g2_vp9_dec_run,
.done = hantro_g2_vp9_dec_done,
- .reset = imx8m_vpu_g2_reset,
.init = hantro_vp9_dec_init,
.exit = hantro_vp9_dec_exit,
},
@@ -267,6 +276,8 @@ static const struct hantro_irq imx8mq_g2_irqs[] = {
static const char * const imx8mq_clk_names[] = { "g1", "g2", "bus" };
static const char * const imx8mq_reg_names[] = { "g1", "g2", "ctrl" };
+static const char * const imx8mq_g1_clk_names[] = { "g1" };
+static const char * const imx8mq_g2_clk_names[] = { "g2" };
const struct hantro_variant imx8mq_vpu_variant = {
.dec_fmts = imx8m_vpu_dec_fmts,
@@ -287,6 +298,21 @@ const struct hantro_variant imx8mq_vpu_variant = {
.num_regs = ARRAY_SIZE(imx8mq_reg_names)
};
+const struct hantro_variant imx8mq_vpu_g1_variant = {
+ .dec_fmts = imx8m_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
+ .postproc_fmts = imx8m_vpu_postproc_fmts,
+ .num_postproc_fmts = ARRAY_SIZE(imx8m_vpu_postproc_fmts),
+ .postproc_ops = &hantro_g1_postproc_ops,
+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
+ HANTRO_H264_DECODER,
+ .codec_ops = imx8mq_vpu_g1_codec_ops,
+ .irqs = imx8mq_irqs,
+ .num_irqs = ARRAY_SIZE(imx8mq_irqs),
+ .clk_names = imx8mq_g1_clk_names,
+ .num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),
+};
+
const struct hantro_variant imx8mq_vpu_g2_variant = {
.dec_offset = 0x0,
.dec_fmts = imx8m_vpu_g2_dec_fmts,
@@ -296,10 +322,20 @@ const struct hantro_variant imx8mq_vpu_g2_variant = {
.postproc_ops = &hantro_g2_postproc_ops,
.codec = HANTRO_HEVC_DECODER | HANTRO_VP9_DECODER,
.codec_ops = imx8mq_vpu_g2_codec_ops,
- .init = imx8mq_vpu_hw_init,
- .runtime_resume = imx8mq_runtime_resume,
.irqs = imx8mq_g2_irqs,
.num_irqs = ARRAY_SIZE(imx8mq_g2_irqs),
- .clk_names = imx8mq_clk_names,
- .num_clocks = ARRAY_SIZE(imx8mq_clk_names),
+ .clk_names = imx8mq_g2_clk_names,
+ .num_clocks = ARRAY_SIZE(imx8mq_g2_clk_names),
+};
+
+const struct hantro_variant imx8mm_vpu_g1_variant = {
+ .dec_fmts = imx8m_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(imx8m_vpu_dec_fmts),
+ .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
+ HANTRO_H264_DECODER,
+ .codec_ops = imx8mq_vpu_g1_codec_ops,
+ .irqs = imx8mq_irqs,
+ .num_irqs = ARRAY_SIZE(imx8mq_irqs),
+ .clk_names = imx8mq_g1_clk_names,
+ .num_clocks = ARRAY_SIZE(imx8mq_g1_clk_names),
};
diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c
index 64a6330475eb..46c1a83bcc4e 100644
--- a/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c
+++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c
@@ -298,7 +298,7 @@ static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf)
static void set_ref(struct hantro_ctx *ctx)
{
- const u8 *b0_reflist, *b1_reflist, *p_reflist;
+ const struct v4l2_h264_reference *b0_reflist, *b1_reflist, *p_reflist;
struct hantro_dev *vpu = ctx->dev;
u32 reg;
int i;
@@ -307,20 +307,20 @@ static void set_ref(struct hantro_ctx *ctx)
b1_reflist = ctx->h264_dec.reflists.b1;
p_reflist = ctx->h264_dec.reflists.p;
- reg = VDPU_REG_PINIT_RLIST_F9(p_reflist[9]) |
- VDPU_REG_PINIT_RLIST_F8(p_reflist[8]) |
- VDPU_REG_PINIT_RLIST_F7(p_reflist[7]) |
- VDPU_REG_PINIT_RLIST_F6(p_reflist[6]) |
- VDPU_REG_PINIT_RLIST_F5(p_reflist[5]) |
- VDPU_REG_PINIT_RLIST_F4(p_reflist[4]);
+ reg = VDPU_REG_PINIT_RLIST_F9(p_reflist[9].index) |
+ VDPU_REG_PINIT_RLIST_F8(p_reflist[8].index) |
+ VDPU_REG_PINIT_RLIST_F7(p_reflist[7].index) |
+ VDPU_REG_PINIT_RLIST_F6(p_reflist[6].index) |
+ VDPU_REG_PINIT_RLIST_F5(p_reflist[5].index) |
+ VDPU_REG_PINIT_RLIST_F4(p_reflist[4].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(74));
- reg = VDPU_REG_PINIT_RLIST_F15(p_reflist[15]) |
- VDPU_REG_PINIT_RLIST_F14(p_reflist[14]) |
- VDPU_REG_PINIT_RLIST_F13(p_reflist[13]) |
- VDPU_REG_PINIT_RLIST_F12(p_reflist[12]) |
- VDPU_REG_PINIT_RLIST_F11(p_reflist[11]) |
- VDPU_REG_PINIT_RLIST_F10(p_reflist[10]);
+ reg = VDPU_REG_PINIT_RLIST_F15(p_reflist[15].index) |
+ VDPU_REG_PINIT_RLIST_F14(p_reflist[14].index) |
+ VDPU_REG_PINIT_RLIST_F13(p_reflist[13].index) |
+ VDPU_REG_PINIT_RLIST_F12(p_reflist[12].index) |
+ VDPU_REG_PINIT_RLIST_F11(p_reflist[11].index) |
+ VDPU_REG_PINIT_RLIST_F10(p_reflist[10].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(75));
reg = VDPU_REG_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, 1)) |
@@ -355,54 +355,54 @@ static void set_ref(struct hantro_ctx *ctx)
VDPU_REG_REFER14_NBR(hantro_h264_get_ref_nbr(ctx, 14));
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(83));
- reg = VDPU_REG_BINIT_RLIST_F5(b0_reflist[5]) |
- VDPU_REG_BINIT_RLIST_F4(b0_reflist[4]) |
- VDPU_REG_BINIT_RLIST_F3(b0_reflist[3]) |
- VDPU_REG_BINIT_RLIST_F2(b0_reflist[2]) |
- VDPU_REG_BINIT_RLIST_F1(b0_reflist[1]) |
- VDPU_REG_BINIT_RLIST_F0(b0_reflist[0]);
+ reg = VDPU_REG_BINIT_RLIST_F5(b0_reflist[5].index) |
+ VDPU_REG_BINIT_RLIST_F4(b0_reflist[4].index) |
+ VDPU_REG_BINIT_RLIST_F3(b0_reflist[3].index) |
+ VDPU_REG_BINIT_RLIST_F2(b0_reflist[2].index) |
+ VDPU_REG_BINIT_RLIST_F1(b0_reflist[1].index) |
+ VDPU_REG_BINIT_RLIST_F0(b0_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(100));
- reg = VDPU_REG_BINIT_RLIST_F11(b0_reflist[11]) |
- VDPU_REG_BINIT_RLIST_F10(b0_reflist[10]) |
- VDPU_REG_BINIT_RLIST_F9(b0_reflist[9]) |
- VDPU_REG_BINIT_RLIST_F8(b0_reflist[8]) |
- VDPU_REG_BINIT_RLIST_F7(b0_reflist[7]) |
- VDPU_REG_BINIT_RLIST_F6(b0_reflist[6]);
+ reg = VDPU_REG_BINIT_RLIST_F11(b0_reflist[11].index) |
+ VDPU_REG_BINIT_RLIST_F10(b0_reflist[10].index) |
+ VDPU_REG_BINIT_RLIST_F9(b0_reflist[9].index) |
+ VDPU_REG_BINIT_RLIST_F8(b0_reflist[8].index) |
+ VDPU_REG_BINIT_RLIST_F7(b0_reflist[7].index) |
+ VDPU_REG_BINIT_RLIST_F6(b0_reflist[6].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(101));
- reg = VDPU_REG_BINIT_RLIST_F15(b0_reflist[15]) |
- VDPU_REG_BINIT_RLIST_F14(b0_reflist[14]) |
- VDPU_REG_BINIT_RLIST_F13(b0_reflist[13]) |
- VDPU_REG_BINIT_RLIST_F12(b0_reflist[12]);
+ reg = VDPU_REG_BINIT_RLIST_F15(b0_reflist[15].index) |
+ VDPU_REG_BINIT_RLIST_F14(b0_reflist[14].index) |
+ VDPU_REG_BINIT_RLIST_F13(b0_reflist[13].index) |
+ VDPU_REG_BINIT_RLIST_F12(b0_reflist[12].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(102));
- reg = VDPU_REG_BINIT_RLIST_B5(b1_reflist[5]) |
- VDPU_REG_BINIT_RLIST_B4(b1_reflist[4]) |
- VDPU_REG_BINIT_RLIST_B3(b1_reflist[3]) |
- VDPU_REG_BINIT_RLIST_B2(b1_reflist[2]) |
- VDPU_REG_BINIT_RLIST_B1(b1_reflist[1]) |
- VDPU_REG_BINIT_RLIST_B0(b1_reflist[0]);
+ reg = VDPU_REG_BINIT_RLIST_B5(b1_reflist[5].index) |
+ VDPU_REG_BINIT_RLIST_B4(b1_reflist[4].index) |
+ VDPU_REG_BINIT_RLIST_B3(b1_reflist[3].index) |
+ VDPU_REG_BINIT_RLIST_B2(b1_reflist[2].index) |
+ VDPU_REG_BINIT_RLIST_B1(b1_reflist[1].index) |
+ VDPU_REG_BINIT_RLIST_B0(b1_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(103));
- reg = VDPU_REG_BINIT_RLIST_B11(b1_reflist[11]) |
- VDPU_REG_BINIT_RLIST_B10(b1_reflist[10]) |
- VDPU_REG_BINIT_RLIST_B9(b1_reflist[9]) |
- VDPU_REG_BINIT_RLIST_B8(b1_reflist[8]) |
- VDPU_REG_BINIT_RLIST_B7(b1_reflist[7]) |
- VDPU_REG_BINIT_RLIST_B6(b1_reflist[6]);
+ reg = VDPU_REG_BINIT_RLIST_B11(b1_reflist[11].index) |
+ VDPU_REG_BINIT_RLIST_B10(b1_reflist[10].index) |
+ VDPU_REG_BINIT_RLIST_B9(b1_reflist[9].index) |
+ VDPU_REG_BINIT_RLIST_B8(b1_reflist[8].index) |
+ VDPU_REG_BINIT_RLIST_B7(b1_reflist[7].index) |
+ VDPU_REG_BINIT_RLIST_B6(b1_reflist[6].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(104));
- reg = VDPU_REG_BINIT_RLIST_B15(b1_reflist[15]) |
- VDPU_REG_BINIT_RLIST_B14(b1_reflist[14]) |
- VDPU_REG_BINIT_RLIST_B13(b1_reflist[13]) |
- VDPU_REG_BINIT_RLIST_B12(b1_reflist[12]);
+ reg = VDPU_REG_BINIT_RLIST_B15(b1_reflist[15].index) |
+ VDPU_REG_BINIT_RLIST_B14(b1_reflist[14].index) |
+ VDPU_REG_BINIT_RLIST_B13(b1_reflist[13].index) |
+ VDPU_REG_BINIT_RLIST_B12(b1_reflist[12].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(105));
- reg = VDPU_REG_PINIT_RLIST_F3(p_reflist[3]) |
- VDPU_REG_PINIT_RLIST_F2(p_reflist[2]) |
- VDPU_REG_PINIT_RLIST_F1(p_reflist[1]) |
- VDPU_REG_PINIT_RLIST_F0(p_reflist[0]);
+ reg = VDPU_REG_PINIT_RLIST_F3(p_reflist[3].index) |
+ VDPU_REG_PINIT_RLIST_F2(p_reflist[2].index) |
+ VDPU_REG_PINIT_RLIST_F1(p_reflist[1].index) |
+ VDPU_REG_PINIT_RLIST_F0(p_reflist[0].index);
vdpu_write_relaxed(vpu, reg, VDPU_SWREG(106));
reg = VDPU_REG_REFER_LTERM_E(ctx->h264_dec.dpb_longterm);
diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
index 4df16f59fb97..8395c4d48dd0 100644
--- a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
+++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c
@@ -35,18 +35,23 @@
static void rockchip_vpu2_set_src_img_ctrl(struct hantro_dev *vpu,
struct hantro_ctx *ctx)
{
- struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
+ u32 overfill_r, overfill_b;
u32 reg;
/*
- * The pix fmt width/height are already macroblock aligned
- * by .vidioc_s_fmt_vid_cap_mplane() callback
+ * The format width and height are already macroblock aligned
+ * by .vidioc_s_fmt_vid_cap_mplane() callback. Destination
+ * format width and height can be further modified by
+ * .vidioc_s_selection(), and the width is 4-aligned.
*/
- reg = VEPU_REG_IN_IMG_CTRL_ROW_LEN(pix_fmt->width);
+ overfill_r = ctx->src_fmt.width - ctx->dst_fmt.width;
+ overfill_b = ctx->src_fmt.height - ctx->dst_fmt.height;
+
+ reg = VEPU_REG_IN_IMG_CTRL_ROW_LEN(ctx->src_fmt.width);
vepu_write_relaxed(vpu, reg, VEPU_REG_INPUT_LUMA_INFO);
- reg = VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(0) |
- VEPU_REG_IN_IMG_CTRL_OVRFLB(0);
+ reg = VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r / 4) |
+ VEPU_REG_IN_IMG_CTRL_OVRFLB(overfill_b);
/*
* This register controls the input crop, as the offset
* from the right/bottom within the last macroblock. The offset from the
@@ -61,17 +66,23 @@ static void rockchip_vpu2_set_src_img_ctrl(struct hantro_dev *vpu,
static void rockchip_vpu2_jpeg_enc_set_buffers(struct hantro_dev *vpu,
struct hantro_ctx *ctx,
- struct vb2_buffer *src_buf)
+ struct vb2_buffer *src_buf,
+ struct vb2_buffer *dst_buf)
{
struct v4l2_pix_format_mplane *pix_fmt = &ctx->src_fmt;
dma_addr_t src[3];
+ u32 size_left;
+
+ size_left = vb2_plane_size(dst_buf, 0) - ctx->vpu_dst_fmt->header_size;
+ if (WARN_ON(vb2_plane_size(dst_buf, 0) < ctx->vpu_dst_fmt->header_size))
+ size_left = 0;
WARN_ON(pix_fmt->num_planes > 3);
- vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.dma,
+ vepu_write_relaxed(vpu, vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
+ ctx->vpu_dst_fmt->header_size,
VEPU_REG_ADDR_OUTPUT_STREAM);
- vepu_write_relaxed(vpu, ctx->jpeg_enc.bounce_buffer.size,
- VEPU_REG_STR_BUF_LIMIT);
+ vepu_write_relaxed(vpu, size_left, VEPU_REG_STR_BUF_LIMIT);
if (pix_fmt->num_planes == 1) {
src[0] = vb2_dma_contig_plane_dma_addr(src_buf, 0);
@@ -132,6 +143,9 @@ int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx)
memset(&jpeg_ctx, 0, sizeof(jpeg_ctx));
jpeg_ctx.buffer = vb2_plane_vaddr(&dst_buf->vb2_buf, 0);
+ if (!jpeg_ctx.buffer)
+ return -ENOMEM;
+
jpeg_ctx.width = ctx->dst_fmt.width;
jpeg_ctx.height = ctx->dst_fmt.height;
jpeg_ctx.quality = ctx->jpeg_quality;
@@ -142,7 +156,8 @@ int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx)
VEPU_REG_ENCODE_START);
rockchip_vpu2_set_src_img_ctrl(vpu, ctx);
- rockchip_vpu2_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf);
+ rockchip_vpu2_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf,
+ &dst_buf->vb2_buf);
rockchip_vpu2_jpeg_enc_set_qtable(vpu, jpeg_ctx.hw_luma_qtable,
jpeg_ctx.hw_chroma_qtable);
@@ -177,13 +192,6 @@ void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx)
u32 bytesused = vepu_read(vpu, VEPU_REG_STR_BUF_LIMIT) / 8;
struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx);
- /*
- * TODO: Rework the JPEG encoder to eliminate the need
- * for a bounce buffer.
- */
- memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) +
- ctx->vpu_dst_fmt->header_size,
- ctx->jpeg_enc.bounce_buffer.cpu, bytesused);
vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
ctx->vpu_dst_fmt->header_size + bytesused);
}
diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c
index c203b606e6e7..fc96501f3bc8 100644
--- a/drivers/staging/media/hantro/rockchip_vpu_hw.c
+++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c
@@ -343,9 +343,7 @@ static const struct hantro_codec_ops rk3066_vpu_codec_ops[] = {
[HANTRO_MODE_JPEG_ENC] = {
.run = hantro_h1_jpeg_enc_run,
.reset = rockchip_vpu1_enc_reset,
- .init = hantro_jpeg_enc_init,
.done = hantro_h1_jpeg_enc_done,
- .exit = hantro_jpeg_enc_exit,
},
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
@@ -371,9 +369,7 @@ static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = {
[HANTRO_MODE_JPEG_ENC] = {
.run = hantro_h1_jpeg_enc_run,
.reset = rockchip_vpu1_enc_reset,
- .init = hantro_jpeg_enc_init,
.done = hantro_h1_jpeg_enc_done,
- .exit = hantro_jpeg_enc_exit,
},
[HANTRO_MODE_H264_DEC] = {
.run = hantro_g1_h264_dec_run,
@@ -399,9 +395,7 @@ static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = {
[HANTRO_MODE_JPEG_ENC] = {
.run = rockchip_vpu2_jpeg_enc_run,
.reset = rockchip_vpu2_enc_reset,
- .init = hantro_jpeg_enc_init,
.done = rockchip_vpu2_jpeg_enc_done,
- .exit = hantro_jpeg_enc_exit,
},
[HANTRO_MODE_H264_DEC] = {
.run = rockchip_vpu2_h264_dec_run,
@@ -551,6 +545,20 @@ const struct hantro_variant rk3399_vpu_variant = {
.num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
};
+const struct hantro_variant rk3568_vpu_variant = {
+ .dec_offset = 0x400,
+ .dec_fmts = rk3399_vpu_dec_fmts,
+ .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts),
+ .codec = HANTRO_MPEG2_DECODER |
+ HANTRO_VP8_DECODER | HANTRO_H264_DECODER,
+ .codec_ops = rk3399_vpu_codec_ops,
+ .irqs = rockchip_vdpu2_irqs,
+ .num_irqs = ARRAY_SIZE(rockchip_vdpu2_irqs),
+ .init = rockchip_vpu_hw_init,
+ .clk_names = rockchip_vpu_clk_names,
+ .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names)
+};
+
const struct hantro_variant px30_vpu_variant = {
.enc_offset = 0x0,
.enc_fmts = rockchip_vpu_enc_fmts,
diff --git a/drivers/staging/media/hantro/sunxi_vpu_hw.c b/drivers/staging/media/hantro/sunxi_vpu_hw.c
index 90633406c4eb..c0edd5856a0c 100644
--- a/drivers/staging/media/hantro/sunxi_vpu_hw.c
+++ b/drivers/staging/media/hantro/sunxi_vpu_hw.c
@@ -29,10 +29,10 @@ static const struct hantro_fmt sunxi_vpu_dec_fmts[] = {
.frmsize = {
.min_width = 48,
.max_width = 3840,
- .step_width = MB_DIM,
+ .step_width = 32,
.min_height = 48,
.max_height = 2160,
- .step_height = MB_DIM,
+ .step_height = 32,
},
},
};
diff --git a/drivers/staging/media/imx/Kconfig b/drivers/staging/media/imx/Kconfig
index c3bf433ba3e3..0bacac302d7e 100644
--- a/drivers/staging/media/imx/Kconfig
+++ b/drivers/staging/media/imx/Kconfig
@@ -4,7 +4,7 @@ config VIDEO_IMX_MEDIA
depends on ARCH_MXC || COMPILE_TEST
depends on HAS_DMA
depends on VIDEO_DEV
- depends on VIDEO_V4L2
+ depends on VIDEO_DEV
select MEDIA_CONTROLLER
select V4L2_FWNODE
select V4L2_MEM2MEM_DEV
diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile
index 19c2fc54d424..d82be898145b 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -15,5 +15,4 @@ obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media-csi.o
obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
-obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-mipi-csis.o
obj-$(CONFIG_VIDEO_IMX7_CSI) += imx8mq-mipi-csi2.o
diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO
index 06c94f20ecf8..5d3a337c8702 100644
--- a/drivers/staging/media/imx/TODO
+++ b/drivers/staging/media/imx/TODO
@@ -27,3 +27,28 @@
- i.MX7: all of the above, since it uses the imx media core
- i.MX7: use Frame Interval Monitor
+
+- imx7-media-csi: Restrict the supported formats list to the SoC version.
+
+ The imx7 CSI bridge can be configured to sample pixel components from the Rx
+ queue in single (8bpp) or double (16bpp) component modes. Image format
+ variants with different sample sizes (ie YUYV_2X8 vs YUYV_1X16) determine the
+ pixel components sampling size per each clock cycle and their packing mode
+ (see imx7_csi_configure() for details).
+
+ As the imx7 CSI bridge can be interfaced with different IP blocks depending on
+ the SoC model it is integrated on, the Rx queue sampling size should match
+ the size of the samples transferred by the transmitting IP block.
+
+ To avoid mis-configurations of the capture pipeline, the enumeration of the
+ supported formats should be restricted to match the pixel source transmitting
+ mode.
+
+ Example: i.MX8MM SoC integrates the CSI bridge with the Samsung CSIS CSI-2
+ receiver which operates in dual pixel sampling mode. The CSI bridge should
+ only expose the 1X16 formats variant which instructs it to operate in dual
+ pixel sampling mode. When the CSI bridge is instead integrated on an i.MX7,
+ which supports both serial and parallel input, it should expose both variants.
+
+ This currently only applies to YUYV formats, but other formats might need
+ to be handled in the same way.
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index bd7f156f2d52..b2b1f4dd41d7 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -718,9 +718,10 @@ static int csi_setup(struct csi_priv *priv)
/* compose mbus_config from the upstream endpoint */
mbus_cfg.type = priv->upstream_ep.bus_type;
- mbus_cfg.flags = is_parallel_bus(&priv->upstream_ep) ?
- priv->upstream_ep.bus.parallel.flags :
- priv->upstream_ep.bus.mipi_csi2.flags;
+ if (is_parallel_bus(&priv->upstream_ep))
+ mbus_cfg.bus.parallel = priv->upstream_ep.bus.parallel;
+ else
+ mbus_cfg.bus.mipi_csi2 = priv->upstream_ep.bus.mipi_csi2;
if_fmt = *infmt;
crop = priv->crop;
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 558b256ac935..c4cb558a85c6 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -303,7 +303,6 @@ static void csi2ipu_gasket_init(struct csi2_dev *csi2)
static int csi2_get_active_lanes(struct csi2_dev *csi2, unsigned int *lanes)
{
struct v4l2_mbus_config mbus_config = { 0 };
- unsigned int num_lanes = UINT_MAX;
int ret;
*lanes = csi2->data_lanes;
@@ -326,32 +325,14 @@ static int csi2_get_active_lanes(struct csi2_dev *csi2, unsigned int *lanes)
return -EINVAL;
}
- switch (mbus_config.flags & V4L2_MBUS_CSI2_LANES) {
- case V4L2_MBUS_CSI2_1_LANE:
- num_lanes = 1;
- break;
- case V4L2_MBUS_CSI2_2_LANE:
- num_lanes = 2;
- break;
- case V4L2_MBUS_CSI2_3_LANE:
- num_lanes = 3;
- break;
- case V4L2_MBUS_CSI2_4_LANE:
- num_lanes = 4;
- break;
- default:
- num_lanes = csi2->data_lanes;
- break;
- }
-
- if (num_lanes > csi2->data_lanes) {
+ if (mbus_config.bus.mipi_csi2.num_data_lanes > csi2->data_lanes) {
dev_err(csi2->dev,
"Unsupported mbus config: too many data lanes %u\n",
- num_lanes);
+ mbus_config.bus.mipi_csi2.num_data_lanes);
return -EINVAL;
}
- *lanes = num_lanes;
+ *lanes = mbus_config.bus.mipi_csi2.num_data_lanes;
return 0;
}
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
index 2288dadb2683..8467a1491048 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
@@ -122,6 +123,10 @@
#define BIT_DATA_FROM_MIPI BIT(22)
#define BIT_MIPI_YU_SWAP BIT(21)
#define BIT_MIPI_DOUBLE_CMPNT BIT(20)
+#define BIT_MASK_OPTION_FIRST_FRAME (0 << 18)
+#define BIT_MASK_OPTION_CSI_EN (1 << 18)
+#define BIT_MASK_OPTION_SECOND_FRAME (2 << 18)
+#define BIT_MASK_OPTION_ON_DATA (3 << 18)
#define BIT_BASEADDR_CHG_ERR_EN BIT(9)
#define BIT_BASEADDR_SWITCH_SEL BIT(5)
#define BIT_BASEADDR_SWITCH_EN BIT(4)
@@ -154,6 +159,11 @@
#define CSI_CSICR18 0x48
#define CSI_CSICR19 0x4c
+enum imx_csi_model {
+ IMX7_CSI_IMX7 = 0,
+ IMX7_CSI_IMX8MQ,
+};
+
struct imx7_csi {
struct device *dev;
struct v4l2_subdev sd;
@@ -189,6 +199,8 @@ struct imx7_csi {
bool is_csi2;
struct completion last_eof_completion;
+
+ enum imx_csi_model model;
};
static struct imx7_csi *
@@ -486,16 +498,40 @@ static void imx7_csi_configure(struct imx7_csi *csi)
cr3 |= BIT_TWO_8BIT_SENSOR;
cr18 |= BIT_MIPI_DATA_FORMAT_RAW14;
break;
+
/*
- * CSI-2 sources are supposed to use the 1X16 formats, but not
- * all of them comply. Support both variants.
+ * The CSI bridge has a 16-bit input bus. Depending on the
+ * connected source, data may be transmitted with 8 or 10 bits
+ * per clock sample (in bits [9:2] or [9:0] respectively) or
+ * with 16 bits per clock sample (in bits [15:0]). The data is
+ * then packed into a 32-bit FIFO (as shown in figure 13-11 of
+ * the i.MX8MM reference manual rev. 3).
+ *
+ * The data packing in a 32-bit FIFO input word is controlled by
+ * the CR3 TWO_8BIT_SENSOR field (also known as SENSOR_16BITS in
+ * the i.MX8MM reference manual). When set to 0, data packing
+ * groups four 8-bit input samples (bits [9:2]). When set to 1,
+ * data packing groups two 16-bit input samples (bits [15:0]).
+ *
+ * The register field CR18 MIPI_DOUBLE_CMPNT also needs to be
+ * configured according to the input format for YUV 4:2:2 data.
+ * The field controls the gasket between the CSI-2 receiver and
+ * the CSI bridge. On i.MX7 and i.MX8MM, the field must be set
+ * to 1 when the CSIS outputs 16-bit samples. On i.MX8MQ, the
+ * gasket ignores the MIPI_DOUBLE_CMPNT bit and YUV 4:2:2 always
+ * uses 16-bit samples. Setting MIPI_DOUBLE_CMPNT in that case
+ * has no effect, but doesn't cause any issue.
*/
case MEDIA_BUS_FMT_UYVY8_2X8:
- case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YUYV8_1X16:
cr18 |= BIT_MIPI_DATA_FORMAT_YUV422_8B;
break;
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ case MEDIA_BUS_FMT_YUYV8_1X16:
+ cr3 |= BIT_TWO_8BIT_SENSOR;
+ cr18 |= BIT_MIPI_DATA_FORMAT_YUV422_8B |
+ BIT_MIPI_DOUBLE_CMPNT;
+ break;
}
}
@@ -537,6 +573,16 @@ static void imx7_csi_deinit(struct imx7_csi *csi,
clk_disable_unprepare(csi->mclk);
}
+static void imx7_csi_baseaddr_switch_on_second_frame(struct imx7_csi *csi)
+{
+ u32 cr18 = imx7_csi_reg_read(csi, CSI_CSICR18);
+
+ cr18 |= BIT_BASEADDR_SWITCH_EN | BIT_BASEADDR_SWITCH_SEL |
+ BIT_BASEADDR_CHG_ERR_EN;
+ cr18 |= BIT_MASK_OPTION_SECOND_FRAME;
+ imx7_csi_reg_write(csi, cr18, CSI_CSICR18);
+}
+
static void imx7_csi_enable(struct imx7_csi *csi)
{
/* Clear the Rx FIFO and reflash the DMA controller. */
@@ -552,6 +598,9 @@ static void imx7_csi_enable(struct imx7_csi *csi)
/* Enable the RxFIFO DMA and the CSI. */
imx7_csi_dmareq_rff_enable(csi);
imx7_csi_hw_enable(csi);
+
+ if (csi->model == IMX7_CSI_IMX8MQ)
+ imx7_csi_baseaddr_switch_on_second_frame(csi);
}
static void imx7_csi_disable(struct imx7_csi *csi)
@@ -1155,6 +1204,8 @@ static int imx7_csi_probe(struct platform_device *pdev)
if (IS_ERR(csi->regbase))
return PTR_ERR(csi->regbase);
+ csi->model = (enum imx_csi_model)(uintptr_t)of_device_get_match_data(&pdev->dev);
+
spin_lock_init(&csi->irqlock);
mutex_init(&csi->lock);
@@ -1249,8 +1300,9 @@ static int imx7_csi_remove(struct platform_device *pdev)
}
static const struct of_device_id imx7_csi_of_match[] = {
- { .compatible = "fsl,imx7-csi" },
- { .compatible = "fsl,imx6ul-csi" },
+ { .compatible = "fsl,imx8mq-csi", .data = (void *)IMX7_CSI_IMX8MQ },
+ { .compatible = "fsl,imx7-csi", .data = (void *)IMX7_CSI_IMX7 },
+ { .compatible = "fsl,imx6ul-csi", .data = (void *)IMX7_CSI_IMX7 },
{ },
};
MODULE_DEVICE_TABLE(of, imx7_csi_of_match);
diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
deleted file mode 100644
index 2b73fa55c938..000000000000
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ /dev/null
@@ -1,1494 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Freescale i.MX7 SoC series MIPI-CSI V3.3 receiver driver
- *
- * Copyright (C) 2019 Linaro Ltd
- * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
- *
- */
-
-#include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/spinlock.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fwnode.h>
-#include <media/v4l2-mc.h>
-#include <media/v4l2-subdev.h>
-
-#define CSIS_DRIVER_NAME "imx7-mipi-csis"
-#define CSIS_SUBDEV_NAME CSIS_DRIVER_NAME
-
-#define CSIS_PAD_SINK 0
-#define CSIS_PAD_SOURCE 1
-#define CSIS_PADS_NUM 2
-
-#define MIPI_CSIS_DEF_PIX_WIDTH 640
-#define MIPI_CSIS_DEF_PIX_HEIGHT 480
-
-/* Register map definition */
-
-/* CSIS common control */
-#define MIPI_CSIS_CMN_CTRL 0x04
-#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW BIT(16)
-#define MIPI_CSIS_CMN_CTRL_INTER_MODE BIT(10)
-#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL BIT(2)
-#define MIPI_CSIS_CMN_CTRL_RESET BIT(1)
-#define MIPI_CSIS_CMN_CTRL_ENABLE BIT(0)
-
-#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET 8
-#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK (3 << 8)
-
-/* CSIS clock control */
-#define MIPI_CSIS_CLK_CTRL 0x08
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x) ((x) << 28)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x) ((x) << 24)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x) ((x) << 20)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x) ((x) << 16)
-#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK (0xf << 4)
-#define MIPI_CSIS_CLK_CTRL_WCLK_SRC BIT(0)
-
-/* CSIS Interrupt mask */
-#define MIPI_CSIS_INT_MSK 0x10
-#define MIPI_CSIS_INT_MSK_EVEN_BEFORE BIT(31)
-#define MIPI_CSIS_INT_MSK_EVEN_AFTER BIT(30)
-#define MIPI_CSIS_INT_MSK_ODD_BEFORE BIT(29)
-#define MIPI_CSIS_INT_MSK_ODD_AFTER BIT(28)
-#define MIPI_CSIS_INT_MSK_FRAME_START BIT(24)
-#define MIPI_CSIS_INT_MSK_FRAME_END BIT(20)
-#define MIPI_CSIS_INT_MSK_ERR_SOT_HS BIT(16)
-#define MIPI_CSIS_INT_MSK_ERR_LOST_FS BIT(12)
-#define MIPI_CSIS_INT_MSK_ERR_LOST_FE BIT(8)
-#define MIPI_CSIS_INT_MSK_ERR_OVER BIT(4)
-#define MIPI_CSIS_INT_MSK_ERR_WRONG_CFG BIT(3)
-#define MIPI_CSIS_INT_MSK_ERR_ECC BIT(2)
-#define MIPI_CSIS_INT_MSK_ERR_CRC BIT(1)
-#define MIPI_CSIS_INT_MSK_ERR_UNKNOWN BIT(0)
-
-/* CSIS Interrupt source */
-#define MIPI_CSIS_INT_SRC 0x14
-#define MIPI_CSIS_INT_SRC_EVEN_BEFORE BIT(31)
-#define MIPI_CSIS_INT_SRC_EVEN_AFTER BIT(30)
-#define MIPI_CSIS_INT_SRC_EVEN BIT(30)
-#define MIPI_CSIS_INT_SRC_ODD_BEFORE BIT(29)
-#define MIPI_CSIS_INT_SRC_ODD_AFTER BIT(28)
-#define MIPI_CSIS_INT_SRC_ODD (0x3 << 28)
-#define MIPI_CSIS_INT_SRC_NON_IMAGE_DATA (0xf << 28)
-#define MIPI_CSIS_INT_SRC_FRAME_START BIT(24)
-#define MIPI_CSIS_INT_SRC_FRAME_END BIT(20)
-#define MIPI_CSIS_INT_SRC_ERR_SOT_HS BIT(16)
-#define MIPI_CSIS_INT_SRC_ERR_LOST_FS BIT(12)
-#define MIPI_CSIS_INT_SRC_ERR_LOST_FE BIT(8)
-#define MIPI_CSIS_INT_SRC_ERR_OVER BIT(4)
-#define MIPI_CSIS_INT_SRC_ERR_WRONG_CFG BIT(3)
-#define MIPI_CSIS_INT_SRC_ERR_ECC BIT(2)
-#define MIPI_CSIS_INT_SRC_ERR_CRC BIT(1)
-#define MIPI_CSIS_INT_SRC_ERR_UNKNOWN BIT(0)
-#define MIPI_CSIS_INT_SRC_ERRORS 0xfffff
-
-/* D-PHY status control */
-#define MIPI_CSIS_DPHY_STATUS 0x20
-#define MIPI_CSIS_DPHY_STATUS_ULPS_DAT BIT(8)
-#define MIPI_CSIS_DPHY_STATUS_STOPSTATE_DAT BIT(4)
-#define MIPI_CSIS_DPHY_STATUS_ULPS_CLK BIT(1)
-#define MIPI_CSIS_DPHY_STATUS_STOPSTATE_CLK BIT(0)
-
-/* D-PHY common control */
-#define MIPI_CSIS_DPHY_CMN_CTRL 0x24
-#define MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(n) ((n) << 24)
-#define MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE_MASK GENMASK(31, 24)
-#define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(n) ((n) << 22)
-#define MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE_MASK GENMASK(23, 22)
-#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_CLK BIT(6)
-#define MIPI_CSIS_DPHY_CMN_CTRL_DPDN_SWAP_DAT BIT(5)
-#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_DAT BIT(1)
-#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE_CLK BIT(0)
-#define MIPI_CSIS_DPHY_CMN_CTRL_ENABLE (0x1f << 0)
-
-/* D-PHY Master and Slave Control register Low */
-#define MIPI_CSIS_DPHY_BCTRL_L 0x30
-#define MIPI_CSIS_DPHY_BCTRL_L_USER_DATA_PATTERN_LOW(n) (((n) & 3U) << 30)
-#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_715MV (0 << 28)
-#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_724MV (1 << 28)
-#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_733MV (2 << 28)
-#define MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_706MV (3 << 28)
-#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_3MHZ (0 << 27)
-#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_1_5MHZ (1 << 27)
-#define MIPI_CSIS_DPHY_BCTRL_L_VREG12_EXTPWR_EN_CTL BIT(26)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_2V (0 << 24)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_23V (1 << 24)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_17V (2 << 24)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_26V (3 << 24)
-#define MIPI_CSIS_DPHY_BCTRL_L_REG_1P2_LVL_SEL BIT(23)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_80MV (0 << 21)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_100MV (1 << 21)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_120MV (2 << 21)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_140MV (3 << 21)
-#define MIPI_CSIS_DPHY_BCTRL_L_VREF_SRC_SEL BIT(20)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_715MV (0 << 18)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_743MV (1 << 18)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_650MV (2 << 18)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_682MV (3 << 18)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_RX_PULSE_REJECT BIT(17)
-#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_0 (0 << 15)
-#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_15P (1 << 15)
-#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_DOWN_30P (3 << 15)
-#define MIPI_CSIS_DPHY_BCTRL_L_MSTRCLK_LP_SLEW_RATE_UP BIT(14)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_60MV (0 << 13)
-#define MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_70MV (1 << 13)
-#define MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_EN BIT(12)
-#define MIPI_CSIS_DPHY_BCTRL_L_ERRCONTENTION_LP_EN BIT(11)
-#define MIPI_CSIS_DPHY_BCTRL_L_TXTRIGGER_CLK_EN BIT(10)
-#define MIPI_CSIS_DPHY_BCTRL_L_B_DPHYCTRL(n) (((n) * 25 / 1000000) << 0)
-
-/* D-PHY Master and Slave Control register High */
-#define MIPI_CSIS_DPHY_BCTRL_H 0x34
-/* D-PHY Slave Control register Low */
-#define MIPI_CSIS_DPHY_SCTRL_L 0x38
-/* D-PHY Slave Control register High */
-#define MIPI_CSIS_DPHY_SCTRL_H 0x3c
-
-/* ISP Configuration register */
-#define MIPI_CSIS_ISP_CONFIG_CH(n) (0x40 + (n) * 0x10)
-#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK (0xff << 24)
-#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x) ((x) << 24)
-#define MIPI_CSIS_ISPCFG_PIXEL_MODE_SINGLE (0 << 12)
-#define MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL (1 << 12)
-#define MIPI_CSIS_ISPCFG_PIXEL_MODE_QUAD (2 << 12) /* i.MX8M[MNP] only */
-#define MIPI_CSIS_ISPCFG_ALIGN_32BIT BIT(11)
-#define MIPI_CSIS_ISPCFG_FMT(fmt) ((fmt) << 2)
-#define MIPI_CSIS_ISPCFG_FMT_MASK (0x3f << 2)
-
-/* ISP Image Resolution register */
-#define MIPI_CSIS_ISP_RESOL_CH(n) (0x44 + (n) * 0x10)
-#define CSIS_MAX_PIX_WIDTH 0xffff
-#define CSIS_MAX_PIX_HEIGHT 0xffff
-
-/* ISP SYNC register */
-#define MIPI_CSIS_ISP_SYNC_CH(n) (0x48 + (n) * 0x10)
-#define MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET 18
-#define MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET 12
-#define MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET 0
-
-/* ISP shadow registers */
-#define MIPI_CSIS_SDW_CONFIG_CH(n) (0x80 + (n) * 0x10)
-#define MIPI_CSIS_SDW_RESOL_CH(n) (0x84 + (n) * 0x10)
-#define MIPI_CSIS_SDW_SYNC_CH(n) (0x88 + (n) * 0x10)
-
-/* Debug control register */
-#define MIPI_CSIS_DBG_CTRL 0xc0
-#define MIPI_CSIS_DBG_INTR_MSK 0xc4
-#define MIPI_CSIS_DBG_INTR_MSK_DT_NOT_SUPPORT BIT(25)
-#define MIPI_CSIS_DBG_INTR_MSK_DT_IGNORE BIT(24)
-#define MIPI_CSIS_DBG_INTR_MSK_ERR_FRAME_SIZE BIT(20)
-#define MIPI_CSIS_DBG_INTR_MSK_TRUNCATED_FRAME BIT(16)
-#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FE BIT(12)
-#define MIPI_CSIS_DBG_INTR_MSK_EARLY_FS BIT(8)
-#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_FALL BIT(4)
-#define MIPI_CSIS_DBG_INTR_MSK_CAM_VSYNC_RISE BIT(0)
-#define MIPI_CSIS_DBG_INTR_SRC 0xc8
-#define MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT BIT(25)
-#define MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE BIT(24)
-#define MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE BIT(20)
-#define MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME BIT(16)
-#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FE BIT(12)
-#define MIPI_CSIS_DBG_INTR_SRC_EARLY_FS BIT(8)
-#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL BIT(4)
-#define MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE BIT(0)
-
-/* Non-image packet data buffers */
-#define MIPI_CSIS_PKTDATA_ODD 0x2000
-#define MIPI_CSIS_PKTDATA_EVEN 0x3000
-#define MIPI_CSIS_PKTDATA_SIZE SZ_4K
-
-#define DEFAULT_SCLK_CSIS_FREQ 166000000UL
-
-/* MIPI CSI-2 Data Types */
-#define MIPI_CSI2_DATA_TYPE_YUV420_8 0x18
-#define MIPI_CSI2_DATA_TYPE_YUV420_10 0x19
-#define MIPI_CSI2_DATA_TYPE_LE_YUV420_8 0x1a
-#define MIPI_CSI2_DATA_TYPE_CS_YUV420_8 0x1c
-#define MIPI_CSI2_DATA_TYPE_CS_YUV420_10 0x1d
-#define MIPI_CSI2_DATA_TYPE_YUV422_8 0x1e
-#define MIPI_CSI2_DATA_TYPE_YUV422_10 0x1f
-#define MIPI_CSI2_DATA_TYPE_RGB565 0x22
-#define MIPI_CSI2_DATA_TYPE_RGB666 0x23
-#define MIPI_CSI2_DATA_TYPE_RGB888 0x24
-#define MIPI_CSI2_DATA_TYPE_RAW6 0x28
-#define MIPI_CSI2_DATA_TYPE_RAW7 0x29
-#define MIPI_CSI2_DATA_TYPE_RAW8 0x2a
-#define MIPI_CSI2_DATA_TYPE_RAW10 0x2b
-#define MIPI_CSI2_DATA_TYPE_RAW12 0x2c
-#define MIPI_CSI2_DATA_TYPE_RAW14 0x2d
-#define MIPI_CSI2_DATA_TYPE_USER(x) (0x30 + (x))
-
-enum {
- ST_POWERED = 1,
- ST_STREAMING = 2,
- ST_SUSPENDED = 4,
-};
-
-struct mipi_csis_event {
- bool debug;
- u32 mask;
- const char * const name;
- unsigned int counter;
-};
-
-static const struct mipi_csis_event mipi_csis_events[] = {
- /* Errors */
- { false, MIPI_CSIS_INT_SRC_ERR_SOT_HS, "SOT Error" },
- { false, MIPI_CSIS_INT_SRC_ERR_LOST_FS, "Lost Frame Start Error" },
- { false, MIPI_CSIS_INT_SRC_ERR_LOST_FE, "Lost Frame End Error" },
- { false, MIPI_CSIS_INT_SRC_ERR_OVER, "FIFO Overflow Error" },
- { false, MIPI_CSIS_INT_SRC_ERR_WRONG_CFG, "Wrong Configuration Error" },
- { false, MIPI_CSIS_INT_SRC_ERR_ECC, "ECC Error" },
- { false, MIPI_CSIS_INT_SRC_ERR_CRC, "CRC Error" },
- { false, MIPI_CSIS_INT_SRC_ERR_UNKNOWN, "Unknown Error" },
- { true, MIPI_CSIS_DBG_INTR_SRC_DT_NOT_SUPPORT, "Data Type Not Supported" },
- { true, MIPI_CSIS_DBG_INTR_SRC_DT_IGNORE, "Data Type Ignored" },
- { true, MIPI_CSIS_DBG_INTR_SRC_ERR_FRAME_SIZE, "Frame Size Error" },
- { true, MIPI_CSIS_DBG_INTR_SRC_TRUNCATED_FRAME, "Truncated Frame" },
- { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FE, "Early Frame End" },
- { true, MIPI_CSIS_DBG_INTR_SRC_EARLY_FS, "Early Frame Start" },
- /* Non-image data receive events */
- { false, MIPI_CSIS_INT_SRC_EVEN_BEFORE, "Non-image data before even frame" },
- { false, MIPI_CSIS_INT_SRC_EVEN_AFTER, "Non-image data after even frame" },
- { false, MIPI_CSIS_INT_SRC_ODD_BEFORE, "Non-image data before odd frame" },
- { false, MIPI_CSIS_INT_SRC_ODD_AFTER, "Non-image data after odd frame" },
- /* Frame start/end */
- { false, MIPI_CSIS_INT_SRC_FRAME_START, "Frame Start" },
- { false, MIPI_CSIS_INT_SRC_FRAME_END, "Frame End" },
- { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_FALL, "VSYNC Falling Edge" },
- { true, MIPI_CSIS_DBG_INTR_SRC_CAM_VSYNC_RISE, "VSYNC Rising Edge" },
-};
-
-#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events)
-
-enum mipi_csis_clk {
- MIPI_CSIS_CLK_PCLK,
- MIPI_CSIS_CLK_WRAP,
- MIPI_CSIS_CLK_PHY,
- MIPI_CSIS_CLK_AXI,
-};
-
-static const char * const mipi_csis_clk_id[] = {
- "pclk",
- "wrap",
- "phy",
- "axi",
-};
-
-enum mipi_csis_version {
- MIPI_CSIS_V3_3,
- MIPI_CSIS_V3_6_3,
-};
-
-struct mipi_csis_info {
- enum mipi_csis_version version;
- unsigned int num_clocks;
-};
-
-struct csi_state {
- struct device *dev;
- void __iomem *regs;
- struct clk_bulk_data *clks;
- struct reset_control *mrst;
- struct regulator *mipi_phy_regulator;
- const struct mipi_csis_info *info;
- u8 index;
-
- struct v4l2_subdev sd;
- struct media_pad pads[CSIS_PADS_NUM];
- struct v4l2_async_notifier notifier;
- struct v4l2_subdev *src_sd;
-
- struct v4l2_fwnode_bus_mipi_csi2 bus;
- u32 clk_frequency;
- u32 hs_settle;
- u32 clk_settle;
-
- struct mutex lock; /* Protect csis_fmt, format_mbus and state */
- const struct csis_pix_format *csis_fmt;
- struct v4l2_mbus_framefmt format_mbus;
- u32 state;
-
- spinlock_t slock; /* Protect events */
- struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
- struct dentry *debugfs_root;
- bool debug;
-};
-
-/* -----------------------------------------------------------------------------
- * Format helpers
- */
-
-struct csis_pix_format {
- u32 code;
- u32 data_type;
- u8 width;
-};
-
-static const struct csis_pix_format mipi_csis_formats[] = {
- /* YUV formats. */
- {
- .code = MEDIA_BUS_FMT_UYVY8_1X16,
- .data_type = MIPI_CSI2_DATA_TYPE_YUV422_8,
- .width = 16,
- },
- /* RAW (Bayer and greyscale) formats. */
- {
- .code = MEDIA_BUS_FMT_SBGGR8_1X8,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
- .width = 8,
- }, {
- .code = MEDIA_BUS_FMT_SGBRG8_1X8,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
- .width = 8,
- }, {
- .code = MEDIA_BUS_FMT_SGRBG8_1X8,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
- .width = 8,
- }, {
- .code = MEDIA_BUS_FMT_SRGGB8_1X8,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
- .width = 8,
- }, {
- .code = MEDIA_BUS_FMT_Y8_1X8,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW8,
- .width = 8,
- }, {
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
- .width = 10,
- }, {
- .code = MEDIA_BUS_FMT_SGBRG10_1X10,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
- .width = 10,
- }, {
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
- .width = 10,
- }, {
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
- .width = 10,
- }, {
- .code = MEDIA_BUS_FMT_Y10_1X10,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW10,
- .width = 10,
- }, {
- .code = MEDIA_BUS_FMT_SBGGR12_1X12,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
- .width = 12,
- }, {
- .code = MEDIA_BUS_FMT_SGBRG12_1X12,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
- .width = 12,
- }, {
- .code = MEDIA_BUS_FMT_SGRBG12_1X12,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
- .width = 12,
- }, {
- .code = MEDIA_BUS_FMT_SRGGB12_1X12,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
- .width = 12,
- }, {
- .code = MEDIA_BUS_FMT_Y12_1X12,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW12,
- .width = 12,
- }, {
- .code = MEDIA_BUS_FMT_SBGGR14_1X14,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
- .width = 14,
- }, {
- .code = MEDIA_BUS_FMT_SGBRG14_1X14,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
- .width = 14,
- }, {
- .code = MEDIA_BUS_FMT_SGRBG14_1X14,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
- .width = 14,
- }, {
- .code = MEDIA_BUS_FMT_SRGGB14_1X14,
- .data_type = MIPI_CSI2_DATA_TYPE_RAW14,
- .width = 14,
- }
-};
-
-static const struct csis_pix_format *find_csis_format(u32 code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++)
- if (code == mipi_csis_formats[i].code)
- return &mipi_csis_formats[i];
- return NULL;
-}
-
-/* -----------------------------------------------------------------------------
- * Hardware configuration
- */
-
-static inline u32 mipi_csis_read(struct csi_state *state, u32 reg)
-{
- return readl(state->regs + reg);
-}
-
-static inline void mipi_csis_write(struct csi_state *state, u32 reg, u32 val)
-{
- writel(val, state->regs + reg);
-}
-
-static void mipi_csis_enable_interrupts(struct csi_state *state, bool on)
-{
- mipi_csis_write(state, MIPI_CSIS_INT_MSK, on ? 0xffffffff : 0);
- mipi_csis_write(state, MIPI_CSIS_DBG_INTR_MSK, on ? 0xffffffff : 0);
-}
-
-static void mipi_csis_sw_reset(struct csi_state *state)
-{
- u32 val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
-
- mipi_csis_write(state, MIPI_CSIS_CMN_CTRL,
- val | MIPI_CSIS_CMN_CTRL_RESET);
- usleep_range(10, 20);
-}
-
-static void mipi_csis_system_enable(struct csi_state *state, int on)
-{
- u32 val, mask;
-
- val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
- if (on)
- val |= MIPI_CSIS_CMN_CTRL_ENABLE;
- else
- val &= ~MIPI_CSIS_CMN_CTRL_ENABLE;
- mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
-
- val = mipi_csis_read(state, MIPI_CSIS_DPHY_CMN_CTRL);
- val &= ~MIPI_CSIS_DPHY_CMN_CTRL_ENABLE;
- if (on) {
- mask = (1 << (state->bus.num_data_lanes + 1)) - 1;
- val |= (mask & MIPI_CSIS_DPHY_CMN_CTRL_ENABLE);
- }
- mipi_csis_write(state, MIPI_CSIS_DPHY_CMN_CTRL, val);
-}
-
-/* Called with the state.lock mutex held */
-static void __mipi_csis_set_format(struct csi_state *state)
-{
- struct v4l2_mbus_framefmt *mf = &state->format_mbus;
- u32 val;
-
- /* Color format */
- val = mipi_csis_read(state, MIPI_CSIS_ISP_CONFIG_CH(0));
- val &= ~(MIPI_CSIS_ISPCFG_ALIGN_32BIT | MIPI_CSIS_ISPCFG_FMT_MASK);
- val |= MIPI_CSIS_ISPCFG_FMT(state->csis_fmt->data_type);
- mipi_csis_write(state, MIPI_CSIS_ISP_CONFIG_CH(0), val);
-
- /* Pixel resolution */
- val = mf->width | (mf->height << 16);
- mipi_csis_write(state, MIPI_CSIS_ISP_RESOL_CH(0), val);
-}
-
-static int mipi_csis_calculate_params(struct csi_state *state)
-{
- s64 link_freq;
- u32 lane_rate;
-
- /* Calculate the line rate from the pixel rate. */
- link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler,
- state->csis_fmt->width,
- state->bus.num_data_lanes * 2);
- if (link_freq < 0) {
- dev_err(state->dev, "Unable to obtain link frequency: %d\n",
- (int)link_freq);
- return link_freq;
- }
-
- lane_rate = link_freq * 2;
-
- if (lane_rate < 80000000 || lane_rate > 1500000000) {
- dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
- return -EINVAL;
- }
-
- /*
- * The HSSETTLE counter value is document in a table, but can also
- * easily be calculated. Hardcode the CLKSETTLE value to 0 for now
- * (which is documented as corresponding to CSI-2 v0.87 to v1.00) until
- * we figure out how to compute it correctly.
- */
- state->hs_settle = (lane_rate - 5000000) / 45000000;
- state->clk_settle = 0;
-
- dev_dbg(state->dev, "lane rate %u, Tclk_settle %u, Ths_settle %u\n",
- lane_rate, state->clk_settle, state->hs_settle);
-
- return 0;
-}
-
-static void mipi_csis_set_params(struct csi_state *state)
-{
- int lanes = state->bus.num_data_lanes;
- u32 val;
-
- val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
- val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
- val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
- if (state->info->version == MIPI_CSIS_V3_3)
- val |= MIPI_CSIS_CMN_CTRL_INTER_MODE;
- mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
-
- __mipi_csis_set_format(state);
-
- mipi_csis_write(state, MIPI_CSIS_DPHY_CMN_CTRL,
- MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(state->hs_settle) |
- MIPI_CSIS_DPHY_CMN_CTRL_CLKSETTLE(state->clk_settle));
-
- val = (0 << MIPI_CSIS_ISP_SYNC_HSYNC_LINTV_OFFSET)
- | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_SINTV_OFFSET)
- | (0 << MIPI_CSIS_ISP_SYNC_VSYNC_EINTV_OFFSET);
- mipi_csis_write(state, MIPI_CSIS_ISP_SYNC_CH(0), val);
-
- val = mipi_csis_read(state, MIPI_CSIS_CLK_CTRL);
- val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC;
- val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15);
- val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK;
- mipi_csis_write(state, MIPI_CSIS_CLK_CTRL, val);
-
- mipi_csis_write(state, MIPI_CSIS_DPHY_BCTRL_L,
- MIPI_CSIS_DPHY_BCTRL_L_BIAS_REF_VOLT_715MV |
- MIPI_CSIS_DPHY_BCTRL_L_BGR_CHOPPER_FREQ_3MHZ |
- MIPI_CSIS_DPHY_BCTRL_L_REG_12P_LVL_CTL_1_2V |
- MIPI_CSIS_DPHY_BCTRL_L_LP_RX_HYS_LVL_80MV |
- MIPI_CSIS_DPHY_BCTRL_L_LP_RX_VREF_LVL_715MV |
- MIPI_CSIS_DPHY_BCTRL_L_LP_CD_HYS_60MV |
- MIPI_CSIS_DPHY_BCTRL_L_B_DPHYCTRL(20000000));
- mipi_csis_write(state, MIPI_CSIS_DPHY_BCTRL_H, 0);
-
- /* Update the shadow register. */
- val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
- mipi_csis_write(state, MIPI_CSIS_CMN_CTRL,
- val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW |
- MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL);
-}
-
-static int mipi_csis_clk_enable(struct csi_state *state)
-{
- return clk_bulk_prepare_enable(state->info->num_clocks, state->clks);
-}
-
-static void mipi_csis_clk_disable(struct csi_state *state)
-{
- clk_bulk_disable_unprepare(state->info->num_clocks, state->clks);
-}
-
-static int mipi_csis_clk_get(struct csi_state *state)
-{
- unsigned int i;
- int ret;
-
- state->clks = devm_kcalloc(state->dev, state->info->num_clocks,
- sizeof(*state->clks), GFP_KERNEL);
-
- if (!state->clks)
- return -ENOMEM;
-
- for (i = 0; i < state->info->num_clocks; i++)
- state->clks[i].id = mipi_csis_clk_id[i];
-
- ret = devm_clk_bulk_get(state->dev, state->info->num_clocks,
- state->clks);
- if (ret < 0)
- return ret;
-
- /* Set clock rate */
- ret = clk_set_rate(state->clks[MIPI_CSIS_CLK_WRAP].clk,
- state->clk_frequency);
- if (ret < 0)
- dev_err(state->dev, "set rate=%d failed: %d\n",
- state->clk_frequency, ret);
-
- return ret;
-}
-
-static void mipi_csis_start_stream(struct csi_state *state)
-{
- mipi_csis_sw_reset(state);
- mipi_csis_set_params(state);
- mipi_csis_system_enable(state, true);
- mipi_csis_enable_interrupts(state, true);
-}
-
-static void mipi_csis_stop_stream(struct csi_state *state)
-{
- mipi_csis_enable_interrupts(state, false);
- mipi_csis_system_enable(state, false);
-}
-
-static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
-{
- struct csi_state *state = dev_id;
- unsigned long flags;
- unsigned int i;
- u32 status;
- u32 dbg_status;
-
- status = mipi_csis_read(state, MIPI_CSIS_INT_SRC);
- dbg_status = mipi_csis_read(state, MIPI_CSIS_DBG_INTR_SRC);
-
- spin_lock_irqsave(&state->slock, flags);
-
- /* Update the event/error counters */
- if ((status & MIPI_CSIS_INT_SRC_ERRORS) || state->debug) {
- for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) {
- struct mipi_csis_event *event = &state->events[i];
-
- if ((!event->debug && (status & event->mask)) ||
- (event->debug && (dbg_status & event->mask)))
- event->counter++;
- }
- }
- spin_unlock_irqrestore(&state->slock, flags);
-
- mipi_csis_write(state, MIPI_CSIS_INT_SRC, status);
- mipi_csis_write(state, MIPI_CSIS_DBG_INTR_SRC, dbg_status);
-
- return IRQ_HANDLED;
-}
-
-/* -----------------------------------------------------------------------------
- * PHY regulator and reset
- */
-
-static int mipi_csis_phy_enable(struct csi_state *state)
-{
- if (state->info->version != MIPI_CSIS_V3_3)
- return 0;
-
- return regulator_enable(state->mipi_phy_regulator);
-}
-
-static int mipi_csis_phy_disable(struct csi_state *state)
-{
- if (state->info->version != MIPI_CSIS_V3_3)
- return 0;
-
- return regulator_disable(state->mipi_phy_regulator);
-}
-
-static void mipi_csis_phy_reset(struct csi_state *state)
-{
- if (state->info->version != MIPI_CSIS_V3_3)
- return;
-
- reset_control_assert(state->mrst);
- msleep(20);
- reset_control_deassert(state->mrst);
-}
-
-static int mipi_csis_phy_init(struct csi_state *state)
-{
- if (state->info->version != MIPI_CSIS_V3_3)
- return 0;
-
- /* Get MIPI PHY reset and regulator. */
- state->mrst = devm_reset_control_get_exclusive(state->dev, NULL);
- if (IS_ERR(state->mrst))
- return PTR_ERR(state->mrst);
-
- state->mipi_phy_regulator = devm_regulator_get(state->dev, "phy");
- if (IS_ERR(state->mipi_phy_regulator))
- return PTR_ERR(state->mipi_phy_regulator);
-
- return regulator_set_voltage(state->mipi_phy_regulator, 1000000,
- 1000000);
-}
-
-/* -----------------------------------------------------------------------------
- * Debug
- */
-
-static void mipi_csis_clear_counters(struct csi_state *state)
-{
- unsigned long flags;
- unsigned int i;
-
- spin_lock_irqsave(&state->slock, flags);
- for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++)
- state->events[i].counter = 0;
- spin_unlock_irqrestore(&state->slock, flags);
-}
-
-static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
-{
- unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS
- : MIPI_CSIS_NUM_EVENTS - 8;
- unsigned long flags;
- unsigned int i;
-
- spin_lock_irqsave(&state->slock, flags);
-
- for (i = 0; i < num_events; ++i) {
- if (state->events[i].counter > 0 || state->debug)
- dev_info(state->dev, "%s events: %d\n",
- state->events[i].name,
- state->events[i].counter);
- }
- spin_unlock_irqrestore(&state->slock, flags);
-}
-
-static int mipi_csis_dump_regs(struct csi_state *state)
-{
- static const struct {
- u32 offset;
- const char * const name;
- } registers[] = {
- { MIPI_CSIS_CMN_CTRL, "CMN_CTRL" },
- { MIPI_CSIS_CLK_CTRL, "CLK_CTRL" },
- { MIPI_CSIS_INT_MSK, "INT_MSK" },
- { MIPI_CSIS_DPHY_STATUS, "DPHY_STATUS" },
- { MIPI_CSIS_DPHY_CMN_CTRL, "DPHY_CMN_CTRL" },
- { MIPI_CSIS_DPHY_SCTRL_L, "DPHY_SCTRL_L" },
- { MIPI_CSIS_DPHY_SCTRL_H, "DPHY_SCTRL_H" },
- { MIPI_CSIS_ISP_CONFIG_CH(0), "ISP_CONFIG_CH0" },
- { MIPI_CSIS_ISP_RESOL_CH(0), "ISP_RESOL_CH0" },
- { MIPI_CSIS_SDW_CONFIG_CH(0), "SDW_CONFIG_CH0" },
- { MIPI_CSIS_SDW_RESOL_CH(0), "SDW_RESOL_CH0" },
- { MIPI_CSIS_DBG_CTRL, "DBG_CTRL" },
- };
-
- unsigned int i;
- u32 cfg;
-
- dev_info(state->dev, "--- REGISTERS ---\n");
-
- for (i = 0; i < ARRAY_SIZE(registers); i++) {
- cfg = mipi_csis_read(state, registers[i].offset);
- dev_info(state->dev, "%14s: 0x%08x\n", registers[i].name, cfg);
- }
-
- return 0;
-}
-
-static int mipi_csis_dump_regs_show(struct seq_file *m, void *private)
-{
- struct csi_state *state = m->private;
-
- return mipi_csis_dump_regs(state);
-}
-DEFINE_SHOW_ATTRIBUTE(mipi_csis_dump_regs);
-
-static void mipi_csis_debugfs_init(struct csi_state *state)
-{
- state->debugfs_root = debugfs_create_dir(dev_name(state->dev), NULL);
-
- debugfs_create_bool("debug_enable", 0600, state->debugfs_root,
- &state->debug);
- debugfs_create_file("dump_regs", 0600, state->debugfs_root, state,
- &mipi_csis_dump_regs_fops);
-}
-
-static void mipi_csis_debugfs_exit(struct csi_state *state)
-{
- debugfs_remove_recursive(state->debugfs_root);
-}
-
-/* -----------------------------------------------------------------------------
- * V4L2 subdev operations
- */
-
-static struct csi_state *mipi_sd_to_csis_state(struct v4l2_subdev *sdev)
-{
- return container_of(sdev, struct csi_state, sd);
-}
-
-static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable)
-{
- struct csi_state *state = mipi_sd_to_csis_state(sd);
- int ret;
-
- if (enable) {
- ret = mipi_csis_calculate_params(state);
- if (ret < 0)
- return ret;
-
- mipi_csis_clear_counters(state);
-
- ret = pm_runtime_resume_and_get(state->dev);
- if (ret < 0)
- return ret;
-
- ret = v4l2_subdev_call(state->src_sd, core, s_power, 1);
- if (ret < 0 && ret != -ENOIOCTLCMD)
- goto done;
- }
-
- mutex_lock(&state->lock);
-
- if (enable) {
- if (state->state & ST_SUSPENDED) {
- ret = -EBUSY;
- goto unlock;
- }
-
- mipi_csis_start_stream(state);
- ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1);
- if (ret < 0)
- goto unlock;
-
- mipi_csis_log_counters(state, true);
-
- state->state |= ST_STREAMING;
- } else {
- v4l2_subdev_call(state->src_sd, video, s_stream, 0);
- ret = v4l2_subdev_call(state->src_sd, core, s_power, 0);
- if (ret == -ENOIOCTLCMD)
- ret = 0;
- mipi_csis_stop_stream(state);
- state->state &= ~ST_STREAMING;
- if (state->debug)
- mipi_csis_log_counters(state, true);
- }
-
-unlock:
- mutex_unlock(&state->lock);
-
-done:
- if (!enable || ret < 0)
- pm_runtime_put(state->dev);
-
- return ret;
-}
-
-static struct v4l2_mbus_framefmt *
-mipi_csis_get_format(struct csi_state *state,
- struct v4l2_subdev_state *sd_state,
- enum v4l2_subdev_format_whence which,
- unsigned int pad)
-{
- if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&state->sd, sd_state, pad);
-
- return &state->format_mbus;
-}
-
-static int mipi_csis_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
-{
- struct csi_state *state = mipi_sd_to_csis_state(sd);
- struct v4l2_mbus_framefmt *fmt_sink;
- struct v4l2_mbus_framefmt *fmt_source;
- enum v4l2_subdev_format_whence which;
-
- which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- fmt_sink = mipi_csis_get_format(state, sd_state, which, CSIS_PAD_SINK);
-
- fmt_sink->code = MEDIA_BUS_FMT_UYVY8_1X16;
- fmt_sink->width = MIPI_CSIS_DEF_PIX_WIDTH;
- fmt_sink->height = MIPI_CSIS_DEF_PIX_HEIGHT;
- fmt_sink->field = V4L2_FIELD_NONE;
-
- fmt_sink->colorspace = V4L2_COLORSPACE_SMPTE170M;
- fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
- fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
- fmt_sink->quantization =
- V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
- fmt_sink->ycbcr_enc);
-
- /*
- * When called from mipi_csis_subdev_init() to initialize the active
- * configuration, cfg is NULL, which indicates there's no source pad
- * configuration to set.
- */
- if (!sd_state)
- return 0;
-
- fmt_source = mipi_csis_get_format(state, sd_state, which,
- CSIS_PAD_SOURCE);
- *fmt_source = *fmt_sink;
-
- return 0;
-}
-
-static int mipi_csis_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *sdformat)
-{
- struct csi_state *state = mipi_sd_to_csis_state(sd);
- struct v4l2_mbus_framefmt *fmt;
-
- fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
- sdformat->pad);
-
- mutex_lock(&state->lock);
- sdformat->format = *fmt;
- mutex_unlock(&state->lock);
-
- return 0;
-}
-
-static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- struct csi_state *state = mipi_sd_to_csis_state(sd);
-
- /*
- * The CSIS can't transcode in any way, the source format is identical
- * to the sink format.
- */
- if (code->pad == CSIS_PAD_SOURCE) {
- struct v4l2_mbus_framefmt *fmt;
-
- if (code->index > 0)
- return -EINVAL;
-
- fmt = mipi_csis_get_format(state, sd_state, code->which,
- code->pad);
- code->code = fmt->code;
- return 0;
- }
-
- if (code->pad != CSIS_PAD_SINK)
- return -EINVAL;
-
- if (code->index >= ARRAY_SIZE(mipi_csis_formats))
- return -EINVAL;
-
- code->code = mipi_csis_formats[code->index].code;
-
- return 0;
-}
-
-static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *sdformat)
-{
- struct csi_state *state = mipi_sd_to_csis_state(sd);
- struct csis_pix_format const *csis_fmt;
- struct v4l2_mbus_framefmt *fmt;
- unsigned int align;
-
- /*
- * The CSIS can't transcode in any way, the source format can't be
- * modified.
- */
- if (sdformat->pad == CSIS_PAD_SOURCE)
- return mipi_csis_get_fmt(sd, sd_state, sdformat);
-
- if (sdformat->pad != CSIS_PAD_SINK)
- return -EINVAL;
-
- /*
- * Validate the media bus code and clamp and align the size.
- *
- * The total number of bits per line must be a multiple of 8. We thus
- * need to align the width for formats that are not multiples of 8
- * bits.
- */
- csis_fmt = find_csis_format(sdformat->format.code);
- if (!csis_fmt)
- csis_fmt = &mipi_csis_formats[0];
-
- switch (csis_fmt->width % 8) {
- case 0:
- align = 0;
- break;
- case 4:
- align = 1;
- break;
- case 2:
- case 6:
- align = 2;
- break;
- default:
- /* 1, 3, 5, 7 */
- align = 3;
- break;
- }
-
- v4l_bound_align_image(&sdformat->format.width, 1,
- CSIS_MAX_PIX_WIDTH, align,
- &sdformat->format.height, 1,
- CSIS_MAX_PIX_HEIGHT, 0, 0);
-
- fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
- sdformat->pad);
-
- mutex_lock(&state->lock);
-
- fmt->code = csis_fmt->code;
- fmt->width = sdformat->format.width;
- fmt->height = sdformat->format.height;
-
- sdformat->format = *fmt;
-
- /* Propagate the format from sink to source. */
- fmt = mipi_csis_get_format(state, sd_state, sdformat->which,
- CSIS_PAD_SOURCE);
- *fmt = sdformat->format;
-
- /* Store the CSIS format descriptor for active formats. */
- if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
- state->csis_fmt = csis_fmt;
-
- mutex_unlock(&state->lock);
-
- return 0;
-}
-
-static int mipi_csis_log_status(struct v4l2_subdev *sd)
-{
- struct csi_state *state = mipi_sd_to_csis_state(sd);
-
- mutex_lock(&state->lock);
- mipi_csis_log_counters(state, true);
- if (state->debug && (state->state & ST_POWERED))
- mipi_csis_dump_regs(state);
- mutex_unlock(&state->lock);
-
- return 0;
-}
-
-static const struct v4l2_subdev_core_ops mipi_csis_core_ops = {
- .log_status = mipi_csis_log_status,
-};
-
-static const struct v4l2_subdev_video_ops mipi_csis_video_ops = {
- .s_stream = mipi_csis_s_stream,
-};
-
-static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = {
- .init_cfg = mipi_csis_init_cfg,
- .enum_mbus_code = mipi_csis_enum_mbus_code,
- .get_fmt = mipi_csis_get_fmt,
- .set_fmt = mipi_csis_set_fmt,
-};
-
-static const struct v4l2_subdev_ops mipi_csis_subdev_ops = {
- .core = &mipi_csis_core_ops,
- .video = &mipi_csis_video_ops,
- .pad = &mipi_csis_pad_ops,
-};
-
-/* -----------------------------------------------------------------------------
- * Media entity operations
- */
-
-static int mipi_csis_link_setup(struct media_entity *entity,
- const struct media_pad *local_pad,
- const struct media_pad *remote_pad, u32 flags)
-{
- struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
- struct csi_state *state = mipi_sd_to_csis_state(sd);
- struct v4l2_subdev *remote_sd;
-
- dev_dbg(state->dev, "link setup %s -> %s", remote_pad->entity->name,
- local_pad->entity->name);
-
- /* We only care about the link to the source. */
- if (!(local_pad->flags & MEDIA_PAD_FL_SINK))
- return 0;
-
- remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
-
- if (flags & MEDIA_LNK_FL_ENABLED) {
- if (state->src_sd)
- return -EBUSY;
-
- state->src_sd = remote_sd;
- } else {
- state->src_sd = NULL;
- }
-
- return 0;
-}
-
-static const struct media_entity_operations mipi_csis_entity_ops = {
- .link_setup = mipi_csis_link_setup,
- .link_validate = v4l2_subdev_link_validate,
- .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
-};
-
-/* -----------------------------------------------------------------------------
- * Async subdev notifier
- */
-
-static struct csi_state *
-mipi_notifier_to_csis_state(struct v4l2_async_notifier *n)
-{
- return container_of(n, struct csi_state, notifier);
-}
-
-static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier,
- struct v4l2_subdev *sd,
- struct v4l2_async_subdev *asd)
-{
- struct csi_state *state = mipi_notifier_to_csis_state(notifier);
- struct media_pad *sink = &state->sd.entity.pads[CSIS_PAD_SINK];
-
- return v4l2_create_fwnode_links_to_pad(sd, sink, 0);
-}
-
-static const struct v4l2_async_notifier_operations mipi_csis_notify_ops = {
- .bound = mipi_csis_notify_bound,
-};
-
-static int mipi_csis_async_register(struct csi_state *state)
-{
- struct v4l2_fwnode_endpoint vep = {
- .bus_type = V4L2_MBUS_CSI2_DPHY,
- };
- struct v4l2_async_subdev *asd;
- struct fwnode_handle *ep;
- unsigned int i;
- int ret;
-
- v4l2_async_nf_init(&state->notifier);
-
- ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
- FWNODE_GRAPH_ENDPOINT_NEXT);
- if (!ep)
- return -ENOTCONN;
-
- ret = v4l2_fwnode_endpoint_parse(ep, &vep);
- if (ret)
- goto err_parse;
-
- for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) {
- if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) {
- dev_err(state->dev,
- "data lanes reordering is not supported");
- ret = -EINVAL;
- goto err_parse;
- }
- }
-
- state->bus = vep.bus.mipi_csi2;
-
- dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes);
- dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags);
-
- asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
- struct v4l2_async_subdev);
- if (IS_ERR(asd)) {
- ret = PTR_ERR(asd);
- goto err_parse;
- }
-
- fwnode_handle_put(ep);
-
- state->notifier.ops = &mipi_csis_notify_ops;
-
- ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier);
- if (ret)
- return ret;
-
- return v4l2_async_register_subdev(&state->sd);
-
-err_parse:
- fwnode_handle_put(ep);
-
- return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * Suspend/resume
- */
-
-static int mipi_csis_pm_suspend(struct device *dev, bool runtime)
-{
- struct v4l2_subdev *sd = dev_get_drvdata(dev);
- struct csi_state *state = mipi_sd_to_csis_state(sd);
- int ret = 0;
-
- mutex_lock(&state->lock);
- if (state->state & ST_POWERED) {
- mipi_csis_stop_stream(state);
- ret = mipi_csis_phy_disable(state);
- if (ret)
- goto unlock;
- mipi_csis_clk_disable(state);
- state->state &= ~ST_POWERED;
- if (!runtime)
- state->state |= ST_SUSPENDED;
- }
-
-unlock:
- mutex_unlock(&state->lock);
-
- return ret ? -EAGAIN : 0;
-}
-
-static int mipi_csis_pm_resume(struct device *dev, bool runtime)
-{
- struct v4l2_subdev *sd = dev_get_drvdata(dev);
- struct csi_state *state = mipi_sd_to_csis_state(sd);
- int ret = 0;
-
- mutex_lock(&state->lock);
- if (!runtime && !(state->state & ST_SUSPENDED))
- goto unlock;
-
- if (!(state->state & ST_POWERED)) {
- ret = mipi_csis_phy_enable(state);
- if (ret)
- goto unlock;
-
- state->state |= ST_POWERED;
- mipi_csis_clk_enable(state);
- }
- if (state->state & ST_STREAMING)
- mipi_csis_start_stream(state);
-
- state->state &= ~ST_SUSPENDED;
-
-unlock:
- mutex_unlock(&state->lock);
-
- return ret ? -EAGAIN : 0;
-}
-
-static int __maybe_unused mipi_csis_suspend(struct device *dev)
-{
- return mipi_csis_pm_suspend(dev, false);
-}
-
-static int __maybe_unused mipi_csis_resume(struct device *dev)
-{
- return mipi_csis_pm_resume(dev, false);
-}
-
-static int __maybe_unused mipi_csis_runtime_suspend(struct device *dev)
-{
- return mipi_csis_pm_suspend(dev, true);
-}
-
-static int __maybe_unused mipi_csis_runtime_resume(struct device *dev)
-{
- return mipi_csis_pm_resume(dev, true);
-}
-
-static const struct dev_pm_ops mipi_csis_pm_ops = {
- SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume,
- NULL)
- SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume)
-};
-
-/* -----------------------------------------------------------------------------
- * Probe/remove & platform driver
- */
-
-static int mipi_csis_subdev_init(struct csi_state *state)
-{
- struct v4l2_subdev *sd = &state->sd;
-
- v4l2_subdev_init(sd, &mipi_csis_subdev_ops);
- sd->owner = THIS_MODULE;
- snprintf(sd->name, sizeof(sd->name), "%s.%d",
- CSIS_SUBDEV_NAME, state->index);
-
- sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- sd->ctrl_handler = NULL;
-
- sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
- sd->entity.ops = &mipi_csis_entity_ops;
-
- sd->dev = state->dev;
-
- state->csis_fmt = &mipi_csis_formats[0];
- mipi_csis_init_cfg(sd, NULL);
-
- state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
- | MEDIA_PAD_FL_MUST_CONNECT;
- state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
- | MEDIA_PAD_FL_MUST_CONNECT;
- return media_entity_pads_init(&sd->entity, CSIS_PADS_NUM,
- state->pads);
-}
-
-static int mipi_csis_parse_dt(struct csi_state *state)
-{
- struct device_node *node = state->dev->of_node;
-
- if (of_property_read_u32(node, "clock-frequency",
- &state->clk_frequency))
- state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
-
- return 0;
-}
-
-static int mipi_csis_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct csi_state *state;
- int irq;
- int ret;
-
- state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
- if (!state)
- return -ENOMEM;
-
- mutex_init(&state->lock);
- spin_lock_init(&state->slock);
-
- state->dev = dev;
- state->info = of_device_get_match_data(dev);
-
- memcpy(state->events, mipi_csis_events, sizeof(state->events));
-
- /* Parse DT properties. */
- ret = mipi_csis_parse_dt(state);
- if (ret < 0) {
- dev_err(dev, "Failed to parse device tree: %d\n", ret);
- return ret;
- }
-
- /* Acquire resources. */
- state->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(state->regs))
- return PTR_ERR(state->regs);
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
-
- ret = mipi_csis_phy_init(state);
- if (ret < 0)
- return ret;
-
- ret = mipi_csis_clk_get(state);
- if (ret < 0)
- return ret;
-
- /* Reset PHY and enable the clocks. */
- mipi_csis_phy_reset(state);
-
- ret = mipi_csis_clk_enable(state);
- if (ret < 0) {
- dev_err(state->dev, "failed to enable clocks: %d\n", ret);
- return ret;
- }
-
- /* Now that the hardware is initialized, request the interrupt. */
- ret = devm_request_irq(dev, irq, mipi_csis_irq_handler, 0,
- dev_name(dev), state);
- if (ret) {
- dev_err(dev, "Interrupt request failed\n");
- goto disable_clock;
- }
-
- /* Initialize and register the subdev. */
- ret = mipi_csis_subdev_init(state);
- if (ret < 0)
- goto disable_clock;
-
- platform_set_drvdata(pdev, &state->sd);
-
- ret = mipi_csis_async_register(state);
- if (ret < 0) {
- dev_err(dev, "async register failed: %d\n", ret);
- goto cleanup;
- }
-
- /* Initialize debugfs. */
- mipi_csis_debugfs_init(state);
-
- /* Enable runtime PM. */
- pm_runtime_enable(dev);
- if (!pm_runtime_enabled(dev)) {
- ret = mipi_csis_pm_resume(dev, true);
- if (ret < 0)
- goto unregister_all;
- }
-
- dev_info(dev, "lanes: %d, freq: %u\n",
- state->bus.num_data_lanes, state->clk_frequency);
-
- return 0;
-
-unregister_all:
- mipi_csis_debugfs_exit(state);
-cleanup:
- media_entity_cleanup(&state->sd.entity);
- v4l2_async_nf_unregister(&state->notifier);
- v4l2_async_nf_cleanup(&state->notifier);
- v4l2_async_unregister_subdev(&state->sd);
-disable_clock:
- mipi_csis_clk_disable(state);
- mutex_destroy(&state->lock);
-
- return ret;
-}
-
-static int mipi_csis_remove(struct platform_device *pdev)
-{
- struct v4l2_subdev *sd = platform_get_drvdata(pdev);
- struct csi_state *state = mipi_sd_to_csis_state(sd);
-
- mipi_csis_debugfs_exit(state);
- v4l2_async_nf_unregister(&state->notifier);
- v4l2_async_nf_cleanup(&state->notifier);
- v4l2_async_unregister_subdev(&state->sd);
-
- pm_runtime_disable(&pdev->dev);
- mipi_csis_pm_suspend(&pdev->dev, true);
- mipi_csis_clk_disable(state);
- media_entity_cleanup(&state->sd.entity);
- mutex_destroy(&state->lock);
- pm_runtime_set_suspended(&pdev->dev);
-
- return 0;
-}
-
-static const struct of_device_id mipi_csis_of_match[] = {
- {
- .compatible = "fsl,imx7-mipi-csi2",
- .data = &(const struct mipi_csis_info){
- .version = MIPI_CSIS_V3_3,
- .num_clocks = 3,
- },
- }, {
- .compatible = "fsl,imx8mm-mipi-csi2",
- .data = &(const struct mipi_csis_info){
- .version = MIPI_CSIS_V3_6_3,
- .num_clocks = 4,
- },
- },
- { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
-
-static struct platform_driver mipi_csis_driver = {
- .probe = mipi_csis_probe,
- .remove = mipi_csis_remove,
- .driver = {
- .of_match_table = mipi_csis_of_match,
- .name = CSIS_DRIVER_NAME,
- .pm = &mipi_csis_pm_ops,
- },
-};
-
-module_platform_driver(mipi_csis_driver);
-
-MODULE_DESCRIPTION("i.MX7 & i.MX8 MIPI CSI-2 receiver driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:imx7-mipi-csi2");
diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
index 7adbdd14daa9..83194328d010 100644
--- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
@@ -117,7 +117,7 @@ struct csi_state {
struct v4l2_async_notifier notifier;
struct v4l2_subdev *src_sd;
- struct v4l2_fwnode_bus_mipi_csi2 bus;
+ struct v4l2_mbus_config_mipi_csi2 bus;
struct mutex lock; /* Protect csi2_fmt, format_mbus, state, hs_settle */
const struct csi2_pix_format *csi2_fmt;
@@ -200,12 +200,13 @@ static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = {
}, {
.code = MEDIA_BUS_FMT_SRGGB14_1X14,
.width = 14,
- }, {
+ },
/* YUV formats */
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ {
+ .code = MEDIA_BUS_FMT_YUYV8_1X16,
.width = 16,
}, {
- .code = MEDIA_BUS_FMT_YUYV8_1X16,
+ .code = MEDIA_BUS_FMT_UYVY8_1X16,
.width = 16,
}
};
@@ -398,9 +399,6 @@ static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable)
struct csi_state *state = mipi_sd_to_csi2_state(sd);
int ret = 0;
- imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK,
- CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE);
-
if (enable) {
ret = pm_runtime_resume_and_get(state->dev);
if (ret < 0)
@@ -696,11 +694,10 @@ err_parse:
* Suspend/resume
*/
-static int imx8mq_mipi_csi_pm_suspend(struct device *dev, bool runtime)
+static void imx8mq_mipi_csi_pm_suspend(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct csi_state *state = mipi_sd_to_csi2_state(sd);
- int ret = 0;
mutex_lock(&state->lock);
@@ -708,36 +705,19 @@ static int imx8mq_mipi_csi_pm_suspend(struct device *dev, bool runtime)
imx8mq_mipi_csi_stop_stream(state);
imx8mq_mipi_csi_clk_disable(state);
state->state &= ~ST_POWERED;
- if (!runtime)
- state->state |= ST_SUSPENDED;
}
mutex_unlock(&state->lock);
-
- ret = icc_set_bw(state->icc_path, 0, 0);
- if (ret)
- dev_err(dev, "icc_set_bw failed with %d\n", ret);
-
- return ret ? -EAGAIN : 0;
}
-static int imx8mq_mipi_csi_pm_resume(struct device *dev, bool runtime)
+static int imx8mq_mipi_csi_pm_resume(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct csi_state *state = mipi_sd_to_csi2_state(sd);
int ret = 0;
- ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw);
- if (ret) {
- dev_err(dev, "icc_set_bw failed with %d\n", ret);
- return ret;
- }
-
mutex_lock(&state->lock);
- if (!runtime && !(state->state & ST_SUSPENDED))
- goto unlock;
-
if (!(state->state & ST_POWERED)) {
state->state |= ST_POWERED;
ret = imx8mq_mipi_csi_clk_enable(state);
@@ -758,22 +738,55 @@ unlock:
static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev)
{
- return imx8mq_mipi_csi_pm_suspend(dev, false);
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+
+ imx8mq_mipi_csi_pm_suspend(dev);
+
+ state->state |= ST_SUSPENDED;
+
+ return 0;
}
static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev)
{
- return imx8mq_mipi_csi_pm_resume(dev, false);
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+
+ if (!(state->state & ST_SUSPENDED))
+ return 0;
+
+ return imx8mq_mipi_csi_pm_resume(dev);
}
static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev)
{
- return imx8mq_mipi_csi_pm_suspend(dev, true);
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ int ret;
+
+ imx8mq_mipi_csi_pm_suspend(dev);
+
+ ret = icc_set_bw(state->icc_path, 0, 0);
+ if (ret)
+ dev_err(dev, "icc_set_bw failed with %d\n", ret);
+
+ return ret;
}
static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev)
{
- return imx8mq_mipi_csi_pm_resume(dev, true);
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+ int ret;
+
+ ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw);
+ if (ret) {
+ dev_err(dev, "icc_set_bw failed with %d\n", ret);
+ return ret;
+ }
+
+ return imx8mq_mipi_csi_pm_resume(dev);
}
static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = {
@@ -921,7 +934,7 @@ static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
/* Enable runtime PM. */
pm_runtime_enable(dev);
if (!pm_runtime_enabled(dev)) {
- ret = imx8mq_mipi_csi_pm_resume(dev, true);
+ ret = imx8mq_mipi_csi_runtime_resume(dev);
if (ret < 0)
goto icc;
}
@@ -934,7 +947,7 @@ static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
cleanup:
pm_runtime_disable(&pdev->dev);
- imx8mq_mipi_csi_pm_suspend(&pdev->dev, true);
+ imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
media_entity_cleanup(&state->sd.entity);
v4l2_async_nf_unregister(&state->notifier);
@@ -958,7 +971,7 @@ static int imx8mq_mipi_csi_remove(struct platform_device *pdev)
v4l2_async_unregister_subdev(&state->sd);
pm_runtime_disable(&pdev->dev);
- imx8mq_mipi_csi_pm_suspend(&pdev->dev, true);
+ imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
media_entity_cleanup(&state->sd.entity);
mutex_destroy(&state->lock);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/staging/media/ipu3/Kconfig b/drivers/staging/media/ipu3/Kconfig
index 3e9640523e50..114a1d8e7cc8 100644
--- a/drivers/staging/media/ipu3/Kconfig
+++ b/drivers/staging/media/ipu3/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config VIDEO_IPU3_IMGU
tristate "Intel ipu3-imgu driver"
- depends on PCI && VIDEO_V4L2
+ depends on PCI && VIDEO_DEV
depends on X86
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.c b/drivers/staging/media/ipu3/ipu3-css-fw.c
index 981693eed815..2b659b0ccca1 100644
--- a/drivers/staging/media/ipu3/ipu3-css-fw.c
+++ b/drivers/staging/media/ipu3/ipu3-css-fw.c
@@ -117,7 +117,9 @@ int imgu_css_fw_init(struct imgu_css *css)
unsigned int i, j, binary_nr;
int r;
- r = request_firmware(&css->fw, IMGU_FW_NAME, css->dev);
+ r = request_firmware(&css->fw, IMGU_FW_NAME_20161208, css->dev);
+ if (r == -ENOENT)
+ r = request_firmware(&css->fw, IMGU_FW_NAME, css->dev);
if (r)
return r;
diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.h b/drivers/staging/media/ipu3/ipu3-css-fw.h
index c0bc57fd678a..f9403da75785 100644
--- a/drivers/staging/media/ipu3/ipu3-css-fw.h
+++ b/drivers/staging/media/ipu3/ipu3-css-fw.h
@@ -6,7 +6,9 @@
/******************* Firmware file definitions *******************/
-#define IMGU_FW_NAME "intel/ipu3-fw.bin"
+#define IMGU_FW_NAME "intel/ipu3-fw.bin"
+#define IMGU_FW_NAME_20161208 \
+ "intel/irci_irci_ecr-master_20161208_0213_20170112_1500.bin"
typedef u32 imgu_fw_ptr;
diff --git a/drivers/staging/media/ipu3/ipu3-css-params.c b/drivers/staging/media/ipu3/ipu3-css-params.c
index d9e3c3785075..76ad802d694e 100644
--- a/drivers/staging/media/ipu3/ipu3-css-params.c
+++ b/drivers/staging/media/ipu3/ipu3-css-params.c
@@ -2556,6 +2556,15 @@ int imgu_css_cfg_acc(struct imgu_css *css, unsigned int pipe,
/* Enable only for rightmost stripe, disable left */
acc->af.stripes[0].grid_cfg.y_start &=
~IPU3_UAPI_GRID_Y_START_EN;
+ acc->af.stripes[1].grid_cfg.x_start =
+ (acc->af.stripes[1].grid_cfg.x_start -
+ acc->stripe.down_scaled_stripes[1].offset) &
+ IPU3_UAPI_GRID_START_MASK;
+ b_w_log2 = acc->af.stripes[1].grid_cfg.block_width_log2;
+ acc->af.stripes[1].grid_cfg.x_end =
+ imgu_css_grid_end(acc->af.stripes[1].grid_cfg.x_start,
+ acc->af.stripes[1].grid_cfg.width,
+ b_w_log2);
} else if (acc->af.config.grid_cfg.x_end <=
acc->stripe.bds_out_stripes[0].width - min_overlap) {
/* Enable only for leftmost stripe, disable right */
@@ -2627,6 +2636,17 @@ int imgu_css_cfg_acc(struct imgu_css *css, unsigned int pipe,
acc->stripe.down_scaled_stripes[1].offset + min_overlap) {
/* Enable only for rightmost stripe, disable left */
acc->awb.stripes[0].rgbs_thr_b &= ~IPU3_UAPI_AWB_RGBS_THR_B_EN;
+
+ acc->awb.stripes[1].grid.x_start =
+ (acc->awb.stripes[1].grid.x_start -
+ acc->stripe.down_scaled_stripes[1].offset) &
+ IPU3_UAPI_GRID_START_MASK;
+
+ b_w_log2 = acc->awb.stripes[1].grid.block_width_log2;
+ acc->awb.stripes[1].grid.x_end =
+ imgu_css_grid_end(acc->awb.stripes[1].grid.x_start,
+ acc->awb.stripes[1].grid.width,
+ b_w_log2);
} else if (acc->awb.config.grid.x_end <=
acc->stripe.bds_out_stripes[0].width - min_overlap) {
/* Enable only for leftmost stripe, disable right */
diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c
index 0473457b4e64..d1c539cefba8 100644
--- a/drivers/staging/media/ipu3/ipu3-v4l2.c
+++ b/drivers/staging/media/ipu3/ipu3-v4l2.c
@@ -485,6 +485,7 @@ static int imgu_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
pipe = node->pipe;
imgu_pipe = &imgu->imgu_pipe[pipe];
+ atomic_set(&node->sequence, 0);
r = media_pipeline_start(&node->vdev.entity, &imgu_pipe->pipeline);
if (r < 0)
goto fail_return_bufs;
diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c
index 8e1e9e46e604..0c453b37f8c4 100644
--- a/drivers/staging/media/ipu3/ipu3.c
+++ b/drivers/staging/media/ipu3/ipu3.c
@@ -440,6 +440,16 @@ fail_start_streaming:
return r;
}
+static void imgu_video_nodes_exit(struct imgu_device *imgu)
+{
+ int i;
+
+ for (i = 0; i < IMGU_MAX_PIPE_NUM; i++)
+ imgu_dummybufs_cleanup(imgu, i);
+
+ imgu_v4l2_unregister(imgu);
+}
+
static int imgu_video_nodes_init(struct imgu_device *imgu)
{
struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES] = { NULL };
@@ -489,24 +499,11 @@ static int imgu_video_nodes_init(struct imgu_device *imgu)
return 0;
out_cleanup:
- for (j = 0; j < IMGU_MAX_PIPE_NUM; j++)
- imgu_dummybufs_cleanup(imgu, j);
-
- imgu_v4l2_unregister(imgu);
+ imgu_video_nodes_exit(imgu);
return r;
}
-static void imgu_video_nodes_exit(struct imgu_device *imgu)
-{
- int i;
-
- for (i = 0; i < IMGU_MAX_PIPE_NUM; i++)
- imgu_dummybufs_cleanup(imgu, i);
-
- imgu_v4l2_unregister(imgu);
-}
-
/**************** PCI interface ****************/
static irqreturn_t imgu_isr_threaded(int irq, void *imgu_ptr)
diff --git a/drivers/staging/media/max96712/Kconfig b/drivers/staging/media/max96712/Kconfig
index acde14fd5c4d..117fadf81bd0 100644
--- a/drivers/staging/media/max96712/Kconfig
+++ b/drivers/staging/media/max96712/Kconfig
@@ -3,7 +3,7 @@ config VIDEO_MAX96712
tristate "Maxim MAX96712 Quad GMSL2 Deserializer support"
depends on I2C
depends on OF_GPIO
- depends on VIDEO_V4L2
+ depends on VIDEO_DEV
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c
index 9bc72d9a858b..6b5abd958bff 100644
--- a/drivers/staging/media/max96712/max96712.c
+++ b/drivers/staging/media/max96712/max96712.c
@@ -30,7 +30,7 @@ struct max96712_priv {
struct regmap *regmap;
struct gpio_desc *gpiod_pwdn;
- struct v4l2_fwnode_bus_mipi_csi2 mipi;
+ struct v4l2_mbus_config_mipi_csi2 mipi;
struct v4l2_subdev sd;
struct v4l2_ctrl_handler ctrl_handler;
diff --git a/drivers/staging/media/meson/vdec/Kconfig b/drivers/staging/media/meson/vdec/Kconfig
index 9e1450193392..19ffea987b89 100644
--- a/drivers/staging/media/meson/vdec/Kconfig
+++ b/drivers/staging/media/meson/vdec/Kconfig
@@ -2,7 +2,7 @@
config VIDEO_MESON_VDEC
tristate "Amlogic video decoder driver"
- depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
+ depends on VIDEO_DEV && HAS_DMA
depends on ARCH_MESON || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c
index db7022707ff8..86ccc8937afc 100644
--- a/drivers/staging/media/meson/vdec/esparser.c
+++ b/drivers/staging/media/meson/vdec/esparser.c
@@ -328,7 +328,12 @@ esparser_queue(struct amvdec_session *sess, struct vb2_v4l2_buffer *vbuf)
offset = esparser_get_offset(sess);
- amvdec_add_ts(sess, vb->timestamp, vbuf->timecode, offset, vbuf->flags);
+ ret = amvdec_add_ts(sess, vb->timestamp, vbuf->timecode, offset, vbuf->flags);
+ if (ret) {
+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+ return ret;
+ }
+
dev_dbg(core->dev, "esparser: ts = %llu pld_size = %u offset = %08X flags = %08X\n",
vb->timestamp, payload_size, offset, vbuf->flags);
diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.c b/drivers/staging/media/meson/vdec/vdec_helpers.c
index 203d7afa085d..7d2a75653250 100644
--- a/drivers/staging/media/meson/vdec/vdec_helpers.c
+++ b/drivers/staging/media/meson/vdec/vdec_helpers.c
@@ -227,13 +227,16 @@ int amvdec_set_canvases(struct amvdec_session *sess,
}
EXPORT_SYMBOL_GPL(amvdec_set_canvases);
-void amvdec_add_ts(struct amvdec_session *sess, u64 ts,
- struct v4l2_timecode tc, u32 offset, u32 vbuf_flags)
+int amvdec_add_ts(struct amvdec_session *sess, u64 ts,
+ struct v4l2_timecode tc, u32 offset, u32 vbuf_flags)
{
struct amvdec_timestamp *new_ts;
unsigned long flags;
new_ts = kzalloc(sizeof(*new_ts), GFP_KERNEL);
+ if (!new_ts)
+ return -ENOMEM;
+
new_ts->ts = ts;
new_ts->tc = tc;
new_ts->offset = offset;
@@ -242,6 +245,7 @@ void amvdec_add_ts(struct amvdec_session *sess, u64 ts,
spin_lock_irqsave(&sess->ts_spinlock, flags);
list_add_tail(&new_ts->list, &sess->timestamps);
spin_unlock_irqrestore(&sess->ts_spinlock, flags);
+ return 0;
}
EXPORT_SYMBOL_GPL(amvdec_add_ts);
diff --git a/drivers/staging/media/meson/vdec/vdec_helpers.h b/drivers/staging/media/meson/vdec/vdec_helpers.h
index 88137d15aa3a..4bf3e61d081b 100644
--- a/drivers/staging/media/meson/vdec/vdec_helpers.h
+++ b/drivers/staging/media/meson/vdec/vdec_helpers.h
@@ -56,8 +56,8 @@ void amvdec_dst_buf_done_offset(struct amvdec_session *sess,
* @offset: offset in the VIFIFO where the associated packet was written
* @flags: the vb2_v4l2_buffer flags
*/
-void amvdec_add_ts(struct amvdec_session *sess, u64 ts,
- struct v4l2_timecode tc, u32 offset, u32 flags);
+int amvdec_add_ts(struct amvdec_session *sess, u64 ts,
+ struct v4l2_timecode tc, u32 offset, u32 flags);
void amvdec_remove_ts(struct amvdec_session *sess, u64 ts);
/**
diff --git a/drivers/staging/media/meson/vdec/vdec_platform.c b/drivers/staging/media/meson/vdec/vdec_platform.c
index eabbebab2da2..88c9d72e1c83 100644
--- a/drivers/staging/media/meson/vdec/vdec_platform.c
+++ b/drivers/staging/media/meson/vdec/vdec_platform.c
@@ -103,6 +103,18 @@ static const struct amvdec_format vdec_formats_gxl[] = {
static const struct amvdec_format vdec_formats_gxm[] = {
{
+ .pixfmt = V4L2_PIX_FMT_VP9,
+ .min_buffers = 16,
+ .max_buffers = 24,
+ .max_width = 3840,
+ .max_height = 2160,
+ .vdec_ops = &vdec_hevc_ops,
+ .codec_ops = &codec_vp9_ops,
+ .firmware_path = "meson/vdec/gxl_vp9.bin",
+ .pixfmts_cap = { V4L2_PIX_FMT_NV12M, 0 },
+ .flags = V4L2_FMT_FLAG_COMPRESSED |
+ V4L2_FMT_FLAG_DYN_RESOLUTION,
+ }, {
.pixfmt = V4L2_PIX_FMT_H264,
.min_buffers = 2,
.max_buffers = 24,
diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig
index 6c254907a27b..6d1f55b09132 100644
--- a/drivers/staging/media/omap4iss/Kconfig
+++ b/drivers/staging/media/omap4iss/Kconfig
@@ -2,7 +2,7 @@
config VIDEO_OMAP4
tristate "OMAP 4 Camera support"
- depends on VIDEO_V4L2 && I2C
+ depends on VIDEO_DEV && I2C
depends on ARCH_OMAP4 || COMPILE_TEST
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/staging/media/rkvdec/Kconfig b/drivers/staging/media/rkvdec/Kconfig
index dc7292f346fa..e963d60cc6ad 100644
--- a/drivers/staging/media/rkvdec/Kconfig
+++ b/drivers/staging/media/rkvdec/Kconfig
@@ -2,7 +2,7 @@
config VIDEO_ROCKCHIP_VDEC
tristate "Rockchip Video Decoder driver"
depends on ARCH_ROCKCHIP || COMPILE_TEST
- depends on VIDEO_DEV && VIDEO_V4L2
+ depends on VIDEO_DEV
select MEDIA_CONTROLLER
select MEDIA_CONTROLLER_REQUEST_API
select VIDEOBUF2_DMA_CONTIG
diff --git a/drivers/staging/media/rkvdec/TODO b/drivers/staging/media/rkvdec/TODO
index e0f0f12f0ac5..2c0779383276 100644
--- a/drivers/staging/media/rkvdec/TODO
+++ b/drivers/staging/media/rkvdec/TODO
@@ -1,6 +1,6 @@
-* Support for VP9 is planned for this driver.
+* Support for HEVC is planned for this driver.
- Given the V4L controls for those CODECs will be part of
+ Given the V4L controls for that CODEC will be part of
the uABI, it will be required to have the driver in staging.
For this reason, we are keeping this driver in staging for now.
diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c
index 951e19231da2..2992fb87cf72 100644
--- a/drivers/staging/media/rkvdec/rkvdec-h264.c
+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c
@@ -97,13 +97,10 @@ struct rkvdec_h264_priv_tbl {
u8 err_info[RKV_ERROR_INFO_SIZE];
};
-#define RKVDEC_H264_DPB_SIZE 16
-
struct rkvdec_h264_reflists {
- u8 p[RKVDEC_H264_DPB_SIZE];
- u8 b0[RKVDEC_H264_DPB_SIZE];
- u8 b1[RKVDEC_H264_DPB_SIZE];
- u8 num_valid;
+ struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN];
+ struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN];
+ struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN];
};
struct rkvdec_h264_run {
@@ -112,6 +109,7 @@ struct rkvdec_h264_run {
const struct v4l2_ctrl_h264_sps *sps;
const struct v4l2_ctrl_h264_pps *pps;
const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix;
+ int ref_buf_idx[V4L2_H264_NUM_DPB_ENTRIES];
};
struct rkvdec_h264_ctx {
@@ -661,8 +659,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
WRITE_PPS(0xff, PROFILE_IDC);
WRITE_PPS(1, CONSTRAINT_SET3_FLAG);
WRITE_PPS(sps->chroma_format_idc, CHROMA_FORMAT_IDC);
- WRITE_PPS(sps->bit_depth_luma_minus8 + 8, BIT_DEPTH_LUMA);
- WRITE_PPS(sps->bit_depth_chroma_minus8 + 8, BIT_DEPTH_CHROMA);
+ WRITE_PPS(sps->bit_depth_luma_minus8, BIT_DEPTH_LUMA);
+ WRITE_PPS(sps->bit_depth_chroma_minus8, BIT_DEPTH_CHROMA);
WRITE_PPS(0, QPPRIME_Y_ZERO_TRANSFORM_BYPASS_FLAG);
WRITE_PPS(sps->log2_max_frame_num_minus4, LOG2_MAX_FRAME_NUM_MINUS4);
WRITE_PPS(sps->max_num_ref_frames, MAX_NUM_REF_FRAMES);
@@ -671,8 +669,17 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4);
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO),
DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG);
- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.width, 16), PIC_WIDTH_IN_MBS);
- WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.height, 16), PIC_HEIGHT_IN_MBS);
+
+ /*
+ * Use the SPS values since they are already in macroblocks
+ * dimensions, height can be field height (halved) if
+ * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is not set and also it allows
+ * decoding smaller images into larger allocation which can be used
+ * to implementing SVC spatial layer support.
+ */
+ WRITE_PPS(sps->pic_width_in_mbs_minus1 + 1, PIC_WIDTH_IN_MBS);
+ WRITE_PPS(sps->pic_height_in_map_units_minus1 + 1, PIC_HEIGHT_IN_MBS);
+
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY),
FRAME_MBS_ONLY_FLAG);
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD),
@@ -725,15 +732,38 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
}
}
+static void lookup_ref_buf_idx(struct rkvdec_ctx *ctx,
+ struct rkvdec_h264_run *run)
+{
+ const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
+ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+ const struct v4l2_h264_dpb_entry *dpb = run->decode_params->dpb;
+ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
+ int buf_idx = -1;
+
+ if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) {
+ buf_idx = vb2_find_timestamp(cap_q,
+ dpb[i].reference_ts, 0);
+ if (buf_idx < 0)
+ pr_debug("No buffer for reference_ts %llu",
+ dpb[i].reference_ts);
+ }
+
+ run->ref_buf_idx[i] = buf_idx;
+ }
+}
+
static void assemble_hw_rps(struct rkvdec_ctx *ctx,
+ struct v4l2_h264_reflist_builder *builder,
struct rkvdec_h264_run *run)
{
const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params;
const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb;
struct rkvdec_h264_ctx *h264_ctx = ctx->priv;
- const struct v4l2_ctrl_h264_sps *sps = run->sps;
struct rkvdec_h264_priv_tbl *priv_tbl = h264_ctx->priv_tbl.cpu;
- u32 max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
u32 *hw_rps = priv_tbl->rps;
u32 i, j;
@@ -751,39 +781,36 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx,
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
continue;
- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ||
- dpb[i].frame_num < dec_params->frame_num) {
- p[i] = dpb[i].frame_num;
- continue;
- }
-
- p[i] = dpb[i].frame_num - max_frame_num;
+ p[i] = builder->refs[i].frame_num;
}
for (j = 0; j < RKVDEC_NUM_REFLIST; j++) {
- for (i = 0; i < h264_ctx->reflists.num_valid; i++) {
- u8 dpb_valid = 0;
- u8 idx = 0;
+ for (i = 0; i < builder->num_valid; i++) {
+ struct v4l2_h264_reference *ref;
+ bool dpb_valid;
+ bool bottom;
switch (j) {
case 0:
- idx = h264_ctx->reflists.p[i];
+ ref = &h264_ctx->reflists.p[i];
break;
case 1:
- idx = h264_ctx->reflists.b0[i];
+ ref = &h264_ctx->reflists.b0[i];
break;
case 2:
- idx = h264_ctx->reflists.b1[i];
+ ref = &h264_ctx->reflists.b1[i];
break;
}
- if (idx >= ARRAY_SIZE(dec_params->dpb))
+ if (WARN_ON(ref->index >= ARRAY_SIZE(dec_params->dpb)))
continue;
- dpb_valid = !!(dpb[idx].flags &
- V4L2_H264_DPB_ENTRY_FLAG_ACTIVE);
+
+ dpb_valid = run->ref_buf_idx[ref->index] >= 0;
+ bottom = ref->fields == V4L2_H264_BOTTOM_FIELD_REF;
set_ps_field(hw_rps, DPB_INFO(i, j),
- idx | dpb_valid << 4);
+ ref->index | dpb_valid << 4);
+ set_ps_field(hw_rps, BOTTOM_FLAG(i, j), bottom);
}
}
}
@@ -859,13 +886,8 @@ get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_h264_run *run,
unsigned int dpb_idx)
{
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
- const struct v4l2_h264_dpb_entry *dpb = run->decode_params->dpb;
struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
- int buf_idx = -1;
-
- if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
- buf_idx = vb2_find_timestamp(cap_q,
- dpb[dpb_idx].reference_ts, 0);
+ int buf_idx = run->ref_buf_idx[dpb_idx];
/*
* If a DPB entry is unused or invalid, address of current destination
@@ -976,10 +998,6 @@ static void config_registers(struct rkvdec_ctx *ctx,
rkvdec->regs + RKVDEC_REG_H264_BASE_REFER15);
}
- /*
- * Since support frame mode only
- * top_field_order_cnt is the same as bottom_field_order_cnt
- */
reg = RKVDEC_CUR_POC(dec_params->top_field_order_cnt);
writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0);
@@ -1021,13 +1039,61 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
return 0;
}
+static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
+ const struct v4l2_ctrl_h264_sps *sps)
+{
+ unsigned int width, height;
+
+ /*
+ * TODO: The hardware supports 10-bit and 4:2:2 profiles,
+ * but it's currently broken in the driver.
+ * Reject them for now, until it's fixed.
+ */
+ if (sps->chroma_format_idc > 1)
+ /* Only 4:0:0 and 4:2:0 are supported */
+ return -EINVAL;
+ if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
+ /* Luma and chroma bit depth mismatch */
+ return -EINVAL;
+ if (sps->bit_depth_luma_minus8 != 0)
+ /* Only 8-bit is supported */
+ return -EINVAL;
+
+ width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
+ height = (sps->pic_height_in_map_units_minus1 + 1) * 16;
+
+ /*
+ * When frame_mbs_only_flag is not set, this is field height,
+ * which is half the final height (see (7-18) in the
+ * specification)
+ */
+ if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
+ height *= 2;
+
+ if (width > ctx->coded_fmt.fmt.pix_mp.width ||
+ height > ctx->coded_fmt.fmt.pix_mp.height)
+ return -EINVAL;
+
+ return 0;
+}
+
static int rkvdec_h264_start(struct rkvdec_ctx *ctx)
{
struct rkvdec_dev *rkvdec = ctx->dev;
struct rkvdec_h264_priv_tbl *priv_tbl;
struct rkvdec_h264_ctx *h264_ctx;
+ struct v4l2_ctrl *ctrl;
int ret;
+ ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
+ V4L2_CID_STATELESS_H264_SPS);
+ if (!ctrl)
+ return -EINVAL;
+
+ ret = rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps);
+ if (ret)
+ return ret;
+
h264_ctx = kzalloc(sizeof(*h264_ctx), GFP_KERNEL);
if (!h264_ctx)
return -ENOMEM;
@@ -1095,14 +1161,14 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
/* Build the P/B{0,1} ref lists. */
v4l2_h264_init_reflist_builder(&reflist_builder, run.decode_params,
run.sps, run.decode_params->dpb);
- h264_ctx->reflists.num_valid = reflist_builder.num_valid;
v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
h264_ctx->reflists.b1);
assemble_hw_scaling_list(ctx, &run);
assemble_hw_pps(ctx, &run);
- assemble_hw_rps(ctx, &run);
+ lookup_ref_buf_idx(ctx, &run);
+ assemble_hw_rps(ctx, &reflist_builder, &run);
config_registers(ctx, &run);
rkvdec_run_postamble(ctx, &run.base);
@@ -1122,9 +1188,18 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
return 0;
}
+static int rkvdec_h264_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
+{
+ if (ctrl->id == V4L2_CID_STATELESS_H264_SPS)
+ return rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps);
+
+ return 0;
+}
+
const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops = {
.adjust_fmt = rkvdec_h264_adjust_fmt,
.start = rkvdec_h264_start,
.stop = rkvdec_h264_stop,
.run = rkvdec_h264_run,
+ .try_ctrl = rkvdec_h264_try_ctrl,
};
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index c0cf3488f970..7bab7586918c 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -29,23 +29,12 @@
static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
{
- if (ctrl->id == V4L2_CID_STATELESS_H264_SPS) {
- const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
- /*
- * TODO: The hardware supports 10-bit and 4:2:2 profiles,
- * but it's currently broken in the driver.
- * Reject them for now, until it's fixed.
- */
- if (sps->chroma_format_idc > 1)
- /* Only 4:0:0 and 4:2:0 are supported */
- return -EINVAL;
- if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
- /* Luma and chroma bit depth mismatch */
- return -EINVAL;
- if (sps->bit_depth_luma_minus8 != 0)
- /* Only 8-bit is supported */
- return -EINVAL;
- }
+ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
+ const struct rkvdec_coded_fmt_desc *desc = ctx->coded_fmt_desc;
+
+ if (desc->ops->try_ctrl)
+ return desc->ops->try_ctrl(ctx, ctrl);
+
return 0;
}
@@ -138,6 +127,7 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
.ops = &rkvdec_h264_fmt_ops,
.num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_vp9_decoded_fmts),
.decoded_fmts = rkvdec_h264_vp9_decoded_fmts,
+ .subsystem_flags = VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF,
},
{
.fourcc = V4L2_PIX_FMT_VP9_FRAME,
@@ -268,6 +258,8 @@ static int rkvdec_try_capture_fmt(struct file *file, void *priv,
pix_mp->pixelformat = coded_desc->decoded_fmts[0];
/* Always apply the frmsize constraint of the coded end. */
+ pix_mp->width = max(pix_mp->width, ctx->coded_fmt.fmt.pix_mp.width);
+ pix_mp->height = max(pix_mp->height, ctx->coded_fmt.fmt.pix_mp.height);
v4l2_apply_frmsize_constraints(&pix_mp->width,
&pix_mp->height,
&coded_desc->frmsize);
@@ -394,6 +386,9 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv,
cap_fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
cap_fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
+ /* Enable format specific queue features */
+ vq->subsystem_flags |= desc->subsystem_flags;
+
return 0;
}
@@ -1027,12 +1022,6 @@ static int rkvdec_probe(struct platform_device *pdev)
if (ret)
return ret;
- /*
- * Bump ACLK to max. possible freq. (500 MHz) to improve performance
- * When 4k video playback.
- */
- clk_set_rate(rkvdec->clocks[0].clk, 500 * 1000 * 1000);
-
rkvdec->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rkvdec->regs))
return PTR_ERR(rkvdec->regs);
diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h
index 2f4ea1786b93..633335ebb9c4 100644
--- a/drivers/staging/media/rkvdec/rkvdec.h
+++ b/drivers/staging/media/rkvdec/rkvdec.h
@@ -72,6 +72,7 @@ struct rkvdec_coded_fmt_ops {
void (*done)(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *src_buf,
struct vb2_v4l2_buffer *dst_buf,
enum vb2_buffer_state result);
+ int (*try_ctrl)(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl);
};
struct rkvdec_coded_fmt_desc {
@@ -81,6 +82,7 @@ struct rkvdec_coded_fmt_desc {
const struct rkvdec_coded_fmt_ops *ops;
unsigned int num_decoded_fmts;
const u32 *decoded_fmts;
+ u32 subsystem_flags;
};
struct rkvdec_dev {
diff --git a/drivers/staging/media/sunxi/cedrus/Kconfig b/drivers/staging/media/sunxi/cedrus/Kconfig
index da369950bbf2..21c13f9b6e33 100644
--- a/drivers/staging/media/sunxi/cedrus/Kconfig
+++ b/drivers/staging/media/sunxi/cedrus/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config VIDEO_SUNXI_CEDRUS
tristate "Allwinner Cedrus VPU driver"
- depends on VIDEO_DEV && VIDEO_V4L2
+ depends on VIDEO_DEV
depends on HAS_DMA
depends on OF
select MEDIA_CONTROLLER
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
index 4a4b714b0f26..68b3dcdb5df3 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -439,6 +439,8 @@ static int cedrus_probe(struct platform_device *pdev)
mutex_init(&dev->dev_mutex);
+ INIT_DELAYED_WORK(&dev->watchdog_work, cedrus_watchdog);
+
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to register V4L2 device\n");
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h
index c345f2984041..3bc094eb497f 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.h
@@ -24,6 +24,7 @@
#include <linux/iopoll.h>
#include <linux/platform_device.h>
+#include <linux/workqueue.h>
#define CEDRUS_NAME "cedrus"
@@ -194,6 +195,8 @@ struct cedrus_dev {
struct reset_control *rstc;
unsigned int capabilities;
+
+ struct delayed_work watchdog_work;
};
extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
index a16c1422558f..9c7200299465 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
@@ -97,4 +97,8 @@ void cedrus_device_run(void *priv)
v4l2_ctrl_request_complete(src_req, &ctx->hdl);
dev->dec_ops[ctx->current_codec]->trigger(ctx);
+
+ /* Start the watchdog timer. */
+ schedule_delayed_work(&dev->watchdog_work,
+ msecs_to_jiffies(2000));
}
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
index b4173a8926d6..d8fb93035470 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -38,7 +38,7 @@ struct cedrus_h264_sram_ref_pic {
#define CEDRUS_H264_FRAME_NUM 18
-#define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (16 * SZ_1K)
+#define CEDRUS_NEIGHBOR_INFO_BUF_SIZE (32 * SZ_1K)
#define CEDRUS_MIN_PIC_INFO_BUF_SIZE (130 * SZ_1K)
static void cedrus_h264_write_sram(struct cedrus_dev *dev,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
index 8829a7bab07e..44f385be9f6c 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
@@ -23,7 +23,7 @@
* Subsequent BSP implementations seem to double the neighbor info buffer size
* for the H6 SoC, which may be related to 10 bit H265 support.
*/
-#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (397 * SZ_1K)
+#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (794 * SZ_1K)
#define CEDRUS_H265_ENTRY_POINTS_BUF_SIZE (4 * SZ_1K)
#define CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE 160
@@ -169,7 +169,7 @@ static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev,
unsigned int index = list[i];
u8 value = list[i];
- if (dpb[index].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR)
+ if (dpb[index].flags & V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE)
value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF;
/* Each SRAM word gathers up to 4 references. */
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
index 2d7663726467..a6470a89851e 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
@@ -118,6 +118,13 @@ static irqreturn_t cedrus_irq(int irq, void *data)
enum vb2_buffer_state state;
enum cedrus_irq_status status;
+ /*
+ * If cancel_delayed_work returns false it means watchdog already
+ * executed and finished the job.
+ */
+ if (!cancel_delayed_work(&dev->watchdog_work))
+ return IRQ_HANDLED;
+
ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
if (!ctx) {
v4l2_err(&dev->v4l2_dev,
@@ -143,6 +150,24 @@ static irqreturn_t cedrus_irq(int irq, void *data)
return IRQ_HANDLED;
}
+void cedrus_watchdog(struct work_struct *work)
+{
+ struct cedrus_dev *dev;
+ struct cedrus_ctx *ctx;
+
+ dev = container_of(to_delayed_work(work),
+ struct cedrus_dev, watchdog_work);
+
+ ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+ if (!ctx)
+ return;
+
+ v4l2_err(&dev->v4l2_dev, "frame processing timed out!\n");
+ reset_control_reset(dev->rstc);
+ v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx,
+ VB2_BUF_STATE_ERROR);
+}
+
int cedrus_hw_suspend(struct device *device)
{
struct cedrus_dev *dev = dev_get_drvdata(device);
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
index 45f641f0bfa2..7c92f00e36da 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
@@ -28,4 +28,6 @@ int cedrus_hw_resume(struct device *device);
int cedrus_hw_probe(struct cedrus_dev *dev);
void cedrus_hw_remove(struct cedrus_dev *dev);
+void cedrus_watchdog(struct work_struct *work);
+
#endif
diff --git a/drivers/staging/media/tegra-vde/Kconfig b/drivers/staging/media/tegra-vde/Kconfig
deleted file mode 100644
index 0dc78afd09e0..000000000000
--- a/drivers/staging/media/tegra-vde/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config TEGRA_VDE
- tristate "NVIDIA Tegra Video Decoder Engine driver"
- depends on ARCH_TEGRA || COMPILE_TEST
- select DMA_SHARED_BUFFER
- select IOMMU_IOVA
- select SRAM
- help
- Say Y here to enable support for the NVIDIA Tegra video decoder
- driver.
diff --git a/drivers/staging/media/tegra-vde/Makefile b/drivers/staging/media/tegra-vde/Makefile
deleted file mode 100644
index 2827f7601de8..000000000000
--- a/drivers/staging/media/tegra-vde/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-tegra-vde-y := vde.o iommu.o dmabuf-cache.o
-obj-$(CONFIG_TEGRA_VDE) += tegra-vde.o
diff --git a/drivers/staging/media/tegra-vde/TODO b/drivers/staging/media/tegra-vde/TODO
deleted file mode 100644
index 31aaa3e66d80..000000000000
--- a/drivers/staging/media/tegra-vde/TODO
+++ /dev/null
@@ -1,4 +0,0 @@
-TODO:
- - Implement V4L2 API once it gains support for stateless decoders.
-
-Contact: Dmitry Osipenko <digetx@gmail.com>
diff --git a/drivers/staging/media/tegra-vde/dmabuf-cache.c b/drivers/staging/media/tegra-vde/dmabuf-cache.c
deleted file mode 100644
index a98d03419b8f..000000000000
--- a/drivers/staging/media/tegra-vde/dmabuf-cache.c
+++ /dev/null
@@ -1,229 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * NVIDIA Tegra Video decoder driver
- *
- * Copyright (C) 2016-2019 GRATE-DRIVER project
- */
-
-#include <linux/dma-buf.h>
-#include <linux/iova.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/module.h>
-
-#include "vde.h"
-
-MODULE_IMPORT_NS(DMA_BUF);
-
-struct tegra_vde_cache_entry {
- enum dma_data_direction dma_dir;
- struct dma_buf_attachment *a;
- struct delayed_work dwork;
- struct tegra_vde *vde;
- struct list_head list;
- struct sg_table *sgt;
- struct iova *iova;
- unsigned int refcnt;
-};
-
-static void tegra_vde_release_entry(struct tegra_vde_cache_entry *entry)
-{
- struct dma_buf *dmabuf = entry->a->dmabuf;
-
- WARN_ON_ONCE(entry->refcnt);
-
- if (entry->vde->domain)
- tegra_vde_iommu_unmap(entry->vde, entry->iova);
-
- dma_buf_unmap_attachment(entry->a, entry->sgt, entry->dma_dir);
- dma_buf_detach(dmabuf, entry->a);
- dma_buf_put(dmabuf);
-
- list_del(&entry->list);
- kfree(entry);
-}
-
-static void tegra_vde_delayed_unmap(struct work_struct *work)
-{
- struct tegra_vde_cache_entry *entry;
- struct tegra_vde *vde;
-
- entry = container_of(work, struct tegra_vde_cache_entry,
- dwork.work);
- vde = entry->vde;
-
- mutex_lock(&vde->map_lock);
- tegra_vde_release_entry(entry);
- mutex_unlock(&vde->map_lock);
-}
-
-int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde,
- struct dma_buf *dmabuf,
- enum dma_data_direction dma_dir,
- struct dma_buf_attachment **ap,
- dma_addr_t *addrp)
-{
- struct device *dev = vde->miscdev.parent;
- struct dma_buf_attachment *attachment;
- struct tegra_vde_cache_entry *entry;
- struct sg_table *sgt;
- struct iova *iova;
- int err;
-
- mutex_lock(&vde->map_lock);
-
- list_for_each_entry(entry, &vde->map_list, list) {
- if (entry->a->dmabuf != dmabuf)
- continue;
-
- if (!cancel_delayed_work(&entry->dwork))
- continue;
-
- if (entry->dma_dir != dma_dir)
- entry->dma_dir = DMA_BIDIRECTIONAL;
-
- dma_buf_put(dmabuf);
-
- if (vde->domain)
- *addrp = iova_dma_addr(&vde->iova, entry->iova);
- else
- *addrp = sg_dma_address(entry->sgt->sgl);
-
- goto ref;
- }
-
- attachment = dma_buf_attach(dmabuf, dev);
- if (IS_ERR(attachment)) {
- dev_err(dev, "Failed to attach dmabuf\n");
- err = PTR_ERR(attachment);
- goto err_unlock;
- }
-
- sgt = dma_buf_map_attachment(attachment, dma_dir);
- if (IS_ERR(sgt)) {
- dev_err(dev, "Failed to get dmabufs sg_table\n");
- err = PTR_ERR(sgt);
- goto err_detach;
- }
-
- if (!vde->domain && sgt->nents > 1) {
- dev_err(dev, "Sparse DMA region is unsupported, please enable IOMMU\n");
- err = -EINVAL;
- goto err_unmap;
- }
-
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- err = -ENOMEM;
- goto err_unmap;
- }
-
- if (vde->domain) {
- err = tegra_vde_iommu_map(vde, sgt, &iova, dmabuf->size);
- if (err)
- goto err_free;
-
- *addrp = iova_dma_addr(&vde->iova, iova);
- } else {
- *addrp = sg_dma_address(sgt->sgl);
- iova = NULL;
- }
-
- INIT_DELAYED_WORK(&entry->dwork, tegra_vde_delayed_unmap);
- list_add(&entry->list, &vde->map_list);
-
- entry->dma_dir = dma_dir;
- entry->iova = iova;
- entry->vde = vde;
- entry->sgt = sgt;
- entry->a = attachment;
-ref:
- entry->refcnt++;
-
- *ap = entry->a;
-
- mutex_unlock(&vde->map_lock);
-
- return 0;
-
-err_free:
- kfree(entry);
-err_unmap:
- dma_buf_unmap_attachment(attachment, sgt, dma_dir);
-err_detach:
- dma_buf_detach(dmabuf, attachment);
-err_unlock:
- mutex_unlock(&vde->map_lock);
-
- return err;
-}
-
-void tegra_vde_dmabuf_cache_unmap(struct tegra_vde *vde,
- struct dma_buf_attachment *a,
- bool release)
-{
- struct tegra_vde_cache_entry *entry;
-
- mutex_lock(&vde->map_lock);
-
- list_for_each_entry(entry, &vde->map_list, list) {
- if (entry->a != a)
- continue;
-
- WARN_ON_ONCE(!entry->refcnt);
-
- if (--entry->refcnt == 0) {
- if (release)
- tegra_vde_release_entry(entry);
- else
- schedule_delayed_work(&entry->dwork, 5 * HZ);
- }
- break;
- }
-
- mutex_unlock(&vde->map_lock);
-}
-
-void tegra_vde_dmabuf_cache_unmap_sync(struct tegra_vde *vde)
-{
- struct tegra_vde_cache_entry *entry, *tmp;
-
- mutex_lock(&vde->map_lock);
-
- list_for_each_entry_safe(entry, tmp, &vde->map_list, list) {
- if (entry->refcnt)
- continue;
-
- if (!cancel_delayed_work(&entry->dwork))
- continue;
-
- tegra_vde_release_entry(entry);
- }
-
- mutex_unlock(&vde->map_lock);
-}
-
-void tegra_vde_dmabuf_cache_unmap_all(struct tegra_vde *vde)
-{
- struct tegra_vde_cache_entry *entry, *tmp;
-
- mutex_lock(&vde->map_lock);
-
- while (!list_empty(&vde->map_list)) {
- list_for_each_entry_safe(entry, tmp, &vde->map_list, list) {
- if (!cancel_delayed_work(&entry->dwork))
- continue;
-
- tegra_vde_release_entry(entry);
- }
-
- mutex_unlock(&vde->map_lock);
- schedule();
- mutex_lock(&vde->map_lock);
- }
-
- mutex_unlock(&vde->map_lock);
-}
diff --git a/drivers/staging/media/tegra-vde/iommu.c b/drivers/staging/media/tegra-vde/iommu.c
deleted file mode 100644
index adf8dc7ee25c..000000000000
--- a/drivers/staging/media/tegra-vde/iommu.c
+++ /dev/null
@@ -1,157 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * NVIDIA Tegra Video decoder driver
- *
- * Copyright (C) 2016-2019 GRATE-DRIVER project
- */
-
-#include <linux/iommu.h>
-#include <linux/iova.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
-#include <asm/dma-iommu.h>
-#endif
-
-#include "vde.h"
-
-int tegra_vde_iommu_map(struct tegra_vde *vde,
- struct sg_table *sgt,
- struct iova **iovap,
- size_t size)
-{
- struct iova *iova;
- unsigned long shift;
- unsigned long end;
- dma_addr_t addr;
-
- end = vde->domain->geometry.aperture_end;
- size = iova_align(&vde->iova, size);
- shift = iova_shift(&vde->iova);
-
- iova = alloc_iova(&vde->iova, size >> shift, end >> shift, true);
- if (!iova)
- return -ENOMEM;
-
- addr = iova_dma_addr(&vde->iova, iova);
-
- size = iommu_map_sgtable(vde->domain, addr, sgt,
- IOMMU_READ | IOMMU_WRITE);
- if (!size) {
- __free_iova(&vde->iova, iova);
- return -ENXIO;
- }
-
- *iovap = iova;
-
- return 0;
-}
-
-void tegra_vde_iommu_unmap(struct tegra_vde *vde, struct iova *iova)
-{
- unsigned long shift = iova_shift(&vde->iova);
- unsigned long size = iova_size(iova) << shift;
- dma_addr_t addr = iova_dma_addr(&vde->iova, iova);
-
- iommu_unmap(vde->domain, addr, size);
- __free_iova(&vde->iova, iova);
-}
-
-int tegra_vde_iommu_init(struct tegra_vde *vde)
-{
- struct device *dev = vde->miscdev.parent;
- struct iova *iova;
- unsigned long order;
- unsigned long shift;
- int err;
-
- vde->group = iommu_group_get(dev);
- if (!vde->group)
- return 0;
-
-#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
- if (dev->archdata.mapping) {
- struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
-
- arm_iommu_detach_device(dev);
- arm_iommu_release_mapping(mapping);
- }
-#endif
- vde->domain = iommu_domain_alloc(&platform_bus_type);
- if (!vde->domain) {
- err = -ENOMEM;
- goto put_group;
- }
-
- err = iova_cache_get();
- if (err)
- goto free_domain;
-
- order = __ffs(vde->domain->pgsize_bitmap);
- init_iova_domain(&vde->iova, 1UL << order, 0);
-
- err = iommu_attach_group(vde->domain, vde->group);
- if (err)
- goto put_iova;
-
- /*
- * We're using some static addresses that are not accessible by VDE
- * to trap invalid memory accesses.
- */
- shift = iova_shift(&vde->iova);
- iova = reserve_iova(&vde->iova, 0x60000000 >> shift,
- 0x70000000 >> shift);
- if (!iova) {
- err = -ENOMEM;
- goto detach_group;
- }
-
- vde->iova_resv_static_addresses = iova;
-
- /*
- * BSEV's end-address wraps around due to integer overflow during
- * of hardware context preparation if IOVA is allocated at the end
- * of address space and VDE can't handle that. Hence simply reserve
- * the last page to avoid the problem.
- */
- iova = reserve_iova(&vde->iova, 0xffffffff >> shift,
- (0xffffffff >> shift) + 1);
- if (!iova) {
- err = -ENOMEM;
- goto unreserve_iova;
- }
-
- vde->iova_resv_last_page = iova;
-
- return 0;
-
-unreserve_iova:
- __free_iova(&vde->iova, vde->iova_resv_static_addresses);
-detach_group:
- iommu_detach_group(vde->domain, vde->group);
-put_iova:
- put_iova_domain(&vde->iova);
- iova_cache_put();
-free_domain:
- iommu_domain_free(vde->domain);
-put_group:
- iommu_group_put(vde->group);
-
- return err;
-}
-
-void tegra_vde_iommu_deinit(struct tegra_vde *vde)
-{
- if (vde->domain) {
- __free_iova(&vde->iova, vde->iova_resv_last_page);
- __free_iova(&vde->iova, vde->iova_resv_static_addresses);
- iommu_detach_group(vde->domain, vde->group);
- put_iova_domain(&vde->iova);
- iova_cache_put();
- iommu_domain_free(vde->domain);
- iommu_group_put(vde->group);
-
- vde->domain = NULL;
- }
-}
diff --git a/drivers/staging/media/tegra-vde/trace.h b/drivers/staging/media/tegra-vde/trace.h
deleted file mode 100644
index e5714107db58..000000000000
--- a/drivers/staging/media/tegra-vde/trace.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM tegra_vde
-
-#if !defined(TEGRA_VDE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define TEGRA_VDE_TRACE_H
-
-#include <linux/tracepoint.h>
-
-#include "vde.h"
-
-DECLARE_EVENT_CLASS(register_access,
- TP_PROTO(struct tegra_vde *vde, void __iomem *base,
- u32 offset, u32 value),
- TP_ARGS(vde, base, offset, value),
- TP_STRUCT__entry(
- __string(hw_name, tegra_vde_reg_base_name(vde, base))
- __field(u32, offset)
- __field(u32, value)
- ),
- TP_fast_assign(
- __assign_str(hw_name, tegra_vde_reg_base_name(vde, base));
- __entry->offset = offset;
- __entry->value = value;
- ),
- TP_printk("%s:0x%03x 0x%08x", __get_str(hw_name), __entry->offset,
- __entry->value)
-);
-
-DEFINE_EVENT(register_access, vde_writel,
- TP_PROTO(struct tegra_vde *vde, void __iomem *base,
- u32 offset, u32 value),
- TP_ARGS(vde, base, offset, value));
-DEFINE_EVENT(register_access, vde_readl,
- TP_PROTO(struct tegra_vde *vde, void __iomem *base,
- u32 offset, u32 value),
- TP_ARGS(vde, base, offset, value));
-
-TRACE_EVENT(vde_setup_iram_entry,
- TP_PROTO(unsigned int table, unsigned int row, u32 value, u32 aux_addr),
- TP_ARGS(table, row, value, aux_addr),
- TP_STRUCT__entry(
- __field(unsigned int, table)
- __field(unsigned int, row)
- __field(u32, value)
- __field(u32, aux_addr)
- ),
- TP_fast_assign(
- __entry->table = table;
- __entry->row = row;
- __entry->value = value;
- __entry->aux_addr = aux_addr;
- ),
- TP_printk("[%u][%u] = { 0x%08x (flags = \"%s\", frame_num = %u); 0x%08x }",
- __entry->table, __entry->row, __entry->value,
- __print_flags(__entry->value, " ", { (1 << 25), "B" }),
- __entry->value & 0x7FFFFF, __entry->aux_addr)
-);
-
-TRACE_EVENT(vde_ref_l0,
- TP_PROTO(unsigned int frame_num),
- TP_ARGS(frame_num),
- TP_STRUCT__entry(
- __field(unsigned int, frame_num)
- ),
- TP_fast_assign(
- __entry->frame_num = frame_num;
- ),
- TP_printk("REF L0: DPB: Frame 0: frame_num = %u", __entry->frame_num)
-);
-
-TRACE_EVENT(vde_ref_l1,
- TP_PROTO(unsigned int with_later_poc_nb,
- unsigned int with_earlier_poc_nb),
- TP_ARGS(with_later_poc_nb, with_earlier_poc_nb),
- TP_STRUCT__entry(
- __field(unsigned int, with_later_poc_nb)
- __field(unsigned int, with_earlier_poc_nb)
- ),
- TP_fast_assign(
- __entry->with_later_poc_nb = with_later_poc_nb;
- __entry->with_earlier_poc_nb = with_earlier_poc_nb;
- ),
- TP_printk("REF L1: with_later_poc_nb %u, with_earlier_poc_nb %u",
- __entry->with_later_poc_nb, __entry->with_earlier_poc_nb)
-);
-
-#endif /* TEGRA_VDE_TRACE_H */
-
-/* This part must be outside protection */
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH ../../drivers/staging/media/tegra-vde
-#define TRACE_INCLUDE_FILE trace
-#include <trace/define_trace.h>
diff --git a/drivers/staging/media/tegra-vde/uapi.h b/drivers/staging/media/tegra-vde/uapi.h
deleted file mode 100644
index ffb4983e5bb6..000000000000
--- a/drivers/staging/media/tegra-vde/uapi.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/* Copyright (C) 2016-2017 Dmitry Osipenko <digetx@gmail.com> */
-#ifndef _UAPI_TEGRA_VDE_H_
-#define _UAPI_TEGRA_VDE_H_
-
-#include <linux/types.h>
-#include <asm/ioctl.h>
-
-#define FLAG_B_FRAME 0x1
-#define FLAG_REFERENCE 0x2
-
-struct tegra_vde_h264_frame {
- __s32 y_fd;
- __s32 cb_fd;
- __s32 cr_fd;
- __s32 aux_fd;
- __u32 y_offset;
- __u32 cb_offset;
- __u32 cr_offset;
- __u32 aux_offset;
- __u32 frame_num;
- __u32 flags;
-
- // Must be zero'ed
- __u32 reserved[6];
-};
-
-struct tegra_vde_h264_decoder_ctx {
- __s32 bitstream_data_fd;
- __u32 bitstream_data_offset;
-
- __u64 dpb_frames_ptr;
- __u32 dpb_frames_nb;
- __u32 dpb_ref_frames_with_earlier_poc_nb;
-
- // SPS
- __u32 baseline_profile;
- __u32 level_idc;
- __u32 log2_max_pic_order_cnt_lsb;
- __u32 log2_max_frame_num;
- __u32 pic_order_cnt_type;
- __u32 direct_8x8_inference_flag;
- __u32 pic_width_in_mbs;
- __u32 pic_height_in_mbs;
-
- // PPS
- __u32 pic_init_qp;
- __u32 deblocking_filter_control_present_flag;
- __u32 constrained_intra_pred_flag;
- __u32 chroma_qp_index_offset;
- __u32 pic_order_present_flag;
-
- // Slice header
- __u32 num_ref_idx_l0_active_minus1;
- __u32 num_ref_idx_l1_active_minus1;
-
- // Must be zero'ed
- __u32 reserved[11];
-};
-
-#define VDE_IOCTL_BASE ('v' + 0x20)
-
-#define VDE_IO(nr) _IO(VDE_IOCTL_BASE, nr)
-#define VDE_IOR(nr, type) _IOR(VDE_IOCTL_BASE, nr, type)
-#define VDE_IOW(nr, type) _IOW(VDE_IOCTL_BASE, nr, type)
-#define VDE_IOWR(nr, type) _IOWR(VDE_IOCTL_BASE, nr, type)
-
-#define TEGRA_VDE_DECODE_H264 0x00
-
-#define TEGRA_VDE_IOCTL_DECODE_H264 \
- VDE_IOW(TEGRA_VDE_DECODE_H264, struct tegra_vde_h264_decoder_ctx)
-
-#endif // _UAPI_TEGRA_VDE_H_
diff --git a/drivers/staging/media/tegra-vde/vde.c b/drivers/staging/media/tegra-vde/vde.c
deleted file mode 100644
index a8f1a024c343..000000000000
--- a/drivers/staging/media/tegra-vde/vde.c
+++ /dev/null
@@ -1,1358 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * NVIDIA Tegra Video decoder driver
- *
- * Copyright (C) 2016-2017 Dmitry Osipenko <digetx@gmail.com>
- *
- */
-
-#include <linux/clk.h>
-#include <linux/dma-buf.h>
-#include <linux/genalloc.h>
-#include <linux/interrupt.h>
-#include <linux/iopoll.h>
-#include <linux/list.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include <soc/tegra/common.h>
-#include <soc/tegra/pmc.h>
-
-#include "uapi.h"
-#include "vde.h"
-
-#define CREATE_TRACE_POINTS
-#include "trace.h"
-
-#define ICMDQUE_WR 0x00
-#define CMDQUE_CONTROL 0x08
-#define INTR_STATUS 0x18
-#define BSE_INT_ENB 0x40
-#define BSE_CONFIG 0x44
-
-#define BSE_ICMDQUE_EMPTY BIT(3)
-#define BSE_DMA_BUSY BIT(23)
-
-struct video_frame {
- struct dma_buf_attachment *y_dmabuf_attachment;
- struct dma_buf_attachment *cb_dmabuf_attachment;
- struct dma_buf_attachment *cr_dmabuf_attachment;
- struct dma_buf_attachment *aux_dmabuf_attachment;
- dma_addr_t y_addr;
- dma_addr_t cb_addr;
- dma_addr_t cr_addr;
- dma_addr_t aux_addr;
- u32 frame_num;
- u32 flags;
-};
-
-static void tegra_vde_writel(struct tegra_vde *vde,
- u32 value, void __iomem *base, u32 offset)
-{
- trace_vde_writel(vde, base, offset, value);
-
- writel_relaxed(value, base + offset);
-}
-
-static u32 tegra_vde_readl(struct tegra_vde *vde,
- void __iomem *base, u32 offset)
-{
- u32 value = readl_relaxed(base + offset);
-
- trace_vde_readl(vde, base, offset, value);
-
- return value;
-}
-
-static void tegra_vde_set_bits(struct tegra_vde *vde,
- u32 mask, void __iomem *base, u32 offset)
-{
- u32 value = tegra_vde_readl(vde, base, offset);
-
- tegra_vde_writel(vde, value | mask, base, offset);
-}
-
-static int tegra_vde_wait_mbe(struct tegra_vde *vde)
-{
- u32 tmp;
-
- return readl_relaxed_poll_timeout(vde->mbe + 0x8C, tmp,
- (tmp >= 0x10), 1, 100);
-}
-
-static int tegra_vde_alloc_bo(struct tegra_vde *vde,
- struct tegra_vde_bo **ret_bo,
- enum dma_data_direction dma_dir,
- size_t size)
-{
- struct device *dev = vde->miscdev.parent;
- struct tegra_vde_bo *bo;
- int err;
-
- bo = kzalloc(sizeof(*bo), GFP_KERNEL);
- if (!bo)
- return -ENOMEM;
-
- bo->vde = vde;
- bo->size = size;
- bo->dma_dir = dma_dir;
- bo->dma_attrs = DMA_ATTR_WRITE_COMBINE |
- DMA_ATTR_NO_KERNEL_MAPPING;
-
- if (!vde->domain)
- bo->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
-
- bo->dma_cookie = dma_alloc_attrs(dev, bo->size, &bo->dma_handle,
- GFP_KERNEL, bo->dma_attrs);
- if (!bo->dma_cookie) {
- dev_err(dev, "Failed to allocate DMA buffer of size: %zu\n",
- bo->size);
- err = -ENOMEM;
- goto free_bo;
- }
-
- err = dma_get_sgtable_attrs(dev, &bo->sgt, bo->dma_cookie,
- bo->dma_handle, bo->size, bo->dma_attrs);
- if (err) {
- dev_err(dev, "Failed to get DMA buffer SG table: %d\n", err);
- goto free_attrs;
- }
-
- err = dma_map_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs);
- if (err) {
- dev_err(dev, "Failed to map DMA buffer SG table: %d\n", err);
- goto free_table;
- }
-
- if (vde->domain) {
- err = tegra_vde_iommu_map(vde, &bo->sgt, &bo->iova, bo->size);
- if (err) {
- dev_err(dev, "Failed to map DMA buffer IOVA: %d\n", err);
- goto unmap_sgtable;
- }
-
- bo->dma_addr = iova_dma_addr(&vde->iova, bo->iova);
- } else {
- bo->dma_addr = sg_dma_address(bo->sgt.sgl);
- }
-
- *ret_bo = bo;
-
- return 0;
-
-unmap_sgtable:
- dma_unmap_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs);
-free_table:
- sg_free_table(&bo->sgt);
-free_attrs:
- dma_free_attrs(dev, bo->size, bo->dma_cookie, bo->dma_handle,
- bo->dma_attrs);
-free_bo:
- kfree(bo);
-
- return err;
-}
-
-static void tegra_vde_free_bo(struct tegra_vde_bo *bo)
-{
- struct tegra_vde *vde = bo->vde;
- struct device *dev = vde->miscdev.parent;
-
- if (vde->domain)
- tegra_vde_iommu_unmap(vde, bo->iova);
-
- dma_unmap_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs);
-
- sg_free_table(&bo->sgt);
-
- dma_free_attrs(dev, bo->size, bo->dma_cookie, bo->dma_handle,
- bo->dma_attrs);
- kfree(bo);
-}
-
-static int tegra_vde_setup_mbe_frame_idx(struct tegra_vde *vde,
- unsigned int refs_nb,
- bool setup_refs)
-{
- u32 frame_idx_enb_mask = 0;
- u32 value;
- unsigned int frame_idx;
- unsigned int idx;
- int err;
-
- tegra_vde_writel(vde, 0xD0000000 | (0 << 23), vde->mbe, 0x80);
- tegra_vde_writel(vde, 0xD0200000 | (0 << 23), vde->mbe, 0x80);
-
- err = tegra_vde_wait_mbe(vde);
- if (err)
- return err;
-
- if (!setup_refs)
- return 0;
-
- for (idx = 0, frame_idx = 1; idx < refs_nb; idx++, frame_idx++) {
- tegra_vde_writel(vde, 0xD0000000 | (frame_idx << 23),
- vde->mbe, 0x80);
- tegra_vde_writel(vde, 0xD0200000 | (frame_idx << 23),
- vde->mbe, 0x80);
-
- frame_idx_enb_mask |= frame_idx << (6 * (idx % 4));
-
- if (idx % 4 == 3 || idx == refs_nb - 1) {
- value = 0xC0000000;
- value |= (idx >> 2) << 24;
- value |= frame_idx_enb_mask;
-
- tegra_vde_writel(vde, value, vde->mbe, 0x80);
-
- err = tegra_vde_wait_mbe(vde);
- if (err)
- return err;
-
- frame_idx_enb_mask = 0;
- }
- }
-
- return 0;
-}
-
-static void tegra_vde_mbe_set_0xa_reg(struct tegra_vde *vde, int reg, u32 val)
-{
- tegra_vde_writel(vde, 0xA0000000 | (reg << 24) | (val & 0xFFFF),
- vde->mbe, 0x80);
- tegra_vde_writel(vde, 0xA0000000 | ((reg + 1) << 24) | (val >> 16),
- vde->mbe, 0x80);
-}
-
-static int tegra_vde_wait_bsev(struct tegra_vde *vde, bool wait_dma)
-{
- struct device *dev = vde->miscdev.parent;
- u32 value;
- int err;
-
- err = readl_relaxed_poll_timeout(vde->bsev + INTR_STATUS, value,
- !(value & BIT(2)), 1, 100);
- if (err) {
- dev_err(dev, "BSEV unknown bit timeout\n");
- return err;
- }
-
- err = readl_relaxed_poll_timeout(vde->bsev + INTR_STATUS, value,
- (value & BSE_ICMDQUE_EMPTY), 1, 100);
- if (err) {
- dev_err(dev, "BSEV ICMDQUE flush timeout\n");
- return err;
- }
-
- if (!wait_dma)
- return 0;
-
- err = readl_relaxed_poll_timeout(vde->bsev + INTR_STATUS, value,
- !(value & BSE_DMA_BUSY), 1, 100);
- if (err) {
- dev_err(dev, "BSEV DMA timeout\n");
- return err;
- }
-
- return 0;
-}
-
-static int tegra_vde_push_to_bsev_icmdqueue(struct tegra_vde *vde,
- u32 value, bool wait_dma)
-{
- tegra_vde_writel(vde, value, vde->bsev, ICMDQUE_WR);
-
- return tegra_vde_wait_bsev(vde, wait_dma);
-}
-
-static void tegra_vde_setup_frameid(struct tegra_vde *vde,
- struct video_frame *frame,
- unsigned int frameid,
- u32 mbs_width, u32 mbs_height)
-{
- u32 y_addr = frame ? frame->y_addr : 0x6CDEAD00;
- u32 cb_addr = frame ? frame->cb_addr : 0x6CDEAD00;
- u32 cr_addr = frame ? frame->cr_addr : 0x6CDEAD00;
- u32 value1 = frame ? ((mbs_width << 16) | mbs_height) : 0;
- u32 value2 = frame ? ((((mbs_width + 1) >> 1) << 6) | 1) : 0;
-
- tegra_vde_writel(vde, y_addr >> 8, vde->frameid, 0x000 + frameid * 4);
- tegra_vde_writel(vde, cb_addr >> 8, vde->frameid, 0x100 + frameid * 4);
- tegra_vde_writel(vde, cr_addr >> 8, vde->frameid, 0x180 + frameid * 4);
- tegra_vde_writel(vde, value1, vde->frameid, 0x080 + frameid * 4);
- tegra_vde_writel(vde, value2, vde->frameid, 0x280 + frameid * 4);
-}
-
-static void tegra_setup_frameidx(struct tegra_vde *vde,
- struct video_frame *frames,
- unsigned int frames_nb,
- u32 mbs_width, u32 mbs_height)
-{
- unsigned int idx;
-
- for (idx = 0; idx < frames_nb; idx++)
- tegra_vde_setup_frameid(vde, &frames[idx], idx,
- mbs_width, mbs_height);
-
- for (; idx < 17; idx++)
- tegra_vde_setup_frameid(vde, NULL, idx, 0, 0);
-}
-
-static void tegra_vde_setup_iram_entry(struct tegra_vde *vde,
- unsigned int table,
- unsigned int row,
- u32 value1, u32 value2)
-{
- u32 *iram_tables = vde->iram;
-
- trace_vde_setup_iram_entry(table, row, value1, value2);
-
- iram_tables[0x20 * table + row * 2] = value1;
- iram_tables[0x20 * table + row * 2 + 1] = value2;
-}
-
-static void tegra_vde_setup_iram_tables(struct tegra_vde *vde,
- struct video_frame *dpb_frames,
- unsigned int ref_frames_nb,
- unsigned int with_earlier_poc_nb)
-{
- struct video_frame *frame;
- u32 value, aux_addr;
- int with_later_poc_nb;
- unsigned int i, k;
-
- trace_vde_ref_l0(dpb_frames[0].frame_num);
-
- for (i = 0; i < 16; i++) {
- if (i < ref_frames_nb) {
- frame = &dpb_frames[i + 1];
-
- aux_addr = frame->aux_addr;
-
- value = (i + 1) << 26;
- value |= !(frame->flags & FLAG_B_FRAME) << 25;
- value |= 1 << 24;
- value |= frame->frame_num;
- } else {
- aux_addr = 0x6ADEAD00;
- value = 0x3f;
- }
-
- tegra_vde_setup_iram_entry(vde, 0, i, value, aux_addr);
- tegra_vde_setup_iram_entry(vde, 1, i, value, aux_addr);
- tegra_vde_setup_iram_entry(vde, 2, i, value, aux_addr);
- tegra_vde_setup_iram_entry(vde, 3, i, value, aux_addr);
- }
-
- if (!(dpb_frames[0].flags & FLAG_B_FRAME))
- return;
-
- if (with_earlier_poc_nb >= ref_frames_nb)
- return;
-
- with_later_poc_nb = ref_frames_nb - with_earlier_poc_nb;
-
- trace_vde_ref_l1(with_later_poc_nb, with_earlier_poc_nb);
-
- for (i = 0, k = with_earlier_poc_nb; i < with_later_poc_nb; i++, k++) {
- frame = &dpb_frames[k + 1];
-
- aux_addr = frame->aux_addr;
-
- value = (k + 1) << 26;
- value |= !(frame->flags & FLAG_B_FRAME) << 25;
- value |= 1 << 24;
- value |= frame->frame_num;
-
- tegra_vde_setup_iram_entry(vde, 2, i, value, aux_addr);
- }
-
- for (k = 0; i < ref_frames_nb; i++, k++) {
- frame = &dpb_frames[k + 1];
-
- aux_addr = frame->aux_addr;
-
- value = (k + 1) << 26;
- value |= !(frame->flags & FLAG_B_FRAME) << 25;
- value |= 1 << 24;
- value |= frame->frame_num;
-
- tegra_vde_setup_iram_entry(vde, 2, i, value, aux_addr);
- }
-}
-
-static int tegra_vde_setup_hw_context(struct tegra_vde *vde,
- struct tegra_vde_h264_decoder_ctx *ctx,
- struct video_frame *dpb_frames,
- dma_addr_t bitstream_data_addr,
- size_t bitstream_data_size,
- unsigned int macroblocks_nb)
-{
- struct device *dev = vde->miscdev.parent;
- u32 value;
- int err;
-
- tegra_vde_set_bits(vde, 0x000A, vde->sxe, 0xF0);
- tegra_vde_set_bits(vde, 0x000B, vde->bsev, CMDQUE_CONTROL);
- tegra_vde_set_bits(vde, 0x8002, vde->mbe, 0x50);
- tegra_vde_set_bits(vde, 0x000A, vde->mbe, 0xA0);
- tegra_vde_set_bits(vde, 0x000A, vde->ppe, 0x14);
- tegra_vde_set_bits(vde, 0x000A, vde->ppe, 0x28);
- tegra_vde_set_bits(vde, 0x0A00, vde->mce, 0x08);
- tegra_vde_set_bits(vde, 0x000A, vde->tfe, 0x00);
- tegra_vde_set_bits(vde, 0x0005, vde->vdma, 0x04);
-
- tegra_vde_writel(vde, 0x00000000, vde->vdma, 0x1C);
- tegra_vde_writel(vde, 0x00000000, vde->vdma, 0x00);
- tegra_vde_writel(vde, 0x00000007, vde->vdma, 0x04);
- tegra_vde_writel(vde, 0x00000007, vde->frameid, 0x200);
- tegra_vde_writel(vde, 0x00000005, vde->tfe, 0x04);
- tegra_vde_writel(vde, 0x00000000, vde->mbe, 0x84);
- tegra_vde_writel(vde, 0x00000010, vde->sxe, 0x08);
- tegra_vde_writel(vde, 0x00000150, vde->sxe, 0x54);
- tegra_vde_writel(vde, 0x0000054C, vde->sxe, 0x58);
- tegra_vde_writel(vde, 0x00000E34, vde->sxe, 0x5C);
- tegra_vde_writel(vde, 0x063C063C, vde->mce, 0x10);
- tegra_vde_writel(vde, 0x0003FC00, vde->bsev, INTR_STATUS);
- tegra_vde_writel(vde, 0x0000150D, vde->bsev, BSE_CONFIG);
- tegra_vde_writel(vde, 0x00000100, vde->bsev, BSE_INT_ENB);
- tegra_vde_writel(vde, 0x00000000, vde->bsev, 0x98);
- tegra_vde_writel(vde, 0x00000060, vde->bsev, 0x9C);
-
- memset(vde->iram + 128, 0, macroblocks_nb / 2);
-
- tegra_setup_frameidx(vde, dpb_frames, ctx->dpb_frames_nb,
- ctx->pic_width_in_mbs, ctx->pic_height_in_mbs);
-
- tegra_vde_setup_iram_tables(vde, dpb_frames,
- ctx->dpb_frames_nb - 1,
- ctx->dpb_ref_frames_with_earlier_poc_nb);
-
- /*
- * The IRAM mapping is write-combine, ensure that CPU buffers have
- * been flushed at this point.
- */
- wmb();
-
- tegra_vde_writel(vde, 0x00000000, vde->bsev, 0x8C);
- tegra_vde_writel(vde, bitstream_data_addr + bitstream_data_size,
- vde->bsev, 0x54);
-
- value = ctx->pic_width_in_mbs << 11 | ctx->pic_height_in_mbs << 3;
-
- tegra_vde_writel(vde, value, vde->bsev, 0x88);
-
- err = tegra_vde_wait_bsev(vde, false);
- if (err)
- return err;
-
- err = tegra_vde_push_to_bsev_icmdqueue(vde, 0x800003FC, false);
- if (err)
- return err;
-
- value = 0x01500000;
- value |= ((vde->iram_lists_addr + 512) >> 2) & 0xFFFF;
-
- err = tegra_vde_push_to_bsev_icmdqueue(vde, value, true);
- if (err)
- return err;
-
- err = tegra_vde_push_to_bsev_icmdqueue(vde, 0x840F054C, false);
- if (err)
- return err;
-
- err = tegra_vde_push_to_bsev_icmdqueue(vde, 0x80000080, false);
- if (err)
- return err;
-
- value = 0x0E340000 | ((vde->iram_lists_addr >> 2) & 0xFFFF);
-
- err = tegra_vde_push_to_bsev_icmdqueue(vde, value, true);
- if (err)
- return err;
-
- value = 0x00800005;
- value |= ctx->pic_width_in_mbs << 11;
- value |= ctx->pic_height_in_mbs << 3;
-
- tegra_vde_writel(vde, value, vde->sxe, 0x10);
-
- value = !ctx->baseline_profile << 17;
- value |= ctx->level_idc << 13;
- value |= ctx->log2_max_pic_order_cnt_lsb << 7;
- value |= ctx->pic_order_cnt_type << 5;
- value |= ctx->log2_max_frame_num;
-
- tegra_vde_writel(vde, value, vde->sxe, 0x40);
-
- value = ctx->pic_init_qp << 25;
- value |= !!(ctx->deblocking_filter_control_present_flag) << 2;
- value |= !!ctx->pic_order_present_flag;
-
- tegra_vde_writel(vde, value, vde->sxe, 0x44);
-
- value = ctx->chroma_qp_index_offset;
- value |= ctx->num_ref_idx_l0_active_minus1 << 5;
- value |= ctx->num_ref_idx_l1_active_minus1 << 10;
- value |= !!ctx->constrained_intra_pred_flag << 15;
-
- tegra_vde_writel(vde, value, vde->sxe, 0x48);
-
- value = 0x0C000000;
- value |= !!(dpb_frames[0].flags & FLAG_B_FRAME) << 24;
-
- tegra_vde_writel(vde, value, vde->sxe, 0x4C);
-
- value = 0x03800000;
- value |= bitstream_data_size & GENMASK(19, 15);
-
- tegra_vde_writel(vde, value, vde->sxe, 0x68);
-
- tegra_vde_writel(vde, bitstream_data_addr, vde->sxe, 0x6C);
-
- if (vde->soc->supports_ref_pic_marking)
- tegra_vde_writel(vde, vde->secure_bo->dma_addr, vde->sxe, 0x7c);
-
- value = 0x10000005;
- value |= ctx->pic_width_in_mbs << 11;
- value |= ctx->pic_height_in_mbs << 3;
-
- tegra_vde_writel(vde, value, vde->mbe, 0x80);
-
- value = 0x26800000;
- value |= ctx->level_idc << 4;
- value |= !ctx->baseline_profile << 1;
- value |= !!ctx->direct_8x8_inference_flag;
-
- tegra_vde_writel(vde, value, vde->mbe, 0x80);
-
- tegra_vde_writel(vde, 0xF4000001, vde->mbe, 0x80);
- tegra_vde_writel(vde, 0x20000000, vde->mbe, 0x80);
- tegra_vde_writel(vde, 0xF4000101, vde->mbe, 0x80);
-
- value = 0x20000000;
- value |= ctx->chroma_qp_index_offset << 8;
-
- tegra_vde_writel(vde, value, vde->mbe, 0x80);
-
- err = tegra_vde_setup_mbe_frame_idx(vde,
- ctx->dpb_frames_nb - 1,
- ctx->pic_order_cnt_type == 0);
- if (err) {
- dev_err(dev, "MBE frames setup failed %d\n", err);
- return err;
- }
-
- tegra_vde_mbe_set_0xa_reg(vde, 0, 0x000009FC);
- tegra_vde_mbe_set_0xa_reg(vde, 2, 0x61DEAD00);
- tegra_vde_mbe_set_0xa_reg(vde, 4, 0x62DEAD00);
- tegra_vde_mbe_set_0xa_reg(vde, 6, 0x63DEAD00);
- tegra_vde_mbe_set_0xa_reg(vde, 8, dpb_frames[0].aux_addr);
-
- value = 0xFC000000;
- value |= !!(dpb_frames[0].flags & FLAG_B_FRAME) << 2;
-
- if (!ctx->baseline_profile)
- value |= !!(dpb_frames[0].flags & FLAG_REFERENCE) << 1;
-
- tegra_vde_writel(vde, value, vde->mbe, 0x80);
-
- err = tegra_vde_wait_mbe(vde);
- if (err) {
- dev_err(dev, "MBE programming failed %d\n", err);
- return err;
- }
-
- return 0;
-}
-
-static void tegra_vde_decode_frame(struct tegra_vde *vde,
- unsigned int macroblocks_nb)
-{
- reinit_completion(&vde->decode_completion);
-
- tegra_vde_writel(vde, 0x00000001, vde->bsev, 0x8C);
- tegra_vde_writel(vde, 0x20000000 | (macroblocks_nb - 1),
- vde->sxe, 0x00);
-}
-
-static int tegra_vde_attach_dmabuf(struct tegra_vde *vde,
- int fd,
- unsigned long offset,
- size_t min_size,
- size_t align_size,
- struct dma_buf_attachment **a,
- dma_addr_t *addrp,
- size_t *size,
- enum dma_data_direction dma_dir)
-{
- struct device *dev = vde->miscdev.parent;
- struct dma_buf *dmabuf;
- int err;
-
- dmabuf = dma_buf_get(fd);
- if (IS_ERR(dmabuf)) {
- dev_err(dev, "Invalid dmabuf FD\n");
- return PTR_ERR(dmabuf);
- }
-
- if (dmabuf->size & (align_size - 1)) {
- dev_err(dev, "Unaligned dmabuf 0x%zX, should be aligned to 0x%zX\n",
- dmabuf->size, align_size);
- return -EINVAL;
- }
-
- if ((u64)offset + min_size > dmabuf->size) {
- dev_err(dev, "Too small dmabuf size %zu @0x%lX, should be at least %zu\n",
- dmabuf->size, offset, min_size);
- return -EINVAL;
- }
-
- err = tegra_vde_dmabuf_cache_map(vde, dmabuf, dma_dir, a, addrp);
- if (err)
- goto err_put;
-
- *addrp = *addrp + offset;
-
- if (size)
- *size = dmabuf->size - offset;
-
- return 0;
-
-err_put:
- dma_buf_put(dmabuf);
-
- return err;
-}
-
-static int tegra_vde_attach_dmabufs_to_frame(struct tegra_vde *vde,
- struct video_frame *frame,
- struct tegra_vde_h264_frame *src,
- enum dma_data_direction dma_dir,
- bool baseline_profile,
- size_t lsize, size_t csize)
-{
- int err;
-
- err = tegra_vde_attach_dmabuf(vde, src->y_fd,
- src->y_offset, lsize, SZ_256,
- &frame->y_dmabuf_attachment,
- &frame->y_addr,
- NULL, dma_dir);
- if (err)
- return err;
-
- err = tegra_vde_attach_dmabuf(vde, src->cb_fd,
- src->cb_offset, csize, SZ_256,
- &frame->cb_dmabuf_attachment,
- &frame->cb_addr,
- NULL, dma_dir);
- if (err)
- goto err_release_y;
-
- err = tegra_vde_attach_dmabuf(vde, src->cr_fd,
- src->cr_offset, csize, SZ_256,
- &frame->cr_dmabuf_attachment,
- &frame->cr_addr,
- NULL, dma_dir);
- if (err)
- goto err_release_cb;
-
- if (baseline_profile) {
- frame->aux_addr = 0x64DEAD00;
- return 0;
- }
-
- err = tegra_vde_attach_dmabuf(vde, src->aux_fd,
- src->aux_offset, csize, SZ_256,
- &frame->aux_dmabuf_attachment,
- &frame->aux_addr,
- NULL, dma_dir);
- if (err)
- goto err_release_cr;
-
- return 0;
-
-err_release_cr:
- tegra_vde_dmabuf_cache_unmap(vde, frame->cr_dmabuf_attachment, true);
-err_release_cb:
- tegra_vde_dmabuf_cache_unmap(vde, frame->cb_dmabuf_attachment, true);
-err_release_y:
- tegra_vde_dmabuf_cache_unmap(vde, frame->y_dmabuf_attachment, true);
-
- return err;
-}
-
-static void tegra_vde_release_frame_dmabufs(struct tegra_vde *vde,
- struct video_frame *frame,
- enum dma_data_direction dma_dir,
- bool baseline_profile,
- bool release)
-{
- if (!baseline_profile)
- tegra_vde_dmabuf_cache_unmap(vde, frame->aux_dmabuf_attachment,
- release);
-
- tegra_vde_dmabuf_cache_unmap(vde, frame->cr_dmabuf_attachment, release);
- tegra_vde_dmabuf_cache_unmap(vde, frame->cb_dmabuf_attachment, release);
- tegra_vde_dmabuf_cache_unmap(vde, frame->y_dmabuf_attachment, release);
-}
-
-static int tegra_vde_validate_frame(struct device *dev,
- struct tegra_vde_h264_frame *frame)
-{
- if (frame->frame_num > 0x7FFFFF) {
- dev_err(dev, "Bad frame_num %u\n", frame->frame_num);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int tegra_vde_validate_h264_ctx(struct device *dev,
- struct tegra_vde_h264_decoder_ctx *ctx)
-{
- if (ctx->dpb_frames_nb == 0 || ctx->dpb_frames_nb > 17) {
- dev_err(dev, "Bad DPB size %u\n", ctx->dpb_frames_nb);
- return -EINVAL;
- }
-
- if (ctx->level_idc > 15) {
- dev_err(dev, "Bad level value %u\n", ctx->level_idc);
- return -EINVAL;
- }
-
- if (ctx->pic_init_qp > 52) {
- dev_err(dev, "Bad pic_init_qp value %u\n", ctx->pic_init_qp);
- return -EINVAL;
- }
-
- if (ctx->log2_max_pic_order_cnt_lsb > 16) {
- dev_err(dev, "Bad log2_max_pic_order_cnt_lsb value %u\n",
- ctx->log2_max_pic_order_cnt_lsb);
- return -EINVAL;
- }
-
- if (ctx->log2_max_frame_num > 16) {
- dev_err(dev, "Bad log2_max_frame_num value %u\n",
- ctx->log2_max_frame_num);
- return -EINVAL;
- }
-
- if (ctx->chroma_qp_index_offset > 31) {
- dev_err(dev, "Bad chroma_qp_index_offset value %u\n",
- ctx->chroma_qp_index_offset);
- return -EINVAL;
- }
-
- if (ctx->pic_order_cnt_type > 2) {
- dev_err(dev, "Bad pic_order_cnt_type value %u\n",
- ctx->pic_order_cnt_type);
- return -EINVAL;
- }
-
- if (ctx->num_ref_idx_l0_active_minus1 > 15) {
- dev_err(dev, "Bad num_ref_idx_l0_active_minus1 value %u\n",
- ctx->num_ref_idx_l0_active_minus1);
- return -EINVAL;
- }
-
- if (ctx->num_ref_idx_l1_active_minus1 > 15) {
- dev_err(dev, "Bad num_ref_idx_l1_active_minus1 value %u\n",
- ctx->num_ref_idx_l1_active_minus1);
- return -EINVAL;
- }
-
- if (!ctx->pic_width_in_mbs || ctx->pic_width_in_mbs > 127) {
- dev_err(dev, "Bad pic_width_in_mbs value %u\n",
- ctx->pic_width_in_mbs);
- return -EINVAL;
- }
-
- if (!ctx->pic_height_in_mbs || ctx->pic_height_in_mbs > 127) {
- dev_err(dev, "Bad pic_height_in_mbs value %u\n",
- ctx->pic_height_in_mbs);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int tegra_vde_ioctl_decode_h264(struct tegra_vde *vde,
- unsigned long vaddr)
-{
- struct device *dev = vde->miscdev.parent;
- struct tegra_vde_h264_decoder_ctx ctx;
- struct tegra_vde_h264_frame *frames;
- struct tegra_vde_h264_frame __user *frames_user;
- struct video_frame *dpb_frames;
- struct dma_buf_attachment *bitstream_data_dmabuf_attachment;
- enum dma_data_direction dma_dir;
- dma_addr_t bitstream_data_addr;
- dma_addr_t bsev_ptr;
- size_t lsize, csize;
- size_t bitstream_data_size;
- unsigned int macroblocks_nb;
- unsigned int read_bytes;
- unsigned int cstride;
- unsigned int i;
- long timeout;
- int ret, err;
-
- if (copy_from_user(&ctx, (void __user *)vaddr, sizeof(ctx)))
- return -EFAULT;
-
- ret = tegra_vde_validate_h264_ctx(dev, &ctx);
- if (ret)
- return ret;
-
- ret = tegra_vde_attach_dmabuf(vde, ctx.bitstream_data_fd,
- ctx.bitstream_data_offset,
- SZ_16K, SZ_16K,
- &bitstream_data_dmabuf_attachment,
- &bitstream_data_addr,
- &bitstream_data_size,
- DMA_TO_DEVICE);
- if (ret)
- return ret;
-
- frames = kmalloc_array(ctx.dpb_frames_nb, sizeof(*frames), GFP_KERNEL);
- if (!frames) {
- ret = -ENOMEM;
- goto release_bitstream_dmabuf;
- }
-
- dpb_frames = kcalloc(ctx.dpb_frames_nb, sizeof(*dpb_frames),
- GFP_KERNEL);
- if (!dpb_frames) {
- ret = -ENOMEM;
- goto free_frames;
- }
-
- macroblocks_nb = ctx.pic_width_in_mbs * ctx.pic_height_in_mbs;
- frames_user = u64_to_user_ptr(ctx.dpb_frames_ptr);
-
- if (copy_from_user(frames, frames_user,
- ctx.dpb_frames_nb * sizeof(*frames))) {
- ret = -EFAULT;
- goto free_dpb_frames;
- }
-
- cstride = ALIGN(ctx.pic_width_in_mbs * 8, 16);
- csize = cstride * ctx.pic_height_in_mbs * 8;
- lsize = macroblocks_nb * 256;
-
- for (i = 0; i < ctx.dpb_frames_nb; i++) {
- ret = tegra_vde_validate_frame(dev, &frames[i]);
- if (ret)
- goto release_dpb_frames;
-
- dpb_frames[i].flags = frames[i].flags;
- dpb_frames[i].frame_num = frames[i].frame_num;
-
- dma_dir = (i == 0) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
- ret = tegra_vde_attach_dmabufs_to_frame(vde, &dpb_frames[i],
- &frames[i], dma_dir,
- ctx.baseline_profile,
- lsize, csize);
- if (ret)
- goto release_dpb_frames;
- }
-
- ret = mutex_lock_interruptible(&vde->lock);
- if (ret)
- goto release_dpb_frames;
-
- ret = pm_runtime_resume_and_get(dev);
- if (ret < 0)
- goto unlock;
-
- /*
- * We rely on the VDE registers reset value, otherwise VDE
- * causes bus lockup.
- */
- ret = reset_control_assert(vde->rst_mc);
- if (ret) {
- dev_err(dev, "DEC start: Failed to assert MC reset: %d\n",
- ret);
- goto put_runtime_pm;
- }
-
- ret = reset_control_reset(vde->rst);
- if (ret) {
- dev_err(dev, "DEC start: Failed to reset HW: %d\n", ret);
- goto put_runtime_pm;
- }
-
- ret = reset_control_deassert(vde->rst_mc);
- if (ret) {
- dev_err(dev, "DEC start: Failed to deassert MC reset: %d\n",
- ret);
- goto put_runtime_pm;
- }
-
- ret = tegra_vde_setup_hw_context(vde, &ctx, dpb_frames,
- bitstream_data_addr,
- bitstream_data_size,
- macroblocks_nb);
- if (ret)
- goto put_runtime_pm;
-
- tegra_vde_decode_frame(vde, macroblocks_nb);
-
- timeout = wait_for_completion_interruptible_timeout(
- &vde->decode_completion, msecs_to_jiffies(1000));
- if (timeout == 0) {
- bsev_ptr = tegra_vde_readl(vde, vde->bsev, 0x10);
- macroblocks_nb = tegra_vde_readl(vde, vde->sxe, 0xC8) & 0x1FFF;
- read_bytes = bsev_ptr ? bsev_ptr - bitstream_data_addr : 0;
-
- dev_err(dev, "Decoding failed: read 0x%X bytes, %u macroblocks parsed\n",
- read_bytes, macroblocks_nb);
-
- ret = -EIO;
- } else if (timeout < 0) {
- ret = timeout;
- }
-
- /*
- * At first reset memory client to avoid resetting VDE HW in the
- * middle of DMA which could result into memory corruption or hang
- * the whole system.
- */
- err = reset_control_assert(vde->rst_mc);
- if (err)
- dev_err(dev, "DEC end: Failed to assert MC reset: %d\n", err);
-
- err = reset_control_assert(vde->rst);
- if (err)
- dev_err(dev, "DEC end: Failed to assert HW reset: %d\n", err);
-
-put_runtime_pm:
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-
-unlock:
- mutex_unlock(&vde->lock);
-
-release_dpb_frames:
- while (i--) {
- dma_dir = (i == 0) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
- tegra_vde_release_frame_dmabufs(vde, &dpb_frames[i], dma_dir,
- ctx.baseline_profile, ret != 0);
- }
-
-free_dpb_frames:
- kfree(dpb_frames);
-
-free_frames:
- kfree(frames);
-
-release_bitstream_dmabuf:
- tegra_vde_dmabuf_cache_unmap(vde, bitstream_data_dmabuf_attachment,
- ret != 0);
-
- return ret;
-}
-
-static long tegra_vde_unlocked_ioctl(struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- struct miscdevice *miscdev = filp->private_data;
- struct tegra_vde *vde = container_of(miscdev, struct tegra_vde,
- miscdev);
-
- switch (cmd) {
- case TEGRA_VDE_IOCTL_DECODE_H264:
- return tegra_vde_ioctl_decode_h264(vde, arg);
- }
-
- dev_err(miscdev->parent, "Invalid IOCTL command %u\n", cmd);
-
- return -ENOTTY;
-}
-
-static int tegra_vde_release_file(struct inode *inode, struct file *filp)
-{
- struct miscdevice *miscdev = filp->private_data;
- struct tegra_vde *vde = container_of(miscdev, struct tegra_vde,
- miscdev);
-
- tegra_vde_dmabuf_cache_unmap_sync(vde);
-
- return 0;
-}
-
-static const struct file_operations tegra_vde_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = tegra_vde_unlocked_ioctl,
- .release = tegra_vde_release_file,
-};
-
-static irqreturn_t tegra_vde_isr(int irq, void *data)
-{
- struct tegra_vde *vde = data;
-
- if (completion_done(&vde->decode_completion))
- return IRQ_NONE;
-
- tegra_vde_set_bits(vde, 0, vde->frameid, 0x208);
- complete(&vde->decode_completion);
-
- return IRQ_HANDLED;
-}
-
-static __maybe_unused int tegra_vde_runtime_suspend(struct device *dev)
-{
- struct tegra_vde *vde = dev_get_drvdata(dev);
- int err;
-
- if (!dev->pm_domain) {
- err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
- if (err) {
- dev_err(dev, "Failed to power down HW: %d\n", err);
- return err;
- }
- }
-
- clk_disable_unprepare(vde->clk);
- reset_control_release(vde->rst);
- reset_control_release(vde->rst_mc);
-
- return 0;
-}
-
-static __maybe_unused int tegra_vde_runtime_resume(struct device *dev)
-{
- struct tegra_vde *vde = dev_get_drvdata(dev);
- int err;
-
- err = reset_control_acquire(vde->rst_mc);
- if (err) {
- dev_err(dev, "Failed to acquire mc reset: %d\n", err);
- return err;
- }
-
- err = reset_control_acquire(vde->rst);
- if (err) {
- dev_err(dev, "Failed to acquire reset: %d\n", err);
- goto release_mc_reset;
- }
-
- if (!dev->pm_domain) {
- err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
- vde->clk, vde->rst);
- if (err) {
- dev_err(dev, "Failed to power up HW : %d\n", err);
- goto release_reset;
- }
- } else {
- /*
- * tegra_powergate_sequence_power_up() leaves clocks enabled,
- * while GENPD not.
- */
- err = clk_prepare_enable(vde->clk);
- if (err) {
- dev_err(dev, "Failed to enable clock: %d\n", err);
- goto release_reset;
- }
- }
-
- return 0;
-
-release_reset:
- reset_control_release(vde->rst);
-release_mc_reset:
- reset_control_release(vde->rst_mc);
-
- return err;
-}
-
-static int tegra_vde_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct tegra_vde *vde;
- int irq, err;
-
- vde = devm_kzalloc(dev, sizeof(*vde), GFP_KERNEL);
- if (!vde)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, vde);
-
- vde->soc = of_device_get_match_data(&pdev->dev);
-
- vde->sxe = devm_platform_ioremap_resource_byname(pdev, "sxe");
- if (IS_ERR(vde->sxe))
- return PTR_ERR(vde->sxe);
-
- vde->bsev = devm_platform_ioremap_resource_byname(pdev, "bsev");
- if (IS_ERR(vde->bsev))
- return PTR_ERR(vde->bsev);
-
- vde->mbe = devm_platform_ioremap_resource_byname(pdev, "mbe");
- if (IS_ERR(vde->mbe))
- return PTR_ERR(vde->mbe);
-
- vde->ppe = devm_platform_ioremap_resource_byname(pdev, "ppe");
- if (IS_ERR(vde->ppe))
- return PTR_ERR(vde->ppe);
-
- vde->mce = devm_platform_ioremap_resource_byname(pdev, "mce");
- if (IS_ERR(vde->mce))
- return PTR_ERR(vde->mce);
-
- vde->tfe = devm_platform_ioremap_resource_byname(pdev, "tfe");
- if (IS_ERR(vde->tfe))
- return PTR_ERR(vde->tfe);
-
- vde->ppb = devm_platform_ioremap_resource_byname(pdev, "ppb");
- if (IS_ERR(vde->ppb))
- return PTR_ERR(vde->ppb);
-
- vde->vdma = devm_platform_ioremap_resource_byname(pdev, "vdma");
- if (IS_ERR(vde->vdma))
- return PTR_ERR(vde->vdma);
-
- vde->frameid = devm_platform_ioremap_resource_byname(pdev, "frameid");
- if (IS_ERR(vde->frameid))
- return PTR_ERR(vde->frameid);
-
- vde->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(vde->clk)) {
- err = PTR_ERR(vde->clk);
- dev_err(dev, "Could not get VDE clk %d\n", err);
- return err;
- }
-
- vde->rst = devm_reset_control_get_exclusive_released(dev, NULL);
- if (IS_ERR(vde->rst)) {
- err = PTR_ERR(vde->rst);
- dev_err(dev, "Could not get VDE reset %d\n", err);
- return err;
- }
-
- vde->rst_mc = devm_reset_control_get_optional_exclusive_released(dev, "mc");
- if (IS_ERR(vde->rst_mc)) {
- err = PTR_ERR(vde->rst_mc);
- dev_err(dev, "Could not get MC reset %d\n", err);
- return err;
- }
-
- irq = platform_get_irq_byname(pdev, "sync-token");
- if (irq < 0)
- return irq;
-
- err = devm_request_irq(dev, irq, tegra_vde_isr, 0,
- dev_name(dev), vde);
- if (err) {
- dev_err(dev, "Could not request IRQ %d\n", err);
- return err;
- }
-
- err = devm_tegra_core_dev_init_opp_table_common(dev);
- if (err) {
- dev_err(dev, "Could initialize OPP table %d\n", err);
- return err;
- }
-
- vde->iram_pool = of_gen_pool_get(dev->of_node, "iram", 0);
- if (!vde->iram_pool) {
- dev_err(dev, "Could not get IRAM pool\n");
- return -EPROBE_DEFER;
- }
-
- vde->iram = gen_pool_dma_alloc(vde->iram_pool,
- gen_pool_size(vde->iram_pool),
- &vde->iram_lists_addr);
- if (!vde->iram) {
- dev_err(dev, "Could not reserve IRAM\n");
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&vde->map_list);
- mutex_init(&vde->map_lock);
- mutex_init(&vde->lock);
- init_completion(&vde->decode_completion);
-
- vde->miscdev.minor = MISC_DYNAMIC_MINOR;
- vde->miscdev.name = "tegra_vde";
- vde->miscdev.fops = &tegra_vde_fops;
- vde->miscdev.parent = dev;
-
- err = tegra_vde_iommu_init(vde);
- if (err) {
- dev_err(dev, "Failed to initialize IOMMU: %d\n", err);
- goto err_gen_free;
- }
-
- pm_runtime_enable(dev);
- pm_runtime_use_autosuspend(dev);
- pm_runtime_set_autosuspend_delay(dev, 300);
-
- /*
- * VDE partition may be left ON after bootloader, hence let's
- * power-cycle it in order to put hardware into a predictable lower
- * power state.
- */
- err = pm_runtime_resume_and_get(dev);
- if (err)
- goto err_pm_runtime;
-
- pm_runtime_put(dev);
-
- err = tegra_vde_alloc_bo(vde, &vde->secure_bo, DMA_FROM_DEVICE, 4096);
- if (err) {
- dev_err(dev, "Failed to allocate secure BO: %d\n", err);
- goto err_pm_runtime;
- }
-
- err = misc_register(&vde->miscdev);
- if (err) {
- dev_err(dev, "Failed to register misc device: %d\n", err);
- goto err_free_secure_bo;
- }
-
- return 0;
-
-err_free_secure_bo:
- tegra_vde_free_bo(vde->secure_bo);
-err_pm_runtime:
- pm_runtime_dont_use_autosuspend(dev);
- pm_runtime_disable(dev);
-
- tegra_vde_iommu_deinit(vde);
-
-err_gen_free:
- gen_pool_free(vde->iram_pool, (unsigned long)vde->iram,
- gen_pool_size(vde->iram_pool));
-
- return err;
-}
-
-static int tegra_vde_remove(struct platform_device *pdev)
-{
- struct tegra_vde *vde = platform_get_drvdata(pdev);
- struct device *dev = &pdev->dev;
-
- misc_deregister(&vde->miscdev);
-
- tegra_vde_free_bo(vde->secure_bo);
-
- /*
- * As it increments RPM usage_count even on errors, we don't need to
- * check the returned code here.
- */
- pm_runtime_get_sync(dev);
-
- pm_runtime_dont_use_autosuspend(dev);
- pm_runtime_disable(dev);
-
- /*
- * Balance RPM state, the VDE power domain is left ON and hardware
- * is clock-gated. It's safe to reboot machine now.
- */
- pm_runtime_put_noidle(dev);
- clk_disable_unprepare(vde->clk);
-
- tegra_vde_dmabuf_cache_unmap_all(vde);
- tegra_vde_iommu_deinit(vde);
-
- gen_pool_free(vde->iram_pool, (unsigned long)vde->iram,
- gen_pool_size(vde->iram_pool));
-
- return 0;
-}
-
-static void tegra_vde_shutdown(struct platform_device *pdev)
-{
- /*
- * On some devices bootloader isn't ready to a power-gated VDE on
- * a warm-reboot, machine will hang in that case.
- */
- pm_runtime_get_sync(&pdev->dev);
-}
-
-static __maybe_unused int tegra_vde_pm_suspend(struct device *dev)
-{
- struct tegra_vde *vde = dev_get_drvdata(dev);
- int err;
-
- mutex_lock(&vde->lock);
-
- err = pm_runtime_force_suspend(dev);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-static __maybe_unused int tegra_vde_pm_resume(struct device *dev)
-{
- struct tegra_vde *vde = dev_get_drvdata(dev);
- int err;
-
- err = pm_runtime_force_resume(dev);
- if (err < 0)
- return err;
-
- mutex_unlock(&vde->lock);
-
- return 0;
-}
-
-static const struct dev_pm_ops tegra_vde_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra_vde_runtime_suspend,
- tegra_vde_runtime_resume,
- NULL)
- SET_SYSTEM_SLEEP_PM_OPS(tegra_vde_pm_suspend,
- tegra_vde_pm_resume)
-};
-
-static const struct tegra_vde_soc tegra124_vde_soc = {
- .supports_ref_pic_marking = true,
-};
-
-static const struct tegra_vde_soc tegra114_vde_soc = {
- .supports_ref_pic_marking = true,
-};
-
-static const struct tegra_vde_soc tegra30_vde_soc = {
- .supports_ref_pic_marking = false,
-};
-
-static const struct tegra_vde_soc tegra20_vde_soc = {
- .supports_ref_pic_marking = false,
-};
-
-static const struct of_device_id tegra_vde_of_match[] = {
- { .compatible = "nvidia,tegra124-vde", .data = &tegra124_vde_soc },
- { .compatible = "nvidia,tegra114-vde", .data = &tegra114_vde_soc },
- { .compatible = "nvidia,tegra30-vde", .data = &tegra30_vde_soc },
- { .compatible = "nvidia,tegra20-vde", .data = &tegra20_vde_soc },
- { },
-};
-MODULE_DEVICE_TABLE(of, tegra_vde_of_match);
-
-static struct platform_driver tegra_vde_driver = {
- .probe = tegra_vde_probe,
- .remove = tegra_vde_remove,
- .shutdown = tegra_vde_shutdown,
- .driver = {
- .name = "tegra-vde",
- .of_match_table = tegra_vde_of_match,
- .pm = &tegra_vde_pm_ops,
- },
-};
-module_platform_driver(tegra_vde_driver);
-
-MODULE_DESCRIPTION("NVIDIA Tegra Video Decoder driver");
-MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/tegra-vde/vde.h b/drivers/staging/media/tegra-vde/vde.h
deleted file mode 100644
index bbd42b8d9991..000000000000
--- a/drivers/staging/media/tegra-vde/vde.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * NVIDIA Tegra Video decoder driver
- *
- * Copyright (C) 2016-2019 GRATE-DRIVER project
- */
-
-#ifndef TEGRA_VDE_H
-#define TEGRA_VDE_H
-
-#include <linux/completion.h>
-#include <linux/dma-direction.h>
-#include <linux/iova.h>
-#include <linux/list.h>
-#include <linux/miscdevice.h>
-#include <linux/mutex.h>
-#include <linux/types.h>
-
-struct clk;
-struct dma_buf;
-struct gen_pool;
-struct iommu_group;
-struct iommu_domain;
-struct reset_control;
-struct dma_buf_attachment;
-
-struct tegra_vde_soc {
- bool supports_ref_pic_marking;
-};
-
-struct tegra_vde_bo {
- struct iova *iova;
- struct sg_table sgt;
- struct tegra_vde *vde;
- enum dma_data_direction dma_dir;
- unsigned long dma_attrs;
- dma_addr_t dma_handle;
- dma_addr_t dma_addr;
- void *dma_cookie;
- size_t size;
-};
-
-struct tegra_vde {
- void __iomem *sxe;
- void __iomem *bsev;
- void __iomem *mbe;
- void __iomem *ppe;
- void __iomem *mce;
- void __iomem *tfe;
- void __iomem *ppb;
- void __iomem *vdma;
- void __iomem *frameid;
- struct mutex lock;
- struct mutex map_lock;
- struct list_head map_list;
- struct miscdevice miscdev;
- struct reset_control *rst;
- struct reset_control *rst_mc;
- struct gen_pool *iram_pool;
- struct completion decode_completion;
- struct clk *clk;
- struct iommu_domain *domain;
- struct iommu_group *group;
- struct iova_domain iova;
- struct iova *iova_resv_static_addresses;
- struct iova *iova_resv_last_page;
- const struct tegra_vde_soc *soc;
- struct tegra_vde_bo *secure_bo;
- dma_addr_t iram_lists_addr;
- u32 *iram;
-};
-
-int tegra_vde_iommu_init(struct tegra_vde *vde);
-void tegra_vde_iommu_deinit(struct tegra_vde *vde);
-int tegra_vde_iommu_map(struct tegra_vde *vde,
- struct sg_table *sgt,
- struct iova **iovap,
- size_t size);
-void tegra_vde_iommu_unmap(struct tegra_vde *vde, struct iova *iova);
-
-int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde,
- struct dma_buf *dmabuf,
- enum dma_data_direction dma_dir,
- struct dma_buf_attachment **ap,
- dma_addr_t *addrp);
-void tegra_vde_dmabuf_cache_unmap(struct tegra_vde *vde,
- struct dma_buf_attachment *a,
- bool release);
-void tegra_vde_dmabuf_cache_unmap_sync(struct tegra_vde *vde);
-void tegra_vde_dmabuf_cache_unmap_all(struct tegra_vde *vde);
-
-static __maybe_unused char const *
-tegra_vde_reg_base_name(struct tegra_vde *vde, void __iomem *base)
-{
- if (vde->sxe == base)
- return "SXE";
-
- if (vde->bsev == base)
- return "BSEV";
-
- if (vde->mbe == base)
- return "MBE";
-
- if (vde->ppe == base)
- return "PPE";
-
- if (vde->mce == base)
- return "MCE";
-
- if (vde->tfe == base)
- return "TFE";
-
- if (vde->ppb == base)
- return "PPB";
-
- if (vde->vdma == base)
- return "VDMA";
-
- if (vde->frameid == base)
- return "FRAMEID";
-
- return "???";
-}
-
-#endif /* TEGRA_VDE_H */
diff --git a/drivers/staging/media/tegra-video/Kconfig b/drivers/staging/media/tegra-video/Kconfig
index 1f35da4b134e..df1b2cff2417 100644
--- a/drivers/staging/media/tegra-video/Kconfig
+++ b/drivers/staging/media/tegra-video/Kconfig
@@ -2,7 +2,7 @@
config VIDEO_TEGRA
tristate "NVIDIA Tegra VI driver"
depends on TEGRA_HOST1X
- depends on VIDEO_V4L2
+ depends on VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEOBUF2_DMA_CONTIG
select V4L2_FWNODE
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index d1f43f465c22..8e184aa4c252 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -491,6 +491,7 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
struct v4l2_pix_format *pix)
{
const struct tegra_video_format *fmtinfo;
+ static struct lock_class_key key;
struct v4l2_subdev *subdev;
struct v4l2_subdev_format fmt;
struct v4l2_subdev_state *sd_state;
@@ -507,7 +508,12 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
if (!subdev)
return -ENODEV;
- sd_state = v4l2_subdev_alloc_state(subdev);
+ /*
+ * FIXME: Drop this call, drivers are not supposed to use
+ * __v4l2_subdev_state_alloc().
+ */
+ sd_state = __v4l2_subdev_state_alloc(subdev, "tegra:state->lock",
+ &key);
if (IS_ERR(sd_state))
return PTR_ERR(sd_state);
/*
@@ -558,7 +564,7 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
v4l2_fill_pix_format(pix, &fmt.format);
tegra_channel_fmt_align(chan, pix, fmtinfo->bpp);
- v4l2_subdev_free_state(sd_state);
+ __v4l2_subdev_state_free(sd_state);
return 0;
}
diff --git a/drivers/staging/media/zoran/Kconfig b/drivers/staging/media/zoran/Kconfig
index 7874842033ca..3fb3e27e04a8 100644
--- a/drivers/staging/media/zoran/Kconfig
+++ b/drivers/staging/media/zoran/Kconfig
@@ -1,8 +1,19 @@
config VIDEO_ZORAN
tristate "Zoran ZR36057/36067 Video For Linux (Deprecated)"
- depends on PCI && I2C_ALGOBIT && VIDEO_V4L2
+ depends on PCI && I2C_ALGOBIT && VIDEO_DEV
depends on !ALPHA
+ depends on DEBUG_FS
select VIDEOBUF2_DMA_CONTIG
+ select VIDEO_ADV7170 if VIDEO_ZORAN_LML33R10
+ select VIDEO_ADV7175 if VIDEO_ZORAN_DC10 || VIDEO_ZORAN_DC30
+ select VIDEO_BT819 if VIDEO_ZORAN_LML33
+ select VIDEO_BT856 if VIDEO_ZORAN_LML33 || VIDEO_ZORAN_AVS6EYES
+ select VIDEO_BT866 if VIDEO_ZORAN_AVS6EYES
+ select VIDEO_KS0127 if VIDEO_ZORAN_AVS6EYES
+ select VIDEO_SAA711X if VIDEO_ZORAN_BUZ || VIDEO_ZORAN_LML33R10
+ select VIDEO_SAA7110 if VIDEO_ZORAN_DC10
+ select VIDEO_SAA7185 if VIDEO_ZORAN_BUZ
+ select VIDEO_VPX3220 if VIDEO_ZORAN_DC30
help
Say Y for support for MJPEG capture cards based on the Zoran
36057/36067 PCI controller chipset. This includes the Iomega
@@ -14,17 +25,15 @@ config VIDEO_ZORAN
module will be called zr36067.
config VIDEO_ZORAN_DC30
- tristate "Pinnacle/Miro DC30(+) support"
+ bool "Pinnacle/Miro DC30(+) support"
depends on VIDEO_ZORAN
- select VIDEO_ADV7175 if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_VPX3220 if MEDIA_SUBDRV_AUTOSELECT
help
Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
card. This also supports really old DC10 cards based on the
zr36050 MJPEG codec and zr36016 VFE.
config VIDEO_ZORAN_ZR36060
- tristate "Zoran ZR36060"
+ bool "Zoran ZR36060"
depends on VIDEO_ZORAN
help
Say Y to support Zoran boards based on 36060 chips.
@@ -32,45 +41,34 @@ config VIDEO_ZORAN_ZR36060
and 33 R10 and AverMedia 6 boards.
config VIDEO_ZORAN_BUZ
- tristate "Iomega Buz support"
+ bool "Iomega Buz support"
depends on VIDEO_ZORAN_ZR36060
- select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_SAA7185 if MEDIA_SUBDRV_AUTOSELECT
help
Support for the Iomega Buz MJPEG capture/playback card.
config VIDEO_ZORAN_DC10
- tristate "Pinnacle/Miro DC10(+) support"
+ bool "Pinnacle/Miro DC10(+) support"
depends on VIDEO_ZORAN_ZR36060
- select VIDEO_SAA7110 if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_ADV7175 if MEDIA_SUBDRV_AUTOSELECT
help
Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
card.
config VIDEO_ZORAN_LML33
- tristate "Linux Media Labs LML33 support"
+ bool "Linux Media Labs LML33 support"
depends on VIDEO_ZORAN_ZR36060
- select VIDEO_BT819 if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_BT856 if MEDIA_SUBDRV_AUTOSELECT
help
Support for the Linux Media Labs LML33 MJPEG capture/playback
card.
config VIDEO_ZORAN_LML33R10
- tristate "Linux Media Labs LML33R10 support"
+ bool "Linux Media Labs LML33R10 support"
depends on VIDEO_ZORAN_ZR36060
- select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_ADV7170 if MEDIA_SUBDRV_AUTOSELECT
help
support for the Linux Media Labs LML33R10 MJPEG capture/playback
card.
config VIDEO_ZORAN_AVS6EYES
- tristate "AverMedia 6 Eyes support"
+ bool "AverMedia 6 Eyes support"
depends on VIDEO_ZORAN_ZR36060
- select VIDEO_BT856 if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_BT866 if MEDIA_SUBDRV_AUTOSELECT
- select VIDEO_KS0127 if MEDIA_SUBDRV_AUTOSELECT
help
Support for the AverMedia 6 Eyes video surveillance card.
diff --git a/drivers/staging/media/zoran/Makefile b/drivers/staging/media/zoran/Makefile
index 7023158e3892..9603bac0195c 100644
--- a/drivers/staging/media/zoran/Makefile
+++ b/drivers/staging/media/zoran/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
zr36067-objs := zoran_device.o \
- zoran_driver.o zoran_card.o
+ zoran_driver.o zoran_card.o videocodec.o
-obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
-obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
-obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
+obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o
+zr36067-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
+zr36067-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
diff --git a/drivers/staging/media/zoran/videocodec.c b/drivers/staging/media/zoran/videocodec.c
index 28031d3fd757..3af7d02bd910 100644
--- a/drivers/staging/media/zoran/videocodec.c
+++ b/drivers/staging/media/zoran/videocodec.c
@@ -8,31 +8,21 @@
* (c) 2002 Wolfgang Scherr <scherr@net4you.at>
*/
-#define VIDEOCODEC_VERSION "v0.2"
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
-// kernel config is here (procfs flag)
-
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#endif
-
#include "videocodec.h"
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
+static int videocodec_debug;
+module_param(videocodec_debug, int, 0);
+MODULE_PARM_DESC(videocodec_debug, "Debug level (0-4)");
#define dprintk(num, format, args...) \
do { \
- if (debug >= num) \
+ if (videocodec_debug >= num) \
printk(format, ##args); \
} while (0)
@@ -80,12 +70,9 @@ struct videocodec *videocodec_attach(struct videocodec_master *master)
if ((master->flags & h->codec->flags) == master->flags) {
dprintk(4, "%s: try '%s'\n", __func__, h->codec->name);
- if (!try_module_get(h->codec->owner))
- return NULL;
-
codec = kmemdup(h->codec, sizeof(struct videocodec), GFP_KERNEL);
if (!codec)
- goto out_module_put;
+ goto out_kfree;
res = strlen(codec->name);
snprintf(codec->name + res, sizeof(codec->name) - res, "[%d]", h->attached);
@@ -121,13 +108,10 @@ struct videocodec *videocodec_attach(struct videocodec_master *master)
pr_err("%s: no codec found!\n", __func__);
return NULL;
- out_module_put:
- module_put(h->codec->owner);
out_kfree:
kfree(codec);
return NULL;
}
-EXPORT_SYMBOL(videocodec_attach);
int videocodec_detach(struct videocodec *codec)
{
@@ -168,7 +152,6 @@ int videocodec_detach(struct videocodec *codec)
prev->next = a->next;
dprintk(4, "videocodec: delete middle\n");
}
- module_put(a->codec->owner);
kfree(a->codec);
kfree(a);
h->attached -= 1;
@@ -183,7 +166,6 @@ int videocodec_detach(struct videocodec *codec)
pr_err("%s: given codec not found!\n", __func__);
return -EINVAL;
}
-EXPORT_SYMBOL(videocodec_detach);
int videocodec_register(const struct videocodec *codec)
{
@@ -216,7 +198,6 @@ int videocodec_register(const struct videocodec *codec)
return 0;
}
-EXPORT_SYMBOL(videocodec_register);
int videocodec_unregister(const struct videocodec *codec)
{
@@ -263,10 +244,8 @@ int videocodec_unregister(const struct videocodec *codec)
pr_err("%s: given codec not found!\n", __func__);
return -EINVAL;
}
-EXPORT_SYMBOL(videocodec_unregister);
-#ifdef CONFIG_PROC_FS
-static int proc_videocodecs_show(struct seq_file *m, void *v)
+int videocodec_debugfs_show(struct seq_file *m)
{
struct codec_list *h = codeclist_top;
struct attached_list *a;
@@ -293,38 +272,3 @@ static int proc_videocodecs_show(struct seq_file *m, void *v)
return 0;
}
-#endif
-
-/* ===================== */
-/* hook in driver module */
-/* ===================== */
-static int __init videocodec_init(void)
-{
-#ifdef CONFIG_PROC_FS
- static struct proc_dir_entry *videocodec_proc_entry;
-#endif
-
- pr_info("Linux video codec intermediate layer: %s\n", VIDEOCODEC_VERSION);
-
-#ifdef CONFIG_PROC_FS
- videocodec_proc_entry = proc_create_single("videocodecs", 0, NULL, proc_videocodecs_show);
- if (!videocodec_proc_entry)
- pr_err("videocodec: can't init procfs.\n");
-#endif
- return 0;
-}
-
-static void __exit videocodec_exit(void)
-{
-#ifdef CONFIG_PROC_FS
- remove_proc_entry("videocodecs", NULL);
-#endif
-}
-
-module_init(videocodec_init);
-module_exit(videocodec_exit);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Intermediate API module for video codecs "
- VIDEOCODEC_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/zoran/videocodec.h b/drivers/staging/media/zoran/videocodec.h
index 8a5003dda9f4..9dea348fee40 100644
--- a/drivers/staging/media/zoran/videocodec.h
+++ b/drivers/staging/media/zoran/videocodec.h
@@ -123,6 +123,7 @@ M zr36055[1] 0001 0000c001 00000000 (zr36050[1])
#ifndef __LINUX_VIDEOCODEC_H
#define __LINUX_VIDEOCODEC_H
+#include <linux/debugfs.h>
#include <linux/videodev2.h>
#define CODEC_DO_COMPRESSION 0
@@ -233,7 +234,6 @@ struct jpeg_app_marker {
};
struct videocodec {
- struct module *owner;
/* -- filled in by slave device during register -- */
char name[32];
unsigned long magic; /* may be used for client<->master attaching */
@@ -305,4 +305,6 @@ extern int videocodec_unregister(const struct videocodec *);
/* the other calls are directly done via the videocodec structure! */
+int videocodec_debugfs_show(struct seq_file *m);
+
#endif /*ifndef __LINUX_VIDEOCODEC_H */
diff --git a/drivers/staging/media/zoran/zoran.h b/drivers/staging/media/zoran/zoran.h
index b1ad2a2b914c..654c95fa5aba 100644
--- a/drivers/staging/media/zoran/zoran.h
+++ b/drivers/staging/media/zoran/zoran.h
@@ -18,6 +18,7 @@
#ifndef _BUZ_H_
#define _BUZ_H_
+#include <linux/debugfs.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#include <media/videobuf2-core.h>
@@ -53,22 +54,8 @@ static inline struct zr_buffer *vb2_to_zr_buffer(struct vb2_buffer *vb)
#define BUZ_NUM_STAT_COM 4
#define BUZ_MASK_STAT_COM 3
-#define BUZ_MAX_FRAME 256 /* Must be a power of 2 */
-#define BUZ_MASK_FRAME 255 /* Must be BUZ_MAX_FRAME-1 */
-
#define BUZ_MAX_INPUT 16
-#if VIDEO_MAX_FRAME <= 32
-# define V4L_MAX_FRAME 32
-#elif VIDEO_MAX_FRAME <= 64
-# define V4L_MAX_FRAME 64
-#else
-# error "Too many video frame buffers to handle"
-#endif
-#define V4L_MASK_FRAME (V4L_MAX_FRAME - 1)
-
-#define MAX_FRAME (BUZ_MAX_FRAME > VIDEO_MAX_FRAME ? BUZ_MAX_FRAME : VIDEO_MAX_FRAME)
-
#include "zr36057.h"
enum card_type {
@@ -295,6 +282,7 @@ struct zoran {
struct list_head queued_bufs;
spinlock_t queued_bufs_lock; /* Protects queued_bufs */
struct zr_buffer *inuse[BUZ_NUM_STAT_COM * 2];
+ struct dentry *dbgfs_dir;
};
static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev)
@@ -313,6 +301,6 @@ static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev)
#endif
-int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq);
+int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir);
void zoran_queue_exit(struct zoran *zr);
int zr_set_buf(struct zoran *zr);
diff --git a/drivers/staging/media/zoran/zoran_card.c b/drivers/staging/media/zoran/zoran_card.c
index f259585b0689..26f978a1cc72 100644
--- a/drivers/staging/media/zoran/zoran_card.c
+++ b/drivers/staging/media/zoran/zoran_card.c
@@ -29,6 +29,9 @@
#include "zoran.h"
#include "zoran_card.h"
#include "zoran_device.h"
+#include "zr36016.h"
+#include "zr36050.h"
+#include "zr36060.h"
extern const struct zoran_format zoran_formats[];
@@ -36,17 +39,6 @@ static int card[BUZ_MAX] = { [0 ... (BUZ_MAX - 1)] = -1 };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "Card type");
-/*
- * The video mem address of the video card. The driver has a little database
- * for some videocards to determine it from there. If your video card is not
- * in there you have either to give it to the driver as a parameter or set
- * in a VIDIOCSFBUF ioctl
- */
-
-static unsigned long vidmem; /* default = 0 - Video memory base address */
-module_param_hw(vidmem, ulong, iomem, 0444);
-MODULE_PARM_DESC(vidmem, "Default video memory base address");
-
/* Default input and video norm at startup of the driver. */
static unsigned int default_input; /* default 0 = Composite, 1 = S-Video */
@@ -68,20 +60,6 @@ static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX - 1)] = -1 };
module_param_array(video_nr, int, NULL, 0444);
MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)");
-int v4l_nbufs = 4;
-int v4l_bufsize = 864; /* Everybody should be able to work with this setting */
-module_param(v4l_nbufs, int, 0644);
-MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use");
-module_param(v4l_bufsize, int, 0644);
-MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)");
-
-int jpg_nbufs = 32;
-int jpg_bufsize = 512; /* max size for 100% quality full-PAL frame */
-module_param(jpg_nbufs, int, 0644);
-MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use");
-module_param(jpg_bufsize, int, 0644);
-MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)");
-
/* 1=Pass through TV signal when device is not used */
/* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */
int pass_through;
@@ -266,6 +244,96 @@ static const char *codecid_to_modulename(u16 codecid)
return name;
}
+static int codec_init(struct zoran *zr, u16 codecid)
+{
+ switch (codecid) {
+ case CODEC_TYPE_ZR36060:
+#ifdef CONFIG_VIDEO_ZORAN_ZR36060
+ return zr36060_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36060 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ case CODEC_TYPE_ZR36050:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ return zr36050_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36050 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ case CODEC_TYPE_ZR36016:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ return zr36016_init_module();
+#else
+ pci_err(zr->pci_dev, "ZR36016 support is not enabled\n");
+ return -EINVAL;
+#endif
+ break;
+ }
+
+ pci_err(zr->pci_dev, "unknown codec id %x\n", codecid);
+ return -EINVAL;
+}
+
+static void codec_exit(struct zoran *zr, u16 codecid)
+{
+ switch (codecid) {
+ case CODEC_TYPE_ZR36060:
+#ifdef CONFIG_VIDEO_ZORAN_ZR36060
+ zr36060_cleanup_module();
+#endif
+ break;
+ case CODEC_TYPE_ZR36050:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ zr36050_cleanup_module();
+#endif
+ break;
+ case CODEC_TYPE_ZR36016:
+#ifdef CONFIG_VIDEO_ZORAN_DC30
+ zr36016_cleanup_module();
+#endif
+ break;
+ }
+}
+
+static int videocodec_init(struct zoran *zr)
+{
+ const char *codec_name, *vfe_name;
+ int result;
+
+ codec_name = codecid_to_modulename(zr->card.video_codec);
+ if (codec_name) {
+ result = codec_init(zr, zr->card.video_codec);
+ if (result < 0) {
+ pci_err(zr->pci_dev, "failed to load video codec %s: %d\n",
+ codec_name, result);
+ return result;
+ }
+ }
+ vfe_name = codecid_to_modulename(zr->card.video_vfe);
+ if (vfe_name) {
+ result = codec_init(zr, zr->card.video_vfe);
+ if (result < 0) {
+ pci_err(zr->pci_dev, "failed to load video vfe %s: %d\n",
+ vfe_name, result);
+ if (codec_name)
+ codec_exit(zr, zr->card.video_codec);
+ return result;
+ }
+ }
+ return 0;
+}
+
+static void videocodec_exit(struct zoran *zr)
+{
+ if (zr->card.video_codec != CODEC_TYPE_NONE)
+ codec_exit(zr, zr->card.video_codec);
+ if (zr->card.video_vfe != CODEC_TYPE_NONE)
+ codec_exit(zr, zr->card.video_vfe);
+}
+
// struct tvnorm {
// u16 wt, wa, h_start, h_sync_start, ht, ha, v_start;
// };
@@ -803,6 +871,99 @@ int zoran_check_jpg_settings(struct zoran *zr,
return 0;
}
+static int zoran_init_video_device(struct zoran *zr, struct video_device *video_dev, int dir)
+{
+ int err;
+
+ /* Now add the template and register the device unit. */
+ *video_dev = zoran_template;
+ video_dev->v4l2_dev = &zr->v4l2_dev;
+ video_dev->lock = &zr->lock;
+ video_dev->device_caps = V4L2_CAP_STREAMING | dir;
+
+ strscpy(video_dev->name, ZR_DEVNAME(zr), sizeof(video_dev->name));
+ /*
+ * It's not a mem2mem device, but you can both capture and output from one and the same
+ * device. This should really be split up into two device nodes, but that's a job for
+ * another day.
+ */
+ video_dev->vfl_dir = VFL_DIR_M2M;
+ zoran_queue_init(zr, &zr->vq, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+ err = video_register_device(video_dev, VFL_TYPE_VIDEO, video_nr[zr->id]);
+ if (err < 0)
+ return err;
+ video_set_drvdata(video_dev, zr);
+ return 0;
+}
+
+static void zoran_exit_video_devices(struct zoran *zr)
+{
+ video_unregister_device(zr->video_dev);
+ kfree(zr->video_dev);
+}
+
+static int zoran_init_video_devices(struct zoran *zr)
+{
+ int err;
+
+ zr->video_dev = video_device_alloc();
+ if (!zr->video_dev)
+ return -ENOMEM;
+
+ err = zoran_init_video_device(zr, zr->video_dev, V4L2_CAP_VIDEO_CAPTURE);
+ if (err)
+ kfree(zr->video_dev);
+ return err;
+}
+
+/*
+ * v4l2_device_unregister() will care about removing zr->encoder/zr->decoder
+ * via v4l2_i2c_subdev_unregister()
+ */
+static int zoran_i2c_init(struct zoran *zr)
+{
+ int err;
+
+ pci_info(zr->pci_dev, "Initializing i2c bus...\n");
+
+ err = zoran_register_i2c(zr);
+ if (err) {
+ pci_err(zr->pci_dev, "%s - cannot initialize i2c bus\n", __func__);
+ return err;
+ }
+
+ zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
+ zr->card.i2c_decoder, 0,
+ zr->card.addrs_decoder);
+ if (!zr->decoder) {
+ pci_err(zr->pci_dev, "Fail to get decoder %s\n", zr->card.i2c_decoder);
+ err = -EINVAL;
+ goto error_decoder;
+ }
+
+ if (zr->card.i2c_encoder) {
+ zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
+ zr->card.i2c_encoder, 0,
+ zr->card.addrs_encoder);
+ if (!zr->encoder) {
+ pci_err(zr->pci_dev, "Fail to get encoder %s\n", zr->card.i2c_encoder);
+ err = -EINVAL;
+ goto error_decoder;
+ }
+ }
+ return 0;
+
+error_decoder:
+ zoran_unregister_i2c(zr);
+ return err;
+}
+
+static void zoran_i2c_exit(struct zoran *zr)
+{
+ zoran_unregister_i2c(zr);
+}
+
void zoran_open_init_params(struct zoran *zr)
{
int i;
@@ -874,17 +1035,11 @@ static int zr36057_init(struct zoran *zr)
zoran_open_init_params(zr);
/* allocate memory *before* doing anything to the hardware in case allocation fails */
- zr->video_dev = video_device_alloc();
- if (!zr->video_dev) {
- err = -ENOMEM;
- goto exit;
- }
zr->stat_com = dma_alloc_coherent(&zr->pci_dev->dev,
BUZ_NUM_STAT_COM * sizeof(u32),
&zr->p_sc, GFP_KERNEL);
if (!zr->stat_com) {
- err = -ENOMEM;
- goto exit_video;
+ return -ENOMEM;
}
for (j = 0; j < BUZ_NUM_STAT_COM; j++)
zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
@@ -897,26 +1052,9 @@ static int zr36057_init(struct zoran *zr)
goto exit_statcom;
}
- /* Now add the template and register the device unit. */
- *zr->video_dev = zoran_template;
- zr->video_dev->v4l2_dev = &zr->v4l2_dev;
- zr->video_dev->lock = &zr->lock;
- zr->video_dev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
-
- strscpy(zr->video_dev->name, ZR_DEVNAME(zr), sizeof(zr->video_dev->name));
- /*
- * It's not a mem2mem device, but you can both capture and output from one and the same
- * device. This should really be split up into two device nodes, but that's a job for
- * another day.
- */
- zr->video_dev->vfl_dir = VFL_DIR_M2M;
-
- zoran_queue_init(zr, &zr->vq);
-
- err = video_register_device(zr->video_dev, VFL_TYPE_VIDEO, video_nr[zr->id]);
- if (err < 0)
+ err = zoran_init_video_devices(zr);
+ if (err)
goto exit_statcomb;
- video_set_drvdata(zr->video_dev, zr);
zoran_init_hardware(zr);
if (!pass_through) {
@@ -931,9 +1069,6 @@ exit_statcomb:
dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32) * 2, zr->stat_comb, zr->p_scb);
exit_statcom:
dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32), zr->stat_com, zr->p_sc);
-exit_video:
- kfree(zr->video_dev);
-exit:
return err;
}
@@ -945,6 +1080,8 @@ static void zoran_remove(struct pci_dev *pdev)
if (!zr->initialized)
goto exit_free;
+ debugfs_remove_recursive(zr->dbgfs_dir);
+
zoran_queue_exit(zr);
/* unregister videocodec bus */
@@ -952,9 +1089,10 @@ static void zoran_remove(struct pci_dev *pdev)
videocodec_detach(zr->codec);
if (zr->vfe)
videocodec_detach(zr->vfe);
+ videocodec_exit(zr);
/* unregister i2c bus */
- zoran_unregister_i2c(zr);
+ zoran_i2c_exit(zr);
/* disable PCI bus-mastering */
zoran_set_pci_master(zr, 0);
/* put chip into reset */
@@ -965,7 +1103,7 @@ static void zoran_remove(struct pci_dev *pdev)
dma_free_coherent(&zr->pci_dev->dev, BUZ_NUM_STAT_COM * sizeof(u32) * 2, zr->stat_comb, zr->p_scb);
pci_release_regions(pdev);
pci_disable_device(zr->pci_dev);
- video_unregister_device(zr->video_dev);
+ zoran_exit_video_devices(zr);
exit_free:
v4l2_ctrl_handler_free(&zr->hdl);
v4l2_device_unregister(&zr->v4l2_dev);
@@ -1051,6 +1189,39 @@ static const struct v4l2_ctrl_ops zoran_video_ctrl_ops = {
.s_ctrl = zoran_video_set_ctrl,
};
+static int zoran_debugfs_show(struct seq_file *seq, void *v)
+{
+ struct zoran *zr = seq->private;
+
+ seq_printf(seq, "Running mode %x\n", zr->running);
+ seq_printf(seq, "Codec mode %x\n", zr->codec_mode);
+ seq_printf(seq, "Norm %llx\n", zr->norm);
+ seq_printf(seq, "Input %d\n", zr->input);
+ seq_printf(seq, "Buffersize %d\n", zr->buffer_size);
+
+ seq_printf(seq, "V4L width %dx%d\n", zr->v4l_settings.width, zr->v4l_settings.height);
+ seq_printf(seq, "V4L bytesperline %d\n", zr->v4l_settings.bytesperline);
+
+ seq_printf(seq, "JPG decimation %u\n", zr->jpg_settings.decimation);
+ seq_printf(seq, "JPG hor_dcm %u\n", zr->jpg_settings.hor_dcm);
+ seq_printf(seq, "JPG ver_dcm %u\n", zr->jpg_settings.ver_dcm);
+ seq_printf(seq, "JPG tmp_dcm %u\n", zr->jpg_settings.tmp_dcm);
+ seq_printf(seq, "JPG odd_even %u\n", zr->jpg_settings.odd_even);
+ seq_printf(seq, "JPG crop %dx%d %d %d\n",
+ zr->jpg_settings.img_x,
+ zr->jpg_settings.img_y,
+ zr->jpg_settings.img_width,
+ zr->jpg_settings.img_height);
+
+ seq_printf(seq, "Prepared %u\n", zr->prepared);
+ seq_printf(seq, "Queued %u\n", zr->queued);
+
+ videocodec_debugfs_show(seq);
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(zoran_debugfs);
+
/*
* Scan for a Buz card (actually for the PCI controller ZR36057),
* request the irq and map the io memory
@@ -1063,14 +1234,22 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct videocodec_master *master_vfe = NULL;
struct videocodec_master *master_codec = NULL;
int card_num;
- const char *codec_name, *vfe_name;
unsigned int nr;
int err;
+ pci_info(pdev, "Zoran MJPEG board driver version %s\n", ZORAN_VERSION);
+
+ /* some mainboards might not do PCI-PCI data transfer well */
+ if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
+ pci_warn(pdev, "%s: chipset does not support reliable PCI-PCI DMA\n",
+ ZORAN_NAME);
+
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (err)
- return -ENODEV;
- vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
+ return err;
+ err = vb2_dma_contig_set_max_seg_size(&pdev->dev, U32_MAX);
+ if (err)
+ return err;
nr = zoran_num++;
if (nr >= BUZ_MAX) {
@@ -1174,41 +1353,15 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
zr36057_restart(zr);
- /* i2c */
- pci_info(zr->pci_dev, "Initializing i2c bus...\n");
- if (zoran_register_i2c(zr) < 0) {
- pci_err(pdev, "%s - can't initialize i2c bus\n", __func__);
+ err = zoran_i2c_init(zr);
+ if (err)
goto zr_free_irq;
- }
-
- zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
- zr->card.i2c_decoder, 0,
- zr->card.addrs_decoder);
-
- if (zr->card.i2c_encoder)
- zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter,
- zr->card.i2c_encoder, 0,
- zr->card.addrs_encoder);
pci_info(zr->pci_dev, "Initializing videocodec bus...\n");
-
- if (zr->card.video_codec) {
- codec_name = codecid_to_modulename(zr->card.video_codec);
- if (codec_name) {
- result = request_module(codec_name);
- if (result)
- pci_err(pdev, "failed to load modules %s: %d\n", codec_name, result);
- }
- }
- if (zr->card.video_vfe) {
- vfe_name = codecid_to_modulename(zr->card.video_vfe);
- if (vfe_name) {
- result = request_module(vfe_name);
- if (result < 0)
- pci_err(pdev, "failed to load modules %s: %d\n", vfe_name, result);
- }
- }
+ err = videocodec_init(zr);
+ if (err)
+ goto zr_unreg_i2c;
/* reset JPEG codec */
jpeg_codec_sleep(zr, 1);
@@ -1218,15 +1371,15 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (zr->card.video_codec != 0) {
master_codec = zoran_setup_videocodec(zr, zr->card.video_codec);
if (!master_codec)
- goto zr_unreg_i2c;
+ goto zr_unreg_videocodec;
zr->codec = videocodec_attach(master_codec);
if (!zr->codec) {
pci_err(pdev, "%s - no codec found\n", __func__);
- goto zr_unreg_i2c;
+ goto zr_unreg_videocodec;
}
if (zr->codec->type != zr->card.video_codec) {
pci_err(pdev, "%s - wrong codec\n", __func__);
- goto zr_detach_codec;
+ goto zr_unreg_videocodec;
}
}
if (zr->card.video_vfe != 0) {
@@ -1253,14 +1406,19 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
zr->map_mode = ZORAN_MAP_MODE_RAW;
+ zr->dbgfs_dir = debugfs_create_dir(ZR_DEVNAME(zr), NULL);
+ debugfs_create_file("debug", 0444, zr->dbgfs_dir, zr,
+ &zoran_debugfs_fops);
return 0;
zr_detach_vfe:
videocodec_detach(zr->vfe);
zr_detach_codec:
videocodec_detach(zr->codec);
+zr_unreg_videocodec:
+ videocodec_exit(zr);
zr_unreg_i2c:
- zoran_unregister_i2c(zr);
+ zoran_i2c_exit(zr);
zr_free_irq:
btwrite(0, ZR36057_SPGPPCR);
pci_free_irq(zr->pci_dev, 0, zr);
@@ -1281,54 +1439,4 @@ static struct pci_driver zoran_driver = {
.remove = zoran_remove,
};
-static int __init zoran_init(void)
-{
- int res;
-
- pr_info("Zoran MJPEG board driver version %s\n", ZORAN_VERSION);
-
- /* check the parameters we have been given, adjust if necessary */
- if (v4l_nbufs < 2)
- v4l_nbufs = 2;
- if (v4l_nbufs > VIDEO_MAX_FRAME)
- v4l_nbufs = VIDEO_MAX_FRAME;
- /* The user specifies the in KB, we want them in byte (and page aligned) */
- v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024);
- if (v4l_bufsize < 32768)
- v4l_bufsize = 32768;
- /* 2 MB is arbitrary but sufficient for the maximum possible images */
- if (v4l_bufsize > 2048 * 1024)
- v4l_bufsize = 2048 * 1024;
- if (jpg_nbufs < 4)
- jpg_nbufs = 4;
- if (jpg_nbufs > BUZ_MAX_FRAME)
- jpg_nbufs = BUZ_MAX_FRAME;
- jpg_bufsize = PAGE_ALIGN(jpg_bufsize * 1024);
- if (jpg_bufsize < 8192)
- jpg_bufsize = 8192;
- if (jpg_bufsize > (512 * 1024))
- jpg_bufsize = 512 * 1024;
- /* Use parameter for vidmem or try to find a video card */
- if (vidmem)
- pr_info("%s: Using supplied video memory base address @ 0x%lx\n", ZORAN_NAME, vidmem);
-
- /* some mainboards might not do PCI-PCI data transfer well */
- if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
- pr_warn("%s: chipset does not support reliable PCI-PCI DMA\n", ZORAN_NAME);
-
- res = pci_register_driver(&zoran_driver);
- if (res) {
- pr_err("Unable to register ZR36057 driver\n");
- return res;
- }
-
- return 0;
-}
-
-static void __exit zoran_exit(void)
-{
- pci_unregister_driver(&zoran_driver);
-}
-
-module_init(zoran_init);
-module_exit(zoran_exit);
+module_pci_driver(zoran_driver);
diff --git a/drivers/staging/media/zoran/zoran_device.c b/drivers/staging/media/zoran/zoran_device.c
index 5b12a730a229..2470889a58fa 100644
--- a/drivers/staging/media/zoran/zoran_device.c
+++ b/drivers/staging/media/zoran/zoran_device.c
@@ -239,7 +239,7 @@ static void zr36057_set_vfe(struct zoran *zr, int video_width, int video_height,
wa = tvn->wa;
ha = tvn->ha;
- pci_info(zr->pci_dev, "set_vfe() - width = %d, height = %d\n", video_width, video_height);
+ pci_dbg(zr->pci_dev, "set_vfe() - width = %d, height = %d\n", video_width, video_height);
if (video_width < BUZ_MIN_WIDTH ||
video_height < BUZ_MIN_HEIGHT ||
@@ -664,7 +664,7 @@ void zr36057_enable_jpg(struct zoran *zr, enum zoran_codec_mode mode)
zr36057_set_jpg(zr, mode); // \P_Reset, ... Video param, FIFO
clear_interrupt_counters(zr);
- pci_info(zr->pci_dev, "enable_jpg(MOTION_COMPRESS)\n");
+ pci_dbg(zr->pci_dev, "enable_jpg(MOTION_COMPRESS)\n");
break;
}
@@ -693,7 +693,7 @@ void zr36057_enable_jpg(struct zoran *zr, enum zoran_codec_mode mode)
zr36057_set_jpg(zr, mode); // \P_Reset, ... Video param, FIFO
clear_interrupt_counters(zr);
- pci_info(zr->pci_dev, "enable_jpg(MOTION_DECOMPRESS)\n");
+ pci_dbg(zr->pci_dev, "enable_jpg(MOTION_DECOMPRESS)\n");
break;
case BUZ_MODE_IDLE:
@@ -720,7 +720,7 @@ void zr36057_enable_jpg(struct zoran *zr, enum zoran_codec_mode mode)
decoder_call(zr, video, s_stream, 1);
encoder_call(zr, video, s_routing, 0, 0, 0);
- pci_info(zr->pci_dev, "enable_jpg(IDLE)\n");
+ pci_dbg(zr->pci_dev, "enable_jpg(IDLE)\n");
break;
}
}
@@ -814,7 +814,7 @@ static void zoran_reap_stat_com(struct zoran *zr)
if (zr->jpg_settings.tmp_dcm == 1)
i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
else
- i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2 + 1;
+ i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
stat_com = le32_to_cpu(zr->stat_com[i]);
if ((stat_com & 1) == 0) {
@@ -826,6 +826,11 @@ static void zoran_reap_stat_com(struct zoran *zr)
size = (stat_com & GENMASK(22, 1)) >> 1;
buf = zr->inuse[i];
+ if (!buf) {
+ spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
+ pci_err(zr->pci_dev, "No buffer at slot %d\n", i);
+ return;
+ }
buf->vbuf.vb2_buf.timestamp = ktime_get_ns();
if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
diff --git a/drivers/staging/media/zoran/zoran_device.h b/drivers/staging/media/zoran/zoran_device.h
index 6c5d70238228..322b04c55d41 100644
--- a/drivers/staging/media/zoran/zoran_device.h
+++ b/drivers/staging/media/zoran/zoran_device.h
@@ -47,9 +47,7 @@ extern void zr36057_restart(struct zoran *zr);
extern const struct zoran_format zoran_formats[];
-extern int v4l_nbufs;
extern int v4l_bufsize;
-extern int jpg_nbufs;
extern int jpg_bufsize;
extern int pass_through;
diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c
index 46382e43f1bf..4304b7e21709 100644
--- a/drivers/staging/media/zoran/zoran_driver.c
+++ b/drivers/staging/media/zoran/zoran_driver.c
@@ -153,8 +153,6 @@ static __u32 zoran_v4l2_calc_bufsize(struct zoran_jpg_settings *settings)
result <<= 1;
}
- if (result > jpg_bufsize)
- return jpg_bufsize;
if (result < 8192)
return 8192;
@@ -173,7 +171,7 @@ static int zoran_v4l_set_format(struct zoran *zr, int width, int height,
if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH ||
height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {
- pci_err(zr->pci_dev, "%s - wrong frame size (%dx%d)\n", __func__, width, height);
+ pci_dbg(zr->pci_dev, "%s - wrong frame size (%dx%d)\n", __func__, width, height);
return -EINVAL;
}
@@ -183,7 +181,7 @@ static int zoran_v4l_set_format(struct zoran *zr, int width, int height,
/* Check against available buffer size */
if (height * width * bpp > zr->buffer_size) {
- pci_err(zr->pci_dev, "%s - video buffer size (%d kB) is too small\n",
+ pci_dbg(zr->pci_dev, "%s - video buffer size (%d kB) is too small\n",
__func__, zr->buffer_size >> 10);
return -EINVAL;
}
@@ -191,7 +189,7 @@ static int zoran_v4l_set_format(struct zoran *zr, int width, int height,
/* The video front end needs 4-byte alinged line sizes */
if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
- pci_err(zr->pci_dev, "%s - wrong frame alignment\n", __func__);
+ pci_dbg(zr->pci_dev, "%s - wrong frame alignment\n", __func__);
return -EINVAL;
}
@@ -207,7 +205,7 @@ static int zoran_set_norm(struct zoran *zr, v4l2_std_id norm)
{
if (!(norm & zr->card.norms)) {
- pci_err(zr->pci_dev, "%s - unsupported norm %llx\n", __func__, norm);
+ pci_dbg(zr->pci_dev, "%s - unsupported norm %llx\n", __func__, norm);
return -EINVAL;
}
@@ -233,7 +231,7 @@ static int zoran_set_input(struct zoran *zr, int input)
return 0;
if (input < 0 || input >= zr->card.inputs) {
- pci_err(zr->pci_dev, "%s - unsupported input %d\n", __func__, input);
+ pci_dbg(zr->pci_dev, "%s - unsupported input %d\n", __func__, input);
return -EINVAL;
}
@@ -255,8 +253,6 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability
strscpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
strscpy(cap->driver, "zoran", sizeof(cap->driver));
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(zr->pci_dev));
- cap->device_caps = zr->video_dev->device_caps;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
@@ -402,7 +398,6 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings);
- zr->buffer_size = fmt->fmt.pix.sizeimage;
fmt->fmt.pix.bytesperline = 0;
fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
return res;
@@ -437,6 +432,8 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8);
v4l_bound_align_image(&fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2,
&fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0);
+ fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * bpp;
+ fmt->fmt.pix.sizeimage = fmt->fmt.pix.bytesperline * fmt->fmt.pix.height;
return 0;
}
@@ -535,7 +532,7 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc)
break;
if (i == NUM_FORMATS) {
- pci_err(zr->pci_dev, "VIDIOC_S_FMT - unknown/unsupported format 0x%x\n",
+ pci_dbg(zr->pci_dev, "VIDIOC_S_FMT - unknown/unsupported format 0x%x\n",
fmt->fmt.pix.pixelformat);
/* TODO do not return here to fix the TRY_FMT cannot handle an invalid pixelformat*/
return -EINVAL;
@@ -582,6 +579,9 @@ static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std)
struct zoran *zr = video_drvdata(file);
int res = 0;
+ if (zr->norm == std)
+ return 0;
+
if (zr->running != ZORAN_MAP_MODE_NONE)
return -EBUSY;
@@ -666,7 +666,7 @@ static int zoran_g_selection(struct file *file, void *__fh, struct v4l2_selectio
if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- pci_err(zr->pci_dev, "%s invalid selection type combination\n", __func__);
+ pci_dbg(zr->pci_dev, "%s invalid selection type combination\n", __func__);
return -EINVAL;
}
@@ -712,7 +712,7 @@ static int zoran_s_selection(struct file *file, void *__fh, struct v4l2_selectio
return -EINVAL;
if (zr->map_mode == ZORAN_MAP_MODE_RAW) {
- pci_err(zr->pci_dev, "VIDIOC_S_SELECTION - subcapture only supported for compressed capture\n");
+ pci_dbg(zr->pci_dev, "VIDIOC_S_SELECTION - subcapture only supported for compressed capture\n");
return -EINVAL;
}
@@ -734,14 +734,6 @@ static int zoran_s_selection(struct file *file, void *__fh, struct v4l2_selectio
return res;
}
-static int zoran_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm)
-{
- if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- return 0;
-}
-
/*
* Output is disabled temporarily
* Zoran is picky about jpeg data it accepts. At least it seems to unsupport COM and APPn.
@@ -749,7 +741,6 @@ static int zoran_g_parm(struct file *file, void *priv, struct v4l2_streamparm *p
*/
static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
.vidioc_querycap = zoran_querycap,
- .vidioc_g_parm = zoran_g_parm,
.vidioc_s_selection = zoran_s_selection,
.vidioc_g_selection = zoran_g_selection,
.vidioc_enum_input = zoran_enum_input,
@@ -785,8 +776,6 @@ static const struct v4l2_file_operations zoran_fops = {
.unlocked_ioctl = video_ioctl2,
.open = v4l2_fh_open,
.release = vb2_fop_release,
- .read = vb2_fop_read,
- .write = vb2_fop_write,
.mmap = vb2_fop_mmap,
.poll = vb2_fop_poll,
};
@@ -869,6 +858,10 @@ int zr_set_buf(struct zoran *zr)
vbuf = &buf->vbuf;
buf->vbuf.field = V4L2_FIELD_INTERLACED;
+ if (BUZ_MAX_HEIGHT < (zr->v4l_settings.height * 2))
+ buf->vbuf.field = V4L2_FIELD_INTERLACED;
+ else
+ buf->vbuf.field = V4L2_FIELD_TOP;
vb2_set_plane_payload(&buf->vbuf.vb2_buf, 0, zr->buffer_size);
vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
zr->inuse[0] = NULL;
@@ -889,6 +882,7 @@ int zr_set_buf(struct zoran *zr)
return -EINVAL;
}
list_del(&buf->queue);
+ zr->buf_in_reserve--;
spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
vbuf = &buf->vbuf;
@@ -928,9 +922,10 @@ static int zr_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
zr->stat_com[j] = cpu_to_le32(1);
zr->inuse[j] = NULL;
}
+ zr->vbseq = 0;
if (zr->map_mode != ZORAN_MAP_MODE_RAW) {
- pci_info(zr->pci_dev, "START JPG\n");
+ pci_dbg(zr->pci_dev, "START JPG\n");
zr36057_restart(zr);
zoran_init_hardware(zr);
if (zr->map_mode == ZORAN_MAP_MODE_JPG_REC)
@@ -944,7 +939,7 @@ static int zr_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
return 0;
}
- pci_info(zr->pci_dev, "START RAW\n");
+ pci_dbg(zr->pci_dev, "START RAW\n");
zr36057_restart(zr);
zoran_init_hardware(zr);
@@ -994,7 +989,7 @@ static void zr_vb2_stop_streaming(struct vb2_queue *vq)
}
spin_unlock_irqrestore(&zr->queued_bufs_lock, flags);
if (zr->buf_in_reserve)
- pci_err(zr->pci_dev, "Buffer remaining %d\n", zr->buf_in_reserve);
+ pci_dbg(zr->pci_dev, "Buffer remaining %d\n", zr->buf_in_reserve);
zr->map_mode = ZORAN_MAP_MODE_RAW;
}
@@ -1008,7 +1003,7 @@ static const struct vb2_ops zr_video_qops = {
.wait_finish = vb2_ops_wait_finish,
};
-int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq)
+int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq, int dir)
{
int err;
@@ -1016,8 +1011,9 @@ int zoran_queue_init(struct zoran *zr, struct vb2_queue *vq)
INIT_LIST_HEAD(&zr->queued_bufs);
vq->dev = &zr->pci_dev->dev;
- vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- vq->io_modes = VB2_USERPTR | VB2_DMABUF | VB2_MMAP | VB2_READ | VB2_WRITE;
+ vq->type = dir;
+
+ vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ | VB2_WRITE;
vq->drv_priv = zr;
vq->buf_struct_size = sizeof(struct zr_buffer);
vq->ops = &zr_video_qops;
diff --git a/drivers/staging/media/zoran/zr36016.c b/drivers/staging/media/zoran/zr36016.c
index 9b350a885879..26c7c32b6bc0 100644
--- a/drivers/staging/media/zoran/zr36016.c
+++ b/drivers/staging/media/zoran/zr36016.c
@@ -22,14 +22,14 @@
/* amount of chips attached via this driver */
static int zr36016_codecs;
-/* debugging is available via module parameter */
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
+static int zr36016_debug;
+module_param(zr36016_debug, int, 0);
+MODULE_PARM_DESC(zr36016_debug, "Debug level (0-4)");
+
#define dprintk(num, format, args...) \
do { \
- if (debug >= num) \
+ if (zr36016_debug >= num) \
printk(format, ##args); \
} while (0)
@@ -120,7 +120,7 @@ static u8 zr36016_read_version(struct zr36016 *ptr)
static int zr36016_basic_test(struct zr36016 *ptr)
{
- if (debug) {
+ if (zr36016_debug) {
int i;
zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
@@ -390,7 +390,6 @@ static int zr36016_setup(struct videocodec *codec)
}
static const struct videocodec zr36016_codec = {
- .owner = THIS_MODULE,
.name = "zr36016",
.magic = 0L, /* magic not used */
.flags =
@@ -409,14 +408,13 @@ static const struct videocodec zr36016_codec = {
HOOK IN DRIVER AS KERNEL MODULE
========================================================================= */
-static int __init zr36016_init_module(void)
+int zr36016_init_module(void)
{
- //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION);
zr36016_codecs = 0;
return videocodec_register(&zr36016_codec);
}
-static void __exit zr36016_cleanup_module(void)
+void zr36016_cleanup_module(void)
{
if (zr36016_codecs) {
dprintk(1,
@@ -425,10 +423,3 @@ static void __exit zr36016_cleanup_module(void)
}
videocodec_unregister(&zr36016_codec);
}
-
-module_init(zr36016_init_module);
-module_exit(zr36016_cleanup_module);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Driver module for ZR36016 video frontends");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/zoran/zr36016.h b/drivers/staging/media/zoran/zr36016.h
index 1475f971cc24..04afba35669d 100644
--- a/drivers/staging/media/zoran/zr36016.h
+++ b/drivers/staging/media/zoran/zr36016.h
@@ -89,4 +89,6 @@ struct zr36016 {
#define ZR016_SIGN 0x02
#define ZR016_YMCS 0x01
+int zr36016_init_module(void);
+void zr36016_cleanup_module(void);
#endif /*fndef ZR36016_H */
diff --git a/drivers/staging/media/zoran/zr36050.c b/drivers/staging/media/zoran/zr36050.c
index c62af27f2683..38f7021e7b06 100644
--- a/drivers/staging/media/zoran/zr36050.c
+++ b/drivers/staging/media/zoran/zr36050.c
@@ -5,8 +5,6 @@
* Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
*/
-#define ZR050_VERSION "v0.7.1"
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -32,13 +30,13 @@
static int zr36050_codecs;
/* debugging is available via module parameter */
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
+static int zr36050_debug;
+module_param(zr36050_debug, int, 0);
+MODULE_PARM_DESC(zr36050_debug, "Debug level (0-4)");
#define dprintk(num, format, args...) \
do { \
- if (debug >= num) \
+ if (zr36050_debug >= num) \
printk(format, ##args); \
} while (0)
@@ -798,7 +796,6 @@ static int zr36050_setup(struct videocodec *codec)
}
static const struct videocodec zr36050_codec = {
- .owner = THIS_MODULE,
.name = "zr36050",
.magic = 0L, // magic not used
.flags =
@@ -817,14 +814,13 @@ static const struct videocodec zr36050_codec = {
HOOK IN DRIVER AS KERNEL MODULE
========================================================================= */
-static int __init zr36050_init_module(void)
+int zr36050_init_module(void)
{
- //dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION);
zr36050_codecs = 0;
return videocodec_register(&zr36050_codec);
}
-static void __exit zr36050_cleanup_module(void)
+void zr36050_cleanup_module(void)
{
if (zr36050_codecs) {
dprintk(1,
@@ -833,11 +829,3 @@ static void __exit zr36050_cleanup_module(void)
}
videocodec_unregister(&zr36050_codec);
}
-
-module_init(zr36050_init_module);
-module_exit(zr36050_cleanup_module);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors "
- ZR050_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/zoran/zr36050.h b/drivers/staging/media/zoran/zr36050.h
index 8f972d045b58..f9b58f4c77b9 100644
--- a/drivers/staging/media/zoran/zr36050.h
+++ b/drivers/staging/media/zoran/zr36050.h
@@ -160,4 +160,6 @@ struct zr36050 {
#define ZR050_U_COMPONENT 1
#define ZR050_V_COMPONENT 2
+int zr36050_init_module(void);
+void zr36050_cleanup_module(void);
#endif /*fndef ZR36050_H */
diff --git a/drivers/staging/media/zoran/zr36060.c b/drivers/staging/media/zoran/zr36060.c
index 1c3af11b5f24..d0c369e31c81 100644
--- a/drivers/staging/media/zoran/zr36060.c
+++ b/drivers/staging/media/zoran/zr36060.c
@@ -5,8 +5,6 @@
* Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
*/
-#define ZR060_VERSION "v0.7"
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -34,14 +32,13 @@ static bool low_bitrate;
module_param(low_bitrate, bool, 0);
MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
-/* debugging is available via module parameter */
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
+static int zr36060_debug;
+module_param(zr36060_debug, int, 0);
+MODULE_PARM_DESC(zr36060_debug, "Debug level (0-4)");
#define dprintk(num, format, args...) \
do { \
- if (debug >= num) \
+ if (zr36060_debug >= num) \
printk(format, ##args); \
} while (0)
@@ -832,7 +829,6 @@ static int zr36060_setup(struct videocodec *codec)
}
static const struct videocodec zr36060_codec = {
- .owner = THIS_MODULE,
.name = "zr36060",
.magic = 0L, // magic not used
.flags =
@@ -847,13 +843,13 @@ static const struct videocodec zr36060_codec = {
// others are not used
};
-static int __init zr36060_init_module(void)
+int zr36060_init_module(void)
{
zr36060_codecs = 0;
return videocodec_register(&zr36060_codec);
}
-static void __exit zr36060_cleanup_module(void)
+void zr36060_cleanup_module(void)
{
if (zr36060_codecs) {
dprintk(1,
@@ -864,10 +860,3 @@ static void __exit zr36060_cleanup_module(void)
/* however, we can't just stay alive */
videocodec_unregister(&zr36060_codec);
}
-
-module_init(zr36060_init_module);
-module_exit(zr36060_cleanup_module);
-
-MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
-MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors " ZR060_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/media/zoran/zr36060.h b/drivers/staging/media/zoran/zr36060.h
index d2cdc26bf625..fbf5429534ac 100644
--- a/drivers/staging/media/zoran/zr36060.h
+++ b/drivers/staging/media/zoran/zr36060.h
@@ -198,4 +198,6 @@ struct zr36060 {
#define ZR060_SR_H_SCALE2 BIT(0)
#define ZR060_SR_H_SCALE4 (2 << 0)
+int zr36060_init_module(void);
+void zr36060_cleanup_module(void);
#endif /*fndef ZR36060_H */
diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c
index bd102329d8c8..97dff82b7a5f 100644
--- a/drivers/staging/most/dim2/dim2.c
+++ b/drivers/staging/most/dim2/dim2.c
@@ -45,9 +45,6 @@ MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a powe
static DEFINE_SPINLOCK(dim_lock);
-static void dim2_tasklet_fn(unsigned long data);
-static DECLARE_TASKLET_OLD(dim2_tasklet, dim2_tasklet_fn);
-
/**
* struct hdm_channel - private structure to keep channel specific data
* @name: channel name
@@ -361,15 +358,9 @@ static irqreturn_t dim2_mlb_isr(int irq, void *_dev)
return IRQ_HANDLED;
}
-/**
- * dim2_tasklet_fn - tasklet function
- * @data: private data
- *
- * Service each initialized channel, if needed
- */
-static void dim2_tasklet_fn(unsigned long data)
+static irqreturn_t dim2_task_irq(int irq, void *_dev)
{
- struct dim2_hdm *dev = (struct dim2_hdm *)data;
+ struct dim2_hdm *dev = _dev;
unsigned long flags;
int ch_idx;
@@ -385,6 +376,8 @@ static void dim2_tasklet_fn(unsigned long data)
while (!try_start_dim_transfer(dev->hch + ch_idx))
continue;
}
+
+ return IRQ_HANDLED;
}
/**
@@ -392,8 +385,8 @@ static void dim2_tasklet_fn(unsigned long data)
* @irq: irq number
* @_dev: private data
*
- * Acknowledge the interrupt and schedule a tasklet to service channels.
- * Return IRQ_HANDLED.
+ * Acknowledge the interrupt and service each initialized channel,
+ * if needed, in task context.
*/
static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
{
@@ -405,9 +398,7 @@ static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
dim_service_ahb_int_irq(get_active_channels(dev, buffer));
spin_unlock_irqrestore(&dim_lock, flags);
- dim2_tasklet.data = (unsigned long)dev;
- tasklet_schedule(&dim2_tasklet);
- return IRQ_HANDLED;
+ return IRQ_WAKE_THREAD;
}
/**
@@ -654,14 +645,12 @@ static int poison_channel(struct most_interface *most_iface, int ch_idx)
if (!hdm_ch->is_initialized)
return -EPERM;
- tasklet_disable(&dim2_tasklet);
spin_lock_irqsave(&dim_lock, flags);
hal_ret = dim_destroy_channel(&hdm_ch->ch);
hdm_ch->is_initialized = false;
if (ch_idx == dev->atx_idx)
dev->atx_idx = -1;
spin_unlock_irqrestore(&dim_lock, flags);
- tasklet_enable(&dim2_tasklet);
if (hal_ret != DIM_NO_ERROR) {
pr_err("HAL Failed to close channel %s\n", hdm_ch->name);
ret = -EFAULT;
@@ -821,8 +810,8 @@ static int dim2_probe(struct platform_device *pdev)
goto err_shutdown_dim;
}
- ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0,
- "dim2_ahb0_int", dev);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, dim2_ahb_isr,
+ dim2_task_irq, 0, "dim2_ahb0_int", dev);
if (ret) {
dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq);
goto err_shutdown_dim;
@@ -971,7 +960,7 @@ static void fsl_mx6_disable(struct platform_device *pdev)
clk_disable_unprepare(dev->clk);
}
-static int rcar_h2_enable(struct platform_device *pdev)
+static int rcar_gen2_enable(struct platform_device *pdev)
{
struct dim2_hdm *dev = platform_get_drvdata(pdev);
int ret;
@@ -1006,7 +995,7 @@ static int rcar_h2_enable(struct platform_device *pdev)
return 0;
}
-static void rcar_h2_disable(struct platform_device *pdev)
+static void rcar_gen2_disable(struct platform_device *pdev)
{
struct dim2_hdm *dev = platform_get_drvdata(pdev);
@@ -1016,7 +1005,7 @@ static void rcar_h2_disable(struct platform_device *pdev)
writel(0x0, dev->io_base + 0x600);
}
-static int rcar_m3_enable(struct platform_device *pdev)
+static int rcar_gen3_enable(struct platform_device *pdev)
{
struct dim2_hdm *dev = platform_get_drvdata(pdev);
u32 enable_512fs = dev->clk_speed == CLK_512FS;
@@ -1046,7 +1035,7 @@ static int rcar_m3_enable(struct platform_device *pdev)
return 0;
}
-static void rcar_m3_disable(struct platform_device *pdev)
+static void rcar_gen3_disable(struct platform_device *pdev)
{
struct dim2_hdm *dev = platform_get_drvdata(pdev);
@@ -1058,20 +1047,20 @@ static void rcar_m3_disable(struct platform_device *pdev)
/* ]] platform specific functions */
-enum dim2_platforms { FSL_MX6, RCAR_H2, RCAR_M3 };
+enum dim2_platforms { FSL_MX6, RCAR_GEN2, RCAR_GEN3 };
static struct dim2_platform_data plat_data[] = {
[FSL_MX6] = {
.enable = fsl_mx6_enable,
.disable = fsl_mx6_disable,
},
- [RCAR_H2] = {
- .enable = rcar_h2_enable,
- .disable = rcar_h2_disable,
+ [RCAR_GEN2] = {
+ .enable = rcar_gen2_enable,
+ .disable = rcar_gen2_disable,
},
- [RCAR_M3] = {
- .enable = rcar_m3_enable,
- .disable = rcar_m3_disable,
+ [RCAR_GEN3] = {
+ .enable = rcar_gen3_enable,
+ .disable = rcar_gen3_disable,
.fcnt = 3,
},
};
@@ -1083,11 +1072,11 @@ static const struct of_device_id dim2_of_match[] = {
},
{
.compatible = "renesas,mlp",
- .data = plat_data + RCAR_H2
+ .data = plat_data + RCAR_GEN2
},
{
- .compatible = "rcar,medialb-dim2",
- .data = plat_data + RCAR_M3
+ .compatible = "renesas,rcar-gen3-mlp",
+ .data = plat_data + RCAR_GEN3
},
{
.compatible = "xlnx,axi4-os62420_3pin-1.00.a",
diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c
index 47039f0d262f..1d1fe8bff7ee 100644
--- a/drivers/staging/most/net/net.c
+++ b/drivers/staging/most/net/net.c
@@ -67,7 +67,7 @@ struct net_dev_context {
struct list_head list;
};
-static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
+static LIST_HEAD(net_devices);
static DEFINE_MUTEX(probe_disc_mt); /* ch->linked = true, most_nd_open */
static DEFINE_SPINLOCK(list_lock); /* list_head, ch->linked = false, dev_hold */
static struct most_component comp;
diff --git a/drivers/staging/most/video/Kconfig b/drivers/staging/most/video/Kconfig
index e0964ca5e7b3..e16cc5e104b7 100644
--- a/drivers/staging/most/video/Kconfig
+++ b/drivers/staging/most/video/Kconfig
@@ -5,7 +5,7 @@
config MOST_VIDEO
tristate "Video"
- depends on VIDEO_V4L2
+ depends on VIDEO_DEV
help
Say Y here if you want to commumicate via Video 4 Linux.
diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c
index b7858e47145f..ffa97ef21ea5 100644
--- a/drivers/staging/most/video/video.c
+++ b/drivers/staging/most/video/video.c
@@ -52,7 +52,7 @@ struct comp_fh {
u32 offs;
};
-static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
+static LIST_HEAD(video_devices);
static DEFINE_SPINLOCK(list_lock);
static inline bool data_ready(struct most_video_dev *mdev)
diff --git a/drivers/staging/mt7621-dma/Kconfig b/drivers/staging/mt7621-dma/Kconfig
deleted file mode 100644
index 54a110288f92..000000000000
--- a/drivers/staging/mt7621-dma/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config MTK_HSDMA
- tristate "MTK HSDMA support"
- depends on RALINK && SOC_MT7621
- select DMA_ENGINE
- select DMA_VIRTUAL_CHANNELS
-
diff --git a/drivers/staging/mt7621-dma/Makefile b/drivers/staging/mt7621-dma/Makefile
deleted file mode 100644
index 23256d1286f3..000000000000
--- a/drivers/staging/mt7621-dma/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_MTK_HSDMA) += hsdma-mt7621.o
-
-ccflags-y += -I$(srctree)/drivers/dma
diff --git a/drivers/staging/mt7621-dma/TODO b/drivers/staging/mt7621-dma/TODO
deleted file mode 100644
index fdbc5002c32a..000000000000
--- a/drivers/staging/mt7621-dma/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-
-- general code review and clean up
-- ensure device-tree requirements are documented
-
-Cc: NeilBrown <neil@brown.name>
diff --git a/drivers/staging/mt7621-dma/hsdma-mt7621.c b/drivers/staging/mt7621-dma/hsdma-mt7621.c
deleted file mode 100644
index 1424d01d434b..000000000000
--- a/drivers/staging/mt7621-dma/hsdma-mt7621.c
+++ /dev/null
@@ -1,758 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2015, Michael Lee <igvtee@gmail.com>
- * MTK HSDMA support
- */
-
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/irq.h>
-#include <linux/of_dma.h>
-#include <linux/reset.h>
-#include <linux/of_device.h>
-
-#include "virt-dma.h"
-
-#define HSDMA_BASE_OFFSET 0x800
-
-#define HSDMA_REG_TX_BASE 0x00
-#define HSDMA_REG_TX_CNT 0x04
-#define HSDMA_REG_TX_CTX 0x08
-#define HSDMA_REG_TX_DTX 0x0c
-#define HSDMA_REG_RX_BASE 0x100
-#define HSDMA_REG_RX_CNT 0x104
-#define HSDMA_REG_RX_CRX 0x108
-#define HSDMA_REG_RX_DRX 0x10c
-#define HSDMA_REG_INFO 0x200
-#define HSDMA_REG_GLO_CFG 0x204
-#define HSDMA_REG_RST_CFG 0x208
-#define HSDMA_REG_DELAY_INT 0x20c
-#define HSDMA_REG_FREEQ_THRES 0x210
-#define HSDMA_REG_INT_STATUS 0x220
-#define HSDMA_REG_INT_MASK 0x228
-#define HSDMA_REG_SCH_Q01 0x280
-#define HSDMA_REG_SCH_Q23 0x284
-
-#define HSDMA_DESCS_MAX 0xfff
-#define HSDMA_DESCS_NUM 8
-#define HSDMA_DESCS_MASK (HSDMA_DESCS_NUM - 1)
-#define HSDMA_NEXT_DESC(x) (((x) + 1) & HSDMA_DESCS_MASK)
-
-/* HSDMA_REG_INFO */
-#define HSDMA_INFO_INDEX_MASK 0xf
-#define HSDMA_INFO_INDEX_SHIFT 24
-#define HSDMA_INFO_BASE_MASK 0xff
-#define HSDMA_INFO_BASE_SHIFT 16
-#define HSDMA_INFO_RX_MASK 0xff
-#define HSDMA_INFO_RX_SHIFT 8
-#define HSDMA_INFO_TX_MASK 0xff
-#define HSDMA_INFO_TX_SHIFT 0
-
-/* HSDMA_REG_GLO_CFG */
-#define HSDMA_GLO_TX_2B_OFFSET BIT(31)
-#define HSDMA_GLO_CLK_GATE BIT(30)
-#define HSDMA_GLO_BYTE_SWAP BIT(29)
-#define HSDMA_GLO_MULTI_DMA BIT(10)
-#define HSDMA_GLO_TWO_BUF BIT(9)
-#define HSDMA_GLO_32B_DESC BIT(8)
-#define HSDMA_GLO_BIG_ENDIAN BIT(7)
-#define HSDMA_GLO_TX_DONE BIT(6)
-#define HSDMA_GLO_BT_MASK 0x3
-#define HSDMA_GLO_BT_SHIFT 4
-#define HSDMA_GLO_RX_BUSY BIT(3)
-#define HSDMA_GLO_RX_DMA BIT(2)
-#define HSDMA_GLO_TX_BUSY BIT(1)
-#define HSDMA_GLO_TX_DMA BIT(0)
-
-#define HSDMA_BT_SIZE_16BYTES (0 << HSDMA_GLO_BT_SHIFT)
-#define HSDMA_BT_SIZE_32BYTES (1 << HSDMA_GLO_BT_SHIFT)
-#define HSDMA_BT_SIZE_64BYTES (2 << HSDMA_GLO_BT_SHIFT)
-#define HSDMA_BT_SIZE_128BYTES (3 << HSDMA_GLO_BT_SHIFT)
-
-#define HSDMA_GLO_DEFAULT (HSDMA_GLO_MULTI_DMA | \
- HSDMA_GLO_RX_DMA | HSDMA_GLO_TX_DMA | HSDMA_BT_SIZE_32BYTES)
-
-/* HSDMA_REG_RST_CFG */
-#define HSDMA_RST_RX_SHIFT 16
-#define HSDMA_RST_TX_SHIFT 0
-
-/* HSDMA_REG_DELAY_INT */
-#define HSDMA_DELAY_INT_EN BIT(15)
-#define HSDMA_DELAY_PEND_OFFSET 8
-#define HSDMA_DELAY_TIME_OFFSET 0
-#define HSDMA_DELAY_TX_OFFSET 16
-#define HSDMA_DELAY_RX_OFFSET 0
-
-#define HSDMA_DELAY_INIT(x) (HSDMA_DELAY_INT_EN | \
- ((x) << HSDMA_DELAY_PEND_OFFSET))
-#define HSDMA_DELAY(x) ((HSDMA_DELAY_INIT(x) << \
- HSDMA_DELAY_TX_OFFSET) | HSDMA_DELAY_INIT(x))
-
-/* HSDMA_REG_INT_STATUS */
-#define HSDMA_INT_DELAY_RX_COH BIT(31)
-#define HSDMA_INT_DELAY_RX_INT BIT(30)
-#define HSDMA_INT_DELAY_TX_COH BIT(29)
-#define HSDMA_INT_DELAY_TX_INT BIT(28)
-#define HSDMA_INT_RX_MASK 0x3
-#define HSDMA_INT_RX_SHIFT 16
-#define HSDMA_INT_RX_Q0 BIT(16)
-#define HSDMA_INT_TX_MASK 0xf
-#define HSDMA_INT_TX_SHIFT 0
-#define HSDMA_INT_TX_Q0 BIT(0)
-
-/* tx/rx dma desc flags */
-#define HSDMA_PLEN_MASK 0x3fff
-#define HSDMA_DESC_DONE BIT(31)
-#define HSDMA_DESC_LS0 BIT(30)
-#define HSDMA_DESC_PLEN0(_x) (((_x) & HSDMA_PLEN_MASK) << 16)
-#define HSDMA_DESC_TAG BIT(15)
-#define HSDMA_DESC_LS1 BIT(14)
-#define HSDMA_DESC_PLEN1(_x) ((_x) & HSDMA_PLEN_MASK)
-
-/* align 4 bytes */
-#define HSDMA_ALIGN_SIZE 3
-/* align size 128bytes */
-#define HSDMA_MAX_PLEN 0x3f80
-
-struct hsdma_desc {
- u32 addr0;
- u32 flags;
- u32 addr1;
- u32 unused;
-};
-
-struct mtk_hsdma_sg {
- dma_addr_t src_addr;
- dma_addr_t dst_addr;
- u32 len;
-};
-
-struct mtk_hsdma_desc {
- struct virt_dma_desc vdesc;
- unsigned int num_sgs;
- struct mtk_hsdma_sg sg[1];
-};
-
-struct mtk_hsdma_chan {
- struct virt_dma_chan vchan;
- unsigned int id;
- dma_addr_t desc_addr;
- int tx_idx;
- int rx_idx;
- struct hsdma_desc *tx_ring;
- struct hsdma_desc *rx_ring;
- struct mtk_hsdma_desc *desc;
- unsigned int next_sg;
-};
-
-struct mtk_hsdam_engine {
- struct dma_device ddev;
- struct device_dma_parameters dma_parms;
- void __iomem *base;
- struct tasklet_struct task;
- volatile unsigned long chan_issued;
-
- struct mtk_hsdma_chan chan[1];
-};
-
-static inline struct mtk_hsdam_engine *mtk_hsdma_chan_get_dev(struct mtk_hsdma_chan *chan)
-{
- return container_of(chan->vchan.chan.device, struct mtk_hsdam_engine,
- ddev);
-}
-
-static inline struct mtk_hsdma_chan *to_mtk_hsdma_chan(struct dma_chan *c)
-{
- return container_of(c, struct mtk_hsdma_chan, vchan.chan);
-}
-
-static inline struct mtk_hsdma_desc *to_mtk_hsdma_desc(struct virt_dma_desc *vdesc)
-{
- return container_of(vdesc, struct mtk_hsdma_desc, vdesc);
-}
-
-static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg)
-{
- return readl(hsdma->base + reg);
-}
-
-static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma,
- unsigned int reg, u32 val)
-{
- writel(val, hsdma->base + reg);
-}
-
-static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma,
- struct mtk_hsdma_chan *chan)
-{
- chan->tx_idx = 0;
- chan->rx_idx = HSDMA_DESCS_NUM - 1;
-
- mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx);
- mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx);
-
- mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG,
- 0x1 << (chan->id + HSDMA_RST_TX_SHIFT));
- mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG,
- 0x1 << (chan->id + HSDMA_RST_RX_SHIFT));
-}
-
-static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma)
-{
- dev_dbg(hsdma->ddev.dev,
- "tbase %08x, tcnt %08x, tctx %08x, tdtx: %08x, rbase %08x, rcnt %08x, rctx %08x, rdtx %08x\n",
- mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE),
- mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT),
- mtk_hsdma_read(hsdma, HSDMA_REG_TX_CTX),
- mtk_hsdma_read(hsdma, HSDMA_REG_TX_DTX),
- mtk_hsdma_read(hsdma, HSDMA_REG_RX_BASE),
- mtk_hsdma_read(hsdma, HSDMA_REG_RX_CNT),
- mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX),
- mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX));
-
- dev_dbg(hsdma->ddev.dev,
- "info %08x, glo %08x, delay %08x, intr_stat %08x, intr_mask %08x\n",
- mtk_hsdma_read(hsdma, HSDMA_REG_INFO),
- mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG),
- mtk_hsdma_read(hsdma, HSDMA_REG_DELAY_INT),
- mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS),
- mtk_hsdma_read(hsdma, HSDMA_REG_INT_MASK));
-}
-
-static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma,
- struct mtk_hsdma_chan *chan)
-{
- struct hsdma_desc *tx_desc;
- struct hsdma_desc *rx_desc;
- int i;
-
- dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n",
- chan->tx_idx, chan->rx_idx);
-
- for (i = 0; i < HSDMA_DESCS_NUM; i++) {
- tx_desc = &chan->tx_ring[i];
- rx_desc = &chan->rx_ring[i];
-
- dev_dbg(hsdma->ddev.dev,
- "%d tx addr0: %08x, flags %08x, tx addr1: %08x, rx addr0 %08x, flags %08x\n",
- i, tx_desc->addr0, tx_desc->flags,
- tx_desc->addr1, rx_desc->addr0, rx_desc->flags);
- }
-}
-
-static void mtk_hsdma_reset(struct mtk_hsdam_engine *hsdma,
- struct mtk_hsdma_chan *chan)
-{
- int i;
-
- /* disable dma */
- mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0);
-
- /* disable intr */
- mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0);
-
- /* init desc value */
- for (i = 0; i < HSDMA_DESCS_NUM; i++) {
- chan->tx_ring[i].addr0 = 0;
- chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE;
- }
- for (i = 0; i < HSDMA_DESCS_NUM; i++) {
- chan->rx_ring[i].addr0 = 0;
- chan->rx_ring[i].flags = 0;
- }
-
- /* reset */
- mtk_hsdma_reset_chan(hsdma, chan);
-
- /* enable intr */
- mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0);
-
- /* enable dma */
- mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT);
-}
-
-static int mtk_hsdma_terminate_all(struct dma_chan *c)
-{
- struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
- struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan);
- unsigned long timeout;
- LIST_HEAD(head);
-
- spin_lock_bh(&chan->vchan.lock);
- chan->desc = NULL;
- clear_bit(chan->id, &hsdma->chan_issued);
- vchan_get_all_descriptors(&chan->vchan, &head);
- spin_unlock_bh(&chan->vchan.lock);
-
- vchan_dma_desc_free_list(&chan->vchan, &head);
-
- /* wait dma transfer complete */
- timeout = jiffies + msecs_to_jiffies(2000);
- while (mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG) &
- (HSDMA_GLO_RX_BUSY | HSDMA_GLO_TX_BUSY)) {
- if (time_after_eq(jiffies, timeout)) {
- hsdma_dump_desc(hsdma, chan);
- mtk_hsdma_reset(hsdma, chan);
- dev_err(hsdma->ddev.dev, "timeout, reset it\n");
- break;
- }
- cpu_relax();
- }
-
- return 0;
-}
-
-static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,
- struct mtk_hsdma_chan *chan)
-{
- dma_addr_t src, dst;
- size_t len, tlen;
- struct hsdma_desc *tx_desc, *rx_desc;
- struct mtk_hsdma_sg *sg;
- unsigned int i;
- int rx_idx;
-
- sg = &chan->desc->sg[0];
- len = sg->len;
- chan->desc->num_sgs = DIV_ROUND_UP(len, HSDMA_MAX_PLEN);
-
- /* tx desc */
- src = sg->src_addr;
- for (i = 0; i < chan->desc->num_sgs; i++) {
- tx_desc = &chan->tx_ring[chan->tx_idx];
-
- if (len > HSDMA_MAX_PLEN)
- tlen = HSDMA_MAX_PLEN;
- else
- tlen = len;
-
- if (i & 0x1) {
- tx_desc->addr1 = src;
- tx_desc->flags |= HSDMA_DESC_PLEN1(tlen);
- } else {
- tx_desc->addr0 = src;
- tx_desc->flags = HSDMA_DESC_PLEN0(tlen);
-
- /* update index */
- chan->tx_idx = HSDMA_NEXT_DESC(chan->tx_idx);
- }
-
- src += tlen;
- len -= tlen;
- }
- if (i & 0x1)
- tx_desc->flags |= HSDMA_DESC_LS0;
- else
- tx_desc->flags |= HSDMA_DESC_LS1;
-
- /* rx desc */
- rx_idx = HSDMA_NEXT_DESC(chan->rx_idx);
- len = sg->len;
- dst = sg->dst_addr;
- for (i = 0; i < chan->desc->num_sgs; i++) {
- rx_desc = &chan->rx_ring[rx_idx];
- if (len > HSDMA_MAX_PLEN)
- tlen = HSDMA_MAX_PLEN;
- else
- tlen = len;
-
- rx_desc->addr0 = dst;
- rx_desc->flags = HSDMA_DESC_PLEN0(tlen);
-
- dst += tlen;
- len -= tlen;
-
- /* update index */
- rx_idx = HSDMA_NEXT_DESC(rx_idx);
- }
-
- /* make sure desc and index all up to date */
- wmb();
- mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx);
-
- return 0;
-}
-
-static int gdma_next_desc(struct mtk_hsdma_chan *chan)
-{
- struct virt_dma_desc *vdesc;
-
- vdesc = vchan_next_desc(&chan->vchan);
- if (!vdesc) {
- chan->desc = NULL;
- return 0;
- }
- chan->desc = to_mtk_hsdma_desc(vdesc);
- chan->next_sg = 0;
-
- return 1;
-}
-
-static void mtk_hsdma_chan_done(struct mtk_hsdam_engine *hsdma,
- struct mtk_hsdma_chan *chan)
-{
- struct mtk_hsdma_desc *desc;
- int chan_issued;
-
- chan_issued = 0;
- spin_lock_bh(&chan->vchan.lock);
- desc = chan->desc;
- if (likely(desc)) {
- if (chan->next_sg == desc->num_sgs) {
- list_del(&desc->vdesc.node);
- vchan_cookie_complete(&desc->vdesc);
- chan_issued = gdma_next_desc(chan);
- }
- } else {
- dev_dbg(hsdma->ddev.dev, "no desc to complete\n");
- }
-
- if (chan_issued)
- set_bit(chan->id, &hsdma->chan_issued);
- spin_unlock_bh(&chan->vchan.lock);
-}
-
-static irqreturn_t mtk_hsdma_irq(int irq, void *devid)
-{
- struct mtk_hsdam_engine *hsdma = devid;
- u32 status;
-
- status = mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS);
- if (unlikely(!status))
- return IRQ_NONE;
-
- if (likely(status & HSDMA_INT_RX_Q0))
- tasklet_schedule(&hsdma->task);
- else
- dev_dbg(hsdma->ddev.dev, "unhandle irq status %08x\n", status);
- /* clean intr bits */
- mtk_hsdma_write(hsdma, HSDMA_REG_INT_STATUS, status);
-
- return IRQ_HANDLED;
-}
-
-static void mtk_hsdma_issue_pending(struct dma_chan *c)
-{
- struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
- struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan);
-
- spin_lock_bh(&chan->vchan.lock);
- if (vchan_issue_pending(&chan->vchan) && !chan->desc) {
- if (gdma_next_desc(chan)) {
- set_bit(chan->id, &hsdma->chan_issued);
- tasklet_schedule(&hsdma->task);
- } else {
- dev_dbg(hsdma->ddev.dev, "no desc to issue\n");
- }
- }
- spin_unlock_bh(&chan->vchan.lock);
-}
-
-static struct dma_async_tx_descriptor *mtk_hsdma_prep_dma_memcpy(
- struct dma_chan *c, dma_addr_t dest, dma_addr_t src,
- size_t len, unsigned long flags)
-{
- struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
- struct mtk_hsdma_desc *desc;
-
- if (len <= 0)
- return NULL;
-
- desc = kzalloc(sizeof(*desc), GFP_ATOMIC);
- if (!desc) {
- dev_err(c->device->dev, "alloc memcpy decs error\n");
- return NULL;
- }
-
- desc->sg[0].src_addr = src;
- desc->sg[0].dst_addr = dest;
- desc->sg[0].len = len;
-
- return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
-}
-
-static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c,
- dma_cookie_t cookie,
- struct dma_tx_state *state)
-{
- return dma_cookie_status(c, cookie, state);
-}
-
-static void mtk_hsdma_free_chan_resources(struct dma_chan *c)
-{
- vchan_free_chan_resources(to_virt_chan(c));
-}
-
-static void mtk_hsdma_desc_free(struct virt_dma_desc *vdesc)
-{
- kfree(container_of(vdesc, struct mtk_hsdma_desc, vdesc));
-}
-
-static void mtk_hsdma_tx(struct mtk_hsdam_engine *hsdma)
-{
- struct mtk_hsdma_chan *chan;
-
- if (test_and_clear_bit(0, &hsdma->chan_issued)) {
- chan = &hsdma->chan[0];
- if (chan->desc)
- mtk_hsdma_start_transfer(hsdma, chan);
- else
- dev_dbg(hsdma->ddev.dev, "chan 0 no desc to issue\n");
- }
-}
-
-static void mtk_hsdma_rx(struct mtk_hsdam_engine *hsdma)
-{
- struct mtk_hsdma_chan *chan;
- int next_idx, drx_idx, cnt;
-
- chan = &hsdma->chan[0];
- next_idx = HSDMA_NEXT_DESC(chan->rx_idx);
- drx_idx = mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX);
-
- cnt = (drx_idx - next_idx) & HSDMA_DESCS_MASK;
- if (!cnt)
- return;
-
- chan->next_sg += cnt;
- chan->rx_idx = (chan->rx_idx + cnt) & HSDMA_DESCS_MASK;
-
- /* update rx crx */
- wmb();
- mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx);
-
- mtk_hsdma_chan_done(hsdma, chan);
-}
-
-static void mtk_hsdma_tasklet(struct tasklet_struct *t)
-{
- struct mtk_hsdam_engine *hsdma = from_tasklet(hsdma, t, task);
-
- mtk_hsdma_rx(hsdma);
- mtk_hsdma_tx(hsdma);
-}
-
-static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma,
- struct mtk_hsdma_chan *chan)
-{
- int i;
-
- chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev,
- 2 * HSDMA_DESCS_NUM *
- sizeof(*chan->tx_ring),
- &chan->desc_addr, GFP_ATOMIC | __GFP_ZERO);
- if (!chan->tx_ring)
- goto no_mem;
-
- chan->rx_ring = &chan->tx_ring[HSDMA_DESCS_NUM];
-
- /* init tx ring value */
- for (i = 0; i < HSDMA_DESCS_NUM; i++)
- chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE;
-
- return 0;
-no_mem:
- return -ENOMEM;
-}
-
-static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma,
- struct mtk_hsdma_chan *chan)
-{
- if (chan->tx_ring) {
- dma_free_coherent(hsdma->ddev.dev,
- 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring),
- chan->tx_ring, chan->desc_addr);
- chan->tx_ring = NULL;
- chan->rx_ring = NULL;
- }
-}
-
-static int mtk_hsdma_init(struct mtk_hsdam_engine *hsdma)
-{
- struct mtk_hsdma_chan *chan;
- int ret;
- u32 reg;
-
- /* init desc */
- chan = &hsdma->chan[0];
- ret = mtk_hsdam_alloc_desc(hsdma, chan);
- if (ret)
- return ret;
-
- /* tx */
- mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, chan->desc_addr);
- mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, HSDMA_DESCS_NUM);
- /* rx */
- mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, chan->desc_addr +
- (sizeof(struct hsdma_desc) * HSDMA_DESCS_NUM));
- mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, HSDMA_DESCS_NUM);
- /* reset */
- mtk_hsdma_reset_chan(hsdma, chan);
-
- /* enable rx intr */
- mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0);
-
- /* enable dma */
- mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT);
-
- /* hardware info */
- reg = mtk_hsdma_read(hsdma, HSDMA_REG_INFO);
- dev_info(hsdma->ddev.dev, "rx: %d, tx: %d\n",
- (reg >> HSDMA_INFO_RX_SHIFT) & HSDMA_INFO_RX_MASK,
- (reg >> HSDMA_INFO_TX_SHIFT) & HSDMA_INFO_TX_MASK);
-
- hsdma_dump_reg(hsdma);
-
- return ret;
-}
-
-static void mtk_hsdma_uninit(struct mtk_hsdam_engine *hsdma)
-{
- struct mtk_hsdma_chan *chan;
-
- /* disable dma */
- mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0);
-
- /* disable intr */
- mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0);
-
- /* free desc */
- chan = &hsdma->chan[0];
- mtk_hsdam_free_desc(hsdma, chan);
-
- /* tx */
- mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, 0);
- mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, 0);
- /* rx */
- mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, 0);
- mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, 0);
- /* reset */
- mtk_hsdma_reset_chan(hsdma, chan);
-}
-
-static const struct of_device_id mtk_hsdma_of_match[] = {
- { .compatible = "mediatek,mt7621-hsdma" },
- { },
-};
-
-static int mtk_hsdma_probe(struct platform_device *pdev)
-{
- const struct of_device_id *match;
- struct mtk_hsdma_chan *chan;
- struct mtk_hsdam_engine *hsdma;
- struct dma_device *dd;
- int ret;
- int irq;
- void __iomem *base;
-
- ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
- match = of_match_device(mtk_hsdma_of_match, &pdev->dev);
- if (!match)
- return -EINVAL;
-
- hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL);
- if (!hsdma)
- return -EINVAL;
-
- base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(base))
- return PTR_ERR(base);
- hsdma->base = base + HSDMA_BASE_OFFSET;
- tasklet_setup(&hsdma->task, mtk_hsdma_tasklet);
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return -EINVAL;
- ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq,
- 0, dev_name(&pdev->dev), hsdma);
- if (ret) {
- dev_err(&pdev->dev, "failed to request irq\n");
- return ret;
- }
-
- device_reset(&pdev->dev);
-
- dd = &hsdma->ddev;
- dma_cap_set(DMA_MEMCPY, dd->cap_mask);
- dd->copy_align = HSDMA_ALIGN_SIZE;
- dd->device_free_chan_resources = mtk_hsdma_free_chan_resources;
- dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy;
- dd->device_terminate_all = mtk_hsdma_terminate_all;
- dd->device_tx_status = mtk_hsdma_tx_status;
- dd->device_issue_pending = mtk_hsdma_issue_pending;
- dd->dev = &pdev->dev;
- dd->dev->dma_parms = &hsdma->dma_parms;
- dma_set_max_seg_size(dd->dev, HSDMA_MAX_PLEN);
- INIT_LIST_HEAD(&dd->channels);
-
- chan = &hsdma->chan[0];
- chan->id = 0;
- chan->vchan.desc_free = mtk_hsdma_desc_free;
- vchan_init(&chan->vchan, dd);
-
- /* init hardware */
- ret = mtk_hsdma_init(hsdma);
- if (ret) {
- dev_err(&pdev->dev, "failed to alloc ring descs\n");
- return ret;
- }
-
- ret = dma_async_device_register(dd);
- if (ret) {
- dev_err(&pdev->dev, "failed to register dma device\n");
- goto err_uninit_hsdma;
- }
-
- ret = of_dma_controller_register(pdev->dev.of_node,
- of_dma_xlate_by_chan_id, hsdma);
- if (ret) {
- dev_err(&pdev->dev, "failed to register of dma controller\n");
- goto err_unregister;
- }
-
- platform_set_drvdata(pdev, hsdma);
-
- return 0;
-
-err_unregister:
- dma_async_device_unregister(dd);
-err_uninit_hsdma:
- mtk_hsdma_uninit(hsdma);
- return ret;
-}
-
-static int mtk_hsdma_remove(struct platform_device *pdev)
-{
- struct mtk_hsdam_engine *hsdma = platform_get_drvdata(pdev);
-
- mtk_hsdma_uninit(hsdma);
-
- of_dma_controller_free(pdev->dev.of_node);
- dma_async_device_unregister(&hsdma->ddev);
-
- return 0;
-}
-
-static struct platform_driver mtk_hsdma_driver = {
- .probe = mtk_hsdma_probe,
- .remove = mtk_hsdma_remove,
- .driver = {
- .name = KBUILD_MODNAME,
- .of_match_table = mtk_hsdma_of_match,
- },
-};
-module_platform_driver(mtk_hsdma_driver);
-
-MODULE_AUTHOR("Michael Lee <igvtee@gmail.com>");
-MODULE_DESCRIPTION("MTK HSDMA driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/mt7621-dts/Kconfig b/drivers/staging/mt7621-dts/Kconfig
deleted file mode 100644
index 6932ab7acadf..000000000000
--- a/drivers/staging/mt7621-dts/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config DTB_GNUBEE1
- bool "GnuBee1 2.5inch NAS"
- depends on SOC_MT7621 && DTB_RT_NONE
- select BUILTIN_DTB
-
-config DTB_GNUBEE2
- bool "GnuBee2 3.5inch NAS"
- depends on SOC_MT7621 && DTB_RT_NONE
- select BUILTIN_DTB
-
diff --git a/drivers/staging/mt7621-dts/Makefile b/drivers/staging/mt7621-dts/Makefile
deleted file mode 100644
index b4ab99fed932..000000000000
--- a/drivers/staging/mt7621-dts/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_DTB_GNUBEE1) += gbpc1.dtb
-dtb-$(CONFIG_DTB_GNUBEE2) += gbpc2.dtb
-
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
diff --git a/drivers/staging/mt7621-dts/TODO b/drivers/staging/mt7621-dts/TODO
deleted file mode 100644
index 1b758e5c84e0..000000000000
--- a/drivers/staging/mt7621-dts/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-
-- ensure all usage matches code
-- ensure all features used are documented
-
-Cc: NeilBrown <neil@brown.name>
diff --git a/drivers/staging/mt7621-dts/gbpc1.dts b/drivers/staging/mt7621-dts/gbpc1.dts
deleted file mode 100644
index e38a083811e5..000000000000
--- a/drivers/staging/mt7621-dts/gbpc1.dts
+++ /dev/null
@@ -1,128 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-/dts-v1/;
-
-#include "mt7621.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
-
-/ {
- compatible = "gnubee,gb-pc1", "mediatek,mt7621-soc";
- model = "GB-PC1";
-
- memory@0 {
- device_type = "memory";
- reg = <0x0 0x1c000000>, <0x20000000 0x4000000>;
- };
-
- chosen {
- bootargs = "console=ttyS0,57600";
- };
-
- palmbus: palmbus@1e000000 {
- i2c@900 {
- status = "okay";
- };
- };
-
- gpio-keys {
- compatible = "gpio-keys";
-
- reset {
- label = "reset";
- gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
- linux,code = <KEY_RESTART>;
- };
- };
-
- gpio-leds {
- compatible = "gpio-leds";
-
- system {
- label = "gb-pc1:green:system";
- gpios = <&gpio 6 GPIO_ACTIVE_LOW>;
- };
-
- status {
- label = "gb-pc1:green:status";
- gpios = <&gpio 8 GPIO_ACTIVE_LOW>;
- };
-
- lan1 {
- label = "gb-pc1:green:lan1";
- gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
- };
-
- lan2 {
- label = "gb-pc1:green:lan2";
- gpios = <&gpio 25 GPIO_ACTIVE_LOW>;
- };
- };
-};
-
-&sdhci {
- status = "okay";
-};
-
-&spi0 {
- status = "okay";
-
- m25p80@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "jedec,spi-nor";
- reg = <0>;
- spi-max-frequency = <50000000>;
- broken-flash-reset;
-
- partition@0 {
- label = "u-boot";
- reg = <0x0 0x30000>;
- read-only;
- };
-
- partition@30000 {
- label = "u-boot-env";
- reg = <0x30000 0x10000>;
- read-only;
- };
-
- factory: partition@40000 {
- label = "factory";
- reg = <0x40000 0x10000>;
- read-only;
- };
-
- partition@50000 {
- label = "firmware";
- reg = <0x50000 0x1FB0000>;
- };
-
- };
-};
-
-&pcie {
- status = "okay";
-};
-
-&pinctrl {
- state_default: pinctrl0 {
- default_gpio: gpio {
- groups = "wdt", "rgmii2", "uart3";
- function = "gpio";
- };
- };
-};
-
-&switch0 {
- ports {
- port@0 {
- label = "ethblack";
- status = "ok";
- };
- port@4 {
- label = "ethblue";
- status = "ok";
- };
- };
-};
diff --git a/drivers/staging/mt7621-dts/gbpc2.dts b/drivers/staging/mt7621-dts/gbpc2.dts
deleted file mode 100644
index 6fe603c7711d..000000000000
--- a/drivers/staging/mt7621-dts/gbpc2.dts
+++ /dev/null
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-/dts-v1/;
-
-#include "gbpc1.dts"
-
-/ {
- compatible = "gnubee,gb-pc2", "mediatek,mt7621-soc";
- model = "GB-PC2";
-};
-
-&default_gpio {
- groups = "wdt", "uart3";
- function = "gpio";
-};
-
-&gmac1 {
- status = "ok";
-};
-
-&phy_external {
- status = "ok";
-};
diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
deleted file mode 100644
index 6d158e4f4b8c..000000000000
--- a/drivers/staging/mt7621-dts/mt7621.dtsi
+++ /dev/null
@@ -1,540 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-#include <dt-bindings/interrupt-controller/mips-gic.h>
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/mt7621-clk.h>
-
-/ {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "mediatek,mt7621-soc";
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu@0 {
- device_type = "cpu";
- compatible = "mips,mips1004Kc";
- reg = <0>;
- };
-
- cpu@1 {
- device_type = "cpu";
- compatible = "mips,mips1004Kc";
- reg = <1>;
- };
- };
-
- cpuintc: cpuintc@0 {
- #address-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-controller;
- compatible = "mti,cpu-interrupt-controller";
- };
-
- aliases {
- serial0 = &uartlite;
- };
-
-
- mmc_fixed_3v3: fixedregulator@0 {
- compatible = "regulator-fixed";
- regulator-name = "mmc_power";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- enable-active-high;
- regulator-always-on;
- };
-
- mmc_fixed_1v8_io: fixedregulator@1 {
- compatible = "regulator-fixed";
- regulator-name = "mmc_io";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- enable-active-high;
- regulator-always-on;
- };
-
- palmbus: palmbus@1e000000 {
- compatible = "palmbus";
- reg = <0x1e000000 0x100000>;
- ranges = <0x0 0x1e000000 0x0fffff>;
-
- #address-cells = <1>;
- #size-cells = <1>;
-
- sysc: syscon@0 {
- compatible = "mediatek,mt7621-sysc", "syscon";
- reg = <0x0 0x100>;
- #clock-cells = <1>;
- ralink,memctl = <&memc>;
- clock-output-names = "xtal", "cpu", "bus",
- "50m", "125m", "150m",
- "250m", "270m";
- };
-
- wdt: wdt@100 {
- compatible = "mediatek,mt7621-wdt";
- reg = <0x100 0x100>;